From 0356f8659eac387c2216dda436e544e535eccca6 Mon Sep 17 00:00:00 2001 From: Robert O'Callahan Date: Thu, 2 Sep 2010 21:18:40 +1200 Subject: [PATCH] Bug 579276. Part 3: Change Set/IsOpaqueContent API to a more generic Get/SetContentFlags API. r=cjones,sr=vlad --- content/canvas/src/WebGLContext.cpp | 4 +- .../canvas/src/nsCanvasRenderingContext2D.cpp | 3 +- gfx/layers/Layers.cpp | 20 ++++++--- gfx/layers/Layers.h | 42 ++++++++++++++----- gfx/layers/basic/BasicLayers.cpp | 4 +- gfx/layers/d3d9/ThebesLayerD3D9.cpp | 36 ++++------------ gfx/layers/ipc/PLayers.ipdl | 2 +- gfx/layers/ipc/ShadowLayers.cpp | 2 +- gfx/layers/ipc/ShadowLayersParent.cpp | 2 +- layout/base/FrameLayerBuilder.cpp | 6 ++- 10 files changed, 68 insertions(+), 53 deletions(-) diff --git a/content/canvas/src/WebGLContext.cpp b/content/canvas/src/WebGLContext.cpp index c3505863563..89bb9d15f40 100644 --- a/content/canvas/src/WebGLContext.cpp +++ b/content/canvas/src/WebGLContext.cpp @@ -63,6 +63,7 @@ using namespace mozilla; using namespace mozilla::gl; +using namespace mozilla::layers; nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult); @@ -548,7 +549,8 @@ WebGLContext::GetCanvasLayer(CanvasLayer *aOldLayer, data.mGLBufferIsPremultiplied = PR_FALSE; canvasLayer->Initialize(data); - canvasLayer->SetIsOpaqueContent(gl->CreationFormat().alpha == 0 ? PR_TRUE : PR_FALSE); + PRUint32 flags = gl->CreationFormat().alpha == 0 ? Layer::CONTENT_OPAQUE : 0; + canvasLayer->SetContentFlags(flags); canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); mInvalidated = PR_FALSE; diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index d76eee6f82e..49a9e52f909 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -4174,7 +4174,8 @@ nsCanvasRenderingContext2D::GetCanvasLayer(CanvasLayer *aOldLayer, data.mSize = nsIntSize(mWidth, mHeight); canvasLayer->Initialize(data); - canvasLayer->SetIsOpaqueContent(mOpaque); + PRUint32 flags = mOpaque ? Layer::CONTENT_OPAQUE : 0; + canvasLayer->SetContentFlags(flags); canvasLayer->Updated(nsIntRect(0, 0, mWidth, mHeight)); mResetLayer = PR_FALSE; diff --git a/gfx/layers/Layers.cpp b/gfx/layers/Layers.cpp index cccbd3d76a4..d622b01a5e9 100644 --- a/gfx/layers/Layers.cpp +++ b/gfx/layers/Layers.cpp @@ -147,7 +147,7 @@ Layer::CanUseOpaqueSurface() { // If the visible content in the layer is opaque, there is no need // for an alpha channel. - if (IsOpaqueContent()) + if (GetContentFlags() & CONTENT_OPAQUE) return PR_TRUE; // Also, if this layer is the bottommost layer in a container which // doesn't need an alpha channel, we can use an opaque surface for this @@ -221,14 +221,24 @@ Layer::PrintInfo(nsACString& aTo, const char* aPrefix) if (mUseClipRect) { AppendToString(aTo, mClipRect, " [clip=", "]"); } - if (!mTransform.IsIdentity()) + if (!mTransform.IsIdentity()) { AppendToString(aTo, mTransform, " [transform=", "]"); - if (!mVisibleRegion.IsEmpty()) + } + if (!mVisibleRegion.IsEmpty()) { AppendToString(aTo, mVisibleRegion, " [visible=", "]"); - if (1.0 != mOpacity) + } + if (1.0 != mOpacity) { aTo.AppendPrintf(" [opacity=%g]", mOpacity); - if (IsOpaqueContent()) + } + if (GetContentFlags() & CONTENT_OPAQUE) { aTo += " [opaqueContent]"; + } + if (GetContentFlags() & CONTENT_NO_TEXT) { + aTo += " [noText]"; + } + if (GetContentFlags() & CONTENT_NO_TEXT_OVER_TRANSPARENT) { + aTo += " [noTextOverTransparent]"; + } return aTo; } diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 6643d60f006..fe1e996f297 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -416,17 +416,37 @@ public: */ LayerManager* Manager() { return mManager; } + enum { + /** + * If this is set, the caller is promising that by the end of this + * transaction the entire visible region (as specified by + * SetVisibleRegion) will be filled with opaque content. + */ + CONTENT_OPAQUE = 0x01, + /** + * ThebesLayers only! + * If this is set, the caller is promising that the visible region + * contains no text at all. If this is set, + * CONTENT_NO_TEXT_OVER_TRANSPARENT will also be set. + */ + CONTENT_NO_TEXT = 0x02, + /** + * ThebesLayers only! + * If this is set, the caller is promising that the visible region + * contains no text over transparent pixels (any text, if present, + * is over fully opaque pixels). + */ + CONTENT_NO_TEXT_OVER_TRANSPARENT = 0x04 + }; /** * CONSTRUCTION PHASE ONLY - * If this is called with aOpaque set to true, the caller is promising - * that by the end of this transaction the entire visible region - * (as specified by SetVisibleRegion) will be filled with opaque - * content. This enables some internal quality and performance - * optimizations. + * This lets layout make some promises about what will be drawn into the + * visible region of the ThebesLayer. This enables internal quality + * and performance optimizations. */ - void SetIsOpaqueContent(PRBool aOpaque) + void SetContentFlags(PRUint32 aFlags) { - mIsOpaqueContent = aOpaque; + mContentFlags = aFlags; Mutated(); } /** @@ -509,7 +529,7 @@ public: // These getters can be used anytime. float GetOpacity() { return mOpacity; } const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nsnull; } - PRBool IsOpaqueContent() { return mIsOpaqueContent; } + PRUint32 GetContentFlags() { return mContentFlags; } const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; } ContainerLayer* GetParent() { return mParent; } Layer* GetNextSibling() { return mNextSibling; } @@ -610,8 +630,8 @@ protected: mPrevSibling(nsnull), mImplData(aImplData), mOpacity(1.0), - mUseClipRect(PR_FALSE), - mIsOpaqueContent(PR_FALSE) + mContentFlags(0), + mUseClipRect(PR_FALSE) {} void Mutated() { mManager->Mutated(this); } @@ -633,8 +653,8 @@ protected: gfx3DMatrix mTransform; float mOpacity; nsIntRect mClipRect; + PRUint32 mContentFlags; PRPackedBool mUseClipRect; - PRPackedBool mIsOpaqueContent; }; /** diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index 217ad592637..1cbac945e8a 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -682,7 +682,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect) if (mGLContext) { nsRefPtr isurf = new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height), - IsOpaqueContent() + (GetContentFlags() & CONTENT_OPAQUE) ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32); if (!isurf || isurf->CairoStatus() != 0) { @@ -793,7 +793,7 @@ MayHaveOverlappingOrTransparentLayers(Layer* aLayer, const nsIntRect& aBounds, nsIntRegion* aDirtyVisibleRegionInContainer) { - if (!aLayer->IsOpaqueContent()) { + if (!(aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE)) { return PR_TRUE; } diff --git a/gfx/layers/d3d9/ThebesLayerD3D9.cpp b/gfx/layers/d3d9/ThebesLayerD3D9.cpp index 438e73f0eea..8e7092a4f08 100644 --- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp +++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp @@ -46,27 +46,6 @@ namespace mozilla { namespace layers { -// Returns true if it's OK to save the contents of aLayer in an -// opaque surface (a surface without an alpha channel). -// If we can use a surface without an alpha channel, we should, because -// it will often make painting of antialiased text faster and higher -// quality. -static PRBool -UseOpaqueSurface(Layer* aLayer) -{ - // If the visible content in the layer is opaque, there is no need - // for an alpha channel. - if (aLayer->IsOpaqueContent()) - return PR_TRUE; - // Also, if this layer is the bottommost layer in a container which - // doesn't need an alpha channel, we can use an opaque surface for this - // layer too. Any transparent areas must be covered by something else - // in the container. - ContainerLayer* parent = aLayer->GetParent(); - return parent && parent->GetFirstChild() == aLayer && - UseOpaqueSurface(parent); -} - ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager) : ThebesLayer(aManager, NULL) , LayerD3D9(aManager) @@ -105,7 +84,7 @@ ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion) return; } - D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ? + D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; D3DSURFACE_DESC desc; @@ -199,7 +178,7 @@ ThebesLayerD3D9::RenderLayer() // We differentiate between these formats since D3D9 will only allow us to // call GetDC on an opaque surface. - D3DFORMAT fmt = (UseOpaqueSurface(this) && !mD2DSurface) ? + D3DFORMAT fmt = (CanUseOpaqueSurface() && !mD2DSurface) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; if (mTexture) { @@ -319,7 +298,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) } #endif - D3DFORMAT fmt = UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; + D3DFORMAT fmt = CanUseOpaqueSurface() ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8; nsIntRect bounds = aRegion.GetBounds(); gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32; @@ -332,7 +311,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) nsRefPtr surf; HDC dc; - if (UseOpaqueSurface(this)) { + if (CanUseOpaqueSurface()) { hr = tmpTexture->GetSurfaceLevel(0, getter_AddRefs(surf)); if (FAILED(hr)) { @@ -365,7 +344,7 @@ ThebesLayerD3D9::DrawRegion(const nsIntRegion &aRegion) LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData); - if (UseOpaqueSurface(this)) { + if (CanUseOpaqueSurface()) { surf->ReleaseDC(dc); } else { D3DLOCKED_RECT r; @@ -418,6 +397,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) } mTexture = nsnull; + PRBool canUseOpaqueSurface = CanUseOpaqueSurface(); #ifdef CAIRO_HAS_D2D_SURFACE if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D) { @@ -429,7 +409,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) D3DPOOL_DEFAULT, getter_AddRefs(mTexture), &sharedHandle); mD2DSurfaceInitialized = false; - mD2DSurface = new gfxD2DSurface(sharedHandle, UseOpaqueSurface(this) ? + mD2DSurface = new gfxD2DSurface(sharedHandle, canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA); // If there's an error, go on and do what we always do. @@ -442,7 +422,7 @@ ThebesLayerD3D9::CreateNewTexture(const gfxIntSize &aSize) #endif if (!mTexture) { device()->CreateTexture(aSize.width, aSize.height, 1, - D3DUSAGE_RENDERTARGET, UseOpaqueSurface(this) ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, + D3DUSAGE_RENDERTARGET, canUseOpaqueSurface ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL); } } diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl index 7f90abff46c..fdde16ca689 100644 --- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -93,7 +93,7 @@ struct OpCreateImageBuffer { struct CommonLayerAttributes { nsIntRegion visibleRegion; gfx3DMatrix transform; - bool isOpaqueContent; + PRUint32 contentFlags; float opacity; bool useClipRect; nsIntRect clipRect; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index f0222eb63c0..dc6b1ea6de3 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -271,7 +271,7 @@ ShadowLayerForwarder::EndTransaction(nsTArray* aReplies) CommonLayerAttributes& common = attrs.common(); common.visibleRegion() = mutant->GetVisibleRegion(); common.transform() = mutant->GetTransform(); - common.isOpaqueContent() = mutant->IsOpaqueContent(); + common.contentFlags() = mutant->GetContentFlags(); common.opacity() = mutant->GetOpacity(); common.useClipRect() = !!mutant->GetClipRect(); common.clipRect() = (common.useClipRect() ? diff --git a/gfx/layers/ipc/ShadowLayersParent.cpp b/gfx/layers/ipc/ShadowLayersParent.cpp index 9b4b7142813..e61d886bce3 100644 --- a/gfx/layers/ipc/ShadowLayersParent.cpp +++ b/gfx/layers/ipc/ShadowLayersParent.cpp @@ -229,7 +229,7 @@ ShadowLayersParent::RecvUpdate(const nsTArray& cset, const CommonLayerAttributes& common = attrs.common(); layer->SetVisibleRegion(common.visibleRegion()); - layer->SetIsOpaqueContent(common.isOpaqueContent()); + layer->SetContentFlags(common.contentFlags()); layer->SetOpacity(common.opacity()); layer->SetClipRect(common.useClipRect() ? &common.clipRect() : NULL); layer->SetTransform(common.transform()); diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 1932ea1a512..d35fa352770 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -839,7 +839,8 @@ ContainerState::PopThebesLayerData() } userData->mForcedBackgroundColor = backgroundColor; } - layer->SetIsOpaqueContent(isOpaque); + PRUint32 flags = isOpaque ? Layer::CONTENT_OPAQUE : 0; + layer->SetContentFlags(flags); if (lastIndex > 0) { // Since we're going to pop off the last ThebesLayerData, the @@ -1361,7 +1362,8 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder, state.ProcessDisplayItems(aChildren, nsnull); state.Finish(); - containerLayer->SetIsOpaqueContent(aChildren.IsOpaque()); + PRUint32 flags = aChildren.IsOpaque() ? Layer::CONTENT_OPAQUE : 0; + containerLayer->SetContentFlags(flags); return containerLayer.forget(); }