summaryrefslogtreecommitdiffstats
path: root/gfx/layers/wr/IpcResourceUpdateQueue.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/wr/IpcResourceUpdateQueue.h')
-rw-r--r--gfx/layers/wr/IpcResourceUpdateQueue.h195
1 files changed, 195 insertions, 0 deletions
diff --git a/gfx/layers/wr/IpcResourceUpdateQueue.h b/gfx/layers/wr/IpcResourceUpdateQueue.h
new file mode 100644
index 0000000000..6096ddbddb
--- /dev/null
+++ b/gfx/layers/wr/IpcResourceUpdateQueue.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef GFX_WR_IPCRESOURCEUPDATEQUEUE_H
+#define GFX_WR_IPCRESOURCEUPDATEQUEUE_H
+
+#include "mozilla/layers/WebRenderMessages.h"
+#include "mozilla/layers/RefCountedShmem.h"
+#include "mozilla/layers/TextureClient.h"
+#include "mozilla/webrender/WebRenderTypes.h"
+
+namespace mozilla {
+namespace ipc {
+class IShmemAllocator;
+}
+namespace layers {
+class TextureClient;
+class WebRenderBridgeChild;
+} // namespace layers
+
+namespace wr {
+
+/// ShmSegmentsWriter pushes bytes in a sequence of fixed size shmems for small
+/// allocations and creates dedicated shmems for large allocations.
+class ShmSegmentsWriter {
+ public:
+ ShmSegmentsWriter(layers::WebRenderBridgeChild* aAllocator,
+ size_t aChunkSize);
+ ~ShmSegmentsWriter();
+
+ ShmSegmentsWriter(ShmSegmentsWriter&& aOther) noexcept;
+ ShmSegmentsWriter& operator=(ShmSegmentsWriter&& aOther) noexcept;
+
+ ShmSegmentsWriter(const ShmSegmentsWriter& aOther) = delete;
+ ShmSegmentsWriter& operator=(const ShmSegmentsWriter& aOther) = delete;
+
+ layers::OffsetRange Write(Range<uint8_t> aBytes);
+
+ template <typename T>
+ layers::OffsetRange WriteAsBytes(Range<T> aValues) {
+ return Write(Range<uint8_t>((uint8_t*)aValues.begin().get(),
+ aValues.length() * sizeof(T)));
+ }
+
+ void Flush(nsTArray<layers::RefCountedShmem>& aSmallAllocs,
+ nsTArray<mozilla::ipc::Shmem>& aLargeAllocs);
+
+ void Clear();
+ bool IsEmpty() const;
+
+ layers::WebRenderBridgeChild* WrBridge() const { return mShmAllocator; }
+ size_t ChunkSize() const { return mChunkSize; }
+
+ protected:
+ bool AllocChunk();
+ layers::OffsetRange AllocLargeChunk(size_t aSize);
+
+ nsTArray<layers::RefCountedShmem> mSmallAllocs;
+ nsTArray<mozilla::ipc::Shmem> mLargeAllocs;
+ layers::WebRenderBridgeChild* mShmAllocator;
+ size_t mCursor;
+ size_t mChunkSize;
+};
+
+class ShmSegmentsReader {
+ public:
+ ShmSegmentsReader(const nsTArray<layers::RefCountedShmem>& aSmallShmems,
+ const nsTArray<mozilla::ipc::Shmem>& aLargeShmems);
+
+ bool Read(const layers::OffsetRange& aRange, wr::Vec<uint8_t>& aInto);
+
+ // Get a read pointer, if possible, directly into the shm. If the range has
+ // been broken up into multiple chunks that can't be represented by a single
+ // range, nothing will be returned to indicate failure.
+ Maybe<Range<uint8_t>> GetReadPointer(const layers::OffsetRange& aRange);
+
+ // Get a read pointer, if possible, directly into the shm. Otherwise, copy
+ // it into the Vec and return a pointer to that contiguous memory instead.
+ // If all fails, return nothing.
+ Maybe<Range<uint8_t>> GetReadPointerOrCopy(const layers::OffsetRange& aRange,
+ wr::Vec<uint8_t>& aInto) {
+ if (Maybe<Range<uint8_t>> ptr = GetReadPointer(aRange)) {
+ return ptr;
+ } else {
+ size_t initialLength = aInto.Length();
+ if (Read(aRange, aInto)) {
+ return Some(Range<uint8_t>(aInto.Data() + initialLength,
+ aInto.Length() - initialLength));
+ } else {
+ return Nothing();
+ }
+ }
+ }
+
+ protected:
+ bool ReadLarge(const layers::OffsetRange& aRange, wr::Vec<uint8_t>& aInto);
+
+ Maybe<Range<uint8_t>> GetReadPointerLarge(const layers::OffsetRange& aRange);
+
+ const nsTArray<layers::RefCountedShmem>& mSmallAllocs;
+ const nsTArray<mozilla::ipc::Shmem>& mLargeAllocs;
+ size_t mChunkSize;
+};
+
+class IpcResourceUpdateQueue {
+ public:
+ // Because we are using shmems, the size should be a multiple of the page
+ // size. Each shmem has two guard pages, and the minimum shmem size (at least
+ // one Windows) is 64k which is already quite large for a lot of the resources
+ // we use here. The RefCountedShmem type used to allocate the chunks keeps a
+ // 16 bytes header in the buffer which we account for here as well. So we pick
+ // 64k - 2 * 4k - 16 = 57328 bytes as the default alloc size.
+ explicit IpcResourceUpdateQueue(layers::WebRenderBridgeChild* aAllocator,
+ size_t aChunkSize = 57328);
+
+ IpcResourceUpdateQueue(IpcResourceUpdateQueue&& aOther) noexcept;
+ IpcResourceUpdateQueue& operator=(IpcResourceUpdateQueue&& aOther) noexcept;
+
+ IpcResourceUpdateQueue(const IpcResourceUpdateQueue& aOther) = delete;
+ IpcResourceUpdateQueue& operator=(const IpcResourceUpdateQueue& aOther) =
+ delete;
+
+ // Moves over everything but the subqueues
+ void ReplaceResources(IpcResourceUpdateQueue&& aOther);
+
+ bool AddImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor,
+ Range<uint8_t> aBytes);
+
+ bool AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor,
+ Range<uint8_t> aBytes, ImageIntRect aVisibleRect);
+
+ void AddSharedExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey);
+
+ void PushExternalImageForTexture(wr::ExternalImageId aExtId,
+ wr::ImageKey aKey,
+ layers::TextureClient* aTexture,
+ bool aIsUpdate);
+
+ bool UpdateImageBuffer(wr::ImageKey aKey, const ImageDescriptor& aDescriptor,
+ Range<uint8_t> aBytes);
+
+ bool UpdateBlobImage(wr::BlobImageKey aKey,
+ const ImageDescriptor& aDescriptor,
+ Range<uint8_t> aBytes, ImageIntRect aVisibleRect,
+ ImageIntRect aDirtyRect);
+
+ void UpdateSharedExternalImage(ExternalImageId aExtID, ImageKey aKey,
+ ImageIntRect aDirtyRect);
+
+ void SetBlobImageVisibleArea(BlobImageKey aKey, const ImageIntRect& aArea);
+
+ void DeleteImage(wr::ImageKey aKey);
+
+ void DeleteBlobImage(wr::BlobImageKey aKey);
+
+ bool AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex);
+
+ bool AddFontDescriptor(wr::FontKey aKey, Range<uint8_t> aBytes,
+ uint32_t aIndex);
+
+ void DeleteFont(wr::FontKey aKey);
+
+ void AddFontInstance(wr::FontInstanceKey aKey, wr::FontKey aFontKey,
+ float aGlyphSize,
+ const wr::FontInstanceOptions* aOptions,
+ const wr::FontInstancePlatformOptions* aPlatformOptions,
+ Range<const gfx::FontVariation> aVariations);
+
+ void DeleteFontInstance(wr::FontInstanceKey aKey);
+
+ void Clear();
+
+ void Flush(nsTArray<layers::OpUpdateResource>& aUpdates,
+ nsTArray<layers::RefCountedShmem>& aSmallAllocs,
+ nsTArray<mozilla::ipc::Shmem>& aLargeAllocs);
+
+ bool IsEmpty() const;
+
+ static void ReleaseShmems(mozilla::ipc::IProtocol*,
+ nsTArray<layers::RefCountedShmem>& aShms);
+ static void ReleaseShmems(mozilla::ipc::IProtocol*,
+ nsTArray<mozilla::ipc::Shmem>& aShms);
+
+ protected:
+ ShmSegmentsWriter mWriter;
+ nsTArray<layers::OpUpdateResource> mUpdates;
+};
+
+} // namespace wr
+} // namespace mozilla
+
+#endif