Bug 950312 - Part 6: Share code for computing layers component alpha support. r=roc

This commit is contained in:
Matt Woodrow 2014-05-09 22:06:20 +12:00
Родитель 96efeab991
Коммит f05c7aef5f
4 изменённых файлов: 53 добавлений и 43 удалений

Просмотреть файл

@ -31,6 +31,7 @@
#include "nsCSSValue.h" // for nsCSSValue::Array, etc
#include "nsPrintfCString.h" // for nsPrintfCString
#include "nsStyleStruct.h" // for nsTimingFunction, etc
#include "gfxPrefs.h"
using namespace mozilla::layers;
using namespace mozilla::gfx;
@ -1001,6 +1002,38 @@ ContainerLayer::DefaultComputeEffectiveTransforms(const Matrix4x4& aTransformToS
}
}
void
ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy)
{
bool supportsComponentAlphaChildren = false;
bool needsSurfaceCopy = false;
if (UseIntermediateSurface()) {
if (GetEffectiveVisibleRegion().GetNumRects() == 1 &&
(GetContentFlags() & Layer::CONTENT_OPAQUE))
{
supportsComponentAlphaChildren = true;
} else {
gfx::Matrix transform;
if (HasOpaqueAncestorLayer(this) &&
GetEffectiveTransform().Is2D(&transform) &&
!gfx::ThebesMatrix(transform).HasNonIntegerTranslation()) {
supportsComponentAlphaChildren = true;
needsSurfaceCopy = true;
}
}
} else {
supportsComponentAlphaChildren =
(GetContentFlags() & Layer::CONTENT_OPAQUE) ||
(GetParent() && GetParent()->SupportsComponentAlphaChildren());
}
mSupportsComponentAlphaChildren = supportsComponentAlphaChildren &&
gfxPrefs::ComponentAlphaEnabled();
if (aNeedsSurfaceCopy) {
*aNeedsSurfaceCopy = mSupportsComponentAlphaChildren && needsSurfaceCopy;
}
}
void
ContainerLayer::ComputeEffectiveTransformsForChildren(const Matrix4x4& aTransformToSurface)
{

Просмотреть файл

@ -1760,6 +1760,14 @@ protected:
*/
void DefaultComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface);
/**
* A default implementation to compute and set the value for SupportsComponentAlphaChildren().
*
* If aNeedsSurfaceCopy is provided, then it is set to true if the caller needs to copy the background
* up into the intermediate surface created, false otherwise.
*/
void DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy = nullptr);
/**
* Loops over the children calling ComputeEffectiveTransforms on them.
*/

Просмотреть файл

@ -47,25 +47,7 @@ public:
ToClientLayer(GetMaskLayer())->RenderLayer();
}
// Setup mSupportsComponentAlphaChildren in the same way
// that ContainerLayerComposite will do.
if (UseIntermediateSurface()) {
if (GetEffectiveVisibleRegion().GetNumRects() != 1 ||
!(GetContentFlags() & Layer::CONTENT_OPAQUE))
{
gfx::Matrix transform;
if (HasOpaqueAncestorLayer(this) &&
GetEffectiveTransform().Is2D(&transform) &&
!gfx::ThebesMatrix(transform).HasNonIntegerTranslation()) {
SetSupportsComponentAlphaChildren(
gfxPrefs::ComponentAlphaEnabled());
}
}
} else {
SetSupportsComponentAlphaChildren(
(GetContentFlags() & Layer::CONTENT_OPAQUE) ||
(GetParent() && GetParent()->SupportsComponentAlphaChildren()));
}
DefaultComputeSupportsComponentAlphaChildren();
nsAutoTArray<Layer*, 12> children;
SortChildrenBy3DZOrder(children);

Просмотреть файл

@ -252,17 +252,15 @@ ContainerRender(ContainerT* aContainer,
nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
aContainer->mSupportsComponentAlphaChildren = false;
float opacity = aContainer->GetEffectiveOpacity();
bool needsSurface = aContainer->UseIntermediateSurface();
bool surfaceCopyNeeded;
aContainer->DefaultComputeSupportsComponentAlphaChildren(&surfaceCopyNeeded);
if (needsSurface) {
SurfaceInitMode mode = INIT_MODE_CLEAR;
bool surfaceCopyNeeded = false;
gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y,
visibleRect.width, visibleRect.height);
gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.x, visibleRect.y);
// we're about to create a framebuffer backed by textures to use as an intermediate
// surface. What to do if its size (as given by framebufferRect) would exceed the
// maximum texture size supported by the GL? The present code chooses the compromise
@ -275,28 +273,19 @@ ContainerRender(ContainerT* aContainer,
if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 &&
(aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
{
// don't need a background, we're going to paint all opaque stuff
aContainer->mSupportsComponentAlphaChildren = true;
mode = INIT_MODE_NONE;
} else {
const gfx::Matrix4x4& transform3D = aContainer->GetEffectiveTransform();
gfx::Matrix transform;
// If we have an opaque ancestor layer, then we can be sure that
// all the pixels we draw into are either opaque already or will be
// covered by something opaque. Otherwise copying up the background is
// not safe.
if (ContainerLayer::HasOpaqueAncestorLayer(aContainer) &&
transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) {
surfaceCopyNeeded = gfxPrefs::ComponentAlphaEnabled();
sourcePoint.x += transform._31;
sourcePoint.y += transform._32;
aContainer->mSupportsComponentAlphaChildren
= gfxPrefs::ComponentAlphaEnabled();
}
}
sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin();
if (surfaceCopyNeeded) {
gfx::IntPoint sourcePoint = gfx::IntPoint(visibleRect.x, visibleRect.y);
gfx::Matrix4x4 transform = aContainer->GetEffectiveTransform();
DebugOnly<gfx::Matrix> transform2d;
MOZ_ASSERT(transform.Is2D(&transform2d) && !gfx::ThebesMatrix(transform2d).HasNonIntegerTranslation());
sourcePoint += gfx::IntPoint(transform._41, transform._42);
sourcePoint -= compositor->GetCurrentRenderTarget()->GetOrigin();
surface = compositor->CreateRenderTargetFromSource(surfaceRect, previousTarget, sourcePoint);
} else {
surface = compositor->CreateRenderTarget(surfaceRect, mode);
@ -309,8 +298,6 @@ ContainerRender(ContainerT* aContainer,
compositor->SetRenderTarget(surface);
} else {
surface = previousTarget;
aContainer->mSupportsComponentAlphaChildren = (aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE) ||
(aContainer->GetParent() && aContainer->GetParent()->SupportsComponentAlphaChildren());
}
nsAutoTArray<Layer*, 12> children;