diff --git a/gfx/layers/ImageLayers.h b/gfx/layers/ImageLayers.h index 1e391c5dde25..c3e8e404e1ab 100644 --- a/gfx/layers/ImageLayers.h +++ b/gfx/layers/ImageLayers.h @@ -207,6 +207,23 @@ public: MOZ_LAYER_DECL_NAME("ImageLayer", TYPE_IMAGE) + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + // Snap image edges to pixel boundaries + gfxRect snap(0, 0, 0, 0); + if (mContainer) { + gfxIntSize size = mContainer->GetCurrentSize(); + snap.size = gfxSize(size.width, size.height); + } + // Snap our local transform first, and snap the inherited transform as well. + // This makes our snapping equivalent to what would happen if our content + // was drawn into a ThebesLayer (gfxContext would snap using the local + // transform, then we'd snap again when compositing the ThebesLayer). + mEffectiveTransform = + SnapTransform(GetLocalTransform(), snap, nsnull)* + SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nsnull); + } + protected: ImageLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD) {} diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index 6307600e67d3..e5bba05c5a7d 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -226,23 +226,143 @@ Layer::GetEffectiveVisibleRegion() return GetVisibleRegion(); } -const gfx3DMatrix& -Layer::GetEffectiveTransform() -{ - if (ShadowLayer* shadow = AsShadowLayer()) { - return shadow->GetShadowTransform(); - } - return GetTransform(); -} - #else const nsIntRect* Layer::GetEffectiveClipRect() { return GetClipRect(); } const nsIntRegion& Layer::GetEffectiveVisibleRegion() { return GetVisibleRegion(); } -const gfx3DMatrix& Layer::GetEffectiveTransform() { return GetTransform(); } #endif // MOZ_IPC +gfx3DMatrix +Layer::SnapTransform(const gfx3DMatrix& aTransform, + const gfxRect& aSnapRect, + gfxMatrix* aResidualTransform) +{ + if (aResidualTransform) { + *aResidualTransform = gfxMatrix(); + } + + gfxMatrix matrix2D; + gfx3DMatrix result; + if (mManager->IsSnappingEffectiveTransforms() && + aTransform.Is2D(&matrix2D) && + matrix2D.HasNonIntegerTranslation() && + !matrix2D.IsSingular() && + !matrix2D.HasNonAxisAlignedTransform()) { + gfxMatrix snappedMatrix; + gfxPoint topLeft = matrix2D.Transform(aSnapRect.TopLeft()); + topLeft.Round(); + // first compute scale factors that scale aSnapRect to the snapped rect + if (aSnapRect.IsEmpty()) { + snappedMatrix.xx = matrix2D.xx; + snappedMatrix.yy = matrix2D.yy; + } else { + gfxPoint bottomRight = matrix2D.Transform(aSnapRect.BottomRight()); + bottomRight.Round(); + snappedMatrix.xx = (bottomRight.x - topLeft.x)/aSnapRect.Width(); + snappedMatrix.yy = (bottomRight.y - topLeft.y)/aSnapRect.Height(); + } + // compute translation factors that will move aSnapRect to the snapped rect + // given those scale factors + snappedMatrix.x0 = topLeft.x - aSnapRect.pos.x*snappedMatrix.xx; + snappedMatrix.y0 = topLeft.y - aSnapRect.pos.y*snappedMatrix.yy; + result = gfx3DMatrix::From2D(snappedMatrix); + if (aResidualTransform && !snappedMatrix.IsSingular()) { + // set aResidualTransform so that aResidual * snappedMatrix == matrix2D. + // (i.e., appying snappedMatrix after aResidualTransform gives the + // ideal transform. + gfxMatrix snappedMatrixInverse = snappedMatrix; + snappedMatrixInverse.Invert(); + *aResidualTransform = matrix2D * snappedMatrixInverse; + } + } else { + result = aTransform; + } + return result; +} + +const gfx3DMatrix& +Layer::GetLocalTransform() +{ +#ifdef MOZ_IPC + if (ShadowLayer* shadow = AsShadowLayer()) + return shadow->GetShadowTransform(); +#endif + return mTransform; +} + +float +Layer::GetEffectiveOpacity() +{ + float opacity = GetOpacity(); + for (ContainerLayer* c = GetParent(); c && !c->UseIntermediateSurface(); + c = c->GetParent()) { + opacity *= c->GetOpacity(); + } + return opacity; +} + +PRBool +ContainerLayer::HasMultipleChildren() +{ + PRUint32 count = 0; + for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) { + const nsIntRect *clipRect = child->GetEffectiveClipRect(); + if (clipRect && clipRect->IsEmpty()) + continue; + if (child->GetVisibleRegion().IsEmpty()) + continue; + ++count; + if (count > 1) + return PR_TRUE; + } + + return PR_FALSE; +} + +void +ContainerLayer::DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) +{ + gfxMatrix residual; + gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface; + mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), &residual); + + PRBool useIntermediateSurface; + float opacity = GetEffectiveOpacity(); + if (opacity != 1.0f && HasMultipleChildren()) { + useIntermediateSurface = PR_TRUE; + } else { + useIntermediateSurface = PR_FALSE; + if (!mEffectiveTransform.IsIdentity()) { + for (Layer* child = GetFirstChild(); child; child = child->GetNextSibling()) { + const nsIntRect *clipRect = child->GetEffectiveClipRect(); + /* We can't (easily) forward our transform to children with a non-empty clip + * rect since it would need to be adjusted for the transform. + * TODO: This is easily solvable for translation/scaling transforms. + */ + if (clipRect && !clipRect->IsEmpty() && !child->GetVisibleRegion().IsEmpty()) { + useIntermediateSurface = PR_TRUE; + break; + } + } + } + } + + mUseIntermediateSurface = useIntermediateSurface; + if (useIntermediateSurface) { + ComputeEffectiveTransformsForChildren(gfx3DMatrix::From2D(residual)); + } else { + ComputeEffectiveTransformsForChildren(idealTransform); + } +} + +void +ContainerLayer::ComputeEffectiveTransformsForChildren(const gfx3DMatrix& aTransformToSurface) +{ + for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) { + l->ComputeEffectiveTransforms(aTransformToSurface); + } +} #ifdef MOZ_LAYERS_HAVE_LOG diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 9e522536e2c3..0509e7156073 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -229,7 +229,7 @@ public: LAYERS_D3D10 }; - LayerManager() : mDestroyed(PR_FALSE) + LayerManager() : mDestroyed(PR_FALSE), mSnapEffectiveTransforms(PR_TRUE) { InitLog(); } @@ -300,6 +300,8 @@ public: virtual void EndTransaction(DrawThebesLayerCallback aCallback, void* aCallbackData) = 0; + PRBool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; } + /** * CONSTRUCTION PHASE ONLY * Set the root layer. @@ -425,6 +427,7 @@ protected: nsRefPtr mRoot; LayerUserDataSet mUserData; PRPackedBool mDestroyed; + PRPackedBool mSnapEffectiveTransforms; // Print interesting information about this into aTo. Internally // used to implement Dump*() and Log*(). @@ -655,7 +658,33 @@ public: // accounting for this layer possibly being a shadow. const nsIntRect* GetEffectiveClipRect(); const nsIntRegion& GetEffectiveVisibleRegion(); - const gfx3DMatrix& GetEffectiveTransform(); + /** + * Returns the product of the opacities of this layer and all ancestors up + * to and excluding the nearest ancestor that has UseIntermediateSurface() set. + */ + float GetEffectiveOpacity(); + /** + * This returns the effective transform computed by + * ComputeEffectiveTransforms. Typically this is a transform that transforms + * this layer all the way to some intermediate surface or destination + * surface. For non-BasicLayers this will be a transform to the nearest + * ancestor with UseIntermediateSurface() (or to the root, if there is no + * such ancestor), but for BasicLayers it's different. + */ + const gfx3DMatrix& GetEffectiveTransform() const { return mEffectiveTransform; } + + /** + * @param aTransformToSurface the composition of the transforms + * from the parent layer (if any) to the destination pixel grid. + * + * Computes mEffectiveTransform for this layer and all its descendants. + * mEffectiveTransform transforms this layer up to the destination + * pixel grid (whatever aTransformToSurface is relative to). + * + * We promise that when this is called on a layer, all ancestor layers + * have already had ComputeEffectiveTransforms called. + */ + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) = 0; virtual const char* Name() const =0; virtual LayerType GetType() const =0; @@ -719,6 +748,27 @@ protected: // appends additional info to aTo. virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + /** + * Returns the local transform for this layer: either mTransform or, + * for shadow layers, GetShadowTransform() + */ + const gfx3DMatrix& GetLocalTransform(); + + /** + * Computes a tweaked version of aTransform that snaps a point or a rectangle + * to pixel boundaries. Snapping is only performed if this layer's + * layer manager has enabled snapping (which is the default). + * @param aSnapRect a rectangle whose edges should be snapped to pixel + * boundaries in the destination surface. If the rectangle is empty, + * then the snapping process should preserve the scale factors of the + * transform matrix + * @param aResidualTransform a transform to apply before mEffectiveTransform + * in order to get the results to completely match aTransform + */ + gfx3DMatrix SnapTransform(const gfx3DMatrix& aTransform, + const gfxRect& aSnapRect, + gfxMatrix* aResidualTransform); + LayerManager* mManager; ContainerLayer* mParent; Layer* mNextSibling; @@ -727,6 +777,7 @@ protected: LayerUserDataSet mUserData; nsIntRegion mVisibleRegion; gfx3DMatrix mTransform; + gfx3DMatrix mEffectiveTransform; float mOpacity; nsIntRect mClipRect; PRUint32 mContentFlags; @@ -765,6 +816,13 @@ public: MOZ_LAYER_DECL_NAME("ThebesLayer", TYPE_THEBES) + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + // The default implementation just snaps 0,0 to pixels. + gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface; + mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), nsnull); + } + protected: ThebesLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData) @@ -831,16 +889,50 @@ public: MOZ_LAYER_DECL_NAME("ContainerLayer", TYPE_CONTAINER) + /** + * ContainerLayer backends need to override ComputeEffectiveTransforms + * since the decision about whether to use a temporary surface for the + * container is backend-specific. ComputeEffectiveTransforms must also set + * mUseIntermediateSurface. + */ + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) = 0; + + /** + * Call this only after ComputeEffectiveTransforms has been invoked + * on this layer. + * Returns true if this will use an intermediate surface. This is largely + * backend-dependent, but it affects the operation of GetEffectiveOpacity(). + */ + PRBool UseIntermediateSurface() { return mUseIntermediateSurface; } + + /** + * Returns true if this container has more than one non-empty child + */ + PRBool HasMultipleChildren(); + protected: ContainerLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData), - mFirstChild(nsnull) + mFirstChild(nsnull), + mUseIntermediateSurface(PR_FALSE) {} + /** + * A default implementation of ComputeEffectiveTransforms for use by OpenGL + * and D3D. + */ + void DefaultComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface); + + /** + * Loops over the children calling ComputeEffectiveTransforms on them. + */ + void ComputeEffectiveTransformsForChildren(const gfx3DMatrix& aTransformToSurface); + virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); Layer* mFirstChild; FrameMetrics mFrameMetrics; + PRPackedBool mUseIntermediateSurface; }; /** @@ -864,6 +956,13 @@ public: MOZ_LAYER_DECL_NAME("ColorLayer", TYPE_COLOR) + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + // Snap 0,0 to pixel boundaries, no extra internal transform. + gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface; + mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), nsnull); + } + protected: ColorLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData), @@ -934,12 +1033,28 @@ public: MOZ_LAYER_DECL_NAME("CanvasLayer", TYPE_CANVAS) + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + // Snap our local transform first, and snap the inherited transform as well. + // This makes our snapping equivalent to what would happen if our content + // was drawn into a ThebesLayer (gfxContext would snap using the local + // transform, then we'd snap again when compositing the ThebesLayer). + mEffectiveTransform = + SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height), + nsnull)* + SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nsnull); + } + protected: CanvasLayer(LayerManager* aManager, void* aImplData) : Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD) {} virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix); + /** + * 0, 0, canvaswidth, canvasheight + */ + nsIntRect mBounds; gfxPattern::GraphicsFilter mFilter; }; diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 3e749521622a..96d149000860 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -108,8 +108,7 @@ public: */ virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) {} + void* aCallbackData) {} virtual ShadowableLayer* AsShadowableLayer() { return nsnull; } @@ -174,6 +173,25 @@ public: ContainerRemoveChild(aChild, this); } + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + // We push groups for container layers if we need to, which always + // are aligned in device space, so it doesn't really matter how we snap + // containers. + gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface; + mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), nsnull); + // We always pass the ideal matrix down to our children, so there is no + // need to apply any compensation using the residual from SnapTransform. + ComputeEffectiveTransformsForChildren(idealTransform); + + /* If we have a single child, it can just inherit our opacity, + * otherwise we need a PushGroup and we need to mark ourselves as using + * an intermediate surface so our children don't inherit our opacity + * via GetEffectiveOpacity. + */ + mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren(); + } + protected: BasicLayerManager* BasicManager() { @@ -344,8 +362,7 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); virtual void ClearCachedResources() { mBuffer.Clear(); mValidRegion.SetEmpty(); } @@ -446,8 +463,7 @@ IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext) void BasicThebesLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase"); @@ -461,9 +477,10 @@ BasicThebesLayer::Paint(gfxContext* aContext, Buffer::ContentType contentType = opaqueBuffer ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA; + float opacity = GetEffectiveOpacity(); if (!BasicManager()->IsRetained() || - (aOpacity == 1.0 && !canUseOpaqueSurface && + (opacity == 1.0 && !canUseOpaqueSurface && !ShouldRetainTransparentSurface(mContentFlags, targetSurface) && !MustRetainContent())) { mValidRegion.SetEmpty(); @@ -473,13 +490,13 @@ BasicThebesLayer::Paint(gfxContext* aContext, if (!toDraw.IsEmpty()) { target->Save(); gfxUtils::ClipToRegionSnapped(target, toDraw); - if (aOpacity != 1.0) { + if (opacity != 1.0) { target->PushGroup(contentType); } aCallback(this, target, toDraw, nsIntRegion(), aCallbackData); - if (aOpacity != 1.0) { + if (opacity != 1.0) { target->PopGroupToSource(); - target->Paint(aOpacity); + target->Paint(opacity); } target->Restore(); } @@ -513,7 +530,7 @@ BasicThebesLayer::Paint(gfxContext* aContext, } } - mBuffer.DrawTo(this, canUseOpaqueSurface, target, aOpacity); + mBuffer.DrawTo(this, canUseOpaqueSurface, target, opacity); } static PRBool @@ -600,8 +617,7 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); static void PaintContext(gfxPattern* aPattern, const gfxIntSize& aSize, @@ -624,10 +640,10 @@ protected: void BasicImageLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { - nsRefPtr dontcare = GetAndPaintCurrentImage(aContext, aOpacity); + nsRefPtr dontcare = + GetAndPaintCurrentImage(aContext, GetEffectiveOpacity()); } already_AddRefed @@ -677,8 +693,9 @@ BasicImageLayer::PaintContext(gfxPattern* aPattern, /* Draw RGB surface onto frame */ aContext->NewPath(); - aContext->PixelSnappedRectangleAndSetPattern( - gfxRect(0, 0, aSize.width, aSize.height), aPattern); + // No need to snap here; our transform has already taken care of it. + aContext->Rectangle(gfxRect(0, 0, aSize.width, aSize.height)); + aContext->SetPattern(aPattern); if (aOpacity != 1.0) { aContext->Save(); aContext->Clip(); @@ -710,10 +727,9 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { - PaintColorTo(mColor, mOpacity, aContext); + PaintColorTo(mColor, GetEffectiveOpacity(), aContext); } static void PaintColorTo(gfxRGBA aColor, float aOpacity, @@ -759,8 +775,7 @@ public: virtual void Updated(const nsIntRect& aRect); virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); protected: BasicLayerManager* BasicManager() @@ -772,7 +787,6 @@ protected: nsRefPtr mGLContext; PRUint32 mCanvasFramebuffer; - nsIntRect mBounds; nsIntRect mUpdatedRect; PRPackedBool mGLBufferIsPremultiplied; @@ -870,8 +884,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect) void BasicCanvasLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase"); @@ -881,7 +894,6 @@ BasicCanvasLayer::Paint(gfxContext* aContext, pat->SetFilter(mFilter); pat->SetExtend(gfxPattern::EXTEND_PAD); - gfxRect r(0, 0, mBounds.width, mBounds.height); gfxMatrix m; if (mNeedsYFlip) { m = aContext->CurrentMatrix(); @@ -889,12 +901,16 @@ BasicCanvasLayer::Paint(gfxContext* aContext, aContext->Scale(1.0, -1.0); } + float opacity = GetEffectiveOpacity(); + aContext->NewPath(); - aContext->PixelSnappedRectangleAndSetPattern(r, pat); - if (aOpacity != 1.0) { + // No need to snap here; our transform is already set up to snap our rect + aContext->Rectangle(gfxRect(0, 0, mBounds.width, mBounds.height)); + aContext->SetPattern(pat); + if (opacity != 1.0) { aContext->Save(); aContext->Clip(); - aContext->Paint(aOpacity); + aContext->Paint(opacity); aContext->Restore(); } else { aContext->Fill(); @@ -1108,8 +1124,11 @@ BasicLayerManager::EndTransaction(DrawThebesLayerCallback aCallback, &cachedSurfaceOffset); } - PaintLayer(mRoot, aCallback, aCallbackData, mRoot->GetOpacity()); - + mSnapEffectiveTransforms = + !(mTarget->GetFlags() & gfxContext::FLAG_DISABLE_SNAPPING); + mRoot->ComputeEffectiveTransforms(gfx3DMatrix::From2D(mTarget->CurrentMatrix())); + PaintLayer(mRoot, aCallback, aCallbackData); + if (useDoubleBuffering) { finalTarget->SetOperator(gfxContext::OPERATOR_SOURCE); PopGroupWithCachedSurface(finalTarget, cachedSurfaceOffset); @@ -1138,87 +1157,69 @@ BasicLayerManager::SetRoot(Layer* aLayer) mRoot = aLayer; } -// Returns true if we need to save the state of the gfxContext when -// we start painting aLayer (and restore the state when we've finished -// painting aLayer) -static PRBool -NeedsState(Layer* aLayer) -{ - return aLayer->GetEffectiveClipRect() != nsnull || - !aLayer->GetEffectiveTransform().IsIdentity(); -} - -static inline int -GetChildCount(Layer *aLayer) -{ - int count = 0; - for (Layer* child = aLayer->GetFirstChild(); child; - child = child->GetNextSibling()) { - count++; - } - return count; -} - void BasicLayerManager::PaintLayer(Layer* aLayer, DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { - PRBool needsGroup = aOpacity != 1.0; - PRBool needsSaveRestore = needsGroup || NeedsState(aLayer); - int children = GetChildCount(aLayer); + const nsIntRect* clipRect = aLayer->GetEffectiveClipRect(); + const gfx3DMatrix& effectiveTransform = aLayer->GetEffectiveTransform(); + PRBool needsGroup = aLayer->GetFirstChild() && + static_cast(aLayer)->UseIntermediateSurface(); + // If needsSaveRestore is false, we should still save and restore + // the CTM + PRBool needsSaveRestore = needsGroup || clipRect; - if (needsSaveRestore) { + gfxMatrix savedMatrix; + if (needsSaveRestore) { mTarget->Save(); - if (const nsIntRect* r = aLayer->GetEffectiveClipRect()) { + if (clipRect) { mTarget->NewPath(); - mTarget->Rectangle(gfxRect(r->x, r->y, r->width, r->height), PR_TRUE); + mTarget->Rectangle(gfxRect(clipRect->x, clipRect->y, clipRect->width, clipRect->height), PR_TRUE); mTarget->Clip(); } + } else { + savedMatrix = mTarget->CurrentMatrix(); + } - gfxMatrix transform; - // XXX we need to add some kind of 3D transform support, possibly - // using pixman? - NS_ASSERTION(aLayer->GetEffectiveTransform().Is2D(), - "Only 2D transforms supported currently"); - aLayer->GetEffectiveTransform().Is2D(&transform); - mTarget->Multiply(transform); + gfxMatrix transform; + // XXX we need to add some kind of 3D transform support, possibly + // using pixman? + NS_ASSERTION(effectiveTransform.Is2D(), + "Only 2D transforms supported currently"); + effectiveTransform.Is2D(&transform); + mTarget->SetMatrix(transform); - if (needsGroup && children > 1) { - // If we need to call PushGroup, we should clip to the smallest possible - // area first to minimize the size of the temporary surface. - ClipToContain(mTarget, aLayer->GetEffectiveVisibleRegion().GetBounds()); + if (needsGroup) { + // If we need to call PushGroup, we should clip to the smallest possible + // area first to minimize the size of the temporary surface. + ClipToContain(mTarget, aLayer->GetEffectiveVisibleRegion().GetBounds()); - gfxASurface::gfxContentType type = aLayer->CanUseOpaqueSurface() - ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA; - mTarget->PushGroup(type); - } + gfxASurface::gfxContentType type = aLayer->CanUseOpaqueSurface() + ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA; + mTarget->PushGroup(type); } /* Only paint ourself, or our children - This optimization relies on this! */ - if (!children) { - ToData(aLayer)->Paint(mTarget, aCallback, aCallbackData, aOpacity); + Layer* child = aLayer->GetFirstChild(); + if (!child) { + ToData(aLayer)->Paint(mTarget, aCallback, aCallbackData); } else { - for (Layer* child = aLayer->GetFirstChild(); child; - child = child->GetNextSibling()) { - /* If we have a single child, we can pass the aOpacity down, otherwise we will have double buffered */ - if (needsGroup && children == 1) { - PaintLayer(child, aCallback, aCallbackData, child->GetOpacity() * aOpacity); - } else { - PaintLayer(child, aCallback, aCallbackData, child->GetOpacity()); - } + for (; child; child = child->GetNextSibling()) { + PaintLayer(child, aCallback, aCallbackData); } } - if (needsSaveRestore) { - if (needsGroup && children > 1) { - mTarget->PopGroupToSource(); - mTarget->Paint(aOpacity); - } + if (needsGroup) { + mTarget->PopGroupToSource(); + mTarget->Paint(aLayer->GetEffectiveOpacity()); + } + if (needsSaveRestore) { mTarget->Restore(); + } else { + mTarget->SetMatrix(savedMatrix); } } @@ -1591,8 +1592,7 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { @@ -1625,11 +1625,10 @@ private: void BasicShadowableImageLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { gfxIntSize oldSize = mSize; - nsRefPtr pat = GetAndPaintCurrentImage(aContext, aOpacity); + nsRefPtr pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity()); if (!pat || !HasShadow()) return; @@ -1713,8 +1712,7 @@ public: virtual void Initialize(const Data& aData); virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) { @@ -1777,10 +1775,9 @@ BasicShadowableCanvasLayer::Initialize(const Data& aData) void BasicShadowableCanvasLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { - BasicCanvasLayer::Paint(aContext, aCallback, aCallbackData, aOpacity); + BasicCanvasLayer::Paint(aContext, aCallback, aCallbackData); if (!HasShadow()) return; @@ -1897,8 +1894,7 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); private: BasicShadowLayerManager* BasicManager() @@ -1987,8 +1983,7 @@ BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront, void BasicShadowThebesLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase"); @@ -2002,13 +1997,7 @@ BasicShadowThebesLayer::Paint(gfxContext* aContext, gfxContext* target = BasicManager()->GetTarget(); NS_ASSERTION(target, "We shouldn't be called if there's no target"); - nsRefPtr targetSurface = aContext->CurrentSurface(); - PRBool isOpaqueContent = - (targetSurface->AreSimilarSurfacesSensitiveToContentType() && - aOpacity == 1.0 && - CanUseOpaqueSurface()); - - mFrontBuffer.DrawTo(this, isOpaqueContent, target, aOpacity); + mFrontBuffer.DrawTo(this, CanUseOpaqueSurface(), target, GetEffectiveOpacity()); } class BasicShadowContainerLayer : public ShadowContainerLayer, BasicImplData { @@ -2036,6 +2025,25 @@ public: { ContainerInsertAfter(aChild, aAfter, this); } virtual void RemoveChild(Layer* aChild) { ContainerRemoveChild(aChild, this); } + + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + // We push groups for container layers if we need to, which always + // are aligned in device space, so it doesn't really matter how we snap + // containers. + gfx3DMatrix idealTransform = GetLocalTransform()*aTransformToSurface; + mEffectiveTransform = SnapTransform(idealTransform, gfxRect(0, 0, 0, 0), nsnull); + // We always pass the ideal matrix down to our children, so there is no + // need to apply any compensation using the residual from SnapTransform. + ComputeEffectiveTransformsForChildren(idealTransform); + + /* If we have a single child, it can just inherit our opacity, + * otherwise we need a PushGroup and we need to mark ourselves as using + * an intermediate surface so our children don't inherit our opacity + * via GetEffectiveOpacity. + */ + mUseIntermediateSurface = GetEffectiveOpacity() != 1.0 && HasMultipleChildren(); + } }; class BasicShadowImageLayer : public ShadowImageLayer, BasicImplData { @@ -2071,8 +2079,7 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); protected: BasicShadowLayerManager* BasicManager() @@ -2105,8 +2112,7 @@ BasicShadowImageLayer::Swap(gfxSharedImageSurface* newFront) void BasicShadowImageLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { if (!mFrontSurface) { return; @@ -2114,7 +2120,7 @@ BasicShadowImageLayer::Paint(gfxContext* aContext, nsRefPtr pat = new gfxPattern(mFrontSurface); pat->SetFilter(mFilter); - BasicImageLayer::PaintContext(pat, mSize, aOpacity, aContext); + BasicImageLayer::PaintContext(pat, mSize, GetEffectiveOpacity(), aContext); } class BasicShadowColorLayer : public ShadowColorLayer, @@ -2133,10 +2139,9 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { - BasicColorLayer::PaintColorTo(mColor, aOpacity, aContext); + BasicColorLayer::PaintColorTo(mColor, GetEffectiveOpacity(), aContext); } }; @@ -2178,8 +2183,7 @@ public: virtual void Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); private: BasicShadowLayerManager* BasicManager() @@ -2188,7 +2192,6 @@ private: } nsRefPtr mFrontSurface; - nsIntRect mBounds; }; @@ -2214,8 +2217,7 @@ BasicShadowCanvasLayer::Swap(gfxSharedImageSurface* newFront) void BasicShadowCanvasLayer::Paint(gfxContext* aContext, LayerManager::DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity) + void* aCallbackData) { NS_ASSERTION(BasicManager()->InDrawing(), "Can only draw in drawing phase"); @@ -2231,7 +2233,9 @@ BasicShadowCanvasLayer::Paint(gfxContext* aContext, gfxRect r(0, 0, mBounds.width, mBounds.height); aContext->NewPath(); - aContext->PixelSnappedRectangleAndSetPattern(r, pat); + // No need to snap here; our transform has already taken care of it + aContext->Rectangle(r); + aContext->SetPattern(pat); aContext->Fill(); } diff --git a/gfx/layers/basic/BasicLayers.h b/gfx/layers/basic/BasicLayers.h index dad372ebf7f1..5e488bdb18b4 100644 --- a/gfx/layers/basic/BasicLayers.h +++ b/gfx/layers/basic/BasicLayers.h @@ -193,8 +193,7 @@ private: // Paints aLayer to mTarget. void PaintLayer(Layer* aLayer, DrawThebesLayerCallback aCallback, - void* aCallbackData, - float aOpacity); + void* aCallbackData); // Clear the contents of a layer void ClearLayer(Layer* aLayer); diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.cpp b/gfx/layers/d3d10/CanvasLayerD3D10.cpp index 91e8cb1a31ca..c652dc77150c 100644 --- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp +++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp @@ -202,7 +202,7 @@ CanvasLayerD3D10::GetLayer() } void -CanvasLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +CanvasLayerD3D10::RenderLayer() { if (!mTexture) { return; @@ -210,9 +210,7 @@ CanvasLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) nsIntRect visibleRect = mVisibleRegion.GetBounds(); - gfx3DMatrix transform = mTransform * aTransform; - effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64); - effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(GetOpacity() * aOpacity); + SetEffectTransformAndOpacity(); ID3D10EffectTechnique *technique; diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.h b/gfx/layers/d3d10/CanvasLayerD3D10.h index 08c1050bee87..78d4021329fd 100644 --- a/gfx/layers/d3d10/CanvasLayerD3D10.h +++ b/gfx/layers/d3d10/CanvasLayerD3D10.h @@ -53,7 +53,6 @@ public: CanvasLayerD3D10(LayerManagerD3D10 *aManager) : CanvasLayer(aManager, NULL), LayerD3D10(aManager), - mTexture(0), mDataIsPremultiplied(PR_FALSE), mNeedsYFlip(PR_FALSE) { @@ -68,20 +67,17 @@ public: // LayerD3D10 implementation virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); private: typedef mozilla::gl::GLContext GLContext; nsRefPtr mSurface; nsRefPtr mGLContext; - - PRUint32 mCanvasFramebuffer; - nsRefPtr mTexture; nsRefPtr mSRView; - nsIntRect mBounds; + PRUint32 mCanvasFramebuffer; PRPackedBool mDataIsPremultiplied; PRPackedBool mNeedsYFlip; diff --git a/gfx/layers/d3d10/ColorLayerD3D10.cpp b/gfx/layers/d3d10/ColorLayerD3D10.cpp index 69724fcd73b0..61ba487c9555 100644 --- a/gfx/layers/d3d10/ColorLayerD3D10.cpp +++ b/gfx/layers/d3d10/ColorLayerD3D10.cpp @@ -55,18 +55,19 @@ ColorLayerD3D10::GetLayer() } void -ColorLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ColorLayerD3D10::RenderLayer() { float color[4]; // color is premultiplied, so we need to adjust all channels - color[0] = (float)(mColor.r * GetOpacity() * aOpacity); - color[1] = (float)(mColor.g * GetOpacity() * aOpacity); - color[2] = (float)(mColor.b * GetOpacity() * aOpacity); - color[3] = (float)(mColor.a * GetOpacity() * aOpacity); + float opacity = GetEffectiveOpacity(); + color[0] = (float)(mColor.r * opacity); + color[1] = (float)(mColor.g * opacity); + color[2] = (float)(mColor.b * opacity); + color[3] = (float)(mColor.a * opacity); - gfx3DMatrix transform = mTransform * aTransform; - - effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64); + const gfx3DMatrix& transform = GetEffectiveTransform(); + void* raw = &const_cast(transform)._11; + effect()->GetVariableByName("mLayerTransform")->SetRawValue(raw, 0, 64); effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color); ID3D10EffectTechnique *technique; diff --git a/gfx/layers/d3d10/ColorLayerD3D10.h b/gfx/layers/d3d10/ColorLayerD3D10.h index eeaaae161513..6238a466a464 100644 --- a/gfx/layers/d3d10/ColorLayerD3D10.h +++ b/gfx/layers/d3d10/ColorLayerD3D10.h @@ -52,7 +52,7 @@ public: /* LayerD3D10 implementation */ virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); }; } /* layers */ diff --git a/gfx/layers/d3d10/ContainerLayerD3D10.cpp b/gfx/layers/d3d10/ContainerLayerD3D10.cpp index 16ee47f05e53..0103922c8072 100644 --- a/gfx/layers/d3d10/ContainerLayerD3D10.cpp +++ b/gfx/layers/d3d10/ContainerLayerD3D10.cpp @@ -136,14 +136,13 @@ ContainerLayerD3D10::GetFirstChildD3D10() } void -ContainerLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ContainerLayerD3D10::RenderLayer() { float renderTargetOffset[] = { 0, 0 }; nsIntRect visibleRect = mVisibleRegion.GetBounds(); - float opacity = GetOpacity() * aOpacity; - gfx3DMatrix transform = mTransform * aTransform; - PRBool useIntermediate = ShouldUseIntermediate(aOpacity, transform); + float opacity = GetEffectiveOpacity(); + PRBool useIntermediate = UseIntermediateSurface(); nsRefPtr previousRTView; nsRefPtr renderTexture; @@ -240,11 +239,7 @@ ContainerLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) } // SetScissorRect - if (!useIntermediate) { - layerToRender->RenderLayer(opacity, transform); - } else { - layerToRender->RenderLayer(1.0f, gfx3DMatrix()); - } + layerToRender->RenderLayer(); if (clipRect || useIntermediate) { device()->RSSetScissorRects(1, &oldScissor); @@ -263,8 +258,7 @@ ContainerLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) effect()->GetVariableByName("vRenderTargetOffset")-> SetRawValue(previousRenderTargetOffset, 0, 8); - effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64); - effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(opacity); + SetEffectTransformAndOpacity(); ID3D10EffectTechnique *technique; technique = effect()->GetTechniqueByName("RenderRGBALayerPremul"); @@ -306,32 +300,5 @@ ContainerLayerD3D10::Validate() } } -bool -ContainerLayerD3D10::ShouldUseIntermediate(float aOpacity, - const gfx3DMatrix &aMatrix) -{ - if (aOpacity == 1.0f && aMatrix.IsIdentity()) { - return false; - } - - Layer *firstChild = GetFirstChild(); - - if (!firstChild || (!firstChild->GetNextSibling() && - !firstChild->GetClipRect())) { - // If we forward our transform to a child without using an intermediate, we - // need to be sure that child does not have a clip rect since the clip rect - // needs to be applied after its transform. - return false; - } - - if (aMatrix.IsIdentity() && (!firstChild || !firstChild->GetNextSibling())) { - // If there's no transforms applied and a single child, opacity can always - // be forwarded to our only child. - return false; - } - - return true; -} - } /* layers */ } /* mozilla */ diff --git a/gfx/layers/d3d10/ContainerLayerD3D10.h b/gfx/layers/d3d10/ContainerLayerD3D10.h index 8620a6afb6b6..9f4746f5a3f7 100644 --- a/gfx/layers/d3d10/ContainerLayerD3D10.h +++ b/gfx/layers/d3d10/ContainerLayerD3D10.h @@ -63,13 +63,15 @@ public: virtual LayerD3D10* GetFirstChildD3D10(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); virtual void Validate(); virtual void LayerManagerDestroyed(); -private: - bool ShouldUseIntermediate(float aOpacity, const gfx3DMatrix &aTransform); + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + DefaultComputeEffectiveTransforms(aTransformToSurface); + } }; } /* layers */ diff --git a/gfx/layers/d3d10/ImageLayerD3D10.cpp b/gfx/layers/d3d10/ImageLayerD3D10.cpp index 3898a0c17147..9316e7ad3cbb 100644 --- a/gfx/layers/d3d10/ImageLayerD3D10.cpp +++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp @@ -145,7 +145,7 @@ ImageLayerD3D10::GetLayer() } void -ImageLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ImageLayerD3D10::RenderLayer() { if (!GetContainer()) { return; @@ -153,10 +153,7 @@ ImageLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) nsRefPtr image = GetContainer()->GetCurrentImage(); - - gfx3DMatrix transform = mTransform * aTransform; - effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64); - effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(GetOpacity() * aOpacity); + SetEffectTransformAndOpacity(); ID3D10EffectTechnique *technique; diff --git a/gfx/layers/d3d10/ImageLayerD3D10.h b/gfx/layers/d3d10/ImageLayerD3D10.h index 60b7e346acfb..d1012b2f47b9 100644 --- a/gfx/layers/d3d10/ImageLayerD3D10.h +++ b/gfx/layers/d3d10/ImageLayerD3D10.h @@ -88,7 +88,7 @@ public: // LayerD3D10 Implementation virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); }; class THEBES_API ImageD3D10 diff --git a/gfx/layers/d3d10/LayerManagerD3D10.cpp b/gfx/layers/d3d10/LayerManagerD3D10.cpp index 3049a4d24879..e78d53364db2 100644 --- a/gfx/layers/d3d10/LayerManagerD3D10.cpp +++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp @@ -236,6 +236,11 @@ LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback, { mCurrentCallbackInfo.Callback = aCallback; mCurrentCallbackInfo.CallbackData = aCallbackData; + + // The results of our drawing always go directly into a pixel buffer, + // so we don't need to pass any global transform here. + mRoot->ComputeEffectiveTransforms(gfx3DMatrix()); + Render(); mCurrentCallbackInfo.Callback = nsnull; mCurrentCallbackInfo.CallbackData = nsnull; @@ -462,7 +467,7 @@ LayerManagerD3D10::Render() } device()->RSSetScissorRects(1, &r); - static_cast(mRoot->ImplData())->RenderLayer(1, gfx3DMatrix()); + static_cast(mRoot->ImplData())->RenderLayer(); } if (mTarget) { diff --git a/gfx/layers/d3d10/LayerManagerD3D10.h b/gfx/layers/d3d10/LayerManagerD3D10.h index 70e9740d7f6e..aacd20aecc5c 100644 --- a/gfx/layers/d3d10/LayerManagerD3D10.h +++ b/gfx/layers/d3d10/LayerManagerD3D10.h @@ -191,11 +191,9 @@ public: /** * This will render a child layer to whatever render target is currently - * active. aOpacity and aTransform will pass any 'carried' transformations - * and/or opacity from the parent. This allows the parent to avoid - * rendering to intermediate surfaces when possible. + * active. */ - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) = 0; + virtual void RenderLayer() = 0; virtual void Validate() {} ID3D10Device1 *device() const { return mD3DManager->device(); } @@ -203,6 +201,16 @@ public: /* Called by the layer manager when it's destroyed */ virtual void LayerManagerDestroyed() {} + + void SetEffectTransformAndOpacity() + { + Layer* layer = GetLayer(); + const gfx3DMatrix& transform = layer->GetEffectiveTransform(); + void* raw = &const_cast(transform)._11; + effect()->GetVariableByName("mLayerTransform")->SetRawValue(raw, 0, 64); + effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(layer->GetEffectiveOpacity()); + } + protected: LayerManagerD3D10 *mD3DManager; }; diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.cpp b/gfx/layers/d3d10/ThebesLayerD3D10.cpp index cf3b1191f67d..195b1017910a 100644 --- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp +++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp @@ -152,7 +152,7 @@ ThebesLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion) } void -ThebesLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ThebesLayerD3D10::RenderLayer() { if (!mTexture) { return; @@ -160,9 +160,7 @@ ThebesLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) nsIntRect visibleRect = mVisibleRegion.GetBounds(); - gfx3DMatrix transform = mTransform * aTransform; - effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64); - effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(GetOpacity() * aOpacity); + SetEffectTransformAndOpacity(); ID3D10EffectTechnique *technique; if (CanUseOpaqueSurface()) { diff --git a/gfx/layers/d3d10/ThebesLayerD3D10.h b/gfx/layers/d3d10/ThebesLayerD3D10.h index 48ad38482afc..60fe73bab926 100644 --- a/gfx/layers/d3d10/ThebesLayerD3D10.h +++ b/gfx/layers/d3d10/ThebesLayerD3D10.h @@ -59,7 +59,7 @@ public: /* LayerD3D10 implementation */ virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); virtual void Validate(); virtual void LayerManagerDestroyed(); diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.cpp b/gfx/layers/d3d9/CanvasLayerD3D9.cpp index db34138e81df..dd83a8661985 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp @@ -227,7 +227,7 @@ CanvasLayerD3D9::GetLayer() } void -CanvasLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +CanvasLayerD3D9::RenderLayer() { if (!mTexture) { Updated(mBounds); @@ -246,16 +246,7 @@ CanvasLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) device()->SetVertexShaderConstantF(CBvLayerQuad, quad, 1); - gfx3DMatrix transform = mTransform * aTransform; - device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); - - float opacity[4]; - /* - * We always upload a 4 component float, but the shader will use only the - * first component since it's declared as a 'float'. - */ - opacity[0] = GetOpacity(); - device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1); + SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.h b/gfx/layers/d3d9/CanvasLayerD3D9.h index 1093315feeb2..6178165f13bc 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.h +++ b/gfx/layers/d3d9/CanvasLayerD3D9.h @@ -54,7 +54,6 @@ public: CanvasLayerD3D9(LayerManagerD3D9 *aManager) : CanvasLayer(aManager, NULL), LayerD3D9(aManager), - mTexture(0), mDataIsPremultiplied(PR_FALSE), mNeedsYFlip(PR_FALSE) { @@ -70,7 +69,7 @@ public: // LayerD3D9 implementation virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); virtual void CleanResources(); virtual void LayerManagerDestroyed(); @@ -79,17 +78,14 @@ public: protected: typedef mozilla::gl::GLContext GLContext; - // Indicates whether our texture was obtained through D2D interop. - bool mIsInteropTexture; - nsRefPtr mSurface; nsRefPtr mGLContext; + nsRefPtr mTexture; PRUint32 mCanvasFramebuffer; - nsRefPtr mTexture; - - nsIntRect mBounds; + // Indicates whether our texture was obtained through D2D interop. + bool mIsInteropTexture; PRPackedBool mDataIsPremultiplied; PRPackedBool mNeedsYFlip; diff --git a/gfx/layers/d3d9/ColorLayerD3D9.cpp b/gfx/layers/d3d9/ColorLayerD3D9.cpp index 8118e4278f20..494fa7fad0c5 100644 --- a/gfx/layers/d3d9/ColorLayerD3D9.cpp +++ b/gfx/layers/d3d9/ColorLayerD3D9.cpp @@ -48,7 +48,7 @@ ColorLayerD3D9::GetLayer() } void -ColorLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ColorLayerD3D9::RenderLayer() { // XXX we might be able to improve performance by using // IDirect3DDevice9::Clear @@ -63,15 +63,16 @@ ColorLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) visibleRect.height), 1); - gfx3DMatrix transform = mTransform * aTransform; + const gfx3DMatrix& transform = GetEffectiveTransform(); device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); float color[4]; + float opacity = GetEffectiveOpacity(); // color is premultiplied, so we need to adjust all channels - color[0] = (float)(mColor.r * GetOpacity() * aOpacity); - color[1] = (float)(mColor.g * GetOpacity() * aOpacity); - color[2] = (float)(mColor.b * GetOpacity() * aOpacity); - color[3] = (float)(mColor.a * GetOpacity() * aOpacity); + color[0] = (float)(mColor.r * opacity); + color[1] = (float)(mColor.g * opacity); + color[2] = (float)(mColor.b * opacity); + color[3] = (float)(mColor.a * opacity); device()->SetPixelShaderConstantF(0, color, 1); diff --git a/gfx/layers/d3d9/ColorLayerD3D9.h b/gfx/layers/d3d9/ColorLayerD3D9.h index cf0a968dc705..6756ec95f9df 100644 --- a/gfx/layers/d3d9/ColorLayerD3D9.h +++ b/gfx/layers/d3d9/ColorLayerD3D9.h @@ -58,7 +58,7 @@ public: // LayerD3D9 Implementation virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); }; } /* layers */ diff --git a/gfx/layers/d3d9/ContainerLayerD3D9.cpp b/gfx/layers/d3d9/ContainerLayerD3D9.cpp index ee38a0fdf164..321088ba5f0f 100644 --- a/gfx/layers/d3d9/ContainerLayerD3D9.cpp +++ b/gfx/layers/d3d9/ContainerLayerD3D9.cpp @@ -135,9 +135,8 @@ ContainerLayerD3D9::GetFirstChildD3D9() } void -ContainerLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ContainerLayerD3D9::RenderLayer() { - float opacity = GetOpacity() * aOpacity; nsRefPtr previousRenderTarget; nsRefPtr renderTexture; float previousRenderTargetOffset[4]; @@ -145,10 +144,8 @@ ContainerLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) float renderTargetOffset[] = { 0, 0, 0, 0 }; float oldViewMatrix[4][4]; - gfx3DMatrix transform = mTransform * aTransform; - nsIntRect visibleRect = mVisibleRegion.GetBounds(); - PRBool useIntermediate = ShouldUseIntermediate(opacity, transform); + PRBool useIntermediate = UseIntermediateSurface(); if (useIntermediate) { device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); @@ -223,11 +220,7 @@ ContainerLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) device()->SetScissorRect(&r); } - if (!useIntermediate) { - layerToRender->RenderLayer(opacity, transform); - } else { - layerToRender->RenderLayer(1.0, gfx3DMatrix()); - } + layerToRender->RenderLayer(); if (clipRect || useIntermediate) { device()->SetScissorRect(&oldClipRect); @@ -251,15 +244,7 @@ ContainerLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) visibleRect.height), 1); - device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); - - float opacityVector[4]; - /* - * We always upload a 4 component float, but the shader will use only the - * first component since it's declared as a 'float'. - */ - opacityVector[0] = opacity; - device()->SetPixelShaderConstantF(CBfLayerOpacity, opacityVector, 1); + SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); @@ -277,32 +262,5 @@ ContainerLayerD3D9::LayerManagerDestroyed() } } -bool -ContainerLayerD3D9::ShouldUseIntermediate(float aOpacity, - const gfx3DMatrix &aMatrix) -{ - if (aOpacity == 1.0f && aMatrix.IsIdentity()) { - return false; - } - - Layer *firstChild = GetFirstChild(); - - if (!firstChild || (!firstChild->GetNextSibling() && - !firstChild->GetClipRect())) { - // If we forward our transform to a child without using an intermediate, - // we need to be sure that child does not have a clip rect, since its clip - // rect would be applied after our transform. - return false; - } - - if (aMatrix.IsIdentity() && (!firstChild || !firstChild->GetNextSibling())) { - // If there's no transforms applied and a single child, opacity can always - // be forwarded to our only child. - return false; - } - - return true; -} - } /* layers */ } /* mozilla */ diff --git a/gfx/layers/d3d9/ContainerLayerD3D9.h b/gfx/layers/d3d9/ContainerLayerD3D9.h index ff661319c13c..eb40740cf625 100644 --- a/gfx/layers/d3d9/ContainerLayerD3D9.h +++ b/gfx/layers/d3d9/ContainerLayerD3D9.h @@ -65,13 +65,14 @@ public: PRBool IsEmpty(); - void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + void RenderLayer(); virtual void LayerManagerDestroyed(); -private: - bool ShouldUseIntermediate(float aOpacity, - const gfx3DMatrix &aMatrix); + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + DefaultComputeEffectiveTransforms(aTransformToSurface); + } }; } /* layers */ diff --git a/gfx/layers/d3d9/ImageLayerD3D9.cpp b/gfx/layers/d3d9/ImageLayerD3D9.cpp index 98a4c169042a..066f0820e980 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.cpp +++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp @@ -148,7 +148,7 @@ ImageLayerD3D9::GetLayer() } void -ImageLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ImageLayerD3D9::RenderLayer() { if (!GetContainer()) { return; @@ -172,16 +172,7 @@ ImageLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) yuvImage->mSize.height), 1); - gfx3DMatrix transform = mTransform * aTransform; - device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); - - float opacity[4]; - /* - * We always upload a 4 component float, but the shader will - * only use the the first component since it's declared as a 'float'. - */ - opacity[0] = GetOpacity() * aOpacity; - device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1); + SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::YCBCRLAYER); @@ -221,16 +212,7 @@ ImageLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) cairoImage->mSize.height), 1); - gfx3DMatrix transform = mTransform * aTransform; - device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); - - float opacity[4]; - /* - * We always upload a 4 component float, but the shader will - * only use the the first component since it's declared as a 'float'. - */ - opacity[0] = GetOpacity() * aOpacity; - device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1); + SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); diff --git a/gfx/layers/d3d9/ImageLayerD3D9.h b/gfx/layers/d3d9/ImageLayerD3D9.h index 464a86286656..687d5d6fa0d6 100644 --- a/gfx/layers/d3d9/ImageLayerD3D9.h +++ b/gfx/layers/d3d9/ImageLayerD3D9.h @@ -87,7 +87,7 @@ public: // LayerD3D9 Implementation virtual Layer* GetLayer(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); }; class THEBES_API ImageD3D9 diff --git a/gfx/layers/d3d9/LayerManagerD3D9.cpp b/gfx/layers/d3d9/LayerManagerD3D9.cpp index 7f814b34e6d1..e59c15f819a0 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.cpp +++ b/gfx/layers/d3d9/LayerManagerD3D9.cpp @@ -155,6 +155,11 @@ LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback, { mCurrentCallbackInfo.Callback = aCallback; mCurrentCallbackInfo.CallbackData = aCallbackData; + + // The results of our drawing always go directly into a pixel buffer, + // so we don't need to pass any global transform here. + mRoot->ComputeEffectiveTransforms(gfx3DMatrix()); + Render(); /* Clean this out for sanity */ mCurrentCallbackInfo.Callback = NULL; @@ -298,7 +303,7 @@ LayerManagerD3D9::Render() } device()->SetScissorRect(&r); - static_cast(mRoot->ImplData())->RenderLayer(1.0, gfx3DMatrix()); + static_cast(mRoot->ImplData())->RenderLayer(); } device()->EndScene(); diff --git a/gfx/layers/d3d9/LayerManagerD3D9.h b/gfx/layers/d3d9/LayerManagerD3D9.h index 4222f47c8840..6ee0b939d9b5 100644 --- a/gfx/layers/d3d9/LayerManagerD3D9.h +++ b/gfx/layers/d3d9/LayerManagerD3D9.h @@ -251,8 +251,9 @@ public: virtual Layer* GetLayer() = 0; - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) = 0; + virtual void RenderLayer() = 0; + /** /* This function may be used on device resets to clear all VRAM resources * that a layer might be using. */ @@ -266,6 +267,22 @@ public: void ReportFailure(const nsACString &aMsg, HRESULT aCode) { return mD3DManager->ReportFailure(aMsg, aCode); } + + void SetShaderTransformAndOpacity() + { + Layer* layer = GetLayer(); + const gfx3DMatrix& transform = layer->GetEffectiveTransform(); + device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); + + float opacity[4]; + /* + * We always upload a 4 component float, but the shader will use only the + * first component since it's declared as a 'float'. + */ + opacity[0] = layer->GetEffectiveOpacity(); + device()->SetPixelShaderConstantF(CBfLayerOpacity, opacity, 1); + } + protected: LayerManagerD3D9 *mD3DManager; }; diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 7fe3267f6e7e..b265168581f6 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -172,7 +172,7 @@ ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion) } void -ThebesLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) +ThebesLayerD3D9::RenderLayer() { if (mVisibleRegion.IsEmpty()) { return; @@ -225,16 +225,7 @@ ThebesLayerD3D9::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) mValidRegion = mVisibleRegion; } - gfx3DMatrix transform = mTransform * aTransform; - device()->SetVertexShaderConstantF(CBmLayerTransform, &transform._11, 4); - - float opacity[4]; - /* - * We always upload a 4 component float, but the shader will use only the - * first component since it's declared as a 'float'. - */ - opacity[0] = GetOpacity() * aOpacity; - device()->SetPixelShaderConstantF(0, opacity, 1); + SetShaderTransformAndOpacity(); #ifdef CAIRO_HAS_D2D_SURFACE if (mD2DSurface && CanUseOpaqueSurface()) { diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.h b/gfx/layers/d3d9/ThebesLayerD3D9.h index 892514fc0526..d3e93b262b8b 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.h +++ b/gfx/layers/d3d9/ThebesLayerD3D9.h @@ -61,7 +61,7 @@ public: /* LayerD3D9 implementation */ Layer* GetLayer(); virtual PRBool IsEmpty(); - virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform); + virtual void RenderLayer(); virtual void CleanResources(); virtual void LayerManagerDestroyed(); diff --git a/gfx/layers/opengl/CanvasLayerOGL.cpp b/gfx/layers/opengl/CanvasLayerOGL.cpp index 61556c8c839d..7dfaa8522d03 100644 --- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ b/gfx/layers/opengl/CanvasLayerOGL.cpp @@ -231,9 +231,7 @@ CanvasLayerOGL::Updated(const nsIntRect& aRect) void CanvasLayerOGL::RenderLayer(int aPreviousDestination, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { mOGLManager->MakeCurrent(); @@ -268,8 +266,8 @@ CanvasLayerOGL::RenderLayer(int aPreviousDestination, program->Activate(); program->SetLayerQuadRect(mBounds); - program->SetLayerTransform(GetEffectiveTransform() * aMatrix); - program->SetLayerOpacity(GetOpacity() * aOpacity); + program->SetLayerTransform(GetEffectiveTransform()); + program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); @@ -354,9 +352,7 @@ ShadowCanvasLayerOGL::GetLayer() void ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { mOGLManager->MakeCurrent(); @@ -370,8 +366,8 @@ ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer, program->Activate(); program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mTexImage->GetSize())); - program->SetLayerTransform(mTransform * aMatrix); - program->SetLayerOpacity(GetOpacity() * aOpacity); + program->SetLayerTransform(GetEffectiveTransform()); + program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); diff --git a/gfx/layers/opengl/CanvasLayerOGL.h b/gfx/layers/opengl/CanvasLayerOGL.h index 0e620f5a7942..8092062f42b9 100644 --- a/gfx/layers/opengl/CanvasLayerOGL.h +++ b/gfx/layers/opengl/CanvasLayerOGL.h @@ -71,9 +71,7 @@ public: virtual void Destroy(); virtual Layer* GetLayer() { return this; } virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); protected: nsRefPtr mCanvasSurface; @@ -82,7 +80,6 @@ protected: void MakeTexture(); GLuint mTexture; - nsIntRect mBounds; nsIntRect mUpdatedRect; PRPackedBool mGLBufferIsPremultiplied; @@ -117,9 +114,7 @@ public: void Destroy(); Layer* GetLayer(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); private: nsRefPtr mTexImage; diff --git a/gfx/layers/opengl/ColorLayerOGL.cpp b/gfx/layers/opengl/ColorLayerOGL.cpp index bab0381450cf..82f3ac642083 100644 --- a/gfx/layers/opengl/ColorLayerOGL.cpp +++ b/gfx/layers/opengl/ColorLayerOGL.cpp @@ -43,8 +43,7 @@ namespace layers { static void RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager, - const nsIntPoint& aOffset, float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { aManager->MakeCurrent(); @@ -57,7 +56,7 @@ RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager, * write to the color buffer. This saves a needless * multiply in the fragment shader. */ - float opacity = aLayer->GetOpacity() * aOpacity; + float opacity = aLayer->GetEffectiveOpacity(); gfxRGBA color(aLayer->GetColor()); color.r *= opacity; color.g *= opacity; @@ -67,7 +66,7 @@ RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager, SolidColorLayerProgram *program = aManager->GetColorLayerProgram(); program->Activate(); program->SetLayerQuadRect(visibleRect); - program->SetLayerTransform(aLayer->GetEffectiveTransform() * aMatrix); + program->SetLayerTransform(aLayer->GetEffectiveTransform()); program->SetRenderOffset(aOffset); program->SetRenderColor(color); @@ -78,21 +77,17 @@ RenderColorLayer(ColorLayer* aLayer, LayerManagerOGL *aManager, void ColorLayerOGL::RenderLayer(int, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { - return RenderColorLayer(this, mOGLManager, aOffset, aOpacity, aMatrix); + return RenderColorLayer(this, mOGLManager, aOffset); } #ifdef MOZ_IPC void ShadowColorLayerOGL::RenderLayer(int, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { - return RenderColorLayer(this, mOGLManager, aOffset, aOpacity, aMatrix); + return RenderColorLayer(this, mOGLManager, aOffset); } #endif // MOZ_IPC diff --git a/gfx/layers/opengl/ColorLayerOGL.h b/gfx/layers/opengl/ColorLayerOGL.h index 72bb286be64a..4cd291e079e7 100644 --- a/gfx/layers/opengl/ColorLayerOGL.h +++ b/gfx/layers/opengl/ColorLayerOGL.h @@ -66,9 +66,7 @@ public: virtual void Destroy() { mDestroyed = PR_TRUE; } virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); }; #ifdef MOZ_IPC @@ -90,9 +88,7 @@ public: virtual void Destroy() { mDestroyed = PR_TRUE; } virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); }; #endif // MOZ_IPC diff --git a/gfx/layers/opengl/ContainerLayerOGL.cpp b/gfx/layers/opengl/ContainerLayerOGL.cpp index 6d5bf4fe6073..ec5460e8cce2 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.cpp +++ b/gfx/layers/opengl/ContainerLayerOGL.cpp @@ -120,49 +120,11 @@ ContainerDestroy(Container* aContainer) } } -template -static bool -ShouldUseIntermediate(Container* aContainer, - float aOpacity, - const gfx3DMatrix& aMatrix) -{ - if (aOpacity == 1.0f && aMatrix.IsIdentity()) { - return false; - } - - Layer *firstChild = aContainer->GetFirstChild(); - if (!firstChild) { - return false; - } - - /* We always require an intermediate layer for opacity */ - if (aOpacity != 1.0f) { - return true; - } - - do { - const nsIntRect *clipRect = firstChild->GetClipRect(); - /* We can't (easily) forward our transform to children with a non-emtpy clip - * rect since it would need to be adjusted for the transform. - * TODO: This is easily solvable for translation/scaling transforms. - */ - if (clipRect && !clipRect->IsEmpty() && !firstChild->GetVisibleRegion().IsEmpty()) { - return true; - } - - } while ((firstChild = firstChild->GetNextSibling()) != nsnull); - - /* All children have no clip or are invisible */ - return false; -} - template static void ContainerRender(Container* aContainer, int aPreviousFrameBuffer, const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix, LayerManagerOGL* aManager) { /** @@ -173,13 +135,13 @@ ContainerRender(Container* aContainer, nsIntPoint childOffset(aOffset); nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds(); - const gfx3DMatrix& transform = aContainer->GetEffectiveTransform() * aMatrix; nsIntRect cachedScissor = aContainer->gl()->ScissorRect(); aContainer->gl()->PushScissorRect(); - float opacity = aContainer->GetOpacity() * aOpacity; - bool needsFramebuffer = ShouldUseIntermediate(aContainer, opacity, transform); + float opacity = aContainer->GetEffectiveOpacity(); + const gfx3DMatrix& transform = aContainer->GetEffectiveTransform(); + bool needsFramebuffer = aContainer->UseIntermediateSurface(); if (needsFramebuffer) { aManager->CreateFBOWithTexture(visibleRect.width, visibleRect.height, @@ -237,11 +199,7 @@ ContainerRender(Container* aContainer, cachedScissor.height); } - if (!needsFramebuffer) { - layerToRender->RenderLayer(frameBuffer, childOffset, opacity, transform); - } else { - layerToRender->RenderLayer(frameBuffer, childOffset, 1.0, gfx3DMatrix()); - } + layerToRender->RenderLayer(frameBuffer, childOffset); Layer *nextSibling = layerToRender->GetLayer()->GetNextSibling(); layerToRender = nextSibling ? static_cast(nextSibling-> @@ -336,11 +294,9 @@ ContainerLayerOGL::GetFirstChildOGL() void ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { - ContainerRender(this, aPreviousFrameBuffer, aOffset, aOpacity, aMatrix, mOGLManager); + ContainerRender(this, aPreviousFrameBuffer, aOffset, mOGLManager); } @@ -387,11 +343,9 @@ ShadowContainerLayerOGL::GetFirstChildOGL() void ShadowContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { - ContainerRender(this, aPreviousFrameBuffer, aOffset, aOpacity, aMatrix, mOGLManager); + ContainerRender(this, aPreviousFrameBuffer, aOffset, mOGLManager); } #endif // MOZ_IPC diff --git a/gfx/layers/opengl/ContainerLayerOGL.h b/gfx/layers/opengl/ContainerLayerOGL.h index 17b634725d8d..2a1184335ddd 100644 --- a/gfx/layers/opengl/ContainerLayerOGL.h +++ b/gfx/layers/opengl/ContainerLayerOGL.h @@ -60,12 +60,8 @@ static void ContainerRender(Container* aContainer, int aPreviousFrameBuffer, const nsIntPoint& aOffset, LayerManagerOGL* aManager); -template -static bool ShouldUseIntermediate(Container* aContainer, - float aOpacity, - const gfx3DMatrix& aMatrix); -class ContainerLayerOGL : public ContainerLayer, +class ContainerLayerOGL : public ContainerLayer, public LayerOGL { template @@ -79,10 +75,6 @@ class ContainerLayerOGL : public ContainerLayer, int aPreviousFrameBuffer, const nsIntPoint& aOffset, LayerManagerOGL* aManager); - template - friend bool ShouldUseIntermediate(Container* aContainer, - float aOpacity, - const gfx3DMatrix& aMatrix); public: ContainerLayerOGL(LayerManagerOGL *aManager); @@ -100,9 +92,12 @@ public: LayerOGL* GetFirstChildOGL(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); + + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + DefaultComputeEffectiveTransforms(aTransformToSurface); + } }; #ifdef MOZ_IPC @@ -120,10 +115,6 @@ class ShadowContainerLayerOGL : public ShadowContainerLayer, int aPreviousFrameBuffer, const nsIntPoint& aOffset, LayerManagerOGL* aManager); - template - friend bool ShouldUseIntermediate(Container* aContainer, - float aOpacity, - const gfx3DMatrix& aMatrix); public: ShadowContainerLayerOGL(LayerManagerOGL *aManager); @@ -141,9 +132,12 @@ public: LayerOGL* GetFirstChildOGL(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); + + virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) + { + DefaultComputeEffectiveTransforms(aTransformToSurface); + } }; #endif // MOZ_IPC diff --git a/gfx/layers/opengl/ImageLayerOGL.cpp b/gfx/layers/opengl/ImageLayerOGL.cpp index 86ccc1930874..4fba9ddaeb5f 100644 --- a/gfx/layers/opengl/ImageLayerOGL.cpp +++ b/gfx/layers/opengl/ImageLayerOGL.cpp @@ -371,9 +371,7 @@ ImageLayerOGL::GetLayer() void ImageLayerOGL::RenderLayer(int, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { if (!GetContainer()) return; @@ -412,8 +410,8 @@ ImageLayerOGL::RenderLayer(int, program->SetLayerQuadRect(nsIntRect(0, 0, yuvImage->mSize.width, yuvImage->mSize.height)); - program->SetLayerTransform(GetEffectiveTransform() * aMatrix); - program->SetLayerOpacity(GetOpacity() * aOpacity); + program->SetLayerTransform(GetEffectiveTransform()); + program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetYCbCrTextureUnits(0, 1, 2); @@ -441,8 +439,8 @@ ImageLayerOGL::RenderLayer(int, program->SetLayerQuadRect(nsIntRect(0, 0, cairoImage->mSize.width, cairoImage->mSize.height)); - program->SetLayerTransform(GetEffectiveTransform() * aMatrix); - program->SetLayerOpacity(GetOpacity() * aOpacity); + program->SetLayerTransform(GetEffectiveTransform()); + program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); @@ -789,9 +787,7 @@ ShadowImageLayerOGL::GetLayer() void ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { mOGLManager->MakeCurrent(); @@ -805,8 +801,8 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer, program->Activate(); program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mTexImage->GetSize())); - program->SetLayerTransform(mTransform * aMatrix); - program->SetLayerOpacity(GetOpacity() * aOpacity); + program->SetLayerTransform(GetEffectiveTransform()); + program->SetLayerOpacity(GetEffectiveOpacity()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); diff --git a/gfx/layers/opengl/ImageLayerOGL.h b/gfx/layers/opengl/ImageLayerOGL.h index 09eeb4735972..c7cd8637cd77 100644 --- a/gfx/layers/opengl/ImageLayerOGL.h +++ b/gfx/layers/opengl/ImageLayerOGL.h @@ -184,9 +184,7 @@ public: virtual Layer* GetLayer(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); }; class THEBES_API PlanarYCbCrImageOGL : public PlanarYCbCrImage @@ -264,9 +262,7 @@ public: virtual Layer* GetLayer(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); private: nsRefPtr mTexImage; diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 07d317193f1c..9cee929615d7 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -404,6 +404,10 @@ LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback, return; } + // The results of our drawing always go directly into a pixel buffer, + // so we don't need to pass any global transform here. + mRoot->ComputeEffectiveTransforms(gfx3DMatrix()); + mThebesLayerCallback = aCallback; mThebesLayerCallbackData = aCallbackData; @@ -591,7 +595,7 @@ LayerManagerOGL::Render() // Render our layers. RootLayer()->RenderLayer(mGLContext->IsDoubleBuffered() ? 0 : mBackBufferFBO, - nsIntPoint(0, 0), 1.0, gfx3DMatrix()); + nsIntPoint(0, 0)); DEBUG_GL_ERROR_CHECK(mGLContext); diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index c48e0e3f8c52..798acf42145d 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -462,9 +462,7 @@ public: virtual Layer* GetLayer() = 0; virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) = 0; + const nsIntPoint& aOffset) = 0; typedef mozilla::gl::GLContext GLContext; diff --git a/gfx/layers/opengl/ThebesLayerOGL.cpp b/gfx/layers/opengl/ThebesLayerOGL.cpp index 5b0d3727b2d5..e7cb1e43a94a 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.cpp +++ b/gfx/layers/opengl/ThebesLayerOGL.cpp @@ -133,8 +133,7 @@ public: virtual PaintState BeginPaint(ContentType aContentType) = 0; - void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager, - float aOpacity, const gfx3DMatrix& aMatrix); + void RenderTo(const nsIntPoint& aOffset, LayerManagerOGL* aManager); nsIntSize GetSize() { if (mTexImage) @@ -154,9 +153,7 @@ protected: void ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset, - LayerManagerOGL* aManager, - float aOpacity, - const gfx3DMatrix& aMatrix) + LayerManagerOGL* aManager) { if (!mTexImage) return; @@ -181,8 +178,8 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset, nsIntRect quadRect = *iterRect; program->Activate(); program->SetLayerQuadRect(quadRect); - program->SetLayerOpacity(mLayer->GetOpacity() * aOpacity); - program->SetLayerTransform(mLayer->GetEffectiveTransform() * aMatrix); + program->SetLayerOpacity(mLayer->GetEffectiveOpacity()); + program->SetLayerTransform(mLayer->GetEffectiveTransform()); program->SetRenderOffset(aOffset); program->SetTextureUnit(0); DEBUG_GL_ERROR_CHECK(gl()); @@ -512,9 +509,7 @@ ThebesLayerOGL::InvalidateRegion(const nsIntRegion &aRegion) void ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { if (!mBuffer && !CreateSurface()) { return; @@ -544,7 +539,7 @@ ThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, DEBUG_GL_ERROR_CHECK(gl()); gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); - mBuffer->RenderTo(aOffset, mOGLManager, aOpacity, aMatrix); + mBuffer->RenderTo(aOffset, mOGLManager); DEBUG_GL_ERROR_CHECK(gl()); } @@ -704,9 +699,7 @@ ShadowThebesLayerOGL::IsEmpty() void ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix) + const nsIntPoint& aOffset) { if (!mBuffer) { return; @@ -718,7 +711,7 @@ ShadowThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, DEBUG_GL_ERROR_CHECK(gl()); gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); - mBuffer->RenderTo(aOffset, mOGLManager, aOpacity, aMatrix); + mBuffer->RenderTo(aOffset, mOGLManager); DEBUG_GL_ERROR_CHECK(gl()); } diff --git a/gfx/layers/opengl/ThebesLayerOGL.h b/gfx/layers/opengl/ThebesLayerOGL.h index cb6142e012a7..e604209ee92d 100644 --- a/gfx/layers/opengl/ThebesLayerOGL.h +++ b/gfx/layers/opengl/ThebesLayerOGL.h @@ -76,9 +76,7 @@ public: Layer* GetLayer(); virtual PRBool IsEmpty(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); private: friend class BasicBufferOGL; @@ -112,9 +110,7 @@ public: Layer* GetLayer(); virtual PRBool IsEmpty(); virtual void RenderLayer(int aPreviousFrameBuffer, - const nsIntPoint& aOffset, - float aOpacity, - const gfx3DMatrix& aMatrix); + const nsIntPoint& aOffset); private: nsRefPtr mBuffer; diff --git a/layout/reftests/bugs/581317-1-ref.html b/layout/reftests/bugs/581317-1-ref.html index ae5f02b11628..3316222d9def 100644 --- a/layout/reftests/bugs/581317-1-ref.html +++ b/layout/reftests/bugs/581317-1-ref.html @@ -3,7 +3,7 @@ diff --git a/layout/reftests/bugs/581317-1.html b/layout/reftests/bugs/581317-1.html index 514225a4e46d..8371765260f7 100644 --- a/layout/reftests/bugs/581317-1.html +++ b/layout/reftests/bugs/581317-1.html @@ -3,7 +3,7 @@ diff --git a/layout/reftests/bugs/602200-1-ref.html b/layout/reftests/bugs/602200-1-ref.html new file mode 100644 index 000000000000..10b364f40027 --- /dev/null +++ b/layout/reftests/bugs/602200-1-ref.html @@ -0,0 +1,6 @@ + + + +
+ + diff --git a/layout/reftests/bugs/602200-1.html b/layout/reftests/bugs/602200-1.html new file mode 100644 index 000000000000..35a1ab42a2ac --- /dev/null +++ b/layout/reftests/bugs/602200-1.html @@ -0,0 +1,12 @@ + + + + + + + diff --git a/layout/reftests/bugs/602200-2-ref.html b/layout/reftests/bugs/602200-2-ref.html new file mode 100644 index 000000000000..51b9d46786d0 --- /dev/null +++ b/layout/reftests/bugs/602200-2-ref.html @@ -0,0 +1,7 @@ + + + +
+ + diff --git a/layout/reftests/bugs/602200-2.html b/layout/reftests/bugs/602200-2.html new file mode 100644 index 000000000000..e3c917219325 --- /dev/null +++ b/layout/reftests/bugs/602200-2.html @@ -0,0 +1,16 @@ + + + +
+ +
+
+ + + diff --git a/layout/reftests/bugs/602200-3-ref.html b/layout/reftests/bugs/602200-3-ref.html new file mode 100644 index 000000000000..86dc4e038a1d --- /dev/null +++ b/layout/reftests/bugs/602200-3-ref.html @@ -0,0 +1,6 @@ + + + +
+ + diff --git a/layout/reftests/bugs/602200-3.html b/layout/reftests/bugs/602200-3.html new file mode 100644 index 000000000000..a98e26fdbaa3 --- /dev/null +++ b/layout/reftests/bugs/602200-3.html @@ -0,0 +1,15 @@ + + + +
+ +
+
+ + + diff --git a/layout/reftests/bugs/602200-4-ref.html b/layout/reftests/bugs/602200-4-ref.html new file mode 100644 index 000000000000..dd4db767372e --- /dev/null +++ b/layout/reftests/bugs/602200-4-ref.html @@ -0,0 +1,10 @@ + + + +
+
+
+
+
+ + diff --git a/layout/reftests/bugs/602200-4.html b/layout/reftests/bugs/602200-4.html new file mode 100644 index 000000000000..74053af48447 --- /dev/null +++ b/layout/reftests/bugs/602200-4.html @@ -0,0 +1,15 @@ + + + +
+
+ +
+
+ + + diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index 7ae929808359..952c1a665172 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1525,8 +1525,12 @@ fails-if(!haveTestPlugin) == 599476.html 599476-ref.html == 600045-1.html 600045-1-ref.html == 600803-1.html 600803-1-ref.html == 600974-1.html 600974-1-ref.html -== 604737.html 604737-ref.html == 600974-2.html 600974-1-ref.html == 600974-3.html 600974-1-ref.html +== 602200-1.html 602200-1-ref.html +== 602200-2.html 602200-2-ref.html +== 602200-3.html 602200-3-ref.html +== 602200-4.html 602200-4-ref.html +== 604737.html 604737-ref.html == 605138-1.html 605138-1-ref.html == 605157-1.xhtml 605157-1-ref.xhtml diff --git a/modules/plugin/test/reftest/div-alpha-opacity.html b/modules/plugin/test/reftest/div-alpha-opacity.html index 4a7ba5dc7ce8..f53404c3252f 100644 --- a/modules/plugin/test/reftest/div-alpha-opacity.html +++ b/modules/plugin/test/reftest/div-alpha-opacity.html @@ -6,6 +6,7 @@ position:absolute; left:0px; top:0px; width:400px; height:400px; + border:2px solid blue; background-color: rgb(160,160,160); opacity:0.5; z-index:1; diff --git a/modules/plugin/test/reftest/plugin-alpha-opacity.html b/modules/plugin/test/reftest/plugin-alpha-opacity.html index ae5dd53590a7..68ab5a7b7ef5 100644 --- a/modules/plugin/test/reftest/plugin-alpha-opacity.html +++ b/modules/plugin/test/reftest/plugin-alpha-opacity.html @@ -5,7 +5,8 @@ #one { position:absolute; left:0px; top:0px; - width:400px; height:400px; + width:404px; height:404px; + border:2px solid blue; opacity:.5; z-index:1; }