1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Corporation code.
16 : *
17 : * The Initial Developer of the Original Code is Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2009
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Robert O'Callahan <robert@ocallahan.org>
23 : * Chris Jones <jones.chris.g@gmail.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "mozilla/Attributes.h"
40 :
41 : #include "gfxSharedImageSurface.h"
42 :
43 : #include "mozilla/layers/PLayerChild.h"
44 : #include "mozilla/layers/PLayersChild.h"
45 : #include "mozilla/layers/PLayersParent.h"
46 : #include "mozilla/gfx/2D.h"
47 :
48 : #include "ipc/ShadowLayerChild.h"
49 :
50 : #include "BasicLayers.h"
51 : #include "ImageLayers.h"
52 : #include "RenderTrace.h"
53 :
54 : #include "prprf.h"
55 : #include "nsTArray.h"
56 : #include "nsGUIEvent.h"
57 : #include "gfxContext.h"
58 : #include "gfxImageSurface.h"
59 : #include "gfxPattern.h"
60 : #include "gfxPlatform.h"
61 : #include "gfxUtils.h"
62 : #include "ThebesLayerBuffer.h"
63 : #include "nsIWidget.h"
64 : #include "ReadbackProcessor.h"
65 : #ifdef MOZ_X11
66 : #include "gfxXlibSurface.h"
67 : #endif
68 :
69 : #include "GLContext.h"
70 :
71 : #define PIXMAN_DONT_DEFINE_STDINT
72 : #include "pixman.h"
73 :
74 : namespace mozilla {
75 : namespace layers {
76 :
77 : class BasicContainerLayer;
78 : class ShadowableLayer;
79 :
80 : /**
81 : * This is the ImplData for all Basic layers. It also exposes methods
82 : * private to the Basic implementation that are common to all Basic layer types.
83 : * In particular, there is an internal Paint() method that we can use
84 : * to paint the contents of non-Thebes layers.
85 : *
86 : * The class hierarchy for Basic layers is like this:
87 : * BasicImplData
88 : * Layer | | |
89 : * | | | |
90 : * +-> ContainerLayer | | |
91 : * | | | | |
92 : * | +-> BasicContainerLayer <--+ | |
93 : * | | |
94 : * +-> ThebesLayer | |
95 : * | | | |
96 : * | +-> BasicThebesLayer <---------+ |
97 : * | |
98 : * +-> ImageLayer |
99 : * | |
100 : * +-> BasicImageLayer <--------------+
101 : */
102 : class BasicImplData {
103 : public:
104 0 : BasicImplData() : mHidden(false),
105 0 : mClipToVisibleRegion(false), mOperator(gfxContext::OPERATOR_OVER)
106 : {
107 0 : MOZ_COUNT_CTOR(BasicImplData);
108 0 : }
109 0 : virtual ~BasicImplData()
110 0 : {
111 0 : MOZ_COUNT_DTOR(BasicImplData);
112 0 : }
113 :
114 : /**
115 : * Layers that paint themselves, such as ImageLayers, should paint
116 : * in response to this method call. aContext will already have been
117 : * set up to account for all the properties of the layer (transform,
118 : * opacity, etc).
119 : */
120 0 : virtual void Paint(gfxContext* aContext) {}
121 :
122 : /**
123 : * Like Paint() but called for ThebesLayers with the additional parameters
124 : * they need.
125 : * If mClipToVisibleRegion is set, then the layer must clip to its
126 : * effective visible region (snapped or unsnapped, it doesn't matter).
127 : */
128 0 : virtual void PaintThebes(gfxContext* aContext,
129 : LayerManager::DrawThebesLayerCallback aCallback,
130 : void* aCallbackData,
131 0 : ReadbackProcessor* aReadback) {}
132 :
133 0 : virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
134 :
135 : /**
136 : * Implementations return true here if they *must* retain their
137 : * layer contents. This is true of shadowable layers with shadows,
138 : * because there's no target on which to composite directly in the
139 : * layer-publishing child process.
140 : */
141 0 : virtual bool MustRetainContent() { return false; }
142 :
143 : /**
144 : * Layers will get this call when their layer manager is destroyed, this
145 : * indicates they should clear resources they don't really need after their
146 : * LayerManager ceases to exist.
147 : */
148 0 : virtual void ClearCachedResources() {}
149 :
150 : /**
151 : * This variable is set by MarkLayersHidden() before painting. It indicates
152 : * that the layer should not be composited during this transaction.
153 : */
154 0 : void SetHidden(bool aCovered) { mHidden = aCovered; }
155 0 : bool IsHidden() const { return false; }
156 : /**
157 : * This variable is set by MarkLayersHidden() before painting. This is
158 : * the operator to be used when compositing the layer in this transaction. It must
159 : * be OVER or SOURCE.
160 : */
161 0 : void SetOperator(gfxContext::GraphicsOperator aOperator)
162 : {
163 0 : NS_ASSERTION(aOperator == gfxContext::OPERATOR_OVER ||
164 : aOperator == gfxContext::OPERATOR_SOURCE,
165 : "Bad composition operator");
166 0 : mOperator = aOperator;
167 0 : }
168 0 : gfxContext::GraphicsOperator GetOperator() const { return mOperator; }
169 :
170 0 : bool GetClipToVisibleRegion() { return mClipToVisibleRegion; }
171 0 : void SetClipToVisibleRegion(bool aClip) { mClipToVisibleRegion = aClip; }
172 :
173 : protected:
174 : bool mHidden;
175 : bool mClipToVisibleRegion;
176 : gfxContext::GraphicsOperator mOperator;
177 : };
178 :
179 : class AutoSetOperator {
180 : public:
181 0 : AutoSetOperator(gfxContext* aContext, gfxContext::GraphicsOperator aOperator) {
182 0 : if (aOperator != gfxContext::OPERATOR_OVER) {
183 0 : aContext->SetOperator(aOperator);
184 0 : mContext = aContext;
185 : }
186 0 : }
187 0 : ~AutoSetOperator() {
188 0 : if (mContext) {
189 0 : mContext->SetOperator(gfxContext::OPERATOR_OVER);
190 : }
191 0 : }
192 : private:
193 : nsRefPtr<gfxContext> mContext;
194 : };
195 :
196 : static BasicImplData*
197 0 : ToData(Layer* aLayer)
198 : {
199 0 : return static_cast<BasicImplData*>(aLayer->ImplData());
200 : }
201 :
202 : template<class Container>
203 0 : static void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
204 : template<class Container>
205 0 : static void ContainerRemoveChild(Layer* aChild, Container* aContainer);
206 :
207 : class BasicContainerLayer : public ContainerLayer, public BasicImplData {
208 : template<class Container>
209 : friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
210 : template<class Container>
211 : friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
212 :
213 : public:
214 0 : BasicContainerLayer(BasicLayerManager* aManager) :
215 0 : ContainerLayer(aManager, static_cast<BasicImplData*>(this))
216 : {
217 0 : MOZ_COUNT_CTOR(BasicContainerLayer);
218 0 : mSupportsComponentAlphaChildren = true;
219 0 : }
220 : virtual ~BasicContainerLayer();
221 :
222 0 : virtual void SetVisibleRegion(const nsIntRegion& aRegion)
223 : {
224 0 : NS_ASSERTION(BasicManager()->InConstruction(),
225 : "Can only set properties in construction phase");
226 0 : ContainerLayer::SetVisibleRegion(aRegion);
227 0 : }
228 0 : virtual void InsertAfter(Layer* aChild, Layer* aAfter)
229 : {
230 0 : NS_ASSERTION(BasicManager()->InConstruction(),
231 : "Can only set properties in construction phase");
232 0 : ContainerInsertAfter(aChild, aAfter, this);
233 0 : }
234 :
235 0 : virtual void RemoveChild(Layer* aChild)
236 : {
237 0 : NS_ASSERTION(BasicManager()->InConstruction(),
238 : "Can only set properties in construction phase");
239 0 : ContainerRemoveChild(aChild, this);
240 0 : }
241 :
242 0 : virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
243 : {
244 : // We push groups for container layers if we need to, which always
245 : // are aligned in device space, so it doesn't really matter how we snap
246 : // containers.
247 0 : gfxMatrix residual;
248 0 : gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
249 0 : idealTransform.ProjectTo2D();
250 :
251 0 : if (!idealTransform.CanDraw2D()) {
252 0 : mEffectiveTransform = idealTransform;
253 0 : ComputeEffectiveTransformsForChildren(gfx3DMatrix());
254 0 : mUseIntermediateSurface = true;
255 0 : return;
256 : }
257 :
258 0 : mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
259 : // We always pass the ideal matrix down to our children, so there is no
260 : // need to apply any compensation using the residual from SnapTransform.
261 0 : ComputeEffectiveTransformsForChildren(idealTransform);
262 :
263 : /* If we have a single child, it can just inherit our opacity,
264 : * otherwise we need a PushGroup and we need to mark ourselves as using
265 : * an intermediate surface so our children don't inherit our opacity
266 : * via GetEffectiveOpacity.
267 : */
268 0 : mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren();
269 : }
270 :
271 : /**
272 : * Returns true when:
273 : * a) no (non-hidden) childrens' visible areas overlap in
274 : * (aInRect intersected with this layer's visible region).
275 : * b) the (non-hidden) childrens' visible areas cover
276 : * (aInRect intersected with this layer's visible region).
277 : * c) this layer and all (non-hidden) children have transforms that are translations
278 : * by integers.
279 : * aInRect is in the root coordinate system.
280 : * Child layers with opacity do not contribute to the covered area in check b).
281 : * This method can be conservative; it's OK to return false under any
282 : * circumstances.
283 : */
284 : bool ChildrenPartitionVisibleRegion(const nsIntRect& aInRect);
285 :
286 0 : void ForceIntermediateSurface() { mUseIntermediateSurface = true; }
287 :
288 : protected:
289 0 : BasicLayerManager* BasicManager()
290 : {
291 0 : return static_cast<BasicLayerManager*>(mManager);
292 : }
293 : };
294 :
295 0 : BasicContainerLayer::~BasicContainerLayer()
296 : {
297 0 : while (mFirstChild) {
298 0 : ContainerRemoveChild(mFirstChild, this);
299 : }
300 :
301 0 : MOZ_COUNT_DTOR(BasicContainerLayer);
302 0 : }
303 :
304 : bool
305 0 : BasicContainerLayer::ChildrenPartitionVisibleRegion(const nsIntRect& aInRect)
306 : {
307 0 : gfxMatrix transform;
308 0 : if (!GetEffectiveTransform().CanDraw2D(&transform) ||
309 0 : transform.HasNonIntegerTranslation())
310 0 : return false;
311 :
312 0 : nsIntPoint offset(PRInt32(transform.x0), PRInt32(transform.y0));
313 0 : nsIntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().GetBounds() + offset);
314 0 : nsIntRegion covered;
315 :
316 0 : for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) {
317 0 : if (ToData(l)->IsHidden())
318 0 : continue;
319 :
320 0 : gfxMatrix childTransform;
321 0 : if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) ||
322 0 : childTransform.HasNonIntegerTranslation() ||
323 0 : l->GetEffectiveOpacity() != 1.0)
324 0 : return false;
325 0 : nsIntRegion childRegion = l->GetEffectiveVisibleRegion();
326 0 : childRegion.MoveBy(PRInt32(childTransform.x0), PRInt32(childTransform.y0));
327 0 : childRegion.And(childRegion, rect);
328 0 : if (l->GetClipRect()) {
329 0 : childRegion.And(childRegion, *l->GetClipRect() + offset);
330 : }
331 0 : nsIntRegion intersection;
332 0 : intersection.And(covered, childRegion);
333 0 : if (!intersection.IsEmpty())
334 0 : return false;
335 0 : covered.Or(covered, childRegion);
336 : }
337 :
338 0 : return covered.Contains(rect);
339 : }
340 :
341 : template<class Container>
342 : static void
343 0 : ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer)
344 : {
345 0 : NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
346 : "Child has wrong manager");
347 0 : NS_ASSERTION(!aChild->GetParent(),
348 : "aChild already in the tree");
349 0 : NS_ASSERTION(!aChild->GetNextSibling() && !aChild->GetPrevSibling(),
350 : "aChild already has siblings?");
351 0 : NS_ASSERTION(!aAfter ||
352 : (aAfter->Manager() == aContainer->Manager() &&
353 : aAfter->GetParent() == aContainer),
354 : "aAfter is not our child");
355 :
356 0 : aChild->SetParent(aContainer);
357 0 : if (aAfter == aContainer->mLastChild) {
358 0 : aContainer->mLastChild = aChild;
359 : }
360 0 : if (!aAfter) {
361 0 : aChild->SetNextSibling(aContainer->mFirstChild);
362 0 : if (aContainer->mFirstChild) {
363 0 : aContainer->mFirstChild->SetPrevSibling(aChild);
364 : }
365 0 : aContainer->mFirstChild = aChild;
366 0 : NS_ADDREF(aChild);
367 0 : aContainer->DidInsertChild(aChild);
368 0 : return;
369 : }
370 :
371 0 : Layer* next = aAfter->GetNextSibling();
372 0 : aChild->SetNextSibling(next);
373 0 : aChild->SetPrevSibling(aAfter);
374 0 : if (next) {
375 0 : next->SetPrevSibling(aChild);
376 : }
377 0 : aAfter->SetNextSibling(aChild);
378 0 : NS_ADDREF(aChild);
379 0 : aContainer->DidInsertChild(aChild);
380 : }
381 :
382 : template<class Container>
383 : static void
384 0 : ContainerRemoveChild(Layer* aChild, Container* aContainer)
385 : {
386 0 : NS_ASSERTION(aChild->Manager() == aContainer->Manager(),
387 : "Child has wrong manager");
388 0 : NS_ASSERTION(aChild->GetParent() == aContainer,
389 : "aChild not our child");
390 :
391 0 : Layer* prev = aChild->GetPrevSibling();
392 0 : Layer* next = aChild->GetNextSibling();
393 0 : if (prev) {
394 0 : prev->SetNextSibling(next);
395 : } else {
396 0 : aContainer->mFirstChild = next;
397 : }
398 0 : if (next) {
399 0 : next->SetPrevSibling(prev);
400 : } else {
401 0 : aContainer->mLastChild = prev;
402 : }
403 :
404 0 : aChild->SetNextSibling(nsnull);
405 0 : aChild->SetPrevSibling(nsnull);
406 0 : aChild->SetParent(nsnull);
407 :
408 0 : aContainer->DidRemoveChild(aChild);
409 0 : NS_RELEASE(aChild);
410 0 : }
411 :
412 : class BasicThebesLayer;
413 : class BasicThebesLayerBuffer : public ThebesLayerBuffer {
414 : typedef ThebesLayerBuffer Base;
415 :
416 : public:
417 0 : BasicThebesLayerBuffer(BasicThebesLayer* aLayer)
418 : : Base(ContainsVisibleBounds)
419 0 : , mLayer(aLayer)
420 : {
421 0 : }
422 :
423 0 : virtual ~BasicThebesLayerBuffer()
424 0 : {}
425 :
426 : using Base::BufferRect;
427 : using Base::BufferRotation;
428 :
429 : /**
430 : * Complete the drawing operation. The region to draw must have been
431 : * drawn before this is called. The contents of the buffer are drawn
432 : * to aTarget.
433 : */
434 : void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity);
435 :
436 : virtual already_AddRefed<gfxASurface>
437 : CreateBuffer(ContentType aType, const nsIntSize& aSize, PRUint32 aFlags);
438 :
439 : /**
440 : * Swap out the old backing buffer for |aBuffer| and attributes.
441 : */
442 0 : void SetBackingBuffer(gfxASurface* aBuffer,
443 : const nsIntRect& aRect, const nsIntPoint& aRotation)
444 : {
445 0 : gfxIntSize prevSize = gfxIntSize(BufferRect().width, BufferRect().height);
446 0 : gfxIntSize newSize = aBuffer->GetSize();
447 0 : NS_ABORT_IF_FALSE(newSize == prevSize,
448 : "Swapped-in buffer size doesn't match old buffer's!");
449 0 : nsRefPtr<gfxASurface> oldBuffer;
450 0 : oldBuffer = SetBuffer(aBuffer, aRect, aRotation);
451 0 : }
452 :
453 : void SetBackingBufferAndUpdateFrom(
454 : gfxASurface* aBuffer,
455 : gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
456 : const nsIntRegion& aUpdateRegion);
457 :
458 : private:
459 0 : BasicThebesLayerBuffer(gfxASurface* aBuffer,
460 : const nsIntRect& aRect, const nsIntPoint& aRotation)
461 : // The size policy doesn't really matter here; this constructor is
462 : // intended to be used for creating temporaries
463 0 : : ThebesLayerBuffer(ContainsVisibleBounds)
464 : {
465 0 : SetBuffer(aBuffer, aRect, aRotation);
466 0 : }
467 :
468 : BasicThebesLayer* mLayer;
469 : };
470 :
471 : class BasicThebesLayer : public ThebesLayer, public BasicImplData {
472 : public:
473 : typedef BasicThebesLayerBuffer Buffer;
474 :
475 0 : BasicThebesLayer(BasicLayerManager* aLayerManager) :
476 : ThebesLayer(aLayerManager, static_cast<BasicImplData*>(this)),
477 0 : mBuffer(this)
478 : {
479 0 : MOZ_COUNT_CTOR(BasicThebesLayer);
480 0 : }
481 0 : virtual ~BasicThebesLayer()
482 0 : {
483 0 : MOZ_COUNT_DTOR(BasicThebesLayer);
484 0 : }
485 :
486 0 : virtual void SetVisibleRegion(const nsIntRegion& aRegion)
487 : {
488 0 : NS_ASSERTION(BasicManager()->InConstruction(),
489 : "Can only set properties in construction phase");
490 0 : ThebesLayer::SetVisibleRegion(aRegion);
491 0 : }
492 0 : virtual void InvalidateRegion(const nsIntRegion& aRegion)
493 : {
494 0 : NS_ASSERTION(BasicManager()->InConstruction(),
495 : "Can only set properties in construction phase");
496 0 : mValidRegion.Sub(mValidRegion, aRegion);
497 0 : }
498 :
499 : virtual void PaintThebes(gfxContext* aContext,
500 : LayerManager::DrawThebesLayerCallback aCallback,
501 : void* aCallbackData,
502 : ReadbackProcessor* aReadback);
503 :
504 0 : virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); }
505 :
506 : virtual already_AddRefed<gfxASurface>
507 0 : CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize)
508 : {
509 0 : nsRefPtr<gfxASurface> referenceSurface = mBuffer.GetBuffer();
510 0 : if (!referenceSurface) {
511 0 : gfxContext* defaultTarget = BasicManager()->GetDefaultTarget();
512 0 : if (defaultTarget) {
513 0 : referenceSurface = defaultTarget->CurrentSurface();
514 : } else {
515 0 : nsIWidget* widget = BasicManager()->GetRetainerWidget();
516 0 : if (widget) {
517 0 : referenceSurface = widget->GetThebesSurface();
518 : } else {
519 0 : referenceSurface = BasicManager()->GetTarget()->CurrentSurface();
520 : }
521 : }
522 : }
523 0 : return referenceSurface->CreateSimilarSurface(
524 0 : aType, gfxIntSize(aSize.width, aSize.height));
525 : }
526 :
527 0 : virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
528 : {
529 0 : if (!BasicManager()->IsRetained()) {
530 : // Don't do any snapping of our transform, since we're just going to
531 : // draw straight through without intermediate buffers.
532 0 : mEffectiveTransform = GetLocalTransform()*aTransformToSurface;
533 0 : if (gfxPoint(0,0) != mResidualTranslation) {
534 0 : mResidualTranslation = gfxPoint(0,0);
535 0 : mValidRegion.SetEmpty();
536 : }
537 0 : return;
538 : }
539 0 : ThebesLayer::ComputeEffectiveTransforms(aTransformToSurface);
540 : }
541 :
542 : // Sync front/back buffers content
543 0 : virtual void SyncFrontBufferToBackBuffer() {}
544 :
545 : protected:
546 0 : BasicLayerManager* BasicManager()
547 : {
548 0 : return static_cast<BasicLayerManager*>(mManager);
549 : }
550 :
551 : virtual void
552 0 : PaintBuffer(gfxContext* aContext,
553 : const nsIntRegion& aRegionToDraw,
554 : const nsIntRegion& aExtendedRegionToDraw,
555 : const nsIntRegion& aRegionToInvalidate,
556 : bool aDidSelfCopy,
557 : LayerManager::DrawThebesLayerCallback aCallback,
558 : void* aCallbackData)
559 : {
560 0 : if (!aCallback) {
561 0 : BasicManager()->SetTransactionIncomplete();
562 0 : return;
563 : }
564 : aCallback(this, aContext, aExtendedRegionToDraw, aRegionToInvalidate,
565 0 : aCallbackData);
566 : // Everything that's visible has been validated. Do this instead of just
567 : // OR-ing with aRegionToDraw, since that can lead to a very complex region
568 : // here (OR doesn't automatically simplify to the simplest possible
569 : // representation of a region.)
570 0 : nsIntRegion tmp;
571 0 : tmp.Or(mVisibleRegion, aExtendedRegionToDraw);
572 0 : mValidRegion.Or(mValidRegion, tmp);
573 : }
574 :
575 : Buffer mBuffer;
576 : };
577 :
578 : /**
579 : * Clips to the smallest device-pixel-aligned rectangle containing aRect
580 : * in user space.
581 : * Returns true if the clip is "perfect", i.e. we actually clipped exactly to
582 : * aRect.
583 : */
584 : static bool
585 0 : ClipToContain(gfxContext* aContext, const nsIntRect& aRect)
586 : {
587 0 : gfxRect userRect(aRect.x, aRect.y, aRect.width, aRect.height);
588 0 : gfxRect deviceRect = aContext->UserToDevice(userRect);
589 0 : deviceRect.RoundOut();
590 :
591 0 : gfxMatrix currentMatrix = aContext->CurrentMatrix();
592 0 : aContext->IdentityMatrix();
593 0 : aContext->NewPath();
594 0 : aContext->Rectangle(deviceRect);
595 0 : aContext->Clip();
596 0 : aContext->SetMatrix(currentMatrix);
597 :
598 0 : return aContext->DeviceToUser(deviceRect).IsEqualInterior(userRect);
599 : }
600 :
601 : static nsIntRegion
602 0 : IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
603 : {
604 0 : gfxRect clip = aContext->GetClipExtents();
605 0 : clip.RoundOut();
606 0 : nsIntRect r(clip.X(), clip.Y(), clip.Width(), clip.Height());
607 0 : nsIntRegion result;
608 0 : result.And(aRegion, r);
609 : return result;
610 : }
611 :
612 : static void
613 0 : SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
614 : {
615 0 : if (!aTarget->IsCairo()) {
616 : // Azure targets don't contain antialiasing flags at this point.
617 0 : return;
618 : }
619 :
620 0 : nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
621 0 : if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
622 : // Destination doesn't have alpha channel; no need to set any special flags
623 : return;
624 : }
625 :
626 0 : const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
627 : surface->SetSubpixelAntialiasingEnabled(
628 0 : !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
629 0 : surface->GetOpaqueRect().Contains(
630 0 : aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))));
631 : }
632 :
633 : already_AddRefed<gfxContext>
634 0 : BasicLayerManager::PushGroupForLayer(gfxContext* aContext, Layer* aLayer,
635 : const nsIntRegion& aRegion,
636 : bool* aNeedsClipToVisibleRegion)
637 : {
638 : // If we need to call PushGroup, we should clip to the smallest possible
639 : // area first to minimize the size of the temporary surface.
640 0 : bool didCompleteClip = ClipToContain(aContext, aRegion.GetBounds());
641 :
642 0 : nsRefPtr<gfxContext> result;
643 0 : if (aLayer->CanUseOpaqueSurface() &&
644 0 : ((didCompleteClip && aRegion.GetNumRects() == 1) ||
645 0 : !aContext->CurrentMatrix().HasNonIntegerTranslation())) {
646 : // If the layer is opaque in its visible region we can push a CONTENT_COLOR
647 : // group. We need to make sure that only pixels inside the layer's visible
648 : // region are copied back to the destination. Remember if we've already
649 : // clipped precisely to the visible region.
650 0 : *aNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
651 0 : result = PushGroupWithCachedSurface(aContext, gfxASurface::CONTENT_COLOR);
652 : } else {
653 0 : *aNeedsClipToVisibleRegion = false;
654 0 : result = aContext;
655 0 : aContext->PushGroupAndCopyBackground(gfxASurface::CONTENT_COLOR_ALPHA);
656 : }
657 0 : return result.forget();
658 : }
659 :
660 : void
661 0 : BasicThebesLayer::PaintThebes(gfxContext* aContext,
662 : LayerManager::DrawThebesLayerCallback aCallback,
663 : void* aCallbackData,
664 : ReadbackProcessor* aReadback)
665 : {
666 0 : NS_ASSERTION(BasicManager()->InDrawing(),
667 : "Can only draw in drawing phase");
668 0 : nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
669 :
670 0 : nsTArray<ReadbackProcessor::Update> readbackUpdates;
671 0 : if (aReadback && UsedForReadback()) {
672 0 : aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
673 : }
674 0 : SyncFrontBufferToBackBuffer();
675 :
676 0 : bool canUseOpaqueSurface = CanUseOpaqueSurface();
677 : Buffer::ContentType contentType =
678 : canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
679 0 : gfxASurface::CONTENT_COLOR_ALPHA;
680 0 : float opacity = GetEffectiveOpacity();
681 :
682 0 : if (!BasicManager()->IsRetained() ||
683 0 : (!canUseOpaqueSurface &&
684 : (mContentFlags & CONTENT_COMPONENT_ALPHA) &&
685 0 : !MustRetainContent())) {
686 0 : NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
687 :
688 0 : mValidRegion.SetEmpty();
689 0 : mBuffer.Clear();
690 :
691 0 : nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
692 :
693 : #ifdef MOZ_RENDERTRACE
694 : RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
695 : #endif
696 :
697 0 : if (!toDraw.IsEmpty() && !IsHidden()) {
698 0 : if (!aCallback) {
699 0 : BasicManager()->SetTransactionIncomplete();
700 : return;
701 : }
702 :
703 0 : aContext->Save();
704 :
705 0 : bool needsClipToVisibleRegion = GetClipToVisibleRegion();
706 : bool needsGroup =
707 0 : opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER;
708 0 : nsRefPtr<gfxContext> groupContext;
709 0 : if (needsGroup) {
710 : groupContext =
711 : BasicManager()->PushGroupForLayer(aContext, this, toDraw,
712 0 : &needsClipToVisibleRegion);
713 0 : if (GetOperator() != gfxContext::OPERATOR_OVER) {
714 0 : needsClipToVisibleRegion = true;
715 : }
716 : } else {
717 0 : groupContext = aContext;
718 : }
719 0 : SetAntialiasingFlags(this, groupContext);
720 0 : aCallback(this, groupContext, toDraw, nsIntRegion(), aCallbackData);
721 0 : if (needsGroup) {
722 0 : BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
723 0 : if (needsClipToVisibleRegion) {
724 0 : gfxUtils::ClipToRegion(aContext, toDraw);
725 : }
726 0 : AutoSetOperator setOperator(aContext, GetOperator());
727 0 : aContext->Paint(opacity);
728 : }
729 :
730 0 : aContext->Restore();
731 : }
732 :
733 : #ifdef MOZ_RENDERTRACE
734 : RenderTraceInvalidateEnd(this, "FFFF00");
735 : #endif
736 : return;
737 : }
738 :
739 : {
740 0 : PRUint32 flags = 0;
741 : #ifndef MOZ_GFX_OPTIMIZE_MOBILE
742 0 : gfxMatrix transform;
743 0 : if (!GetEffectiveTransform().CanDraw2D(&transform) ||
744 0 : transform.HasNonIntegerTranslation()) {
745 0 : flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
746 : }
747 : #endif
748 : Buffer::PaintState state =
749 0 : mBuffer.BeginPaint(this, contentType, flags);
750 0 : mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
751 :
752 0 : if (state.mContext) {
753 : // The area that became invalid and is visible needs to be repainted
754 : // (this could be the whole visible area if our buffer switched
755 : // from RGB to RGBA, because we might need to repaint with
756 : // subpixel AA)
757 : state.mRegionToInvalidate.And(state.mRegionToInvalidate,
758 0 : GetEffectiveVisibleRegion());
759 0 : nsIntRegion extendedDrawRegion = state.mRegionToDraw;
760 0 : SetAntialiasingFlags(this, state.mContext);
761 :
762 : #ifdef MOZ_RENDERTRACE
763 : RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
764 : #endif
765 :
766 : PaintBuffer(state.mContext,
767 : state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
768 : state.mDidSelfCopy,
769 0 : aCallback, aCallbackData);
770 0 : Mutated();
771 :
772 : #ifdef MOZ_RENDERTRACE
773 : RenderTraceInvalidateEnd(this, "FFFF00");
774 : #endif
775 : } else {
776 : // It's possible that state.mRegionToInvalidate is nonempty here,
777 : // if we are shrinking the valid region to nothing.
778 0 : NS_ASSERTION(state.mRegionToDraw.IsEmpty(),
779 : "If we need to draw, we should have a context");
780 : }
781 : }
782 :
783 0 : if (BasicManager()->IsTransactionIncomplete())
784 : return;
785 :
786 0 : gfxRect clipExtents;
787 0 : clipExtents = aContext->GetClipExtents();
788 0 : if (!IsHidden() && !clipExtents.IsEmpty()) {
789 0 : AutoSetOperator setOperator(aContext, GetOperator());
790 0 : mBuffer.DrawTo(this, aContext, opacity);
791 : }
792 :
793 0 : for (PRUint32 i = 0; i < readbackUpdates.Length(); ++i) {
794 0 : ReadbackProcessor::Update& update = readbackUpdates[i];
795 0 : nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
796 : nsRefPtr<gfxContext> ctx =
797 0 : update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
798 0 : update.mSequenceCounter);
799 0 : if (ctx) {
800 0 : NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
801 0 : ctx->Translate(gfxPoint(offset.x, offset.y));
802 0 : mBuffer.DrawTo(this, ctx, 1.0);
803 0 : update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
804 : }
805 : }
806 : }
807 :
808 : static bool
809 0 : IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion)
810 : {
811 : // Assume clipping is cheap if the context just has an integer
812 : // translation, and the visible region is simple.
813 0 : return !aTarget->CurrentMatrix().HasNonIntegerTranslation() &&
814 0 : aRegion.GetNumRects() <= 1;
815 : }
816 :
817 : void
818 0 : BasicThebesLayerBuffer::DrawTo(ThebesLayer* aLayer,
819 : gfxContext* aTarget,
820 : float aOpacity)
821 : {
822 0 : aTarget->Save();
823 : // If the entire buffer is valid, we can just draw the whole thing,
824 : // no need to clip. But we'll still clip if clipping is cheap ---
825 : // that might let us copy a smaller region of the buffer.
826 : // Also clip to the visible region if we're told to.
827 0 : if (!aLayer->GetValidRegion().Contains(BufferRect()) ||
828 0 : (ToData(aLayer)->GetClipToVisibleRegion() &&
829 0 : !aLayer->GetVisibleRegion().Contains(BufferRect())) ||
830 0 : IsClippingCheap(aTarget, aLayer->GetEffectiveVisibleRegion())) {
831 : // We don't want to draw invalid stuff, so we need to clip. Might as
832 : // well clip to the smallest area possible --- the visible region.
833 : // Bug 599189 if there is a non-integer-translation transform in aTarget,
834 : // we might sample pixels outside GetEffectiveVisibleRegion(), which is wrong
835 : // and may cause gray lines.
836 0 : gfxUtils::ClipToRegionSnapped(aTarget, aLayer->GetEffectiveVisibleRegion());
837 : }
838 0 : DrawBufferWithRotation(aTarget, aOpacity);
839 0 : aTarget->Restore();
840 0 : }
841 :
842 : already_AddRefed<gfxASurface>
843 0 : BasicThebesLayerBuffer::CreateBuffer(ContentType aType,
844 : const nsIntSize& aSize, PRUint32 aFlags)
845 : {
846 0 : return mLayer->CreateBuffer(aType, aSize);
847 : }
848 :
849 : void
850 0 : BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
851 : gfxASurface* aBuffer,
852 : gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
853 : const nsIntRegion& aUpdateRegion)
854 : {
855 0 : SetBackingBuffer(aBuffer, aRect, aRotation);
856 : nsRefPtr<gfxContext> destCtx =
857 0 : GetContextForQuadrantUpdate(aUpdateRegion.GetBounds());
858 0 : destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
859 0 : if (IsClippingCheap(destCtx, aUpdateRegion)) {
860 0 : gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
861 : }
862 :
863 0 : BasicThebesLayerBuffer srcBuffer(aSource, aRect, aRotation);
864 0 : srcBuffer.DrawBufferWithRotation(destCtx, 1.0);
865 0 : }
866 :
867 : class BasicImageLayer : public ImageLayer, public BasicImplData {
868 : public:
869 0 : BasicImageLayer(BasicLayerManager* aLayerManager) :
870 : ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)),
871 0 : mSize(-1, -1)
872 : {
873 0 : MOZ_COUNT_CTOR(BasicImageLayer);
874 0 : }
875 0 : virtual ~BasicImageLayer()
876 0 : {
877 0 : MOZ_COUNT_DTOR(BasicImageLayer);
878 0 : }
879 :
880 0 : virtual void SetVisibleRegion(const nsIntRegion& aRegion)
881 : {
882 0 : NS_ASSERTION(BasicManager()->InConstruction(),
883 : "Can only set properties in construction phase");
884 0 : ImageLayer::SetVisibleRegion(aRegion);
885 0 : }
886 :
887 : virtual void Paint(gfxContext* aContext);
888 :
889 : static void PaintContext(gfxPattern* aPattern,
890 : const nsIntRegion& aVisible,
891 : const nsIntRect* aTileSourceRect,
892 : float aOpacity,
893 : gfxContext* aContext);
894 :
895 : protected:
896 0 : BasicLayerManager* BasicManager()
897 : {
898 0 : return static_cast<BasicLayerManager*>(mManager);
899 : }
900 :
901 : already_AddRefed<gfxPattern>
902 : GetAndPaintCurrentImage(gfxContext* aContext,
903 : float aOpacity);
904 :
905 : gfxIntSize mSize;
906 : };
907 :
908 : void
909 0 : BasicImageLayer::Paint(gfxContext* aContext)
910 : {
911 0 : if (IsHidden())
912 0 : return;
913 : nsRefPtr<gfxPattern> dontcare =
914 0 : GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
915 : }
916 :
917 : already_AddRefed<gfxPattern>
918 0 : BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
919 : float aOpacity)
920 : {
921 0 : if (!mContainer)
922 0 : return nsnull;
923 :
924 0 : mContainer->SetImageFactory(mManager->IsCompositingCheap() ? nsnull : BasicManager()->GetImageFactory());
925 :
926 0 : nsRefPtr<gfxASurface> surface;
927 0 : AutoLockImage autoLock(mContainer, getter_AddRefs(surface));
928 0 : Image *image = autoLock.GetImage();
929 0 : gfxIntSize size = mSize = autoLock.GetSize();
930 :
931 0 : if (!surface || surface->CairoStatus()) {
932 0 : return nsnull;
933 : }
934 :
935 0 : nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
936 0 : if (!pat) {
937 0 : return nsnull;
938 : }
939 :
940 0 : pat->SetFilter(mFilter);
941 0 : gfxIntSize sourceSize = surface->GetSize();
942 0 : if (mScaleMode != SCALE_NONE) {
943 0 : NS_ASSERTION(mScaleMode == SCALE_STRETCH,
944 : "No other scalemodes than stretch and none supported yet.");
945 0 : gfxMatrix mat = pat->GetMatrix();
946 0 : mat.Scale(float(sourceSize.width) / mScaleToSize.width, float(sourceSize.height) / mScaleToSize.height);
947 0 : pat->SetMatrix(mat);
948 0 : size = mScaleToSize;
949 : }
950 :
951 : // The visible region can extend outside the image. If we're not
952 : // tiling, we don't want to draw into that area, so just draw within
953 : // the image bounds.
954 0 : const nsIntRect* tileSrcRect = GetTileSourceRect();
955 0 : AutoSetOperator setOperator(aContext, GetOperator());
956 : PaintContext(pat,
957 0 : tileSrcRect ? GetVisibleRegion() : nsIntRegion(nsIntRect(0, 0, size.width, size.height)),
958 : tileSrcRect,
959 0 : aOpacity, aContext);
960 :
961 0 : GetContainer()->NotifyPaintedImage(image);
962 :
963 0 : return pat.forget();
964 : }
965 :
966 : /*static*/ void
967 0 : BasicImageLayer::PaintContext(gfxPattern* aPattern,
968 : const nsIntRegion& aVisible,
969 : const nsIntRect* aTileSourceRect,
970 : float aOpacity,
971 : gfxContext* aContext)
972 : {
973 : // Set PAD mode so that when the video is being scaled, we do not sample
974 : // outside the bounds of the video image.
975 0 : gfxPattern::GraphicsExtend extend = gfxPattern::EXTEND_PAD;
976 :
977 0 : if (aContext->IsCairo()) {
978 : // PAD is slow with X11 and Quartz surfaces, so prefer speed over correctness
979 : // and use NONE.
980 0 : nsRefPtr<gfxASurface> target = aContext->CurrentSurface();
981 0 : gfxASurface::gfxSurfaceType type = target->GetType();
982 0 : if (type == gfxASurface::SurfaceTypeXlib ||
983 : type == gfxASurface::SurfaceTypeXcb ||
984 : type == gfxASurface::SurfaceTypeQuartz) {
985 0 : extend = gfxPattern::EXTEND_NONE;
986 : }
987 : }
988 :
989 0 : if (!aTileSourceRect) {
990 0 : aContext->NewPath();
991 : // No need to snap here; our transform has already taken care of it.
992 : // XXX true for arbitrary regions? Don't care yet though
993 0 : gfxUtils::PathFromRegion(aContext, aVisible);
994 0 : aPattern->SetExtend(extend);
995 0 : aContext->SetPattern(aPattern);
996 0 : aContext->FillWithOpacity(aOpacity);
997 : } else {
998 0 : nsRefPtr<gfxASurface> source = aPattern->GetSurface();
999 0 : NS_ABORT_IF_FALSE(source, "Expecting a surface pattern");
1000 0 : gfxIntSize sourceSize = source->GetSize();
1001 0 : nsIntRect sourceRect(0, 0, sourceSize.width, sourceSize.height);
1002 0 : NS_ABORT_IF_FALSE(sourceRect == *aTileSourceRect,
1003 : "Cowardly refusing to create a temporary surface for tiling");
1004 :
1005 0 : gfxContextAutoSaveRestore saveRestore(aContext);
1006 :
1007 0 : aContext->NewPath();
1008 0 : gfxUtils::PathFromRegion(aContext, aVisible);
1009 :
1010 0 : aPattern->SetExtend(gfxPattern::EXTEND_REPEAT);
1011 0 : aContext->SetPattern(aPattern);
1012 0 : aContext->FillWithOpacity(aOpacity);
1013 : }
1014 :
1015 : // Reset extend mode for callers that need to reuse the pattern
1016 0 : aPattern->SetExtend(extend);
1017 0 : }
1018 :
1019 : class BasicColorLayer : public ColorLayer, public BasicImplData {
1020 : public:
1021 0 : BasicColorLayer(BasicLayerManager* aLayerManager) :
1022 0 : ColorLayer(aLayerManager, static_cast<BasicImplData*>(this))
1023 : {
1024 0 : MOZ_COUNT_CTOR(BasicColorLayer);
1025 0 : }
1026 0 : virtual ~BasicColorLayer()
1027 0 : {
1028 0 : MOZ_COUNT_DTOR(BasicColorLayer);
1029 0 : }
1030 :
1031 0 : virtual void SetVisibleRegion(const nsIntRegion& aRegion)
1032 : {
1033 0 : NS_ASSERTION(BasicManager()->InConstruction(),
1034 : "Can only set properties in construction phase");
1035 0 : ColorLayer::SetVisibleRegion(aRegion);
1036 0 : }
1037 :
1038 0 : virtual void Paint(gfxContext* aContext)
1039 : {
1040 0 : if (IsHidden())
1041 0 : return;
1042 0 : AutoSetOperator setOperator(aContext, GetOperator());
1043 0 : PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
1044 : }
1045 :
1046 : static void PaintColorTo(gfxRGBA aColor, float aOpacity,
1047 : gfxContext* aContext);
1048 :
1049 : protected:
1050 0 : BasicLayerManager* BasicManager()
1051 : {
1052 0 : return static_cast<BasicLayerManager*>(mManager);
1053 : }
1054 : };
1055 :
1056 : /*static*/ void
1057 0 : BasicColorLayer::PaintColorTo(gfxRGBA aColor, float aOpacity,
1058 : gfxContext* aContext)
1059 : {
1060 0 : aContext->SetColor(aColor);
1061 0 : aContext->Paint(aOpacity);
1062 0 : }
1063 :
1064 : class BasicCanvasLayer : public CanvasLayer,
1065 : public BasicImplData
1066 : {
1067 : public:
1068 0 : BasicCanvasLayer(BasicLayerManager* aLayerManager) :
1069 0 : CanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
1070 : {
1071 0 : MOZ_COUNT_CTOR(BasicCanvasLayer);
1072 0 : }
1073 0 : virtual ~BasicCanvasLayer()
1074 0 : {
1075 0 : MOZ_COUNT_DTOR(BasicCanvasLayer);
1076 0 : }
1077 :
1078 0 : virtual void SetVisibleRegion(const nsIntRegion& aRegion)
1079 : {
1080 0 : NS_ASSERTION(BasicManager()->InConstruction(),
1081 : "Can only set properties in construction phase");
1082 0 : CanvasLayer::SetVisibleRegion(aRegion);
1083 0 : }
1084 :
1085 : virtual void Initialize(const Data& aData);
1086 : virtual void Paint(gfxContext* aContext);
1087 :
1088 : virtual void PaintWithOpacity(gfxContext* aContext,
1089 : float aOpacity);
1090 :
1091 : protected:
1092 0 : BasicLayerManager* BasicManager()
1093 : {
1094 0 : return static_cast<BasicLayerManager*>(mManager);
1095 : }
1096 : void UpdateSurface(gfxASurface* aDestSurface = nsnull);
1097 :
1098 : nsRefPtr<gfxASurface> mSurface;
1099 : nsRefPtr<mozilla::gl::GLContext> mGLContext;
1100 : mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
1101 :
1102 : PRUint32 mCanvasFramebuffer;
1103 :
1104 : bool mGLBufferIsPremultiplied;
1105 : bool mNeedsYFlip;
1106 : };
1107 :
1108 : void
1109 0 : BasicCanvasLayer::Initialize(const Data& aData)
1110 : {
1111 0 : NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
1112 :
1113 0 : if (aData.mSurface) {
1114 0 : mSurface = aData.mSurface;
1115 0 : NS_ASSERTION(aData.mGLContext == nsnull,
1116 : "CanvasLayer can't have both surface and GLContext");
1117 0 : mNeedsYFlip = false;
1118 0 : } else if (aData.mGLContext) {
1119 0 : NS_ASSERTION(aData.mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
1120 0 : mGLContext = aData.mGLContext;
1121 0 : mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
1122 0 : mCanvasFramebuffer = mGLContext->GetOffscreenFBO();
1123 0 : mNeedsYFlip = true;
1124 0 : } else if (aData.mDrawTarget) {
1125 0 : mDrawTarget = aData.mDrawTarget;
1126 0 : mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
1127 0 : mNeedsYFlip = false;
1128 : } else {
1129 0 : NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
1130 : }
1131 :
1132 0 : mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
1133 0 : }
1134 :
1135 : void
1136 0 : BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface)
1137 : {
1138 0 : if (mDrawTarget) {
1139 0 : mDrawTarget->Flush();
1140 : }
1141 :
1142 0 : if (!mGLContext && aDestSurface) {
1143 0 : nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface);
1144 0 : tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
1145 0 : BasicCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f);
1146 : return;
1147 : }
1148 :
1149 0 : if (!mDirty)
1150 0 : return;
1151 0 : mDirty = false;
1152 :
1153 0 : if (mGLContext) {
1154 0 : if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) {
1155 0 : NS_ASSERTION(aDestSurface->GetType() == gfxASurface::SurfaceTypeImage,
1156 : "Destination surface must be ImageSurface type");
1157 0 : return;
1158 : }
1159 :
1160 : // We need to read from the GLContext
1161 0 : mGLContext->MakeCurrent();
1162 :
1163 : #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
1164 : mGLContext->fFinish();
1165 : gfxASurface* offscreenSurface = mGLContext->GetOffscreenPixmapSurface();
1166 :
1167 : // XRender can only blend premuliplied alpha, so only allow xrender
1168 : // path if we have premultiplied alpha or opaque content.
1169 : if (offscreenSurface && (mGLBufferIsPremultiplied || (GetContentFlags() & CONTENT_OPAQUE))) {
1170 : mSurface = offscreenSurface;
1171 : mNeedsYFlip = false;
1172 : }
1173 : else
1174 : #endif
1175 : {
1176 : nsRefPtr<gfxImageSurface> isurf = aDestSurface ?
1177 : static_cast<gfxImageSurface*>(aDestSurface) :
1178 : new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
1179 0 : (GetContentFlags() & CONTENT_OPAQUE)
1180 : ? gfxASurface::ImageFormatRGB24
1181 0 : : gfxASurface::ImageFormatARGB32);
1182 :
1183 0 : if (!isurf || isurf->CairoStatus() != 0) {
1184 : return;
1185 : }
1186 :
1187 0 : NS_ASSERTION(isurf->Stride() == mBounds.width * 4, "gfxImageSurface stride isn't what we expect!");
1188 :
1189 0 : PRUint32 currentFramebuffer = 0;
1190 :
1191 0 : mGLContext->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)¤tFramebuffer);
1192 :
1193 : // Make sure that we read pixels from the correct framebuffer, regardless
1194 : // of what's currently bound.
1195 0 : if (currentFramebuffer != mCanvasFramebuffer)
1196 0 : mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mCanvasFramebuffer);
1197 :
1198 : mGLContext->ReadPixelsIntoImageSurface(0, 0,
1199 : mBounds.width, mBounds.height,
1200 0 : isurf);
1201 :
1202 : // Put back the previous framebuffer binding.
1203 0 : if (currentFramebuffer != mCanvasFramebuffer)
1204 0 : mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, currentFramebuffer);
1205 :
1206 : // If the underlying GLContext doesn't have a framebuffer into which
1207 : // premultiplied values were written, we have to do this ourselves here.
1208 : // Note that this is a WebGL attribute; GL itself has no knowledge of
1209 : // premultiplied or unpremultiplied alpha.
1210 0 : if (!mGLBufferIsPremultiplied)
1211 0 : gfxUtils::PremultiplyImageSurface(isurf);
1212 :
1213 : // stick our surface into mSurface, so that the Paint() path is the same
1214 0 : if (!aDestSurface) {
1215 0 : mSurface = isurf;
1216 : }
1217 : }
1218 : }
1219 : }
1220 :
1221 : void
1222 0 : BasicCanvasLayer::Paint(gfxContext* aContext)
1223 : {
1224 0 : if (IsHidden())
1225 0 : return;
1226 0 : UpdateSurface();
1227 0 : FireDidTransactionCallback();
1228 0 : PaintWithOpacity(aContext, GetEffectiveOpacity());
1229 : }
1230 :
1231 : void
1232 0 : BasicCanvasLayer::PaintWithOpacity(gfxContext* aContext,
1233 : float aOpacity)
1234 : {
1235 0 : NS_ASSERTION(BasicManager()->InDrawing(),
1236 : "Can only draw in drawing phase");
1237 :
1238 0 : if (!mSurface) {
1239 0 : NS_WARNING("No valid surface to draw!");
1240 0 : return;
1241 : }
1242 :
1243 0 : nsRefPtr<gfxPattern> pat = new gfxPattern(mSurface);
1244 :
1245 0 : pat->SetFilter(mFilter);
1246 0 : pat->SetExtend(gfxPattern::EXTEND_PAD);
1247 :
1248 0 : gfxMatrix m;
1249 0 : if (mNeedsYFlip) {
1250 0 : m = aContext->CurrentMatrix();
1251 0 : aContext->Translate(gfxPoint(0.0, mBounds.height));
1252 0 : aContext->Scale(1.0, -1.0);
1253 : }
1254 :
1255 : // If content opaque, then save off current operator and set to source.
1256 : // This ensures that alpha is not applied even if the source surface
1257 : // has an alpha channel
1258 : gfxContext::GraphicsOperator savedOp;
1259 0 : if (GetContentFlags() & CONTENT_OPAQUE) {
1260 0 : savedOp = aContext->CurrentOperator();
1261 0 : aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
1262 : }
1263 :
1264 0 : AutoSetOperator setOperator(aContext, GetOperator());
1265 0 : aContext->NewPath();
1266 : // No need to snap here; our transform is already set up to snap our rect
1267 0 : aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height));
1268 0 : aContext->SetPattern(pat);
1269 0 : aContext->FillWithOpacity(aOpacity);
1270 :
1271 : #if defined (MOZ_X11) && defined (MOZ_EGL_XRENDER_COMPOSITE)
1272 : if (mGLContext) {
1273 : // Wait for X to complete all operations before continuing
1274 : // Otherwise gl context could get cleared before X is done.
1275 : mGLContext->WaitNative();
1276 : }
1277 : #endif
1278 :
1279 : // Restore surface operator
1280 0 : if (GetContentFlags() & CONTENT_OPAQUE) {
1281 0 : aContext->SetOperator(savedOp);
1282 : }
1283 :
1284 0 : if (mNeedsYFlip) {
1285 0 : aContext->SetMatrix(m);
1286 : }
1287 : }
1288 :
1289 : class BasicReadbackLayer : public ReadbackLayer,
1290 : public BasicImplData
1291 : {
1292 : public:
1293 0 : BasicReadbackLayer(BasicLayerManager* aLayerManager) :
1294 0 : ReadbackLayer(aLayerManager, static_cast<BasicImplData*>(this))
1295 : {
1296 0 : MOZ_COUNT_CTOR(BasicReadbackLayer);
1297 0 : }
1298 0 : virtual ~BasicReadbackLayer()
1299 0 : {
1300 0 : MOZ_COUNT_DTOR(BasicReadbackLayer);
1301 0 : }
1302 :
1303 0 : virtual void SetVisibleRegion(const nsIntRegion& aRegion)
1304 : {
1305 0 : NS_ASSERTION(BasicManager()->InConstruction(),
1306 : "Can only set properties in construction phase");
1307 0 : ReadbackLayer::SetVisibleRegion(aRegion);
1308 0 : }
1309 :
1310 : protected:
1311 0 : BasicLayerManager* BasicManager()
1312 : {
1313 0 : return static_cast<BasicLayerManager*>(mManager);
1314 : }
1315 : };
1316 :
1317 : static nsIntRect
1318 0 : ToOutsideIntRect(const gfxRect &aRect)
1319 : {
1320 0 : gfxRect r = aRect;
1321 0 : r.RoundOut();
1322 0 : return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
1323 : }
1324 :
1325 : static nsIntRect
1326 0 : ToInsideIntRect(const gfxRect& aRect)
1327 : {
1328 0 : gfxRect r = aRect;
1329 0 : r.RoundIn();
1330 0 : return nsIntRect(r.X(), r.Y(), r.Width(), r.Height());
1331 : }
1332 :
1333 0 : BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
1334 : #ifdef DEBUG
1335 : mPhase(PHASE_NONE),
1336 : #endif
1337 : mWidget(aWidget)
1338 : , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
1339 : , mCachedSurfaceInUse(false)
1340 0 : , mTransactionIncomplete(false)
1341 : {
1342 0 : MOZ_COUNT_CTOR(BasicLayerManager);
1343 0 : NS_ASSERTION(aWidget, "Must provide a widget");
1344 0 : }
1345 :
1346 0 : BasicLayerManager::BasicLayerManager() :
1347 : #ifdef DEBUG
1348 : mPhase(PHASE_NONE),
1349 : #endif
1350 : mWidget(nsnull)
1351 : , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false)
1352 : , mCachedSurfaceInUse(false)
1353 0 : , mTransactionIncomplete(false)
1354 : {
1355 0 : MOZ_COUNT_CTOR(BasicLayerManager);
1356 0 : }
1357 :
1358 0 : BasicLayerManager::~BasicLayerManager()
1359 : {
1360 0 : NS_ASSERTION(!InTransaction(), "Died during transaction?");
1361 :
1362 0 : ClearCachedResources();
1363 :
1364 0 : mRoot = nsnull;
1365 :
1366 0 : MOZ_COUNT_DTOR(BasicLayerManager);
1367 0 : }
1368 :
1369 : void
1370 0 : BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
1371 : BufferMode aDoubleBuffering)
1372 : {
1373 0 : NS_ASSERTION(!InTransaction(),
1374 : "Must set default target outside transaction");
1375 0 : mDefaultTarget = aContext;
1376 0 : mDoubleBuffering = aDoubleBuffering;
1377 0 : }
1378 :
1379 : void
1380 0 : BasicLayerManager::BeginTransaction()
1381 : {
1382 0 : mUsingDefaultTarget = true;
1383 0 : BeginTransactionWithTarget(mDefaultTarget);
1384 0 : }
1385 :
1386 : already_AddRefed<gfxContext>
1387 0 : BasicLayerManager::PushGroupWithCachedSurface(gfxContext *aTarget,
1388 : gfxASurface::gfxContentType aContent)
1389 : {
1390 0 : if (mCachedSurfaceInUse || !aTarget->IsCairo()) {
1391 : // We can't cache Azure DrawTargets at this point.
1392 0 : aTarget->PushGroup(aContent);
1393 0 : nsRefPtr<gfxContext> result = aTarget;
1394 0 : return result.forget();
1395 : }
1396 0 : mCachedSurfaceInUse = true;
1397 :
1398 0 : gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
1399 0 : aTarget->IdentityMatrix();
1400 :
1401 0 : nsRefPtr<gfxASurface> currentSurf = aTarget->CurrentSurface();
1402 0 : gfxRect clip = aTarget->GetClipExtents();
1403 0 : clip.RoundOut();
1404 :
1405 0 : nsRefPtr<gfxContext> ctx = mCachedSurface.Get(aContent, clip, currentSurf);
1406 : /* Align our buffer for the original surface */
1407 0 : ctx->SetMatrix(saveMatrix.Matrix());
1408 0 : return ctx.forget();
1409 : }
1410 :
1411 : void
1412 0 : BasicLayerManager::PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed)
1413 : {
1414 0 : if (!aTarget)
1415 0 : return;
1416 0 : nsRefPtr<gfxASurface> current = aPushed->CurrentSurface();
1417 0 : if (aTarget->IsCairo() && mCachedSurface.IsSurface(current)) {
1418 0 : gfxContextMatrixAutoSaveRestore saveMatrix(aTarget);
1419 0 : aTarget->IdentityMatrix();
1420 0 : aTarget->SetSource(current);
1421 0 : mCachedSurfaceInUse = false;
1422 : } else {
1423 0 : aTarget->PopGroupToSource();
1424 : }
1425 : }
1426 :
1427 : void
1428 0 : BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
1429 : {
1430 : #ifdef MOZ_LAYERS_HAVE_LOG
1431 0 : MOZ_LAYERS_LOG(("[----- BeginTransaction"));
1432 0 : Log();
1433 : #endif
1434 :
1435 0 : NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
1436 : #ifdef DEBUG
1437 0 : mPhase = PHASE_CONSTRUCTION;
1438 : #endif
1439 0 : mTarget = aTarget;
1440 0 : }
1441 :
1442 : static void
1443 0 : TransformIntRect(nsIntRect& aRect, const gfxMatrix& aMatrix,
1444 : nsIntRect (*aRoundMethod)(const gfxRect&))
1445 : {
1446 0 : gfxRect gr = gfxRect(aRect.x, aRect.y, aRect.width, aRect.height);
1447 0 : gr = aMatrix.TransformBounds(gr);
1448 0 : aRect = (*aRoundMethod)(gr);
1449 0 : }
1450 :
1451 : /**
1452 : * This function assumes that GetEffectiveTransform transforms
1453 : * all layers to the same coordinate system (the "root coordinate system").
1454 : * It can't be used as is by accelerated layers because of intermediate surfaces.
1455 : * This must set the hidden flag to true or false on *all* layers in the subtree.
1456 : * It also sets the operator for all layers to "OVER".
1457 : * It clears mClipToVisibleRegion on all layers.
1458 : * @param aClipRect the cliprect, in the root coordinate system. We assume
1459 : * that any layer drawing is clipped to this rect. It is therefore not
1460 : * allowed to add to the opaque region outside that rect.
1461 : * @param aDirtyRect the dirty rect that will be painted, in the root
1462 : * coordinate system. Layers outside this rect should be hidden.
1463 : * @param aOpaqueRegion the opaque region covering aLayer, in the
1464 : * root coordinate system.
1465 : */
1466 : enum {
1467 : ALLOW_OPAQUE = 0x01,
1468 : };
1469 : static void
1470 0 : MarkLayersHidden(Layer* aLayer, const nsIntRect& aClipRect,
1471 : const nsIntRect& aDirtyRect,
1472 : nsIntRegion& aOpaqueRegion,
1473 : PRUint32 aFlags)
1474 : {
1475 0 : nsIntRect newClipRect(aClipRect);
1476 0 : PRUint32 newFlags = aFlags;
1477 :
1478 : // Allow aLayer or aLayer's descendants to cover underlying layers
1479 : // only if it's opaque.
1480 0 : if (aLayer->GetOpacity() != 1.0f) {
1481 0 : newFlags &= ~ALLOW_OPAQUE;
1482 : }
1483 :
1484 : {
1485 0 : const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
1486 0 : if (clipRect) {
1487 0 : nsIntRect cr = *clipRect;
1488 : // clipRect is in the container's coordinate system. Get it into the
1489 : // global coordinate system.
1490 0 : if (aLayer->GetParent()) {
1491 0 : gfxMatrix tr;
1492 0 : if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
1493 : // Clip rect is applied after aLayer's transform, i.e., in the coordinate
1494 : // system of aLayer's parent.
1495 0 : TransformIntRect(cr, tr, ToInsideIntRect);
1496 : } else {
1497 0 : cr.SetRect(0, 0, 0, 0);
1498 : }
1499 : }
1500 0 : newClipRect.IntersectRect(newClipRect, cr);
1501 : }
1502 : }
1503 :
1504 0 : BasicImplData* data = ToData(aLayer);
1505 0 : data->SetOperator(gfxContext::OPERATOR_OVER);
1506 0 : data->SetClipToVisibleRegion(false);
1507 :
1508 0 : if (!aLayer->AsContainerLayer()) {
1509 0 : gfxMatrix transform;
1510 0 : if (!aLayer->GetEffectiveTransform().CanDraw2D(&transform)) {
1511 0 : data->SetHidden(false);
1512 0 : return;
1513 : }
1514 :
1515 0 : nsIntRegion region = aLayer->GetEffectiveVisibleRegion();
1516 0 : nsIntRect r = region.GetBounds();
1517 0 : TransformIntRect(r, transform, ToOutsideIntRect);
1518 0 : r.IntersectRect(r, aDirtyRect);
1519 0 : data->SetHidden(aOpaqueRegion.Contains(r));
1520 :
1521 : // Allow aLayer to cover underlying layers only if aLayer's
1522 : // content is opaque
1523 0 : if ((aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
1524 : (newFlags & ALLOW_OPAQUE)) {
1525 0 : nsIntRegionRectIterator it(region);
1526 0 : while (const nsIntRect* sr = it.Next()) {
1527 0 : r = *sr;
1528 0 : TransformIntRect(r, transform, ToInsideIntRect);
1529 :
1530 0 : r.IntersectRect(r, newClipRect);
1531 0 : aOpaqueRegion.Or(aOpaqueRegion, r);
1532 : }
1533 : }
1534 : } else {
1535 0 : Layer* child = aLayer->GetLastChild();
1536 0 : bool allHidden = true;
1537 0 : for (; child; child = child->GetPrevSibling()) {
1538 0 : MarkLayersHidden(child, newClipRect, aDirtyRect, aOpaqueRegion, newFlags);
1539 0 : if (!ToData(child)->IsHidden()) {
1540 0 : allHidden = false;
1541 : }
1542 : }
1543 0 : data->SetHidden(allHidden);
1544 : }
1545 : }
1546 :
1547 : /**
1548 : * This function assumes that GetEffectiveTransform transforms
1549 : * all layers to the same coordinate system (the "root coordinate system").
1550 : * MarkLayersHidden must be called before calling this.
1551 : * @param aVisibleRect the rectangle of aLayer that is visible (i.e. not
1552 : * clipped and in the dirty rect), in the root coordinate system.
1553 : */
1554 : static void
1555 0 : ApplyDoubleBuffering(Layer* aLayer, const nsIntRect& aVisibleRect)
1556 : {
1557 0 : BasicImplData* data = ToData(aLayer);
1558 0 : if (data->IsHidden())
1559 0 : return;
1560 :
1561 0 : nsIntRect newVisibleRect(aVisibleRect);
1562 :
1563 : {
1564 0 : const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
1565 0 : if (clipRect) {
1566 0 : nsIntRect cr = *clipRect;
1567 : // clipRect is in the container's coordinate system. Get it into the
1568 : // global coordinate system.
1569 0 : if (aLayer->GetParent()) {
1570 0 : gfxMatrix tr;
1571 0 : if (aLayer->GetParent()->GetEffectiveTransform().CanDraw2D(&tr)) {
1572 0 : NS_ASSERTION(!tr.HasNonIntegerTranslation(),
1573 : "Parent can only have an integer translation");
1574 0 : cr += nsIntPoint(PRInt32(tr.x0), PRInt32(tr.y0));
1575 : } else {
1576 0 : NS_ERROR("Parent can only have an integer translation");
1577 : }
1578 : }
1579 0 : newVisibleRect.IntersectRect(newVisibleRect, cr);
1580 : }
1581 : }
1582 :
1583 : BasicContainerLayer* container =
1584 0 : static_cast<BasicContainerLayer*>(aLayer->AsContainerLayer());
1585 : // Layers that act as their own backbuffers should be drawn to the destination
1586 : // using OPERATOR_SOURCE to ensure that alpha values in a transparent window
1587 : // are cleared. This can also be faster than OPERATOR_OVER.
1588 0 : if (!container) {
1589 0 : data->SetOperator(gfxContext::OPERATOR_SOURCE);
1590 : } else {
1591 0 : if (container->UseIntermediateSurface() ||
1592 0 : !container->ChildrenPartitionVisibleRegion(newVisibleRect)) {
1593 : // We need to double-buffer this container.
1594 0 : data->SetOperator(gfxContext::OPERATOR_SOURCE);
1595 0 : container->ForceIntermediateSurface();
1596 : } else {
1597 : // Tell the children to clip to their visible regions so our assumption
1598 : // that they don't paint outside their visible regions is valid!
1599 0 : for (Layer* child = aLayer->GetFirstChild(); child;
1600 : child = child->GetNextSibling()) {
1601 0 : ToData(child)->SetClipToVisibleRegion(true);
1602 0 : ApplyDoubleBuffering(child, newVisibleRect);
1603 : }
1604 : }
1605 : }
1606 : }
1607 :
1608 : void
1609 0 : BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
1610 : void* aCallbackData,
1611 : EndTransactionFlags aFlags)
1612 : {
1613 0 : EndTransactionInternal(aCallback, aCallbackData, aFlags);
1614 0 : }
1615 :
1616 : bool
1617 0 : BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
1618 : void* aCallbackData,
1619 : EndTransactionFlags aFlags)
1620 : {
1621 : #ifdef MOZ_LAYERS_HAVE_LOG
1622 0 : MOZ_LAYERS_LOG((" ----- (beginning paint)"));
1623 0 : Log();
1624 : #endif
1625 :
1626 0 : NS_ASSERTION(InConstruction(), "Should be in construction phase");
1627 : #ifdef DEBUG
1628 0 : mPhase = PHASE_DRAWING;
1629 : #endif
1630 :
1631 : #ifdef MOZ_RENDERTRACE
1632 : Layer* aLayer = GetRoot();
1633 : RenderTraceLayers(aLayer, "FF00");
1634 : #endif
1635 :
1636 0 : mTransactionIncomplete = false;
1637 :
1638 0 : if (mTarget && mRoot && !(aFlags & END_NO_IMMEDIATE_REDRAW)) {
1639 0 : nsIntRect clipRect;
1640 0 : if (HasShadowManager()) {
1641 : // If this has a shadow manager, the clip extents of mTarget are meaningless.
1642 : // So instead just use the root layer's visible region bounds.
1643 0 : const nsIntRect& bounds = mRoot->GetVisibleRegion().GetBounds();
1644 : gfxRect deviceRect =
1645 0 : mTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
1646 0 : clipRect = ToOutsideIntRect(deviceRect);
1647 : } else {
1648 0 : gfxContextMatrixAutoSaveRestore save(mTarget);
1649 0 : mTarget->SetMatrix(gfxMatrix());
1650 0 : clipRect = ToOutsideIntRect(mTarget->GetClipExtents());
1651 : }
1652 :
1653 : // Need to do this before we call ApplyDoubleBuffering,
1654 : // which depends on correct effective transforms
1655 : mSnapEffectiveTransforms =
1656 0 : !(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING);
1657 0 : mRoot->ComputeEffectiveTransforms(gfx3DMatrix::From2D(mTarget->CurrentMatrix()));
1658 :
1659 0 : if (IsRetained()) {
1660 0 : nsIntRegion region;
1661 0 : MarkLayersHidden(mRoot, clipRect, clipRect, region, ALLOW_OPAQUE);
1662 0 : if (mUsingDefaultTarget && mDoubleBuffering != BUFFER_NONE) {
1663 0 : ApplyDoubleBuffering(mRoot, clipRect);
1664 : }
1665 : }
1666 :
1667 0 : PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nsnull);
1668 :
1669 0 : if (!mTransactionIncomplete) {
1670 : // Clear out target if we have a complete transaction.
1671 0 : mTarget = nsnull;
1672 : }
1673 : }
1674 :
1675 : #ifdef MOZ_LAYERS_HAVE_LOG
1676 0 : Log();
1677 0 : MOZ_LAYERS_LOG(("]----- EndTransaction"));
1678 : #endif
1679 :
1680 : #ifdef DEBUG
1681 : // Go back to the construction phase if the transaction isn't complete.
1682 : // Layout will update the layer tree and call EndTransaction().
1683 0 : mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
1684 : #endif
1685 :
1686 0 : if (!mTransactionIncomplete) {
1687 : // This is still valid if the transaction was incomplete.
1688 0 : mUsingDefaultTarget = false;
1689 : }
1690 :
1691 0 : NS_ASSERTION(!aCallback || !mTransactionIncomplete,
1692 : "If callback is not null, transaction must be complete");
1693 :
1694 : // XXX - We should probably assert here that for an incomplete transaction
1695 : // out target is the default target.
1696 :
1697 0 : return !mTransactionIncomplete;
1698 : }
1699 :
1700 : bool
1701 0 : BasicLayerManager::EndEmptyTransaction()
1702 : {
1703 0 : if (!mRoot) {
1704 0 : return false;
1705 : }
1706 :
1707 0 : return EndTransactionInternal(nsnull, nsnull);
1708 : }
1709 :
1710 : void
1711 0 : BasicLayerManager::SetRoot(Layer* aLayer)
1712 : {
1713 0 : NS_ASSERTION(aLayer, "Root can't be null");
1714 0 : NS_ASSERTION(aLayer->Manager() == this, "Wrong manager");
1715 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
1716 0 : mRoot = aLayer;
1717 0 : }
1718 :
1719 : static pixman_transform
1720 0 : Matrix3DToPixman(const gfx3DMatrix& aMatrix)
1721 : {
1722 : pixman_f_transform transform;
1723 :
1724 0 : transform.m[0][0] = aMatrix._11;
1725 0 : transform.m[0][1] = aMatrix._21;
1726 0 : transform.m[0][2] = aMatrix._41;
1727 0 : transform.m[1][0] = aMatrix._12;
1728 0 : transform.m[1][1] = aMatrix._22;
1729 0 : transform.m[1][2] = aMatrix._42;
1730 0 : transform.m[2][0] = aMatrix._14;
1731 0 : transform.m[2][1] = aMatrix._24;
1732 0 : transform.m[2][2] = aMatrix._44;
1733 :
1734 : pixman_transform result;
1735 0 : pixman_transform_from_pixman_f_transform(&result, &transform);
1736 :
1737 : return result;
1738 : }
1739 :
1740 : static void
1741 0 : PixmanTransform(const gfxImageSurface *aDest,
1742 : const gfxImageSurface *aSrc,
1743 : const gfx3DMatrix& aTransform,
1744 : gfxPoint aDestOffset)
1745 : {
1746 0 : gfxIntSize destSize = aDest->GetSize();
1747 0 : pixman_image_t* dest = pixman_image_create_bits(aDest->Format() == gfxASurface::ImageFormatARGB32 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
1748 : destSize.width,
1749 : destSize.height,
1750 0 : (uint32_t*)aDest->Data(),
1751 0 : aDest->Stride());
1752 :
1753 0 : gfxIntSize srcSize = aSrc->GetSize();
1754 0 : pixman_image_t* src = pixman_image_create_bits(aSrc->Format() == gfxASurface::ImageFormatARGB32 ? PIXMAN_a8r8g8b8 : PIXMAN_x8r8g8b8,
1755 : srcSize.width,
1756 : srcSize.height,
1757 0 : (uint32_t*)aSrc->Data(),
1758 0 : aSrc->Stride());
1759 :
1760 0 : NS_ABORT_IF_FALSE(src && dest, "Failed to create pixman images?");
1761 :
1762 0 : pixman_transform pixTransform = Matrix3DToPixman(aTransform);
1763 : pixman_transform pixTransformInverted;
1764 :
1765 : // If the transform is singular then nothing would be drawn anyway, return here
1766 0 : if (!pixman_transform_invert(&pixTransformInverted, &pixTransform)) {
1767 0 : return;
1768 : }
1769 0 : pixman_image_set_transform(src, &pixTransformInverted);
1770 :
1771 : pixman_image_composite32(PIXMAN_OP_SRC,
1772 : src,
1773 : nsnull,
1774 : dest,
1775 : aDestOffset.x,
1776 : aDestOffset.y,
1777 : 0,
1778 : 0,
1779 : 0,
1780 : 0,
1781 : destSize.width,
1782 0 : destSize.height);
1783 :
1784 0 : pixman_image_unref(dest);
1785 0 : pixman_image_unref(src);
1786 : }
1787 :
1788 : /**
1789 : * Transform a surface using a gfx3DMatrix and blit to the destination if
1790 : * it is efficient to do so.
1791 : *
1792 : * @param aSource Source surface.
1793 : * @param aDest Desintation context.
1794 : * @param aBounds Area represented by aSource.
1795 : * @param aTransform Transformation matrix.
1796 : * @param aDrawOffset Location to draw returned surface on aDest.
1797 : * @param aDontBlit Never draw to aDest if this is true.
1798 : * @return Transformed surface, or nsnull if it has been drawn to aDest.
1799 : */
1800 : static already_AddRefed<gfxASurface>
1801 0 : Transform3D(gfxASurface* aSource, gfxContext* aDest,
1802 : const gfxRect& aBounds, const gfx3DMatrix& aTransform,
1803 : gfxPoint& aDrawOffset, bool aDontBlit)
1804 : {
1805 0 : nsRefPtr<gfxImageSurface> sourceImage = aSource->GetAsImageSurface();
1806 0 : if (!sourceImage) {
1807 0 : sourceImage = new gfxImageSurface(gfxIntSize(aBounds.width, aBounds.height), gfxASurface::FormatFromContent(aSource->GetContentType()));
1808 0 : nsRefPtr<gfxContext> ctx = new gfxContext(sourceImage);
1809 :
1810 0 : aSource->SetDeviceOffset(gfxPoint(0, 0));
1811 0 : ctx->SetSource(aSource);
1812 0 : ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
1813 0 : ctx->Paint();
1814 : }
1815 :
1816 : // Find the transformed rectangle of our layer.
1817 0 : gfxRect offsetRect = aTransform.TransformBounds(aBounds);
1818 :
1819 : // Intersect the transformed layer with the destination rectangle.
1820 : // This is in device space since we have an identity transform set on aTarget.
1821 0 : gfxRect destRect = aDest->GetClipExtents();
1822 0 : destRect.IntersectRect(destRect, offsetRect);
1823 :
1824 : // Create a surface the size of the transformed object.
1825 0 : nsRefPtr<gfxASurface> dest = aDest->CurrentSurface();
1826 0 : nsRefPtr<gfxImageSurface> destImage = dest->GetAsImageSurface();
1827 0 : destImage = nsnull;
1828 0 : gfxPoint offset;
1829 : bool blitComplete;
1830 0 : if (!destImage || aDontBlit || !aDest->ClipContainsRect(destRect)) {
1831 : destImage = new gfxImageSurface(gfxIntSize(destRect.width, destRect.height),
1832 0 : gfxASurface::ImageFormatARGB32);
1833 0 : offset = destRect.TopLeft();
1834 0 : blitComplete = false;
1835 : } else {
1836 0 : offset = -dest->GetDeviceOffset();
1837 0 : blitComplete = true;
1838 : }
1839 :
1840 : // Include a translation to the correct origin.
1841 0 : gfx3DMatrix translation = gfx3DMatrix::Translation(aBounds.x, aBounds.y, 0);
1842 :
1843 : // Transform the content and offset it such that the content begins at the origin.
1844 0 : PixmanTransform(destImage, sourceImage, translation * aTransform, offset);
1845 :
1846 0 : if (blitComplete) {
1847 0 : return nsnull;
1848 : }
1849 :
1850 : // If we haven't actually drawn to aDest then return our temporary image so that
1851 : // the caller can do this.
1852 0 : aDrawOffset = destRect.TopLeft();
1853 0 : return destImage.forget();
1854 : }
1855 :
1856 :
1857 :
1858 : void
1859 0 : BasicLayerManager::PaintLayer(gfxContext* aTarget,
1860 : Layer* aLayer,
1861 : DrawThebesLayerCallback aCallback,
1862 : void* aCallbackData,
1863 : ReadbackProcessor* aReadback)
1864 : {
1865 0 : const nsIntRect* clipRect = aLayer->GetEffectiveClipRect();
1866 0 : const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform();
1867 0 : BasicContainerLayer* container = static_cast<BasicContainerLayer*>(aLayer);
1868 0 : bool needsGroup = aLayer->GetFirstChild() &&
1869 0 : container->UseIntermediateSurface();
1870 0 : BasicImplData* data = ToData(aLayer);
1871 : bool needsClipToVisibleRegion =
1872 0 : data->GetClipToVisibleRegion() && !aLayer->AsThebesLayer();
1873 0 : NS_ASSERTION(needsGroup || !aLayer->GetFirstChild() ||
1874 : container->GetOperator() == gfxContext::OPERATOR_OVER,
1875 : "non-OVER operator should have forced UseIntermediateSurface");
1876 :
1877 : // If needsSaveRestore is false, we should still save and restore
1878 : // the CTM
1879 0 : bool needsSaveRestore = needsGroup || clipRect || needsClipToVisibleRegion;
1880 0 : gfxMatrix savedMatrix;
1881 0 : if (needsSaveRestore) {
1882 0 : aTarget->Save();
1883 :
1884 0 : if (clipRect) {
1885 0 : aTarget->NewPath();
1886 0 : aTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), true);
1887 0 : aTarget->Clip();
1888 : }
1889 : } else {
1890 0 : savedMatrix = aTarget->CurrentMatrix();
1891 : }
1892 :
1893 0 : gfxMatrix transform;
1894 : // Will return an identity matrix for 3d transforms, and is handled separately below.
1895 0 : bool is2D = effectiveTransform.CanDraw2D(&transform);
1896 0 : NS_ABORT_IF_FALSE(is2D || needsGroup || !aLayer->GetFirstChild(), "Must PushGroup for 3d transforms!");
1897 0 : if (is2D) {
1898 0 : aTarget->SetMatrix(transform);
1899 : } else {
1900 0 : aTarget->SetMatrix(gfxMatrix());
1901 : }
1902 :
1903 0 : const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
1904 : // If needsGroup is true, we'll clip to the visible region after we've popped the group
1905 0 : if (needsClipToVisibleRegion && !needsGroup) {
1906 0 : gfxUtils::ClipToRegion(aTarget, visibleRegion);
1907 : // Don't need to clip to visible region again
1908 0 : needsClipToVisibleRegion = false;
1909 : }
1910 :
1911 0 : bool pushedTargetOpaqueRect = false;
1912 0 : nsRefPtr<gfxASurface> currentSurface = aTarget->CurrentSurface();
1913 0 : const nsIntRect& bounds = visibleRegion.GetBounds();
1914 :
1915 0 : if (aTarget->IsCairo()) {
1916 0 : const gfxRect& targetOpaqueRect = currentSurface->GetOpaqueRect();
1917 :
1918 : // Try to annotate currentSurface with a region of pixels that have been
1919 : // (or will be) painted opaque, if no such region is currently set.
1920 0 : if (targetOpaqueRect.IsEmpty() && visibleRegion.GetNumRects() == 1 &&
1921 0 : (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
1922 0 : !transform.HasNonAxisAlignedTransform()) {
1923 : currentSurface->SetOpaqueRect(
1924 0 : aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height)));
1925 0 : pushedTargetOpaqueRect = true;
1926 : }
1927 : }
1928 :
1929 0 : nsRefPtr<gfxContext> groupTarget;
1930 0 : nsRefPtr<gfxASurface> untransformedSurface;
1931 0 : if (!is2D) {
1932 : untransformedSurface =
1933 0 : gfxPlatform::GetPlatform()->CreateOffscreenSurface(gfxIntSize(bounds.width, bounds.height),
1934 0 : gfxASurface::CONTENT_COLOR_ALPHA);
1935 0 : if (!untransformedSurface) {
1936 0 : if (pushedTargetOpaqueRect) {
1937 0 : currentSurface->SetOpaqueRect(gfxRect(0, 0, 0, 0));
1938 : }
1939 0 : NS_ASSERTION(needsSaveRestore, "Should always need to restore with 3d transforms!");
1940 0 : aTarget->Restore();
1941 : return;
1942 : }
1943 0 : untransformedSurface->SetDeviceOffset(gfxPoint(-bounds.x, -bounds.y));
1944 0 : groupTarget = new gfxContext(untransformedSurface);
1945 0 : } else if (needsGroup) {
1946 0 : groupTarget = PushGroupForLayer(aTarget, aLayer, aLayer->GetEffectiveVisibleRegion(),
1947 0 : &needsClipToVisibleRegion);
1948 : } else {
1949 0 : groupTarget = aTarget;
1950 : }
1951 :
1952 : /* Only paint ourself, or our children - This optimization relies on this! */
1953 0 : Layer* child = aLayer->GetFirstChild();
1954 0 : if (!child) {
1955 : #ifdef MOZ_LAYERS_HAVE_LOG
1956 0 : MOZ_LAYERS_LOG(("%s (0x%p) is covered: %i\n", __FUNCTION__,
1957 : (void*)aLayer, data->IsHidden()));
1958 : #endif
1959 0 : if (aLayer->AsThebesLayer()) {
1960 0 : data->PaintThebes(groupTarget, aCallback, aCallbackData, aReadback);
1961 : } else {
1962 0 : data->Paint(groupTarget);
1963 : }
1964 : } else {
1965 0 : ReadbackProcessor readback;
1966 0 : ContainerLayer* container = static_cast<ContainerLayer*>(aLayer);
1967 0 : if (IsRetained()) {
1968 0 : readback.BuildUpdates(container);
1969 : }
1970 :
1971 0 : nsAutoTArray<Layer*, 12> children;
1972 0 : container->SortChildrenBy3DZOrder(children);
1973 :
1974 0 : for (PRUint32 i = 0; i < children.Length(); i++) {
1975 0 : PaintLayer(groupTarget, children.ElementAt(i), aCallback, aCallbackData, &readback);
1976 0 : if (mTransactionIncomplete)
1977 0 : break;
1978 : }
1979 : }
1980 :
1981 0 : if (needsGroup) {
1982 0 : bool blitComplete = false;
1983 0 : if (is2D) {
1984 0 : PopGroupToSourceWithCachedSurface(aTarget, groupTarget);
1985 : } else {
1986 0 : NS_ABORT_IF_FALSE(untransformedSurface,
1987 : "We should always allocate an untransformed surface with 3d transforms!");
1988 :
1989 : // Temporary fast fix for bug 725886
1990 : // Revert these changes when 725886 is ready
1991 0 : gfxRect clipExtents;
1992 0 : clipExtents = aTarget->GetClipExtents();
1993 0 : if (!clipExtents.IsEmpty()) {
1994 0 : gfxPoint offset;
1995 : bool dontBlit = needsClipToVisibleRegion || mTransactionIncomplete ||
1996 0 : aLayer->GetEffectiveOpacity() != 1.0f;
1997 : nsRefPtr<gfxASurface> result =
1998 : Transform3D(untransformedSurface, aTarget, bounds,
1999 0 : effectiveTransform, offset, dontBlit);
2000 :
2001 0 : blitComplete = !result;
2002 0 : if (result) {
2003 0 : aTarget->SetSource(result, offset);
2004 : }
2005 : }
2006 : }
2007 : // If we're doing our own double-buffering, we need to avoid drawing
2008 : // the results of an incomplete transaction to the destination surface ---
2009 : // that could cause flicker. Double-buffering is implemented using a
2010 : // temporary surface for one or more container layers, so we need to stop
2011 : // those temporary surfaces from being composited to aTarget.
2012 : // ApplyDoubleBuffering guarantees that this container layer can't
2013 : // intersect any other leaf layers, so if the transaction is not yet marked
2014 : // incomplete, the contents of this container layer are the final contents
2015 : // for the window.
2016 0 : if (!mTransactionIncomplete && !blitComplete) {
2017 0 : if (needsClipToVisibleRegion) {
2018 0 : gfxUtils::ClipToRegion(aTarget, aLayer->GetEffectiveVisibleRegion());
2019 : }
2020 0 : AutoSetOperator setOperator(aTarget, container->GetOperator());
2021 0 : aTarget->Paint(aLayer->GetEffectiveOpacity());
2022 : }
2023 : }
2024 :
2025 0 : if (pushedTargetOpaqueRect) {
2026 0 : currentSurface->SetOpaqueRect(gfxRect(0, 0, 0, 0));
2027 : }
2028 :
2029 0 : if (needsSaveRestore) {
2030 0 : aTarget->Restore();
2031 : } else {
2032 0 : aTarget->SetMatrix(savedMatrix);
2033 : }
2034 : }
2035 :
2036 : void
2037 0 : BasicLayerManager::ClearCachedResources()
2038 : {
2039 0 : if (mRoot) {
2040 0 : ClearLayer(mRoot);
2041 : }
2042 :
2043 0 : mCachedSurface.Expire();
2044 0 : }
2045 : void
2046 0 : BasicLayerManager::ClearLayer(Layer* aLayer)
2047 : {
2048 0 : ToData(aLayer)->ClearCachedResources();
2049 0 : for (Layer* child = aLayer->GetFirstChild(); child;
2050 : child = child->GetNextSibling()) {
2051 0 : ClearLayer(child);
2052 : }
2053 0 : }
2054 :
2055 : already_AddRefed<ThebesLayer>
2056 0 : BasicLayerManager::CreateThebesLayer()
2057 : {
2058 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
2059 0 : nsRefPtr<ThebesLayer> layer = new BasicThebesLayer(this);
2060 0 : return layer.forget();
2061 : }
2062 :
2063 : already_AddRefed<ContainerLayer>
2064 0 : BasicLayerManager::CreateContainerLayer()
2065 : {
2066 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
2067 0 : nsRefPtr<ContainerLayer> layer = new BasicContainerLayer(this);
2068 0 : return layer.forget();
2069 : }
2070 :
2071 : already_AddRefed<ImageLayer>
2072 0 : BasicLayerManager::CreateImageLayer()
2073 : {
2074 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
2075 0 : nsRefPtr<ImageLayer> layer = new BasicImageLayer(this);
2076 0 : return layer.forget();
2077 : }
2078 :
2079 : already_AddRefed<ColorLayer>
2080 0 : BasicLayerManager::CreateColorLayer()
2081 : {
2082 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
2083 0 : nsRefPtr<ColorLayer> layer = new BasicColorLayer(this);
2084 0 : return layer.forget();
2085 : }
2086 :
2087 : already_AddRefed<CanvasLayer>
2088 0 : BasicLayerManager::CreateCanvasLayer()
2089 : {
2090 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
2091 0 : nsRefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
2092 0 : return layer.forget();
2093 : }
2094 :
2095 : already_AddRefed<ReadbackLayer>
2096 0 : BasicLayerManager::CreateReadbackLayer()
2097 : {
2098 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
2099 0 : nsRefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
2100 0 : return layer.forget();
2101 : }
2102 :
2103 : class BasicShadowableThebesLayer;
2104 : class BasicShadowableLayer : public ShadowableLayer
2105 : {
2106 : public:
2107 0 : BasicShadowableLayer()
2108 0 : {
2109 0 : MOZ_COUNT_CTOR(BasicShadowableLayer);
2110 0 : }
2111 :
2112 0 : ~BasicShadowableLayer()
2113 0 : {
2114 0 : if (HasShadow()) {
2115 0 : PLayerChild::Send__delete__(GetShadow());
2116 : }
2117 0 : MOZ_COUNT_DTOR(BasicShadowableLayer);
2118 0 : }
2119 :
2120 0 : void SetShadow(PLayerChild* aShadow)
2121 : {
2122 0 : NS_ABORT_IF_FALSE(!mShadow, "can't have two shadows (yet)");
2123 0 : mShadow = aShadow;
2124 0 : }
2125 :
2126 0 : virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
2127 : {
2128 0 : NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
2129 0 : }
2130 :
2131 0 : virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
2132 : gfxSharedImageSurface* aUBuffer,
2133 : gfxSharedImageSurface* aVBuffer)
2134 : {
2135 0 : NS_RUNTIMEABORT("if this default impl is called, |aBuffer| leaks");
2136 0 : }
2137 :
2138 0 : virtual void Disconnect()
2139 : {
2140 : // This is an "emergency Disconnect()", called when the compositing
2141 : // process has died. |mShadow| and our Shmem buffers are
2142 : // automatically managed by IPDL, so we don't need to explicitly
2143 : // free them here (it's hard to get that right on emergency
2144 : // shutdown anyway).
2145 0 : mShadow = nsnull;
2146 0 : }
2147 :
2148 0 : virtual BasicShadowableThebesLayer* AsThebes() { return nsnull; }
2149 : };
2150 :
2151 : static ShadowableLayer*
2152 0 : ToShadowable(Layer* aLayer)
2153 : {
2154 0 : return ToData(aLayer)->AsShadowableLayer();
2155 : }
2156 :
2157 : // Some layers, like ReadbackLayers, can't be shadowed and shadowing
2158 : // them doesn't make sense anyway
2159 : static bool
2160 0 : ShouldShadow(Layer* aLayer)
2161 : {
2162 0 : if (!ToShadowable(aLayer)) {
2163 0 : NS_ABORT_IF_FALSE(aLayer->GetType() == Layer::TYPE_READBACK,
2164 : "Only expect not to shadow ReadbackLayers");
2165 0 : return false;
2166 : }
2167 0 : return true;
2168 : }
2169 :
2170 : template<class OpT>
2171 : static BasicShadowableLayer*
2172 0 : GetBasicShadowable(const OpT& op)
2173 : {
2174 : return static_cast<BasicShadowableLayer*>(
2175 0 : static_cast<const ShadowLayerChild*>(op.layerChild())->layer());
2176 : }
2177 :
2178 : class BasicShadowableContainerLayer : public BasicContainerLayer,
2179 : public BasicShadowableLayer {
2180 : public:
2181 0 : BasicShadowableContainerLayer(BasicShadowLayerManager* aManager) :
2182 0 : BasicContainerLayer(aManager)
2183 : {
2184 0 : MOZ_COUNT_CTOR(BasicShadowableContainerLayer);
2185 0 : }
2186 0 : virtual ~BasicShadowableContainerLayer()
2187 0 : {
2188 0 : MOZ_COUNT_DTOR(BasicShadowableContainerLayer);
2189 0 : }
2190 :
2191 : virtual void InsertAfter(Layer* aChild, Layer* aAfter);
2192 : virtual void RemoveChild(Layer* aChild);
2193 :
2194 0 : virtual Layer* AsLayer() { return this; }
2195 0 : virtual ShadowableLayer* AsShadowableLayer() { return this; }
2196 :
2197 0 : virtual void Disconnect()
2198 : {
2199 0 : BasicShadowableLayer::Disconnect();
2200 0 : }
2201 :
2202 : private:
2203 0 : BasicShadowLayerManager* ShadowManager()
2204 : {
2205 0 : return static_cast<BasicShadowLayerManager*>(mManager);
2206 : }
2207 : };
2208 :
2209 : void
2210 0 : BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
2211 : {
2212 0 : if (HasShadow() && ShouldShadow(aChild)) {
2213 0 : while (aAfter && !ShouldShadow(aAfter)) {
2214 0 : aAfter = aAfter->GetPrevSibling();
2215 : }
2216 0 : ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
2217 : ShadowManager()->Hold(aChild),
2218 0 : aAfter ? ShadowManager()->Hold(aAfter) : nsnull);
2219 : }
2220 0 : BasicContainerLayer::InsertAfter(aChild, aAfter);
2221 0 : }
2222 :
2223 : void
2224 0 : BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
2225 : {
2226 0 : if (HasShadow() && ShouldShadow(aChild)) {
2227 0 : ShadowManager()->RemoveChild(ShadowManager()->Hold(this),
2228 0 : ShadowManager()->Hold(aChild));
2229 : }
2230 0 : BasicContainerLayer::RemoveChild(aChild);
2231 0 : }
2232 :
2233 : class BasicShadowableThebesLayer : public BasicThebesLayer,
2234 : public BasicShadowableLayer
2235 : {
2236 : typedef BasicThebesLayer Base;
2237 :
2238 : public:
2239 0 : BasicShadowableThebesLayer(BasicShadowLayerManager* aManager)
2240 : : BasicThebesLayer(aManager)
2241 : , mIsNewBuffer(false)
2242 0 : , mFrontAndBackBufferDiffer(false)
2243 : {
2244 0 : MOZ_COUNT_CTOR(BasicShadowableThebesLayer);
2245 0 : }
2246 0 : virtual ~BasicShadowableThebesLayer()
2247 0 : {
2248 0 : DestroyBackBuffer();
2249 0 : MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
2250 0 : }
2251 :
2252 0 : virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
2253 : {
2254 0 : aAttrs = ThebesLayerAttributes(GetValidRegion());
2255 0 : }
2256 :
2257 0 : virtual Layer* AsLayer() { return this; }
2258 0 : virtual ShadowableLayer* AsShadowableLayer() { return this; }
2259 0 : virtual bool MustRetainContent() { return HasShadow(); }
2260 :
2261 : void SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
2262 : const nsIntRegion& aValidRegion,
2263 : const OptionalThebesBuffer& aReadOnlyFrontBuffer,
2264 : const nsIntRegion& aFrontUpdatedRegion);
2265 :
2266 0 : virtual void Disconnect()
2267 : {
2268 0 : mBackBuffer = SurfaceDescriptor();
2269 0 : BasicShadowableLayer::Disconnect();
2270 0 : }
2271 :
2272 0 : virtual BasicShadowableThebesLayer* AsThebes() { return this; }
2273 :
2274 : virtual void SyncFrontBufferToBackBuffer();
2275 :
2276 : private:
2277 0 : BasicShadowLayerManager* BasicManager()
2278 : {
2279 0 : return static_cast<BasicShadowLayerManager*>(mManager);
2280 : }
2281 :
2282 : virtual void
2283 : PaintBuffer(gfxContext* aContext,
2284 : const nsIntRegion& aRegionToDraw,
2285 : const nsIntRegion& aExtendedRegionToDraw,
2286 : const nsIntRegion& aRegionToInvalidate,
2287 : bool aDidSelfCopy,
2288 : LayerManager::DrawThebesLayerCallback aCallback,
2289 : void* aCallbackData) MOZ_OVERRIDE;
2290 :
2291 : virtual already_AddRefed<gfxASurface>
2292 : CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
2293 :
2294 0 : void DestroyBackBuffer()
2295 : {
2296 0 : if (IsSurfaceDescriptorValid(mBackBuffer)) {
2297 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
2298 : }
2299 0 : }
2300 :
2301 : // This describes the gfxASurface we hand to mBuffer. We keep a
2302 : // copy of the descriptor here so that we can call
2303 : // DestroySharedSurface() on the descriptor.
2304 : SurfaceDescriptor mBackBuffer;
2305 : nsIntRect mBackBufferRect;
2306 : nsIntPoint mBackBufferRectRotation;
2307 :
2308 : bool mIsNewBuffer;
2309 : OptionalThebesBuffer mROFrontBuffer;
2310 : nsIntRegion mFrontUpdatedRegion;
2311 : nsIntRegion mFrontValidRegion;
2312 : PRPackedBool mFrontAndBackBufferDiffer;
2313 : };
2314 :
2315 : void
2316 0 : BasicShadowableThebesLayer::SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
2317 : const nsIntRegion& aValidRegion,
2318 : const OptionalThebesBuffer& aReadOnlyFrontBuffer,
2319 : const nsIntRegion& aFrontUpdatedRegion)
2320 : {
2321 0 : if (OptionalThebesBuffer::Tnull_t == aBuffer.type()) {
2322 0 : mBackBuffer = SurfaceDescriptor();
2323 0 : } else if (!IsSurfaceDescriptorValid(mBackBuffer)) {
2324 0 : mBackBuffer = aBuffer.get_ThebesBuffer().buffer();
2325 0 : mBackBufferRect = aBuffer.get_ThebesBuffer().rect();
2326 0 : mBackBufferRectRotation = aBuffer.get_ThebesBuffer().rotation();
2327 : } else {
2328 0 : SurfaceDescriptor obsoleteBuffer = aBuffer.get_ThebesBuffer().buffer();
2329 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&obsoleteBuffer);
2330 : }
2331 0 : mFrontAndBackBufferDiffer = true;
2332 0 : mROFrontBuffer = aReadOnlyFrontBuffer;
2333 0 : mFrontUpdatedRegion = aFrontUpdatedRegion;
2334 0 : mFrontValidRegion = aValidRegion;
2335 0 : if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
2336 : // For null readonly front, we have single buffer mode
2337 : // so we can do sync right now, because it does not create new buffer and
2338 : // don't do any graphic operations
2339 0 : SyncFrontBufferToBackBuffer();
2340 : }
2341 0 : }
2342 :
2343 : void
2344 0 : BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
2345 : {
2346 0 : if (!mFrontAndBackBufferDiffer) {
2347 0 : return;
2348 : }
2349 :
2350 0 : nsRefPtr<gfxASurface> backBuffer;
2351 0 : if (!IsSurfaceDescriptorValid(mBackBuffer)) {
2352 0 : NS_ABORT_IF_FALSE(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer,
2353 : "should have a front RO buffer by now");
2354 0 : const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
2355 0 : nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
2356 0 : backBuffer = CreateBuffer(roFrontBuffer->GetContentType(), roFrontBuffer->GetSize());
2357 : } else {
2358 0 : backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
2359 : }
2360 0 : mFrontAndBackBufferDiffer = false;
2361 :
2362 0 : if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
2363 : // We didn't get back a read-only ref to our old back buffer (the
2364 : // parent's new front buffer). If the parent is pushing updates
2365 : // to a texture it owns, then we probably got back the same buffer
2366 : // we pushed in the update and all is well. If not, ...
2367 0 : mValidRegion = mFrontValidRegion;
2368 0 : mBuffer.SetBackingBuffer(backBuffer, mBackBufferRect, mBackBufferRectRotation);
2369 : return;
2370 : }
2371 :
2372 0 : MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
2373 : this,
2374 : mFrontUpdatedRegion.GetBounds().x,
2375 : mFrontUpdatedRegion.GetBounds().y,
2376 : mFrontUpdatedRegion.GetBounds().width,
2377 : mFrontUpdatedRegion.GetBounds().height));
2378 :
2379 0 : const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
2380 0 : nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
2381 : mBuffer.SetBackingBufferAndUpdateFrom(
2382 : backBuffer,
2383 0 : roFrontBuffer, roFront.rect(), roFront.rotation(),
2384 0 : mFrontUpdatedRegion);
2385 0 : mIsNewBuffer = false;
2386 : // Now the new back buffer has the same (interesting) pixels as the
2387 : // new front buffer, and mValidRegion et al. are correct wrt the new
2388 : // back buffer (i.e. as they were for the old back buffer)
2389 : }
2390 :
2391 : void
2392 0 : BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
2393 : const nsIntRegion& aRegionToDraw,
2394 : const nsIntRegion& aExtendedRegionToDraw,
2395 : const nsIntRegion& aRegionToInvalidate,
2396 : bool aDidSelfCopy,
2397 : LayerManager::DrawThebesLayerCallback aCallback,
2398 : void* aCallbackData)
2399 : {
2400 : Base::PaintBuffer(aContext,
2401 : aRegionToDraw, aExtendedRegionToDraw, aRegionToInvalidate,
2402 : aDidSelfCopy,
2403 0 : aCallback, aCallbackData);
2404 0 : if (!HasShadow()) {
2405 0 : return;
2406 : }
2407 :
2408 0 : nsIntRegion updatedRegion;
2409 0 : if (mIsNewBuffer || aDidSelfCopy) {
2410 : // A buffer reallocation clears both buffers. The front buffer has all the
2411 : // content by now, but the back buffer is still clear. Here, in effect, we
2412 : // are saying to copy all of the pixels of the front buffer to the back.
2413 : // Also when we self-copied in the buffer, the buffer space
2414 : // changes and some changed buffer content isn't reflected in the
2415 : // draw or invalidate region (on purpose!). When this happens, we
2416 : // need to read back the entire buffer too.
2417 0 : updatedRegion = mVisibleRegion;
2418 0 : mIsNewBuffer = false;
2419 : } else {
2420 0 : updatedRegion = aRegionToDraw;
2421 : }
2422 :
2423 0 : NS_ASSERTION(mBuffer.BufferRect().Contains(aRegionToDraw.GetBounds()),
2424 : "Update outside of buffer rect!");
2425 0 : NS_ABORT_IF_FALSE(IsSurfaceDescriptorValid(mBackBuffer),
2426 : "should have a back buffer by now");
2427 0 : BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this),
2428 : updatedRegion,
2429 0 : mBuffer.BufferRect(),
2430 0 : mBuffer.BufferRotation(),
2431 0 : mBackBuffer);
2432 0 : mROFrontBuffer = ThebesBuffer(mBackBuffer, mBuffer.BufferRect(), mBuffer.BufferRotation());
2433 0 : mBackBuffer = SurfaceDescriptor();
2434 : }
2435 :
2436 : already_AddRefed<gfxASurface>
2437 0 : BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
2438 : const nsIntSize& aSize)
2439 : {
2440 0 : if (!HasShadow()) {
2441 0 : return BasicThebesLayer::CreateBuffer(aType, aSize);
2442 : }
2443 :
2444 0 : MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): creating %d x %d buffer(x2)",
2445 : this,
2446 : aSize.width, aSize.height));
2447 :
2448 0 : if (IsSurfaceDescriptorValid(mBackBuffer)) {
2449 0 : BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this),
2450 0 : mBackBuffer);
2451 0 : mBackBuffer = SurfaceDescriptor();
2452 : }
2453 :
2454 : // XXX error handling
2455 0 : if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
2456 : aType,
2457 0 : &mBackBuffer)) {
2458 : enum { buflen = 256 };
2459 : char buf[buflen];
2460 : PR_snprintf(buf, buflen,
2461 : "creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
2462 0 : aSize.width, aSize.height, int(aType));
2463 0 : NS_RUNTIMEABORT(buf);
2464 : }
2465 :
2466 0 : NS_ABORT_IF_FALSE(!mIsNewBuffer,
2467 : "Bad! Did we create a buffer twice without painting?");
2468 :
2469 0 : mIsNewBuffer = true;
2470 :
2471 0 : return BasicManager()->OpenDescriptor(mBackBuffer);
2472 : }
2473 :
2474 :
2475 : class BasicShadowableImageLayer : public BasicImageLayer,
2476 : public BasicShadowableLayer
2477 : {
2478 : public:
2479 0 : BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
2480 : BasicImageLayer(aManager),
2481 0 : mBufferIsOpaque(false)
2482 : {
2483 0 : MOZ_COUNT_CTOR(BasicShadowableImageLayer);
2484 0 : }
2485 0 : virtual ~BasicShadowableImageLayer()
2486 0 : {
2487 0 : DestroyBackBuffer();
2488 0 : MOZ_COUNT_DTOR(BasicShadowableImageLayer);
2489 0 : }
2490 :
2491 : virtual void Paint(gfxContext* aContext);
2492 :
2493 0 : virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
2494 : {
2495 0 : aAttrs = ImageLayerAttributes(mFilter);
2496 0 : }
2497 :
2498 0 : virtual Layer* AsLayer() { return this; }
2499 0 : virtual ShadowableLayer* AsShadowableLayer() { return this; }
2500 :
2501 0 : virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
2502 : {
2503 0 : mBackBuffer = aBuffer;
2504 0 : }
2505 :
2506 0 : virtual void SetBackBufferYUVImage(gfxSharedImageSurface* aYBuffer,
2507 : gfxSharedImageSurface* aUBuffer,
2508 : gfxSharedImageSurface* aVBuffer)
2509 : {
2510 0 : mBackBufferY = aYBuffer;
2511 0 : mBackBufferU = aUBuffer;
2512 0 : mBackBufferV = aVBuffer;
2513 0 : }
2514 :
2515 0 : virtual void Disconnect()
2516 : {
2517 0 : mBackBufferY = mBackBufferU = mBackBufferV = nsnull;
2518 0 : mBackBuffer = SurfaceDescriptor();
2519 0 : BasicShadowableLayer::Disconnect();
2520 0 : }
2521 :
2522 0 : void DestroyBackBuffer()
2523 : {
2524 0 : if (IsSurfaceDescriptorValid(mBackBuffer)) {
2525 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
2526 : }
2527 0 : if (mBackBufferY) {
2528 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferY);
2529 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferU);
2530 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBufferV);
2531 : }
2532 0 : }
2533 :
2534 : private:
2535 0 : BasicShadowLayerManager* BasicManager()
2536 : {
2537 0 : return static_cast<BasicShadowLayerManager*>(mManager);
2538 : }
2539 :
2540 : // For YUV Images these are the 3 planes (Y, Cb and Cr),
2541 : // for RGB images only mBackSurface is used.
2542 : SurfaceDescriptor mBackBuffer;
2543 : bool mBufferIsOpaque;
2544 : nsRefPtr<gfxSharedImageSurface> mBackBufferY;
2545 : nsRefPtr<gfxSharedImageSurface> mBackBufferU;
2546 : nsRefPtr<gfxSharedImageSurface> mBackBufferV;
2547 : gfxIntSize mCbCrSize;
2548 : };
2549 :
2550 : void
2551 0 : BasicShadowableImageLayer::Paint(gfxContext* aContext)
2552 : {
2553 0 : if (!HasShadow()) {
2554 0 : BasicImageLayer::Paint(aContext);
2555 0 : return;
2556 : }
2557 :
2558 0 : if (!mContainer) {
2559 0 : return;
2560 : }
2561 :
2562 0 : AutoLockImage autoLock(mContainer);
2563 :
2564 0 : Image *image = autoLock.GetImage();
2565 :
2566 0 : if (!image) {
2567 : return;
2568 : }
2569 :
2570 0 : if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
2571 0 : PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
2572 0 : const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
2573 0 : NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
2574 :
2575 0 : if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !mBackBufferY) {
2576 0 : DestroyBackBuffer();
2577 0 : mSize = data->mYSize;
2578 0 : mCbCrSize = data->mCbCrSize;
2579 :
2580 0 : if (!BasicManager()->AllocBuffer(mSize, gfxASurface::CONTENT_ALPHA,
2581 0 : getter_AddRefs(mBackBufferY)) ||
2582 0 : !BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA,
2583 0 : getter_AddRefs(mBackBufferU)) ||
2584 0 : !BasicManager()->AllocBuffer(mCbCrSize, gfxASurface::CONTENT_ALPHA,
2585 0 : getter_AddRefs(mBackBufferV))) {
2586 0 : NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
2587 : }
2588 : }
2589 :
2590 0 : for (int i = 0; i < data->mYSize.height; i++) {
2591 0 : memcpy(mBackBufferY->Data() + i * mBackBufferY->Stride(),
2592 : data->mYChannel + i * data->mYStride,
2593 0 : data->mYSize.width);
2594 : }
2595 0 : for (int i = 0; i < data->mCbCrSize.height; i++) {
2596 0 : memcpy(mBackBufferU->Data() + i * mBackBufferU->Stride(),
2597 : data->mCbChannel + i * data->mCbCrStride,
2598 0 : data->mCbCrSize.width);
2599 0 : memcpy(mBackBufferV->Data() + i * mBackBufferV->Stride(),
2600 : data->mCrChannel + i * data->mCbCrStride,
2601 0 : data->mCbCrSize.width);
2602 : }
2603 :
2604 0 : YUVImage yuv(mBackBufferY->GetShmem(),
2605 0 : mBackBufferU->GetShmem(),
2606 0 : mBackBufferV->GetShmem(),
2607 0 : data->GetPictureRect());
2608 :
2609 0 : BasicManager()->PaintedImage(BasicManager()->Hold(this),
2610 0 : yuv);
2611 : return;
2612 : }
2613 :
2614 0 : gfxIntSize oldSize = mSize;
2615 0 : nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
2616 0 : if (!pat || !HasShadow())
2617 : return;
2618 :
2619 0 : bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
2620 0 : if (oldSize != mSize ||
2621 0 : !IsSurfaceDescriptorValid(mBackBuffer) ||
2622 : isOpaque != mBufferIsOpaque) {
2623 0 : DestroyBackBuffer();
2624 0 : mBufferIsOpaque = isOpaque;
2625 :
2626 0 : if (!BasicManager()->AllocBuffer(
2627 : mSize,
2628 : isOpaque ?
2629 : gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
2630 0 : &mBackBuffer))
2631 0 : NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
2632 : }
2633 :
2634 : nsRefPtr<gfxASurface> backSurface =
2635 0 : BasicManager()->OpenDescriptor(mBackBuffer);
2636 0 : nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
2637 0 : tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
2638 : PaintContext(pat,
2639 0 : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
2640 0 : nsnull, 1.0, tmpCtx);
2641 :
2642 0 : BasicManager()->PaintedImage(BasicManager()->Hold(this),
2643 0 : mBackBuffer);
2644 : }
2645 :
2646 :
2647 : class BasicShadowableColorLayer : public BasicColorLayer,
2648 : public BasicShadowableLayer
2649 : {
2650 : public:
2651 0 : BasicShadowableColorLayer(BasicShadowLayerManager* aManager) :
2652 0 : BasicColorLayer(aManager)
2653 : {
2654 0 : MOZ_COUNT_CTOR(BasicShadowableColorLayer);
2655 0 : }
2656 0 : virtual ~BasicShadowableColorLayer()
2657 0 : {
2658 0 : MOZ_COUNT_DTOR(BasicShadowableColorLayer);
2659 0 : }
2660 :
2661 0 : virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
2662 : {
2663 0 : aAttrs = ColorLayerAttributes(GetColor());
2664 0 : }
2665 :
2666 0 : virtual Layer* AsLayer() { return this; }
2667 0 : virtual ShadowableLayer* AsShadowableLayer() { return this; }
2668 :
2669 0 : virtual void Disconnect()
2670 : {
2671 0 : BasicShadowableLayer::Disconnect();
2672 0 : }
2673 : };
2674 :
2675 : class BasicShadowableCanvasLayer : public BasicCanvasLayer,
2676 : public BasicShadowableLayer
2677 : {
2678 : public:
2679 0 : BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
2680 : BasicCanvasLayer(aManager),
2681 0 : mBufferIsOpaque(false)
2682 : {
2683 0 : MOZ_COUNT_CTOR(BasicShadowableCanvasLayer);
2684 0 : }
2685 0 : virtual ~BasicShadowableCanvasLayer()
2686 0 : {
2687 0 : DestroyBackBuffer();
2688 0 : MOZ_COUNT_DTOR(BasicShadowableCanvasLayer);
2689 0 : }
2690 :
2691 : virtual void Initialize(const Data& aData);
2692 : virtual void Paint(gfxContext* aContext);
2693 :
2694 0 : virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
2695 : {
2696 0 : aAttrs = CanvasLayerAttributes(mFilter);
2697 0 : }
2698 :
2699 0 : virtual Layer* AsLayer() { return this; }
2700 0 : virtual ShadowableLayer* AsShadowableLayer() { return this; }
2701 :
2702 0 : virtual void SetBackBuffer(const SurfaceDescriptor& aBuffer)
2703 : {
2704 0 : mBackBuffer = aBuffer;
2705 0 : }
2706 :
2707 0 : virtual void Disconnect()
2708 : {
2709 0 : mBackBuffer = SurfaceDescriptor();
2710 0 : BasicShadowableLayer::Disconnect();
2711 0 : }
2712 :
2713 0 : void DestroyBackBuffer()
2714 : {
2715 0 : if (IsSurfaceDescriptorValid(mBackBuffer)) {
2716 0 : BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
2717 0 : mBackBuffer = SurfaceDescriptor();
2718 : }
2719 0 : }
2720 :
2721 : private:
2722 0 : BasicShadowLayerManager* BasicManager()
2723 : {
2724 0 : return static_cast<BasicShadowLayerManager*>(mManager);
2725 : }
2726 :
2727 : SurfaceDescriptor mBackBuffer;
2728 : bool mBufferIsOpaque;
2729 : };
2730 :
2731 : void
2732 0 : BasicShadowableCanvasLayer::Initialize(const Data& aData)
2733 : {
2734 0 : BasicCanvasLayer::Initialize(aData);
2735 0 : if (!HasShadow())
2736 0 : return;
2737 :
2738 : // XXX won't get here currently; need to figure out what to do on
2739 : // canvas resizes
2740 :
2741 0 : if (IsSurfaceDescriptorValid(mBackBuffer)) {
2742 : nsRefPtr<gfxASurface> backSurface =
2743 0 : BasicManager()->OpenDescriptor(mBackBuffer);
2744 0 : if (gfxIntSize(mBounds.width, mBounds.height) != backSurface->GetSize()) {
2745 0 : DestroyBackBuffer();
2746 : }
2747 : }
2748 : }
2749 :
2750 : void
2751 0 : BasicShadowableCanvasLayer::Paint(gfxContext* aContext)
2752 : {
2753 0 : if (!HasShadow()) {
2754 0 : BasicCanvasLayer::Paint(aContext);
2755 0 : return;
2756 : }
2757 :
2758 0 : bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
2759 0 : if (!IsSurfaceDescriptorValid(mBackBuffer) ||
2760 : isOpaque != mBufferIsOpaque) {
2761 0 : DestroyBackBuffer();
2762 0 : mBufferIsOpaque = isOpaque;
2763 0 : if (!BasicManager()->AllocBuffer(
2764 : gfxIntSize(mBounds.width, mBounds.height),
2765 : isOpaque ?
2766 : gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
2767 0 : &mBackBuffer))
2768 0 : NS_RUNTIMEABORT("creating CanvasLayer back buffer failed!");
2769 : }
2770 :
2771 : nsRefPtr<gfxASurface> backSurface =
2772 0 : BasicManager()->OpenDescriptor(mBackBuffer);
2773 :
2774 0 : UpdateSurface(backSurface);
2775 0 : FireDidTransactionCallback();
2776 :
2777 0 : BasicManager()->PaintedCanvas(BasicManager()->Hold(this),
2778 : mNeedsYFlip ? true : false,
2779 0 : mBackBuffer);
2780 : }
2781 :
2782 : class ShadowThebesLayerBuffer : public BasicThebesLayerBuffer
2783 : {
2784 : typedef BasicThebesLayerBuffer Base;
2785 :
2786 : public:
2787 0 : ShadowThebesLayerBuffer()
2788 0 : : Base(NULL)
2789 : {
2790 0 : MOZ_COUNT_CTOR(ShadowThebesLayerBuffer);
2791 0 : }
2792 :
2793 0 : ~ShadowThebesLayerBuffer()
2794 0 : {
2795 0 : MOZ_COUNT_DTOR(ShadowThebesLayerBuffer);
2796 0 : }
2797 :
2798 0 : void Swap(gfxASurface* aNewBuffer,
2799 : const nsIntRect& aNewRect, const nsIntPoint& aNewRotation,
2800 : gfxASurface** aOldBuffer,
2801 : nsIntRect* aOldRect, nsIntPoint* aOldRotation)
2802 : {
2803 0 : *aOldRect = BufferRect();
2804 0 : *aOldRotation = BufferRotation();
2805 :
2806 0 : nsRefPtr<gfxASurface> oldBuffer;
2807 : oldBuffer = SetBuffer(aNewBuffer,
2808 0 : aNewRect, aNewRotation);
2809 0 : oldBuffer.forget(aOldBuffer);
2810 0 : }
2811 :
2812 : protected:
2813 : virtual already_AddRefed<gfxASurface>
2814 0 : CreateBuffer(ContentType, const nsIntSize&, PRUint32)
2815 : {
2816 0 : NS_RUNTIMEABORT("ShadowThebesLayer can't paint content");
2817 0 : return nsnull;
2818 : }
2819 : };
2820 :
2821 :
2822 : class BasicShadowThebesLayer : public ShadowThebesLayer, public BasicImplData {
2823 : public:
2824 0 : BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager)
2825 0 : : ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
2826 : {
2827 0 : MOZ_COUNT_CTOR(BasicShadowThebesLayer);
2828 0 : }
2829 0 : virtual ~BasicShadowThebesLayer()
2830 0 : {
2831 : // If Disconnect() wasn't called on us, then we assume that the
2832 : // remote side shut down and IPC is disconnected, so we let IPDL
2833 : // clean up our front surface Shmem.
2834 0 : MOZ_COUNT_DTOR(BasicShadowThebesLayer);
2835 0 : }
2836 :
2837 0 : virtual void SetValidRegion(const nsIntRegion& aRegion)
2838 : {
2839 0 : mOldValidRegion = mValidRegion;
2840 0 : ShadowThebesLayer::SetValidRegion(aRegion);
2841 0 : }
2842 :
2843 0 : virtual void Disconnect()
2844 : {
2845 0 : DestroyFrontBuffer();
2846 0 : ShadowThebesLayer::Disconnect();
2847 0 : }
2848 :
2849 : virtual void
2850 : Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
2851 : OptionalThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
2852 : OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
2853 :
2854 0 : virtual void DestroyFrontBuffer()
2855 : {
2856 0 : mFrontBuffer.Clear();
2857 0 : mValidRegion.SetEmpty();
2858 0 : mOldValidRegion.SetEmpty();
2859 :
2860 0 : if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
2861 0 : mAllocator->DestroySharedSurface(&mFrontBufferDescriptor);
2862 : }
2863 0 : }
2864 :
2865 : virtual void PaintThebes(gfxContext* aContext,
2866 : LayerManager::DrawThebesLayerCallback aCallback,
2867 : void* aCallbackData,
2868 : ReadbackProcessor* aReadback);
2869 :
2870 : private:
2871 0 : BasicShadowLayerManager* BasicManager()
2872 : {
2873 0 : return static_cast<BasicShadowLayerManager*>(mManager);
2874 : }
2875 :
2876 : ShadowThebesLayerBuffer mFrontBuffer;
2877 : // Describes the gfxASurface we hand out to |mFrontBuffer|.
2878 : SurfaceDescriptor mFrontBufferDescriptor;
2879 : // When we receive an update from our remote partner, we stow away
2880 : // our previous parameters that described our previous front buffer.
2881 : // Then when we Swap() back/front buffers, we can return these
2882 : // parameters to our partner (adjusted as needed).
2883 : nsIntRegion mOldValidRegion;
2884 : };
2885 :
2886 : void
2887 0 : BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
2888 : const nsIntRegion& aUpdatedRegion,
2889 : OptionalThebesBuffer* aNewBack,
2890 : nsIntRegion* aNewBackValidRegion,
2891 : OptionalThebesBuffer* aReadOnlyFront,
2892 : nsIntRegion* aFrontUpdatedRegion)
2893 : {
2894 : nsRefPtr<gfxASurface> newFrontBuffer =
2895 0 : BasicManager()->OpenDescriptor(aNewFront.buffer());
2896 :
2897 0 : if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
2898 0 : nsRefPtr<gfxASurface> currentFront = BasicManager()->OpenDescriptor(mFrontBufferDescriptor);
2899 0 : if (currentFront->GetSize() != newFrontBuffer->GetSize()) {
2900 : // Current front buffer is obsolete
2901 0 : DestroyFrontBuffer();
2902 : }
2903 : }
2904 : // This code relies on Swap() arriving *after* attribute mutations.
2905 0 : if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
2906 0 : *aNewBack = ThebesBuffer();
2907 0 : aNewBack->get_ThebesBuffer().buffer() = mFrontBufferDescriptor;
2908 : } else {
2909 0 : *aNewBack = null_t();
2910 : }
2911 : // We have to invalidate the pixels painted into the new buffer.
2912 : // They might overlap with our old pixels.
2913 0 : aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
2914 :
2915 0 : nsRefPtr<gfxASurface> unused;
2916 0 : nsIntRect backRect;
2917 0 : nsIntPoint backRotation;
2918 : mFrontBuffer.Swap(
2919 0 : newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
2920 0 : getter_AddRefs(unused), &backRect, &backRotation);
2921 :
2922 0 : if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
2923 0 : aNewBack->get_ThebesBuffer().rect() = backRect;
2924 0 : aNewBack->get_ThebesBuffer().rotation() = backRotation;
2925 : }
2926 :
2927 0 : mFrontBufferDescriptor = aNewFront.buffer();
2928 :
2929 0 : *aReadOnlyFront = aNewFront;
2930 0 : *aFrontUpdatedRegion = aUpdatedRegion;
2931 0 : }
2932 :
2933 : void
2934 0 : BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
2935 : LayerManager::DrawThebesLayerCallback aCallback,
2936 : void* aCallbackData,
2937 : ReadbackProcessor* aReadback)
2938 : {
2939 0 : NS_ASSERTION(BasicManager()->InDrawing(),
2940 : "Can only draw in drawing phase");
2941 0 : NS_ASSERTION(BasicManager()->IsRetained(),
2942 : "ShadowThebesLayer makes no sense without retained mode");
2943 :
2944 0 : if (!mFrontBuffer.GetBuffer()) {
2945 0 : return;
2946 : }
2947 :
2948 0 : mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity());
2949 : }
2950 :
2951 : class BasicShadowContainerLayer : public ShadowContainerLayer, public BasicImplData {
2952 : template<class Container>
2953 : friend void ContainerInsertAfter(Layer* aChild, Layer* aAfter, Container* aContainer);
2954 : template<class Container>
2955 : friend void ContainerRemoveChild(Layer* aChild, Container* aContainer);
2956 :
2957 : public:
2958 0 : BasicShadowContainerLayer(BasicShadowLayerManager* aLayerManager) :
2959 0 : ShadowContainerLayer(aLayerManager, static_cast<BasicImplData*>(this))
2960 : {
2961 0 : MOZ_COUNT_CTOR(BasicShadowContainerLayer);
2962 0 : }
2963 0 : virtual ~BasicShadowContainerLayer()
2964 0 : {
2965 0 : while (mFirstChild) {
2966 0 : ContainerRemoveChild(mFirstChild, this);
2967 : }
2968 :
2969 0 : MOZ_COUNT_DTOR(BasicShadowContainerLayer);
2970 0 : }
2971 :
2972 0 : virtual void InsertAfter(Layer* aChild, Layer* aAfter)
2973 0 : { ContainerInsertAfter(aChild, aAfter, this); }
2974 0 : virtual void RemoveChild(Layer* aChild)
2975 0 : { ContainerRemoveChild(aChild, this); }
2976 :
2977 0 : virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
2978 : {
2979 : // We push groups for container layers if we need to, which always
2980 : // are aligned in device space, so it doesn't really matter how we snap
2981 : // containers.
2982 0 : gfxMatrix residual;
2983 0 : gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface;
2984 0 : idealTransform.ProjectTo2D();
2985 :
2986 0 : if (!idealTransform.CanDraw2D()) {
2987 0 : mEffectiveTransform = idealTransform;
2988 0 : ComputeEffectiveTransformsForChildren(gfx3DMatrix());
2989 0 : mUseIntermediateSurface = true;
2990 0 : return;
2991 : }
2992 :
2993 0 : mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual);
2994 : // We always pass the ideal matrix down to our children, so there is no
2995 : // need to apply any compensation using the residual from SnapTransform.
2996 0 : ComputeEffectiveTransformsForChildren(idealTransform);
2997 :
2998 : /* If we have a single child, it can just inherit our opacity,
2999 : * otherwise we need a PushGroup and we need to mark ourselves as using
3000 : * an intermediate surface so our children don't inherit our opacity
3001 : * via GetEffectiveOpacity.
3002 : */
3003 0 : mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren();
3004 : }
3005 : };
3006 :
3007 : class BasicShadowImageLayer : public ShadowImageLayer, public BasicImplData {
3008 : public:
3009 0 : BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
3010 0 : ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
3011 : {
3012 0 : MOZ_COUNT_CTOR(BasicShadowImageLayer);
3013 0 : }
3014 0 : virtual ~BasicShadowImageLayer()
3015 0 : {
3016 0 : MOZ_COUNT_DTOR(BasicShadowImageLayer);
3017 0 : }
3018 :
3019 0 : virtual void Disconnect()
3020 : {
3021 0 : DestroyFrontBuffer();
3022 0 : ShadowImageLayer::Disconnect();
3023 0 : }
3024 :
3025 : virtual void Swap(const SharedImage& aNewFront,
3026 : SharedImage* aNewBack);
3027 :
3028 0 : virtual void DestroyFrontBuffer()
3029 : {
3030 0 : if (mAllocator && IsSurfaceDescriptorValid(mFrontBuffer)) {
3031 0 : mAllocator->DestroySharedSurface(&mFrontBuffer);
3032 : }
3033 0 : }
3034 :
3035 : virtual void Paint(gfxContext* aContext);
3036 :
3037 : protected:
3038 0 : BasicShadowLayerManager* BasicManager()
3039 : {
3040 0 : return static_cast<BasicShadowLayerManager*>(mManager);
3041 : }
3042 :
3043 : SurfaceDescriptor mFrontBuffer;
3044 : gfxIntSize mSize;
3045 : };
3046 :
3047 : void
3048 0 : BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
3049 : SharedImage* aNewBack)
3050 : {
3051 : nsRefPtr<gfxASurface> surface =
3052 0 : BasicManager()->OpenDescriptor(aNewFront);
3053 : // Destroy mFrontBuffer if size different or image type is different
3054 0 : bool surfaceConfigChanged = surface->GetSize() != mSize;
3055 0 : if (IsSurfaceDescriptorValid(mFrontBuffer)) {
3056 0 : nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontBuffer);
3057 : surfaceConfigChanged = surfaceConfigChanged ||
3058 0 : surface->GetContentType() != front->GetContentType();
3059 : }
3060 0 : if (surfaceConfigChanged) {
3061 0 : DestroyFrontBuffer();
3062 0 : mSize = surface->GetSize();
3063 : }
3064 :
3065 : // If mFrontBuffer
3066 0 : if (IsSurfaceDescriptorValid(mFrontBuffer)) {
3067 0 : *aNewBack = mFrontBuffer;
3068 : } else {
3069 0 : *aNewBack = null_t();
3070 : }
3071 0 : mFrontBuffer = aNewFront.get_SurfaceDescriptor();
3072 0 : }
3073 :
3074 : void
3075 0 : BasicShadowImageLayer::Paint(gfxContext* aContext)
3076 : {
3077 0 : if (!IsSurfaceDescriptorValid(mFrontBuffer)) {
3078 0 : return;
3079 : }
3080 :
3081 : nsRefPtr<gfxASurface> surface =
3082 0 : BasicManager()->OpenDescriptor(mFrontBuffer);
3083 0 : nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
3084 0 : pat->SetFilter(mFilter);
3085 :
3086 : // The visible region can extend outside the image. If we're not
3087 : // tiling, we don't want to draw into that area, so just draw within
3088 : // the image bounds.
3089 0 : const nsIntRect* tileSrcRect = GetTileSourceRect();
3090 0 : AutoSetOperator setOperator(aContext, GetOperator());
3091 : BasicImageLayer::PaintContext(pat,
3092 0 : tileSrcRect ? GetEffectiveVisibleRegion() : nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
3093 : tileSrcRect,
3094 0 : GetEffectiveOpacity(), aContext);
3095 : }
3096 :
3097 : class BasicShadowColorLayer : public ShadowColorLayer,
3098 : public BasicImplData
3099 : {
3100 : public:
3101 0 : BasicShadowColorLayer(BasicShadowLayerManager* aLayerManager) :
3102 0 : ShadowColorLayer(aLayerManager, static_cast<BasicImplData*>(this))
3103 : {
3104 0 : MOZ_COUNT_CTOR(BasicShadowColorLayer);
3105 0 : }
3106 0 : virtual ~BasicShadowColorLayer()
3107 0 : {
3108 0 : MOZ_COUNT_DTOR(BasicShadowColorLayer);
3109 0 : }
3110 :
3111 0 : virtual void Paint(gfxContext* aContext)
3112 : {
3113 0 : AutoSetOperator setOperator(aContext, GetOperator());
3114 0 : BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext);
3115 0 : }
3116 : };
3117 :
3118 : class BasicShadowCanvasLayer : public ShadowCanvasLayer,
3119 : public BasicImplData
3120 : {
3121 : public:
3122 0 : BasicShadowCanvasLayer(BasicShadowLayerManager* aLayerManager) :
3123 0 : ShadowCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
3124 : {
3125 0 : MOZ_COUNT_CTOR(BasicShadowCanvasLayer);
3126 0 : }
3127 0 : virtual ~BasicShadowCanvasLayer()
3128 0 : {
3129 0 : MOZ_COUNT_DTOR(BasicShadowCanvasLayer);
3130 0 : }
3131 :
3132 0 : virtual void Disconnect()
3133 : {
3134 0 : DestroyFrontBuffer();
3135 0 : ShadowCanvasLayer::Disconnect();
3136 0 : }
3137 :
3138 : virtual void Initialize(const Data& aData);
3139 : void Swap(const CanvasSurface& aNewFront, bool needYFlip, CanvasSurface* aNewBack);
3140 :
3141 0 : virtual void DestroyFrontBuffer()
3142 : {
3143 0 : if (IsSurfaceDescriptorValid(mFrontSurface)) {
3144 0 : mAllocator->DestroySharedSurface(&mFrontSurface);
3145 : }
3146 0 : }
3147 :
3148 : virtual void Paint(gfxContext* aContext);
3149 :
3150 : private:
3151 0 : BasicShadowLayerManager* BasicManager()
3152 : {
3153 0 : return static_cast<BasicShadowLayerManager*>(mManager);
3154 : }
3155 :
3156 : SurfaceDescriptor mFrontSurface;
3157 : bool mNeedsYFlip;
3158 : };
3159 :
3160 :
3161 : void
3162 0 : BasicShadowCanvasLayer::Initialize(const Data& aData)
3163 : {
3164 0 : NS_RUNTIMEABORT("Incompatibe surface type");
3165 0 : }
3166 :
3167 : void
3168 0 : BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
3169 : CanvasSurface* aNewBack)
3170 : {
3171 : nsRefPtr<gfxASurface> surface =
3172 0 : BasicManager()->OpenDescriptor(aNewFront);
3173 : // Destroy mFrontBuffer if size different
3174 0 : gfxIntSize sz = surface->GetSize();
3175 0 : bool surfaceConfigChanged = sz != gfxIntSize(mBounds.width, mBounds.height);
3176 0 : if (IsSurfaceDescriptorValid(mFrontSurface)) {
3177 0 : nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontSurface);
3178 : surfaceConfigChanged = surfaceConfigChanged ||
3179 0 : surface->GetContentType() != front->GetContentType();
3180 : }
3181 0 : if (surfaceConfigChanged) {
3182 0 : DestroyFrontBuffer();
3183 0 : mBounds.SetRect(0, 0, sz.width, sz.height);
3184 : }
3185 :
3186 0 : mNeedsYFlip = needYFlip;
3187 : // If mFrontBuffer
3188 0 : if (IsSurfaceDescriptorValid(mFrontSurface)) {
3189 0 : *aNewBack = mFrontSurface;
3190 : } else {
3191 0 : *aNewBack = null_t();
3192 : }
3193 0 : mFrontSurface = aNewFront.get_SurfaceDescriptor();
3194 0 : }
3195 :
3196 : void
3197 0 : BasicShadowCanvasLayer::Paint(gfxContext* aContext)
3198 : {
3199 0 : NS_ASSERTION(BasicManager()->InDrawing(),
3200 : "Can only draw in drawing phase");
3201 :
3202 0 : if (!IsSurfaceDescriptorValid(mFrontSurface)) {
3203 0 : return;
3204 : }
3205 :
3206 : nsRefPtr<gfxASurface> surface =
3207 0 : BasicManager()->OpenDescriptor(mFrontSurface);
3208 0 : nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
3209 :
3210 0 : pat->SetFilter(mFilter);
3211 0 : pat->SetExtend(gfxPattern::EXTEND_PAD);
3212 :
3213 0 : gfxRect r(0, 0, mBounds.width, mBounds.height);
3214 :
3215 0 : gfxMatrix m;
3216 0 : if (mNeedsYFlip) {
3217 0 : m = aContext->CurrentMatrix();
3218 0 : aContext->Translate(gfxPoint(0.0, mBounds.height));
3219 0 : aContext->Scale(1.0, -1.0);
3220 : }
3221 :
3222 0 : AutoSetOperator setOperator(aContext, GetOperator());
3223 0 : aContext->NewPath();
3224 : // No need to snap here; our transform has already taken care of it
3225 0 : aContext->Rectangle(r);
3226 0 : aContext->SetPattern(pat);
3227 0 : aContext->FillWithOpacity(GetEffectiveOpacity());
3228 :
3229 0 : if (mNeedsYFlip) {
3230 0 : aContext->SetMatrix(m);
3231 : }
3232 : }
3233 :
3234 : // Create a shadow layer (PLayerChild) for aLayer, if we're forwarding
3235 : // our layer tree to a parent process. Record the new layer creation
3236 : // in the current open transaction as a side effect.
3237 : template<typename CreatedMethod>
3238 : static void
3239 0 : MaybeCreateShadowFor(BasicShadowableLayer* aLayer,
3240 : BasicShadowLayerManager* aMgr,
3241 : CreatedMethod aMethod)
3242 : {
3243 0 : if (!aMgr->HasShadowManager()) {
3244 0 : return;
3245 : }
3246 :
3247 0 : PLayerChild* shadow = aMgr->ConstructShadowFor(aLayer);
3248 : // XXX error handling
3249 0 : NS_ABORT_IF_FALSE(shadow, "failed to create shadow");
3250 :
3251 0 : aLayer->SetShadow(shadow);
3252 0 : (aMgr->*aMethod)(aLayer);
3253 0 : aMgr->Hold(aLayer->AsLayer());
3254 : }
3255 : #define MAYBE_CREATE_SHADOW(_type) \
3256 : MaybeCreateShadowFor(layer, this, \
3257 : &ShadowLayerForwarder::Created ## _type ## Layer)
3258 :
3259 : already_AddRefed<ThebesLayer>
3260 0 : BasicShadowLayerManager::CreateThebesLayer()
3261 : {
3262 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3263 : nsRefPtr<BasicShadowableThebesLayer> layer =
3264 0 : new BasicShadowableThebesLayer(this);
3265 0 : MAYBE_CREATE_SHADOW(Thebes);
3266 0 : return layer.forget();
3267 : }
3268 :
3269 : already_AddRefed<ContainerLayer>
3270 0 : BasicShadowLayerManager::CreateContainerLayer()
3271 : {
3272 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3273 : nsRefPtr<BasicShadowableContainerLayer> layer =
3274 0 : new BasicShadowableContainerLayer(this);
3275 0 : MAYBE_CREATE_SHADOW(Container);
3276 0 : return layer.forget();
3277 : }
3278 :
3279 : already_AddRefed<ImageLayer>
3280 0 : BasicShadowLayerManager::CreateImageLayer()
3281 : {
3282 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3283 : nsRefPtr<BasicShadowableImageLayer> layer =
3284 0 : new BasicShadowableImageLayer(this);
3285 0 : MAYBE_CREATE_SHADOW(Image);
3286 0 : return layer.forget();
3287 : }
3288 :
3289 : already_AddRefed<ColorLayer>
3290 0 : BasicShadowLayerManager::CreateColorLayer()
3291 : {
3292 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3293 : nsRefPtr<BasicShadowableColorLayer> layer =
3294 0 : new BasicShadowableColorLayer(this);
3295 0 : MAYBE_CREATE_SHADOW(Color);
3296 0 : return layer.forget();
3297 : }
3298 :
3299 : already_AddRefed<CanvasLayer>
3300 0 : BasicShadowLayerManager::CreateCanvasLayer()
3301 : {
3302 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3303 : nsRefPtr<BasicShadowableCanvasLayer> layer =
3304 0 : new BasicShadowableCanvasLayer(this);
3305 0 : MAYBE_CREATE_SHADOW(Canvas);
3306 0 : return layer.forget();
3307 : }
3308 : already_AddRefed<ShadowThebesLayer>
3309 0 : BasicShadowLayerManager::CreateShadowThebesLayer()
3310 : {
3311 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3312 0 : nsRefPtr<ShadowThebesLayer> layer = new BasicShadowThebesLayer(this);
3313 0 : return layer.forget();
3314 : }
3315 :
3316 : already_AddRefed<ShadowContainerLayer>
3317 0 : BasicShadowLayerManager::CreateShadowContainerLayer()
3318 : {
3319 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3320 0 : nsRefPtr<ShadowContainerLayer> layer = new BasicShadowContainerLayer(this);
3321 0 : return layer.forget();
3322 : }
3323 :
3324 : already_AddRefed<ShadowImageLayer>
3325 0 : BasicShadowLayerManager::CreateShadowImageLayer()
3326 : {
3327 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3328 0 : nsRefPtr<ShadowImageLayer> layer = new BasicShadowImageLayer(this);
3329 0 : return layer.forget();
3330 : }
3331 :
3332 : already_AddRefed<ShadowColorLayer>
3333 0 : BasicShadowLayerManager::CreateShadowColorLayer()
3334 : {
3335 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3336 0 : nsRefPtr<ShadowColorLayer> layer = new BasicShadowColorLayer(this);
3337 0 : return layer.forget();
3338 : }
3339 :
3340 : already_AddRefed<ShadowCanvasLayer>
3341 0 : BasicShadowLayerManager::CreateShadowCanvasLayer()
3342 : {
3343 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
3344 0 : nsRefPtr<ShadowCanvasLayer> layer = new BasicShadowCanvasLayer(this);
3345 0 : return layer.forget();
3346 : }
3347 :
3348 0 : BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
3349 0 : BasicLayerManager(aWidget)
3350 : {
3351 0 : MOZ_COUNT_CTOR(BasicShadowLayerManager);
3352 0 : }
3353 :
3354 0 : BasicShadowLayerManager::~BasicShadowLayerManager()
3355 : {
3356 0 : MOZ_COUNT_DTOR(BasicShadowLayerManager);
3357 0 : }
3358 :
3359 : void
3360 0 : BasicShadowLayerManager::SetRoot(Layer* aLayer)
3361 : {
3362 0 : if (mRoot != aLayer) {
3363 0 : if (HasShadowManager()) {
3364 : // Have to hold the old root and its children in order to
3365 : // maintain the same view of the layer tree in this process as
3366 : // the parent sees. Otherwise layers can be destroyed
3367 : // mid-transaction and bad things can happen (v. bug 612573)
3368 0 : if (mRoot) {
3369 0 : Hold(mRoot);
3370 : }
3371 0 : ShadowLayerForwarder::SetRoot(Hold(aLayer));
3372 : }
3373 0 : BasicLayerManager::SetRoot(aLayer);
3374 : }
3375 0 : }
3376 :
3377 : void
3378 0 : BasicShadowLayerManager::Mutated(Layer* aLayer)
3379 : {
3380 0 : BasicLayerManager::Mutated(aLayer);
3381 :
3382 0 : NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
3383 0 : if (HasShadowManager() && ShouldShadow(aLayer)) {
3384 0 : ShadowLayerForwarder::Mutated(Hold(aLayer));
3385 : }
3386 0 : }
3387 :
3388 : void
3389 0 : BasicShadowLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
3390 : {
3391 0 : NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
3392 : // If the last transaction was incomplete (a failed DoEmptyTransaction),
3393 : // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
3394 : // to the previous transaction.
3395 0 : if (HasShadowManager()) {
3396 0 : ShadowLayerForwarder::BeginTransaction();
3397 : }
3398 0 : BasicLayerManager::BeginTransactionWithTarget(aTarget);
3399 0 : }
3400 :
3401 : void
3402 0 : BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
3403 : void* aCallbackData,
3404 : EndTransactionFlags aFlags)
3405 : {
3406 0 : BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
3407 0 : ForwardTransaction();
3408 0 : }
3409 :
3410 : bool
3411 0 : BasicShadowLayerManager::EndEmptyTransaction()
3412 : {
3413 0 : if (!BasicLayerManager::EndEmptyTransaction()) {
3414 : // Return without calling ForwardTransaction. This leaves the
3415 : // ShadowLayerForwarder transaction open; the following
3416 : // EndTransaction will complete it.
3417 0 : return false;
3418 : }
3419 0 : ForwardTransaction();
3420 0 : return true;
3421 : }
3422 :
3423 : void
3424 0 : BasicShadowLayerManager::ForwardTransaction()
3425 : {
3426 : #ifdef DEBUG
3427 0 : mPhase = PHASE_FORWARD;
3428 : #endif
3429 :
3430 : // forward this transaction's changeset to our ShadowLayerManager
3431 0 : AutoInfallibleTArray<EditReply, 10> replies;
3432 0 : if (HasShadowManager() && ShadowLayerForwarder::EndTransaction(&replies)) {
3433 0 : for (nsTArray<EditReply>::size_type i = 0; i < replies.Length(); ++i) {
3434 0 : const EditReply& reply = replies[i];
3435 :
3436 0 : switch (reply.type()) {
3437 : case EditReply::TOpThebesBufferSwap: {
3438 0 : MOZ_LAYERS_LOG(("[LayersForwarder] ThebesBufferSwap"));
3439 :
3440 0 : const OpThebesBufferSwap& obs = reply.get_OpThebesBufferSwap();
3441 0 : BasicShadowableThebesLayer* thebes = GetBasicShadowable(obs)->AsThebes();
3442 : thebes->SetBackBufferAndAttrs(
3443 0 : obs.newBackBuffer(), obs.newValidRegion(),
3444 0 : obs.readOnlyFrontBuffer(), obs.frontUpdatedRegion());
3445 0 : break;
3446 : }
3447 : case EditReply::TOpBufferSwap: {
3448 0 : MOZ_LAYERS_LOG(("[LayersForwarder] BufferSwap"));
3449 :
3450 0 : const OpBufferSwap& obs = reply.get_OpBufferSwap();
3451 0 : const CanvasSurface& newBack = obs.newBackBuffer();
3452 0 : if (newBack.type() == CanvasSurface::TSurfaceDescriptor) {
3453 0 : GetBasicShadowable(obs)->SetBackBuffer(newBack.get_SurfaceDescriptor());
3454 0 : } else if (newBack.type() == CanvasSurface::Tnull_t) {
3455 0 : GetBasicShadowable(obs)->SetBackBuffer(SurfaceDescriptor());
3456 : } else {
3457 0 : NS_RUNTIMEABORT("Unknown back image type");
3458 : }
3459 0 : break;
3460 : }
3461 :
3462 : case EditReply::TOpImageSwap: {
3463 0 : MOZ_LAYERS_LOG(("[LayersForwarder] YUVBufferSwap"));
3464 :
3465 0 : const OpImageSwap& ois = reply.get_OpImageSwap();
3466 0 : BasicShadowableLayer* layer = GetBasicShadowable(ois);
3467 0 : const SharedImage& newBack = ois.newBackImage();
3468 :
3469 0 : if (newBack.type() == SharedImage::TSurfaceDescriptor) {
3470 0 : layer->SetBackBuffer(newBack.get_SurfaceDescriptor());
3471 0 : } else if (newBack.type() == SharedImage::TYUVImage) {
3472 0 : const YUVImage& yuv = newBack.get_YUVImage();
3473 0 : nsRefPtr<gfxSharedImageSurface> YSurf = gfxSharedImageSurface::Open(yuv.Ydata());
3474 0 : nsRefPtr<gfxSharedImageSurface> USurf = gfxSharedImageSurface::Open(yuv.Udata());
3475 0 : nsRefPtr<gfxSharedImageSurface> VSurf = gfxSharedImageSurface::Open(yuv.Vdata());
3476 0 : layer->SetBackBufferYUVImage(YSurf, USurf, VSurf);
3477 : } else {
3478 0 : layer->SetBackBuffer(SurfaceDescriptor());
3479 0 : layer->SetBackBufferYUVImage(nsnull, nsnull, nsnull);
3480 : }
3481 :
3482 0 : break;
3483 : }
3484 :
3485 : default:
3486 0 : NS_RUNTIMEABORT("not reached");
3487 : }
3488 : }
3489 0 : } else if (HasShadowManager()) {
3490 0 : NS_WARNING("failed to forward Layers transaction");
3491 : }
3492 :
3493 : #ifdef DEBUG
3494 0 : mPhase = PHASE_NONE;
3495 : #endif
3496 :
3497 : // this may result in Layers being deleted, which results in
3498 : // PLayer::Send__delete__() and DeallocShmem()
3499 0 : mKeepAlive.Clear();
3500 0 : }
3501 :
3502 : ShadowableLayer*
3503 0 : BasicShadowLayerManager::Hold(Layer* aLayer)
3504 : {
3505 0 : NS_ABORT_IF_FALSE(HasShadowManager(),
3506 : "top-level tree, no shadow tree to remote to");
3507 :
3508 0 : ShadowableLayer* shadowable = ToShadowable(aLayer);
3509 0 : NS_ABORT_IF_FALSE(shadowable, "trying to remote an unshadowable layer");
3510 :
3511 0 : mKeepAlive.AppendElement(aLayer);
3512 0 : return shadowable;
3513 : }
3514 :
3515 : bool
3516 0 : BasicShadowLayerManager::IsCompositingCheap()
3517 : {
3518 : // Whether compositing is cheap depends on the parent backend.
3519 : return mShadowManager &&
3520 0 : LayerManager::IsCompositingCheap(GetParentBackendType());
3521 : }
3522 :
3523 : }
3524 : }
|