1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef GFX_WR_IPCRESOURCEUPDATEQUEUE_H 8 #define GFX_WR_IPCRESOURCEUPDATEQUEUE_H 9 10 #include "mozilla/layers/WebRenderMessages.h" 11 #include "mozilla/layers/RefCountedShmem.h" 12 #include "mozilla/layers/TextureClient.h" 13 #include "mozilla/webrender/WebRenderTypes.h" 14 15 namespace mozilla { 16 namespace ipc { 17 class IShmemAllocator; 18 } 19 namespace layers { 20 class TextureClient; 21 class WebRenderBridgeChild; 22 } // namespace layers 23 24 namespace wr { 25 26 /// ShmSegmentsWriter pushes bytes in a sequence of fixed size shmems for small 27 /// allocations and creates dedicated shmems for large allocations. 28 class ShmSegmentsWriter { 29 public: 30 ShmSegmentsWriter(layers::WebRenderBridgeChild* aAllocator, 31 size_t aChunkSize); 32 ~ShmSegmentsWriter(); 33 34 ShmSegmentsWriter(ShmSegmentsWriter&& aOther) noexcept; 35 ShmSegmentsWriter& operator=(ShmSegmentsWriter&& aOther) noexcept; 36 37 ShmSegmentsWriter(const ShmSegmentsWriter& aOther) = delete; 38 ShmSegmentsWriter& operator=(const ShmSegmentsWriter& aOther) = delete; 39 40 layers::OffsetRange Write(Range<uint8_t> aBytes); 41 42 template <typename T> WriteAsBytes(Range<T> aValues)43 layers::OffsetRange WriteAsBytes(Range<T> aValues) { 44 return Write(Range<uint8_t>((uint8_t*)aValues.begin().get(), 45 aValues.length() * sizeof(T))); 46 } 47 48 void Flush(nsTArray<layers::RefCountedShmem>& aSmallAllocs, 49 nsTArray<mozilla::ipc::Shmem>& aLargeAllocs); 50 51 void Clear(); 52 bool IsEmpty() const; 53 WrBridge()54 layers::WebRenderBridgeChild* WrBridge() const { return mShmAllocator; } ChunkSize()55 size_t ChunkSize() const { return mChunkSize; } 56 57 protected: 58 bool AllocChunk(); 59 layers::OffsetRange AllocLargeChunk(size_t aSize); 60 61 nsTArray<layers::RefCountedShmem> mSmallAllocs; 62 nsTArray<mozilla::ipc::Shmem> mLargeAllocs; 63 layers::WebRenderBridgeChild* mShmAllocator; 64 size_t mCursor; 65 size_t mChunkSize; 66 }; 67 68 class ShmSegmentsReader { 69 public: 70 ShmSegmentsReader(const nsTArray<layers::RefCountedShmem>& aSmallShmems, 71 const nsTArray<mozilla::ipc::Shmem>& aLargeShmems); 72 73 bool Read(const layers::OffsetRange& aRange, wr::Vec<uint8_t>& aInto); 74 75 // Get a read pointer, if possible, directly into the shm. If the range has 76 // been broken up into multiple chunks that can't be represented by a single 77 // range, nothing will be returned to indicate failure. 78 Maybe<Range<uint8_t>> GetReadPointer(const layers::OffsetRange& aRange); 79 80 // Get a read pointer, if possible, directly into the shm. Otherwise, copy 81 // it into the Vec and return a pointer to that contiguous memory instead. 82 // If all fails, return nothing. GetReadPointerOrCopy(const layers::OffsetRange & aRange,wr::Vec<uint8_t> & aInto)83 Maybe<Range<uint8_t>> GetReadPointerOrCopy(const layers::OffsetRange& aRange, 84 wr::Vec<uint8_t>& aInto) { 85 if (Maybe<Range<uint8_t>> ptr = GetReadPointer(aRange)) { 86 return ptr; 87 } else { 88 size_t initialLength = aInto.Length(); 89 if (Read(aRange, aInto)) { 90 return Some(Range<uint8_t>(aInto.Data() + initialLength, 91 aInto.Length() - initialLength)); 92 } else { 93 return Nothing(); 94 } 95 } 96 } 97 98 protected: 99 bool ReadLarge(const layers::OffsetRange& aRange, wr::Vec<uint8_t>& aInto); 100 101 Maybe<Range<uint8_t>> GetReadPointerLarge(const layers::OffsetRange& aRange); 102 103 const nsTArray<layers::RefCountedShmem>& mSmallAllocs; 104 const nsTArray<mozilla::ipc::Shmem>& mLargeAllocs; 105 size_t mChunkSize; 106 }; 107 108 class IpcResourceUpdateQueue { 109 public: 110 // Because we are using shmems, the size should be a multiple of the page 111 // size. Each shmem has two guard pages, and the minimum shmem size (at least 112 // one Windows) is 64k which is already quite large for a lot of the resources 113 // we use here. The RefCountedShmem type used to allocate the chunks keeps a 114 // 16 bytes header in the buffer which we account for here as well. So we pick 115 // 64k - 2 * 4k - 16 = 57328 bytes as the default alloc size. 116 explicit IpcResourceUpdateQueue(layers::WebRenderBridgeChild* aAllocator, 117 size_t aChunkSize = 57328); 118 119 IpcResourceUpdateQueue(IpcResourceUpdateQueue&& aOther) noexcept; 120 IpcResourceUpdateQueue& operator=(IpcResourceUpdateQueue&& aOther) noexcept; 121 122 IpcResourceUpdateQueue(const IpcResourceUpdateQueue& aOther) = delete; 123 IpcResourceUpdateQueue& operator=(const IpcResourceUpdateQueue& aOther) = 124 delete; 125 126 // Moves over everything but the subqueues 127 void ReplaceResources(IpcResourceUpdateQueue&& aOther); 128 129 bool AddImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, 130 Range<uint8_t> aBytes); 131 132 bool AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor, 133 Range<uint8_t> aBytes, ImageIntRect aVisibleRect); 134 135 void AddPrivateExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, 136 wr::ImageDescriptor aDesc); 137 138 void AddSharedExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey); 139 140 void PushExternalImageForTexture(wr::ExternalImageId aExtId, 141 wr::ImageKey aKey, 142 layers::TextureClient* aTexture, 143 bool aIsUpdate); 144 145 bool UpdateImageBuffer(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, 146 Range<uint8_t> aBytes); 147 148 bool UpdateBlobImage(wr::BlobImageKey aKey, 149 const ImageDescriptor& aDescriptor, 150 Range<uint8_t> aBytes, ImageIntRect aVisibleRect, 151 ImageIntRect aDirtyRect); 152 153 void UpdatePrivateExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, 154 const wr::ImageDescriptor& aDesc, 155 ImageIntRect aDirtyRect); 156 void UpdateSharedExternalImage(ExternalImageId aExtID, ImageKey aKey, 157 ImageIntRect aDirtyRect); 158 159 void SetBlobImageVisibleArea(BlobImageKey aKey, const ImageIntRect& aArea); 160 161 void DeleteImage(wr::ImageKey aKey); 162 163 void DeleteBlobImage(wr::BlobImageKey aKey); 164 165 bool AddRawFont(wr::FontKey aKey, Range<uint8_t> aBytes, uint32_t aIndex); 166 167 bool AddFontDescriptor(wr::FontKey aKey, Range<uint8_t> aBytes, 168 uint32_t aIndex); 169 170 void DeleteFont(wr::FontKey aKey); 171 172 void AddFontInstance(wr::FontInstanceKey aKey, wr::FontKey aFontKey, 173 float aGlyphSize, 174 const wr::FontInstanceOptions* aOptions, 175 const wr::FontInstancePlatformOptions* aPlatformOptions, 176 Range<const gfx::FontVariation> aVariations); 177 178 void DeleteFontInstance(wr::FontInstanceKey aKey); 179 180 void Clear(); 181 182 void Flush(nsTArray<layers::OpUpdateResource>& aUpdates, 183 nsTArray<layers::RefCountedShmem>& aSmallAllocs, 184 nsTArray<mozilla::ipc::Shmem>& aLargeAllocs); 185 186 bool IsEmpty() const; 187 188 static void ReleaseShmems(mozilla::ipc::IProtocol*, 189 nsTArray<layers::RefCountedShmem>& aShms); 190 static void ReleaseShmems(mozilla::ipc::IProtocol*, 191 nsTArray<mozilla::ipc::Shmem>& aShms); 192 193 protected: 194 ShmSegmentsWriter mWriter; 195 nsTArray<layers::OpUpdateResource> mUpdates; 196 }; 197 198 } // namespace wr 199 } // namespace mozilla 200 201 #endif 202