Bug 579276. Part 3: Change Set/IsOpaqueContent API to a more generic Get/SetContentFlags API. r=cjones,sr=vlad

This commit is contained in:
Robert O'Callahan 2010-09-02 21:18:40 +12:00
parent ad566be621
commit 0356f8659e
10 changed files with 68 additions and 53 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};
/**

View File

@ -682,7 +682,7 @@ BasicCanvasLayer::Updated(const nsIntRect& aRect)
if (mGLContext) {
nsRefPtr<gfxImageSurface> 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;
}

View File

@ -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<IDirect3DSurface9> 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);
}
}

View File

@ -93,7 +93,7 @@ struct OpCreateImageBuffer {
struct CommonLayerAttributes {
nsIntRegion visibleRegion;
gfx3DMatrix transform;
bool isOpaqueContent;
PRUint32 contentFlags;
float opacity;
bool useClipRect;
nsIntRect clipRect;

View File

@ -271,7 +271,7 @@ ShadowLayerForwarder::EndTransaction(nsTArray<EditReply>* 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() ?

View File

@ -229,7 +229,7 @@ ShadowLayersParent::RecvUpdate(const nsTArray<Edit>& 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());

View File

@ -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();
}