Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef MOZILLA_GFX_CONTENTCLIENT_H
7 : #define MOZILLA_GFX_CONTENTCLIENT_H
8 :
9 : #include <stdint.h> // for uint32_t
10 : #include "RotatedBuffer.h" // for RotatedContentBuffer, etc
11 : #include "gfxTypes.h"
12 : #include "gfxPlatform.h" // for gfxPlatform
13 : #include "mozilla/Assertions.h" // for MOZ_CRASH
14 : #include "mozilla/Attributes.h" // for override
15 : #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed
16 : #include "mozilla/gfx/Point.h" // for IntSize
17 : #include "mozilla/layers/CompositableClient.h" // for CompositableClient
18 : #include "mozilla/layers/CompositableForwarder.h"
19 : #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
20 : #include "mozilla/layers/ISurfaceAllocator.h"
21 : #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
22 : #include "mozilla/layers/LayersTypes.h" // for TextureDumpMode
23 : #include "mozilla/layers/TextureClient.h" // for TextureClient
24 : #include "mozilla/mozalloc.h" // for operator delete
25 : #include "ReadbackProcessor.h" // For ReadbackProcessor::Update
26 : #include "nsCOMPtr.h" // for already_AddRefed
27 : #include "nsPoint.h" // for nsIntPoint
28 : #include "nsRect.h" // for mozilla::gfx::IntRect
29 : #include "nsRegion.h" // for nsIntRegion
30 : #include "nsTArray.h" // for nsTArray
31 :
32 : namespace mozilla {
33 : namespace gfx {
34 : class DrawTarget;
35 : } // namespace gfx
36 :
37 : namespace layers {
38 :
39 : class PaintedLayer;
40 :
41 : /**
42 : * A compositable client for PaintedLayers. These are different to Image/Canvas
43 : * clients due to sending a valid region across IPC and because we do a lot more
44 : * optimisation work, encapsualted in RotatedContentBuffers.
45 : *
46 : * We use content clients for OMTC and non-OMTC, basic rendering so that
47 : * BasicPaintedLayer has only one interface to deal with. We support single and
48 : * double buffered flavours. For tiled layers, we do not use a ContentClient
49 : * although we do have a ContentHost, and we do use texture clients and texture
50 : * hosts.
51 : *
52 : * The interface presented by ContentClient is used by the BasicPaintedLayer
53 : * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer
54 : * which is different (the OMTC one does a little more). The 'buffer' in the
55 : * names of a lot of these method is actually the TextureClient. But, 'buffer'
56 : * for the RotatedContentBuffer (as in SetBuffer) means a gfxSurface. See the
57 : * comments for SetBuffer and SetBufferProvider in RotatedContentBuffer. To keep
58 : * these mapped buffers alive, we store a pointer in mOldTextures if the
59 : * RotatedContentBuffer's surface is not the one from our texture client, once we
60 : * are done painting we unmap the surface/texture client and don't need to keep
61 : * it alive anymore, so we clear mOldTextures.
62 : *
63 : * The sequence for painting is: call BeginPaint on the content client;
64 : * call BeginPaintBuffer on the content client. That will initialise the buffer
65 : * for painting, by calling RotatedContentBuffer::BeginPaint (usually) which
66 : * will call back to ContentClient::FinalizeFrame to finalize update of the
67 : * buffers before drawing (i.e., it finalizes the previous frame). Then call
68 : * BorrowDrawTargetForPainting to get a DrawTarget to paint into. Then paint.
69 : * Then return that DrawTarget using ReturnDrawTarget.
70 : * Call EndPaint on the content client;
71 : *
72 : * SwapBuffers is called in response to the transaction reply from the compositor.
73 : */
74 : class ContentClient : public CompositableClient
75 : {
76 : public:
77 : /**
78 : * Creates, configures, and returns a new content client. If necessary, a
79 : * message will be sent to the compositor to create a corresponding content
80 : * host.
81 : */
82 : static already_AddRefed<ContentClient> CreateContentClient(CompositableForwarder* aFwd);
83 :
84 79 : explicit ContentClient(CompositableForwarder* aForwarder)
85 79 : : CompositableClient(aForwarder)
86 79 : {}
87 73 : virtual ~ContentClient()
88 73 : {}
89 :
90 : virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
91 :
92 : virtual void Clear() = 0;
93 : virtual RotatedContentBuffer::PaintState BeginPaintBuffer(PaintedLayer* aLayer,
94 : uint32_t aFlags) = 0;
95 : virtual gfx::DrawTarget* BorrowDrawTargetForPainting(RotatedContentBuffer::PaintState& aPaintState,
96 : RotatedContentBuffer::DrawIterator* aIter = nullptr) = 0;
97 : virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) = 0;
98 :
99 : // Called as part of the layers transation reply. Conveys data about our
100 : // buffer(s) from the compositor. If appropriate we should swap references
101 : // to our buffers.
102 0 : virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {}
103 :
104 : // call before and after painting into this content client
105 0 : virtual void BeginPaint() {}
106 : virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr);
107 : };
108 :
109 : /**
110 : * A ContentClient for use with OMTC.
111 : */
112 19 : class ContentClientRemote : public ContentClient
113 : {
114 : public:
115 22 : explicit ContentClientRemote(CompositableForwarder* aForwarder)
116 22 : : ContentClient(aForwarder)
117 22 : {}
118 :
119 : virtual void Updated(const nsIntRegion& aRegionToDraw,
120 : const nsIntRegion& aVisibleRegion,
121 : bool aDidSelfCopy) = 0;
122 :
123 0 : ContentClientRemote* AsContentClientRemote() override {
124 0 : return this;
125 : }
126 : };
127 :
128 : // thin wrapper around RotatedContentBuffer, for on-mtc
129 162 : class ContentClientBasic final : public ContentClient
130 : , protected RotatedContentBuffer
131 : {
132 : public:
133 : explicit ContentClientBasic(gfx::BackendType aBackend);
134 :
135 : typedef RotatedContentBuffer::PaintState PaintState;
136 : typedef RotatedContentBuffer::ContentType ContentType;
137 :
138 99 : virtual void Clear() override { RotatedContentBuffer::Clear(); }
139 0 : virtual PaintState BeginPaintBuffer(PaintedLayer* aLayer,
140 : uint32_t aFlags) override
141 : {
142 0 : return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
143 : }
144 0 : virtual gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
145 : RotatedContentBuffer::DrawIterator* aIter = nullptr) override
146 : {
147 0 : return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
148 : }
149 0 : virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
150 : {
151 0 : BorrowDrawTarget::ReturnDrawTarget(aReturned);
152 0 : }
153 :
154 0 : void DrawTo(PaintedLayer* aLayer,
155 : gfx::DrawTarget* aTarget,
156 : float aOpacity,
157 : gfx::CompositionOp aOp,
158 : gfx::SourceSurface* aMask,
159 : const gfx::Matrix* aMaskTransform)
160 : {
161 0 : RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aOp,
162 0 : aMask, aMaskTransform);
163 0 : }
164 :
165 : virtual void CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
166 : RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) override;
167 :
168 0 : virtual TextureInfo GetTextureInfo() const override
169 : {
170 0 : MOZ_CRASH("GFX: Should not be called on non-remote ContentClient");
171 : }
172 :
173 : private:
174 : gfx::BackendType mBackend;
175 : };
176 :
177 : /**
178 : * A ContentClientRemote backed by a RotatedContentBuffer.
179 : *
180 : * When using a ContentClientRemote, SurfaceDescriptors are created on
181 : * the rendering side and destroyed on the compositing side. They are only
182 : * passed from one side to the other when the TextureClient/Hosts are created.
183 : * *Ownership* of the SurfaceDescriptor moves from the rendering side to the
184 : * compositing side with the create message (send from CreateBuffer) which
185 : * tells the compositor that TextureClients have been created and that the
186 : * compositor should assign the corresponding TextureHosts to our corresponding
187 : * ContentHost.
188 : *
189 : * If the size or type of our buffer(s) change(s), then we simply destroy and
190 : * create them.
191 : */
192 : // Version using new texture clients
193 19 : class ContentClientRemoteBuffer : public ContentClientRemote
194 : , protected RotatedContentBuffer
195 : {
196 : using RotatedContentBuffer::BufferRect;
197 : using RotatedContentBuffer::BufferRotation;
198 : public:
199 22 : explicit ContentClientRemoteBuffer(CompositableForwarder* aForwarder)
200 22 : : ContentClientRemote(aForwarder)
201 : , RotatedContentBuffer(ContainsVisibleBounds)
202 : , mIsNewBuffer(false)
203 : , mFrontAndBackBufferDiffer(false)
204 22 : , mSurfaceFormat(gfx::SurfaceFormat::B8G8R8A8)
205 22 : {}
206 :
207 : typedef RotatedContentBuffer::PaintState PaintState;
208 : typedef RotatedContentBuffer::ContentType ContentType;
209 :
210 0 : virtual void Clear() override
211 : {
212 0 : RotatedContentBuffer::Clear();
213 0 : mTextureClient = nullptr;
214 0 : mTextureClientOnWhite = nullptr;
215 0 : }
216 :
217 : virtual void Dump(std::stringstream& aStream,
218 : const char* aPrefix="",
219 : bool aDumpHtml=false,
220 : TextureDumpMode aCompress=TextureDumpMode::Compress) override;
221 :
222 77 : virtual PaintState BeginPaintBuffer(PaintedLayer* aLayer,
223 : uint32_t aFlags) override
224 : {
225 77 : return RotatedContentBuffer::BeginPaint(aLayer, aFlags);
226 : }
227 110 : virtual gfx::DrawTarget* BorrowDrawTargetForPainting(PaintState& aPaintState,
228 : RotatedContentBuffer::DrawIterator* aIter = nullptr) override
229 : {
230 110 : return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter);
231 : }
232 46 : virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) override
233 : {
234 46 : BorrowDrawTarget::ReturnDrawTarget(aReturned);
235 46 : }
236 :
237 : /**
238 : * Begin/End Paint map a gfxASurface from the texture client
239 : * into the buffer of RotatedBuffer. The surface is only
240 : * valid when the texture client is locked, so is mapped out
241 : * of RotatedContentBuffer when we are done painting.
242 : * None of the underlying buffer attributes (rect, rotation)
243 : * are affected by mapping/unmapping.
244 : */
245 : virtual void BeginPaint() override;
246 : virtual void EndPaint(nsTArray<ReadbackProcessor::Update>* aReadbackUpdates = nullptr) override;
247 :
248 : virtual void Updated(const nsIntRegion& aRegionToDraw,
249 : const nsIntRegion& aVisibleRegion,
250 : bool aDidSelfCopy) override;
251 :
252 : virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override;
253 :
254 : // Expose these protected methods from the superclass.
255 66 : virtual const gfx::IntRect& BufferRect() const
256 : {
257 66 : return RotatedContentBuffer::BufferRect();
258 : }
259 33 : virtual const nsIntPoint& BufferRotation() const
260 : {
261 33 : return RotatedContentBuffer::BufferRotation();
262 : }
263 :
264 : virtual void CreateBuffer(ContentType aType, const gfx::IntRect& aRect, uint32_t aFlags,
265 : RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) override;
266 :
267 9 : virtual TextureFlags ExtraTextureFlags() const
268 : {
269 9 : return TextureFlags::IMMEDIATE_UPLOAD;
270 : }
271 :
272 : protected:
273 : void DestroyBuffers();
274 :
275 : virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
276 : const nsIntRegion& aVisibleRegion,
277 : bool aDidSelfCopy);
278 :
279 : void BuildTextureClients(gfx::SurfaceFormat aFormat,
280 : const gfx::IntRect& aRect,
281 : uint32_t aFlags);
282 :
283 : void CreateBackBuffer(const gfx::IntRect& aBufferRect);
284 :
285 : // Ensure we have a valid back buffer if we have a valid front buffer (i.e.
286 : // if a backbuffer has been created.)
287 0 : virtual void EnsureBackBufferIfFrontBuffer() {}
288 :
289 : // Create the front buffer for the ContentClient/Host pair if necessary
290 : // and notify the compositor that we have created the buffer(s).
291 0 : virtual void DestroyFrontBuffer() {}
292 :
293 0 : virtual void AbortTextureClientCreation()
294 : {
295 0 : mTextureClient = nullptr;
296 0 : mTextureClientOnWhite = nullptr;
297 0 : mIsNewBuffer = false;
298 0 : }
299 :
300 : virtual bool LockBuffers() override;
301 : virtual void UnlockBuffers() override;
302 :
303 : RefPtr<TextureClient> mTextureClient;
304 : RefPtr<TextureClient> mTextureClientOnWhite;
305 : // keep a record of texture clients we have created and need to keep around
306 : // (for RotatedBuffer to access), then unlock and remove them when we are done
307 : // painting.
308 : nsTArray<RefPtr<TextureClient> > mOldTextures;
309 :
310 : bool mIsNewBuffer;
311 : bool mFrontAndBackBufferDiffer;
312 : gfx::IntSize mSize;
313 : gfx::SurfaceFormat mSurfaceFormat;
314 : };
315 :
316 : /**
317 : * A double buffered ContentClient. mTextureClient is the back buffer, which
318 : * we draw into. mFrontClient is the front buffer which we may read from, but
319 : * not write to, when the compositor does not have the 'soft' lock. We can write
320 : * into mTextureClient at any time.
321 : *
322 : * The ContentHost keeps a reference to both corresponding texture hosts, in
323 : * response to our UpdateTextureRegion message, the compositor swaps its
324 : * references. In response to the compositor's reply we swap our references
325 : * (in SwapBuffers).
326 : */
327 : class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
328 : {
329 : public:
330 22 : explicit ContentClientDoubleBuffered(CompositableForwarder* aFwd)
331 22 : : ContentClientRemoteBuffer(aFwd)
332 22 : {}
333 :
334 57 : virtual ~ContentClientDoubleBuffered() {}
335 :
336 0 : virtual void Clear() override
337 : {
338 0 : ContentClientRemoteBuffer::Clear();
339 0 : mFrontClient = nullptr;
340 0 : mFrontClientOnWhite = nullptr;
341 0 : }
342 :
343 : virtual void Updated(const nsIntRegion& aRegionToDraw,
344 : const nsIntRegion& aVisibleRegion,
345 : bool aDidSelfCopy) override;
346 :
347 : virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) override;
348 :
349 : virtual void BeginPaint() override;
350 :
351 : virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) override;
352 :
353 : virtual void EnsureBackBufferIfFrontBuffer() override;
354 :
355 22 : virtual TextureInfo GetTextureInfo() const override
356 : {
357 22 : return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags);
358 : }
359 :
360 : virtual void Dump(std::stringstream& aStream,
361 : const char* aPrefix="",
362 : bool aDumpHtml=false,
363 : TextureDumpMode aCompress=TextureDumpMode::Compress) override;
364 : protected:
365 : virtual void DestroyFrontBuffer() override;
366 :
367 : private:
368 : void UpdateDestinationFrom(const RotatedBuffer& aSource,
369 : const nsIntRegion& aUpdateRegion);
370 :
371 0 : virtual void AbortTextureClientCreation() override
372 : {
373 0 : mTextureClient = nullptr;
374 0 : mTextureClientOnWhite = nullptr;
375 0 : mFrontClient = nullptr;
376 0 : mFrontClientOnWhite = nullptr;
377 0 : }
378 :
379 : RefPtr<TextureClient> mFrontClient;
380 : RefPtr<TextureClient> mFrontClientOnWhite;
381 : nsIntRegion mFrontUpdatedRegion;
382 : gfx::IntRect mFrontBufferRect;
383 : nsIntPoint mFrontBufferRotation;
384 : };
385 :
386 : /**
387 : * A single buffered ContentClient. We have a single TextureClient/Host
388 : * which we update and then send a message to the compositor that we are
389 : * done updating. It is not safe for the compositor to use the corresponding
390 : * TextureHost's memory directly, it must upload it to video memory of some
391 : * kind. We are free to modify the TextureClient once we receive reply from
392 : * the compositor.
393 : */
394 : class ContentClientSingleBuffered : public ContentClientRemoteBuffer
395 : {
396 : public:
397 0 : explicit ContentClientSingleBuffered(CompositableForwarder* aFwd)
398 0 : : ContentClientRemoteBuffer(aFwd)
399 : {
400 0 : }
401 0 : virtual ~ContentClientSingleBuffered() {}
402 :
403 0 : virtual TextureInfo GetTextureInfo() const override
404 : {
405 0 : return TextureInfo(CompositableType::CONTENT_SINGLE, mTextureFlags | ExtraTextureFlags());
406 : }
407 : };
408 :
409 : } // namespace layers
410 : } // namespace mozilla
411 :
412 : #endif
|