|
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 MOZ_OVERRIDE |
|
15 #include "mozilla/RefPtr.h" // for RefPtr, TemporaryRef |
|
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/TextureClient.h" // for TextureClient |
|
23 #include "mozilla/mozalloc.h" // for operator delete |
|
24 #include "nsCOMPtr.h" // for already_AddRefed |
|
25 #include "nsPoint.h" // for nsIntPoint |
|
26 #include "nsRect.h" // for nsIntRect |
|
27 #include "nsRegion.h" // for nsIntRegion |
|
28 #include "nsTArray.h" // for nsTArray |
|
29 |
|
30 class gfxContext; |
|
31 |
|
32 namespace mozilla { |
|
33 namespace gfx { |
|
34 class DrawTarget; |
|
35 } |
|
36 |
|
37 namespace layers { |
|
38 |
|
39 class BasicLayerManager; |
|
40 class ThebesLayer; |
|
41 |
|
42 /** |
|
43 * A compositable client for Thebes layers. These are different to Image/Canvas |
|
44 * clients due to sending a valid region across IPC and because we do a lot more |
|
45 * optimisation work, encapsualted in RotatedContentBuffers. |
|
46 * |
|
47 * We use content clients for OMTC and non-OMTC, basic rendering so that |
|
48 * BasicThebesLayer has only one interface to deal with. We support single and |
|
49 * double buffered flavours. For tiled layers, we do not use a ContentClient |
|
50 * although we do have a ContentHost, and we do use texture clients and texture |
|
51 * hosts. |
|
52 * |
|
53 * The interface presented by ContentClient is used by the BasicThebesLayer |
|
54 * methods - PaintThebes, which is the same for MT and OMTC, and PaintBuffer |
|
55 * which is different (the OMTC one does a little more). The 'buffer' in the |
|
56 * names of a lot of these method is actually the TextureClient. But, 'buffer' |
|
57 * for the RotatedContentBuffer (as in SetBuffer) means a gfxSurface. See the |
|
58 * comments for SetBuffer and SetBufferProvider in RotatedContentBuffer. To keep |
|
59 * these mapped buffers alive, we store a pointer in mOldTextures if the |
|
60 * RotatedContentBuffer's surface is not the one from our texture client, once we |
|
61 * are done painting we unmap the surface/texture client and don't need to keep |
|
62 * it alive anymore, so we clear mOldTextures. |
|
63 * |
|
64 * The sequence for painting is: call BeginPaint on the content client; |
|
65 * call BeginPaintBuffer on the content client. That will initialise the buffer |
|
66 * for painting, by calling RotatedContentBuffer::BeginPaint (usually) which |
|
67 * will call back to ContentClient::FinalizeFrame to finalize update of the |
|
68 * buffers before drawing (i.e., it finalizes the previous frame). Then call |
|
69 * BorrowDrawTargetForPainting to get a DrawTarget to paint into. Then paint. |
|
70 * Then return that DrawTarget using ReturnDrawTarget. |
|
71 * Call EndPaint on the content client; |
|
72 * |
|
73 * SwapBuffers is called in response to the transaction reply from the compositor. |
|
74 */ |
|
75 class ContentClient : public CompositableClient |
|
76 { |
|
77 public: |
|
78 /** |
|
79 * Creates, configures, and returns a new content client. If necessary, a |
|
80 * message will be sent to the compositor to create a corresponding content |
|
81 * host. |
|
82 */ |
|
83 static TemporaryRef<ContentClient> CreateContentClient(CompositableForwarder* aFwd); |
|
84 |
|
85 ContentClient(CompositableForwarder* aForwarder) |
|
86 : CompositableClient(aForwarder) |
|
87 {} |
|
88 virtual ~ContentClient() |
|
89 {} |
|
90 |
|
91 |
|
92 virtual void Clear() = 0; |
|
93 virtual RotatedContentBuffer::PaintState BeginPaintBuffer(ThebesLayer* aLayer, |
|
94 uint32_t aFlags) = 0; |
|
95 virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const 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 virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) {} |
|
103 |
|
104 // call before and after painting into this content client |
|
105 virtual void BeginPaint() {} |
|
106 virtual void EndPaint(); |
|
107 }; |
|
108 |
|
109 /** |
|
110 * A ContentClient for use with OMTC. |
|
111 */ |
|
112 class ContentClientRemote : public ContentClient |
|
113 { |
|
114 public: |
|
115 ContentClientRemote(CompositableForwarder* aForwarder) |
|
116 : ContentClient(aForwarder) |
|
117 {} |
|
118 |
|
119 virtual void Updated(const nsIntRegion& aRegionToDraw, |
|
120 const nsIntRegion& aVisibleRegion, |
|
121 bool aDidSelfCopy) = 0; |
|
122 }; |
|
123 |
|
124 // thin wrapper around RotatedContentBuffer, for on-mtc |
|
125 class ContentClientBasic : public ContentClient |
|
126 , protected RotatedContentBuffer |
|
127 { |
|
128 public: |
|
129 ContentClientBasic(); |
|
130 |
|
131 typedef RotatedContentBuffer::PaintState PaintState; |
|
132 typedef RotatedContentBuffer::ContentType ContentType; |
|
133 |
|
134 virtual void Clear() { RotatedContentBuffer::Clear(); } |
|
135 virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, |
|
136 uint32_t aFlags) MOZ_OVERRIDE |
|
137 { |
|
138 return RotatedContentBuffer::BeginPaint(aLayer, aFlags); |
|
139 } |
|
140 virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState, |
|
141 RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE |
|
142 { |
|
143 return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter); |
|
144 } |
|
145 virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE |
|
146 { |
|
147 BorrowDrawTarget::ReturnDrawTarget(aReturned); |
|
148 } |
|
149 |
|
150 void DrawTo(ThebesLayer* aLayer, |
|
151 gfx::DrawTarget* aTarget, |
|
152 float aOpacity, |
|
153 gfx::CompositionOp aOp, |
|
154 gfx::SourceSurface* aMask, |
|
155 const gfx::Matrix* aMaskTransform) |
|
156 { |
|
157 RotatedContentBuffer::DrawTo(aLayer, aTarget, aOpacity, aOp, |
|
158 aMask, aMaskTransform); |
|
159 } |
|
160 |
|
161 virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, |
|
162 RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE; |
|
163 |
|
164 virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE |
|
165 { |
|
166 MOZ_CRASH("Should not be called on non-remote ContentClient"); |
|
167 } |
|
168 }; |
|
169 |
|
170 /** |
|
171 * A ContentClientRemote backed by a RotatedContentBuffer. |
|
172 * |
|
173 * When using a ContentClientRemote, SurfaceDescriptors are created on |
|
174 * the rendering side and destroyed on the compositing side. They are only |
|
175 * passed from one side to the other when the TextureClient/Hosts are created. |
|
176 * *Ownership* of the SurfaceDescriptor moves from the rendering side to the |
|
177 * compositing side with the create message (send from CreateBuffer) which |
|
178 * tells the compositor that TextureClients have been created and that the |
|
179 * compositor should assign the corresponding TextureHosts to our corresponding |
|
180 * ContentHost. |
|
181 * |
|
182 * If the size or type of our buffer(s) change(s), then we simply destroy and |
|
183 * create them. |
|
184 */ |
|
185 // Version using new texture clients |
|
186 class ContentClientRemoteBuffer : public ContentClientRemote |
|
187 , protected RotatedContentBuffer |
|
188 { |
|
189 using RotatedContentBuffer::BufferRect; |
|
190 using RotatedContentBuffer::BufferRotation; |
|
191 public: |
|
192 ContentClientRemoteBuffer(CompositableForwarder* aForwarder) |
|
193 : ContentClientRemote(aForwarder) |
|
194 , RotatedContentBuffer(ContainsVisibleBounds) |
|
195 , mIsNewBuffer(false) |
|
196 , mFrontAndBackBufferDiffer(false) |
|
197 , mSurfaceFormat(gfx::SurfaceFormat::B8G8R8A8) |
|
198 {} |
|
199 |
|
200 typedef RotatedContentBuffer::PaintState PaintState; |
|
201 typedef RotatedContentBuffer::ContentType ContentType; |
|
202 |
|
203 virtual void Clear() |
|
204 { |
|
205 RotatedContentBuffer::Clear(); |
|
206 mTextureClient = nullptr; |
|
207 mTextureClientOnWhite = nullptr; |
|
208 } |
|
209 |
|
210 virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, |
|
211 uint32_t aFlags) MOZ_OVERRIDE |
|
212 { |
|
213 return RotatedContentBuffer::BeginPaint(aLayer, aFlags); |
|
214 } |
|
215 virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState, |
|
216 RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE |
|
217 { |
|
218 return RotatedContentBuffer::BorrowDrawTargetForPainting(aPaintState, aIter); |
|
219 } |
|
220 virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE |
|
221 { |
|
222 BorrowDrawTarget::ReturnDrawTarget(aReturned); |
|
223 } |
|
224 |
|
225 /** |
|
226 * Begin/End Paint map a gfxASurface from the texture client |
|
227 * into the buffer of RotatedBuffer. The surface is only |
|
228 * valid when the texture client is locked, so is mapped out |
|
229 * of RotatedContentBuffer when we are done painting. |
|
230 * None of the underlying buffer attributes (rect, rotation) |
|
231 * are affected by mapping/unmapping. |
|
232 */ |
|
233 virtual void BeginPaint() MOZ_OVERRIDE; |
|
234 virtual void EndPaint() MOZ_OVERRIDE; |
|
235 |
|
236 virtual void Updated(const nsIntRegion& aRegionToDraw, |
|
237 const nsIntRegion& aVisibleRegion, |
|
238 bool aDidSelfCopy); |
|
239 |
|
240 virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE; |
|
241 |
|
242 // Expose these protected methods from the superclass. |
|
243 virtual const nsIntRect& BufferRect() const |
|
244 { |
|
245 return RotatedContentBuffer::BufferRect(); |
|
246 } |
|
247 virtual const nsIntPoint& BufferRotation() const |
|
248 { |
|
249 return RotatedContentBuffer::BufferRotation(); |
|
250 } |
|
251 |
|
252 virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, |
|
253 RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE; |
|
254 |
|
255 virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE |
|
256 { |
|
257 return mTextureInfo; |
|
258 } |
|
259 |
|
260 protected: |
|
261 void DestroyBuffers(); |
|
262 |
|
263 virtual nsIntRegion GetUpdatedRegion(const nsIntRegion& aRegionToDraw, |
|
264 const nsIntRegion& aVisibleRegion, |
|
265 bool aDidSelfCopy); |
|
266 |
|
267 void BuildTextureClients(gfx::SurfaceFormat aFormat, |
|
268 const nsIntRect& aRect, |
|
269 uint32_t aFlags); |
|
270 |
|
271 // Create the front buffer for the ContentClient/Host pair if necessary |
|
272 // and notify the compositor that we have created the buffer(s). |
|
273 virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) = 0; |
|
274 virtual void DestroyFrontBuffer() {} |
|
275 |
|
276 bool CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient, |
|
277 TextureFlags aFlags = 0); |
|
278 |
|
279 virtual void AbortTextureClientCreation() |
|
280 { |
|
281 mTextureClient = nullptr; |
|
282 mTextureClientOnWhite = nullptr; |
|
283 mIsNewBuffer = false; |
|
284 } |
|
285 |
|
286 RefPtr<TextureClient> mTextureClient; |
|
287 RefPtr<TextureClient> mTextureClientOnWhite; |
|
288 // keep a record of texture clients we have created and need to keep around |
|
289 // (for RotatedBuffer to access), then unlock and remove them when we are done |
|
290 // painting. |
|
291 nsTArray<RefPtr<TextureClient> > mOldTextures; |
|
292 |
|
293 TextureInfo mTextureInfo; |
|
294 bool mIsNewBuffer; |
|
295 bool mFrontAndBackBufferDiffer; |
|
296 gfx::IntSize mSize; |
|
297 gfx::SurfaceFormat mSurfaceFormat; |
|
298 }; |
|
299 |
|
300 /** |
|
301 * A double buffered ContentClient. mTextureClient is the back buffer, which |
|
302 * we draw into. mFrontClient is the front buffer which we may read from, but |
|
303 * not write to, when the compositor does not have the 'soft' lock. We can write |
|
304 * into mTextureClient at any time. |
|
305 * |
|
306 * The ContentHost keeps a reference to both corresponding texture hosts, in |
|
307 * response to our UpdateTextureRegion message, the compositor swaps its |
|
308 * references. In response to the compositor's reply we swap our references |
|
309 * (in SwapBuffers). |
|
310 */ |
|
311 class ContentClientDoubleBuffered : public ContentClientRemoteBuffer |
|
312 { |
|
313 public: |
|
314 ContentClientDoubleBuffered(CompositableForwarder* aFwd) |
|
315 : ContentClientRemoteBuffer(aFwd) |
|
316 { |
|
317 mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_DOUBLE; |
|
318 } |
|
319 virtual ~ContentClientDoubleBuffered() {} |
|
320 |
|
321 virtual void Clear() MOZ_OVERRIDE |
|
322 { |
|
323 ContentClientRemoteBuffer::Clear(); |
|
324 mFrontClient = nullptr; |
|
325 mFrontClientOnWhite = nullptr; |
|
326 } |
|
327 |
|
328 virtual void SwapBuffers(const nsIntRegion& aFrontUpdatedRegion) MOZ_OVERRIDE; |
|
329 |
|
330 virtual void BeginPaint() MOZ_OVERRIDE; |
|
331 |
|
332 virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE; |
|
333 |
|
334 protected: |
|
335 virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE; |
|
336 virtual void DestroyFrontBuffer() MOZ_OVERRIDE; |
|
337 |
|
338 private: |
|
339 void UpdateDestinationFrom(const RotatedBuffer& aSource, |
|
340 const nsIntRegion& aUpdateRegion); |
|
341 |
|
342 virtual void AbortTextureClientCreation() MOZ_OVERRIDE |
|
343 { |
|
344 mTextureClient = nullptr; |
|
345 mTextureClientOnWhite = nullptr; |
|
346 mFrontClient = nullptr; |
|
347 mFrontClientOnWhite = nullptr; |
|
348 } |
|
349 |
|
350 RefPtr<TextureClient> mFrontClient; |
|
351 RefPtr<TextureClient> mFrontClientOnWhite; |
|
352 nsIntRegion mFrontUpdatedRegion; |
|
353 nsIntRect mFrontBufferRect; |
|
354 nsIntPoint mFrontBufferRotation; |
|
355 }; |
|
356 |
|
357 /** |
|
358 * A single buffered ContentClient. We have a single TextureClient/Host |
|
359 * which we update and then send a message to the compositor that we are |
|
360 * done updating. It is not safe for the compositor to use the corresponding |
|
361 * TextureHost's memory directly, it must upload it to video memory of some |
|
362 * kind. We are free to modify the TextureClient once we receive reply from |
|
363 * the compositor. |
|
364 */ |
|
365 class ContentClientSingleBuffered : public ContentClientRemoteBuffer |
|
366 { |
|
367 public: |
|
368 ContentClientSingleBuffered(CompositableForwarder* aFwd) |
|
369 : ContentClientRemoteBuffer(aFwd) |
|
370 { |
|
371 mTextureInfo.mCompositableType = COMPOSITABLE_CONTENT_SINGLE; |
|
372 } |
|
373 virtual ~ContentClientSingleBuffered() {} |
|
374 |
|
375 virtual void FinalizeFrame(const nsIntRegion& aRegionToDraw) MOZ_OVERRIDE; |
|
376 |
|
377 protected: |
|
378 virtual void CreateFrontBuffer(const nsIntRect& aBufferRect) MOZ_OVERRIDE {} |
|
379 }; |
|
380 |
|
381 /** |
|
382 * A single buffered ContentClient that creates temporary buffers which are |
|
383 * used to update the host-side texture. The ownership of the buffers is |
|
384 * passed to the host side during the transaction, and we need to create |
|
385 * new ones each frame. |
|
386 */ |
|
387 class ContentClientIncremental : public ContentClientRemote |
|
388 , public BorrowDrawTarget |
|
389 { |
|
390 public: |
|
391 ContentClientIncremental(CompositableForwarder* aFwd) |
|
392 : ContentClientRemote(aFwd) |
|
393 , mContentType(gfxContentType::COLOR_ALPHA) |
|
394 , mHasBuffer(false) |
|
395 , mHasBufferOnWhite(false) |
|
396 { |
|
397 mTextureInfo.mCompositableType = BUFFER_CONTENT_INC; |
|
398 } |
|
399 |
|
400 typedef RotatedContentBuffer::PaintState PaintState; |
|
401 typedef RotatedContentBuffer::ContentType ContentType; |
|
402 |
|
403 virtual TextureInfo GetTextureInfo() const |
|
404 { |
|
405 return mTextureInfo; |
|
406 } |
|
407 |
|
408 virtual void Clear() |
|
409 { |
|
410 mBufferRect.SetEmpty(); |
|
411 mHasBuffer = false; |
|
412 mHasBufferOnWhite = false; |
|
413 } |
|
414 |
|
415 virtual PaintState BeginPaintBuffer(ThebesLayer* aLayer, |
|
416 uint32_t aFlags) MOZ_OVERRIDE; |
|
417 virtual gfx::DrawTarget* BorrowDrawTargetForPainting(const PaintState& aPaintState, |
|
418 RotatedContentBuffer::DrawIterator* aIter = nullptr) MOZ_OVERRIDE; |
|
419 virtual void ReturnDrawTargetToBuffer(gfx::DrawTarget*& aReturned) MOZ_OVERRIDE |
|
420 { |
|
421 BorrowDrawTarget::ReturnDrawTarget(aReturned); |
|
422 } |
|
423 |
|
424 virtual void Updated(const nsIntRegion& aRegionToDraw, |
|
425 const nsIntRegion& aVisibleRegion, |
|
426 bool aDidSelfCopy); |
|
427 |
|
428 virtual void EndPaint() |
|
429 { |
|
430 if (IsSurfaceDescriptorValid(mUpdateDescriptor)) { |
|
431 mForwarder->DestroySharedSurface(&mUpdateDescriptor); |
|
432 } |
|
433 if (IsSurfaceDescriptorValid(mUpdateDescriptorOnWhite)) { |
|
434 mForwarder->DestroySharedSurface(&mUpdateDescriptorOnWhite); |
|
435 } |
|
436 ContentClientRemote::EndPaint(); |
|
437 } |
|
438 |
|
439 private: |
|
440 |
|
441 enum BufferType{ |
|
442 BUFFER_BLACK, |
|
443 BUFFER_WHITE |
|
444 }; |
|
445 |
|
446 void NotifyBufferCreated(ContentType aType, uint32_t aFlags) |
|
447 { |
|
448 mTextureInfo.mTextureFlags = aFlags & ~TEXTURE_DEALLOCATE_CLIENT; |
|
449 mContentType = aType; |
|
450 |
|
451 mForwarder->CreatedIncrementalBuffer(this, |
|
452 mTextureInfo, |
|
453 mBufferRect); |
|
454 |
|
455 } |
|
456 |
|
457 TemporaryRef<gfx::DrawTarget> GetUpdateSurface(BufferType aType, |
|
458 const nsIntRegion& aUpdateRegion); |
|
459 |
|
460 TextureInfo mTextureInfo; |
|
461 nsIntRect mBufferRect; |
|
462 nsIntPoint mBufferRotation; |
|
463 |
|
464 SurfaceDescriptor mUpdateDescriptor; |
|
465 SurfaceDescriptor mUpdateDescriptorOnWhite; |
|
466 |
|
467 ContentType mContentType; |
|
468 |
|
469 bool mHasBuffer; |
|
470 bool mHasBufferOnWhite; |
|
471 }; |
|
472 |
|
473 } |
|
474 } |
|
475 |
|
476 #endif |