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