/work/obj-fuzz/dist/include/mozilla/layers/ContentClient.h
Line | Count | Source (jump to first uncovered line) |
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 MOZILLA_GFX_CONTENTCLIENT_H |
8 | | #define MOZILLA_GFX_CONTENTCLIENT_H |
9 | | |
10 | | #include <stdint.h> // for uint32_t |
11 | | #include "RotatedBuffer.h" // for RotatedBuffer, etc |
12 | | #include "gfxTypes.h" |
13 | | #include "gfxPlatform.h" // for gfxPlatform |
14 | | #include "mozilla/Assertions.h" // for MOZ_CRASH |
15 | | #include "mozilla/Attributes.h" // for override |
16 | | #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed |
17 | | #include "mozilla/gfx/Point.h" // for IntSize |
18 | | #include "mozilla/layers/CompositableClient.h" // for CompositableClient |
19 | | #include "mozilla/layers/CompositableForwarder.h" |
20 | | #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc |
21 | | #include "mozilla/layers/ISurfaceAllocator.h" |
22 | | #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor |
23 | | #include "mozilla/layers/LayersTypes.h" // for TextureDumpMode |
24 | | #include "mozilla/layers/TextureClient.h" // for TextureClient |
25 | | #include "mozilla/layers/PaintThread.h" // for PaintTask |
26 | | #include "mozilla/Maybe.h" // for Maybe |
27 | | #include "mozilla/mozalloc.h" // for operator delete |
28 | | #include "mozilla/UniquePtr.h" // for UniquePtr |
29 | | #include "ReadbackProcessor.h" // For ReadbackProcessor::Update |
30 | | #include "nsCOMPtr.h" // for already_AddRefed |
31 | | #include "nsPoint.h" // for nsIntPoint |
32 | | #include "nsRect.h" // for mozilla::gfx::IntRect |
33 | | #include "nsRegion.h" // for nsIntRegion |
34 | | #include "nsTArray.h" // for nsTArray |
35 | | |
36 | | namespace mozilla { |
37 | | namespace gfx { |
38 | | class DrawTarget; |
39 | | } // namespace gfx |
40 | | |
41 | | namespace layers { |
42 | | |
43 | | class PaintedLayer; |
44 | | |
45 | | /** |
46 | | * A compositable client for PaintedLayers. These are different to Image/Canvas |
47 | | * clients due to sending a valid region across IPC and because we do a lot more |
48 | | * optimisation work, encapsulated in RotatedBuffers. |
49 | | * |
50 | | * We use content clients for OMTC and non-OMTC, basic rendering so that |
51 | | * BasicPaintedLayer has only one interface to deal with. We support single and |
52 | | * double buffered flavours. For tiled layers, we do not use a ContentClient |
53 | | * although we do have a ContentHost, and we do use texture clients and texture |
54 | | * hosts. |
55 | | * |
56 | | * The interface presented by ContentClient is used by the BasicPaintedLayer |
57 | | * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer |
58 | | * which is different (the OMTC one does a little more). |
59 | | */ |
60 | | class ContentClient : public CompositableClient |
61 | | { |
62 | | public: |
63 | | typedef gfxContentType ContentType; |
64 | | |
65 | | /** |
66 | | * Creates, configures, and returns a new content client. If necessary, a |
67 | | * message will be sent to the compositor to create a corresponding content |
68 | | * host. |
69 | | */ |
70 | | static already_AddRefed<ContentClient> CreateContentClient(CompositableForwarder* aFwd); |
71 | | |
72 | | /** |
73 | | * Controls the size of the backing buffer of this. |
74 | | * - SizedToVisibleBounds: the backing buffer is exactly the same |
75 | | * size as the bounds of PaintedLayer's visible region |
76 | | * - ContainsVisibleBounds: the backing buffer is large enough to |
77 | | * fit visible bounds. May be larger. |
78 | | */ |
79 | | enum BufferSizePolicy { |
80 | | SizedToVisibleBounds, |
81 | | ContainsVisibleBounds |
82 | | }; |
83 | | |
84 | | explicit ContentClient(CompositableForwarder* aForwarder, |
85 | | BufferSizePolicy aBufferSizePolicy) |
86 | | : CompositableClient(aForwarder) |
87 | | , mBufferSizePolicy(aBufferSizePolicy) |
88 | 0 | {} |
89 | | virtual ~ContentClient() |
90 | 0 | {} |
91 | | |
92 | | virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); |
93 | | |
94 | | virtual void Clear(); |
95 | | |
96 | | /** |
97 | | * This is returned by BeginPaint. The caller should draw into mTarget. |
98 | | * mRegionToDraw must be drawn. mRegionToInvalidate has been invalidated |
99 | | * by ContentClient and must be redrawn on the screen. |
100 | | * mRegionToInvalidate is set when the buffer has changed from |
101 | | * opaque to transparent or vice versa, since the details of rendering can |
102 | | * depend on the buffer type. |
103 | | */ |
104 | | struct PaintState { |
105 | | PaintState() |
106 | | : mRegionToDraw() |
107 | | , mRegionToInvalidate() |
108 | | , mMode(SurfaceMode::SURFACE_NONE) |
109 | | , mClip(DrawRegionClip::NONE) |
110 | | , mContentType(gfxContentType::SENTINEL) |
111 | | , mAsyncPaint(false) |
112 | | , mAsyncTask(nullptr) |
113 | 0 | {} |
114 | | |
115 | | nsIntRegion mRegionToDraw; |
116 | | nsIntRegion mRegionToInvalidate; |
117 | | SurfaceMode mMode; |
118 | | DrawRegionClip mClip; |
119 | | gfxContentType mContentType; |
120 | | bool mAsyncPaint; |
121 | | UniquePtr<PaintTask> mAsyncTask; |
122 | | }; |
123 | | |
124 | | enum { |
125 | | PAINT_WILL_RESAMPLE = 0x01, |
126 | | PAINT_NO_ROTATION = 0x02, |
127 | | PAINT_CAN_DRAW_ROTATED = 0x04, |
128 | | PAINT_ASYNC = 0x08, |
129 | | }; |
130 | | |
131 | | /** |
132 | | * Start a drawing operation. This returns a PaintState describing what |
133 | | * needs to be drawn to bring the buffer up to date in the visible region. |
134 | | * This queries aLayer to get the currently valid and visible regions. |
135 | | * The returned mTarget may be null if mRegionToDraw is empty. |
136 | | * Otherwise it must not be null. |
137 | | * mRegionToInvalidate will contain mRegionToDraw. |
138 | | * @param aFlags when PAINT_WILL_RESAMPLE is passed, this indicates that |
139 | | * buffer will be resampled when rendering (i.e the effective transform |
140 | | * combined with the scale for the resolution is not just an integer |
141 | | * translation). This will disable buffer rotation (since we don't want |
142 | | * to resample across the rotation boundary) and will ensure that we |
143 | | * make the entire buffer contents valid (since we don't want to sample |
144 | | * invalid pixels outside the visible region, if the visible region doesn't |
145 | | * fill the buffer bounds). |
146 | | * PAINT_CAN_DRAW_ROTATED can be passed if the caller supports drawing |
147 | | * rotated content that crosses the physical buffer boundary. The caller |
148 | | * will need to call BorrowDrawTargetForPainting multiple times to achieve |
149 | | * this. |
150 | | */ |
151 | | virtual PaintState BeginPaint(PaintedLayer* aLayer, uint32_t aFlags); |
152 | | virtual void EndPaint(PaintState& aPaintState, nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr); |
153 | | |
154 | | /** |
155 | | * Fetch a DrawTarget for rendering. The DrawTarget remains owned by |
156 | | * this. See notes on BorrowDrawTargetForQuadrantUpdate. |
157 | | * May return null. If the return value is non-null, it must be |
158 | | * 'un-borrowed' using ReturnDrawTarget. |
159 | | * |
160 | | * If PAINT_CAN_DRAW_ROTATED was specified for BeginPaint, then the caller |
161 | | * must call this function repeatedly (with an iterator) until it returns |
162 | | * nullptr. The caller should draw the mDrawRegion of the iterator instead |
163 | | * of mRegionToDraw in the PaintState. |
164 | | * |
165 | | * @param aPaintState Paint state data returned by a call to BeginPaint |
166 | | * @param aIter Paint state iterator. Only required if PAINT_CAN_DRAW_ROTATED |
167 | | * was specified to BeginPaint. |
168 | | */ |
169 | | virtual gfx::DrawTarget* BorrowDrawTargetForPainting( |
170 | | PaintState& aPaintState, |
171 | | RotatedBuffer::DrawIterator* aIter = nullptr); |
172 | | |
173 | | void ReturnDrawTarget(gfx::DrawTarget*& aReturned); |
174 | | |
175 | | enum { |
176 | | BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with |
177 | | // component alpha. |
178 | | }; |
179 | | |
180 | | protected: |
181 | | struct BufferDecision { |
182 | | nsIntRegion mNeededRegion; |
183 | | nsIntRegion mValidRegion; |
184 | | gfx::IntRect mBufferRect; |
185 | | SurfaceMode mBufferMode; |
186 | | gfxContentType mBufferContentType; |
187 | | bool mCanReuseBuffer; |
188 | | bool mCanKeepBufferContents; |
189 | | }; |
190 | | |
191 | | /** |
192 | | * Decide whether we can keep our current buffer and its contents, |
193 | | * and return a struct containing the regions to paint, invalidate, |
194 | | * the new buffer rect, surface mode, and content type. |
195 | | */ |
196 | | BufferDecision CalculateBufferForPaint(PaintedLayer* aLayer, |
197 | | uint32_t aFlags); |
198 | | |
199 | | static bool ValidBufferSize(BufferSizePolicy aPolicy, |
200 | | const gfx::IntSize& aBufferSize, |
201 | | const gfx::IntSize& aVisibleBoundsSize); |
202 | | |
203 | | /** |
204 | | * Any actions that should be performed at the last moment before we begin |
205 | | * rendering the next frame. I.e., after we calculate what we will draw, |
206 | | * but before we rotate the buffer and possibly create new buffers. |
207 | | * aRegionToDraw is the region which is guaranteed to be overwritten when |
208 | | * drawing the next frame. |
209 | | */ |
210 | 0 | virtual void FinalizeFrame(PaintState& aPaintState) { |
211 | 0 | } |
212 | | |
213 | | virtual RefPtr<RotatedBuffer> GetFrontBuffer() const |
214 | 0 | { |
215 | 0 | return mBuffer; |
216 | 0 | } |
217 | | |
218 | | /** |
219 | | * Create a new rotated buffer for the specified content type, buffer rect, |
220 | | * and buffer flags. |
221 | | */ |
222 | | virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType, |
223 | | const gfx::IntRect& aRect, |
224 | | uint32_t aFlags) = 0; |
225 | | |
226 | | RefPtr<RotatedBuffer> mBuffer; |
227 | | BufferSizePolicy mBufferSizePolicy; |
228 | | }; |
229 | | |
230 | | // Thin wrapper around DrawTargetRotatedBuffer, for on-mtc |
231 | | class ContentClientBasic final : public ContentClient |
232 | | { |
233 | | public: |
234 | | explicit ContentClientBasic(gfx::BackendType aBackend); |
235 | | |
236 | | void DrawTo(PaintedLayer* aLayer, |
237 | | gfx::DrawTarget* aTarget, |
238 | | float aOpacity, |
239 | | gfx::CompositionOp aOp, |
240 | | gfx::SourceSurface* aMask, |
241 | | const gfx::Matrix* aMaskTransform); |
242 | | |
243 | | virtual TextureInfo GetTextureInfo() const override |
244 | 0 | { |
245 | 0 | MOZ_CRASH("GFX: Should not be called on non-remote ContentClient"); |
246 | 0 | } |
247 | | |
248 | | protected: |
249 | | virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType, |
250 | | const gfx::IntRect& aRect, |
251 | | uint32_t aFlags) override; |
252 | | |
253 | | private: |
254 | | gfx::BackendType mBackend; |
255 | | }; |
256 | | |
257 | | /** |
258 | | * A ContentClient backed by a RemoteRotatedBuffer. |
259 | | * |
260 | | * When using a ContentClientRemoteBuffer, SurfaceDescriptors are created on |
261 | | * the rendering side and destroyed on the compositing side. They are only |
262 | | * passed from one side to the other when the TextureClient/Hosts are created. |
263 | | * *Ownership* of the SurfaceDescriptor moves from the rendering side to the |
264 | | * compositing side with the create message (send from CreateBuffer) which |
265 | | * tells the compositor that TextureClients have been created and that the |
266 | | * compositor should assign the corresponding TextureHosts to our corresponding |
267 | | * ContentHost. |
268 | | * |
269 | | * If the size or type of our buffer(s) change(s), then we simply destroy and |
270 | | * create them. |
271 | | */ |
272 | | class ContentClientRemoteBuffer : public ContentClient |
273 | | { |
274 | | public: |
275 | | explicit ContentClientRemoteBuffer(CompositableForwarder* aForwarder) |
276 | | : ContentClient(aForwarder, ContainsVisibleBounds) |
277 | | , mIsNewBuffer(false) |
278 | 0 | {} |
279 | | |
280 | | virtual void Dump(std::stringstream& aStream, |
281 | | const char* aPrefix="", |
282 | | bool aDumpHtml=false, |
283 | | TextureDumpMode aCompress=TextureDumpMode::Compress) override; |
284 | | |
285 | | virtual void EndPaint(PaintState& aPaintState, nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr) override; |
286 | | |
287 | | virtual void Updated(const nsIntRegion& aRegionToDraw, |
288 | | const nsIntRegion& aVisibleRegion); |
289 | | |
290 | | virtual TextureFlags ExtraTextureFlags() const |
291 | 0 | { |
292 | 0 | return TextureFlags::IMMEDIATE_UPLOAD; |
293 | 0 | } |
294 | | |
295 | | protected: |
296 | | /** |
297 | | * Called when we have been updated and should swap references to our |
298 | | * buffers. |
299 | | */ |
300 | 0 | virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {} |
301 | | |
302 | | virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw, |
303 | | const nsIntRegion& aVisibleRegion); |
304 | | |
305 | | virtual RefPtr<RotatedBuffer> CreateBuffer(gfxContentType aType, |
306 | | const gfx::IntRect& aRect, |
307 | | uint32_t aFlags) override; |
308 | | |
309 | | RefPtr<RotatedBuffer> CreateBufferInternal(const gfx::IntRect& aRect, |
310 | | gfx::SurfaceFormat aFormat, |
311 | | TextureFlags aFlags); |
312 | | |
313 | | RemoteRotatedBuffer* GetRemoteBuffer() const |
314 | 0 | { |
315 | 0 | return static_cast<RemoteRotatedBuffer*>(mBuffer.get()); |
316 | 0 | } |
317 | | |
318 | | bool mIsNewBuffer; |
319 | | }; |
320 | | |
321 | | /** |
322 | | * A double buffered ContentClientRemoteBuffer. mBuffer is the back buffer, which |
323 | | * we draw into. mFrontBuffer is the front buffer which we may read from, but |
324 | | * not write to, when the compositor does not have the 'soft' lock. |
325 | | * |
326 | | * The ContentHost keeps a reference to both corresponding texture hosts, in |
327 | | * response to our UpdateTextureRegion message, the compositor swaps its |
328 | | * references. |
329 | | */ |
330 | | class ContentClientDoubleBuffered : public ContentClientRemoteBuffer |
331 | | { |
332 | | public: |
333 | | explicit ContentClientDoubleBuffered(CompositableForwarder* aFwd) |
334 | | : ContentClientRemoteBuffer(aFwd) |
335 | | , mFrontAndBackBufferDiffer(false) |
336 | 0 | {} |
337 | | |
338 | 0 | virtual ~ContentClientDoubleBuffered() {} |
339 | | |
340 | | virtual void Dump(std::stringstream& aStream, |
341 | | const char* aPrefix="", |
342 | | bool aDumpHtml=false, |
343 | | TextureDumpMode aCompress=TextureDumpMode::Compress) override; |
344 | | |
345 | | virtual void Clear() override; |
346 | | |
347 | | virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override; |
348 | | |
349 | | virtual PaintState BeginPaint(PaintedLayer* aLayer, uint32_t aFlags) override; |
350 | | |
351 | | virtual void FinalizeFrame(PaintState& aPaintState) override; |
352 | | |
353 | | virtual RefPtr<RotatedBuffer> GetFrontBuffer() const override |
354 | 0 | { |
355 | 0 | return mFrontBuffer; |
356 | 0 | } |
357 | | |
358 | | virtual TextureInfo GetTextureInfo() const override |
359 | 0 | { |
360 | 0 | return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags); |
361 | 0 | } |
362 | | |
363 | | private: |
364 | | void EnsureBackBufferIfFrontBuffer(); |
365 | | |
366 | | RefPtr<RemoteRotatedBuffer> mFrontBuffer; |
367 | | nsIntRegion mFrontUpdatedRegion; |
368 | | bool mFrontAndBackBufferDiffer; |
369 | | }; |
370 | | |
371 | | /** |
372 | | * A single buffered ContentClientRemoteBuffer. We have a single |
373 | | * TextureClient/Host which we update and then send a message to the |
374 | | * compositor that we are done updating. It is not safe for the compositor |
375 | | * to use the corresponding TextureHost's memory directly, it must upload |
376 | | * it to video memory of some kind. We are free to modify the TextureClient |
377 | | * once we receive reply from the compositor. |
378 | | */ |
379 | | class ContentClientSingleBuffered : public ContentClientRemoteBuffer |
380 | | { |
381 | | public: |
382 | | explicit ContentClientSingleBuffered(CompositableForwarder* aFwd) |
383 | | : ContentClientRemoteBuffer(aFwd) |
384 | 0 | { |
385 | 0 | } |
386 | 0 | virtual ~ContentClientSingleBuffered() {} |
387 | | |
388 | | virtual TextureInfo GetTextureInfo() const override |
389 | 0 | { |
390 | 0 | return TextureInfo(CompositableType::CONTENT_SINGLE, mTextureFlags | ExtraTextureFlags()); |
391 | 0 | } |
392 | | }; |
393 | | |
394 | | } // namespace layers |
395 | | } // namespace mozilla |
396 | | |
397 | | #endif |