Bug 814437 - Count low precision rendering 0.5x towards checkerboarding. r=bgirard

This commit is contained in:
Chris Lord 2012-11-29 12:03:27 +00:00
parent 261e6627b6
commit 7d410314ef
4 changed files with 58 additions and 18 deletions

View File

@ -1146,6 +1146,7 @@ public:
* Can be used anytime
*/
const nsIntRegion& GetValidRegion() const { return mValidRegion; }
virtual const nsIntRegion& GetValidLowPrecisionRegion() const { return mValidRegion; }
virtual ThebesLayer* AsThebesLayer() { return this; }

View File

@ -1618,12 +1618,35 @@ LayerManagerOGL::CreateDrawTarget(const IntSize &aSize,
return LayerManager::CreateDrawTarget(aSize, aFormat);
}
static void
SubtractTransformedRegion(nsIntRegion& aRegion,
const nsIntRegion& aRegionToSubtract,
const gfx3DMatrix& aTransform)
{
if (aRegionToSubtract.IsEmpty()) {
return;
}
// For each rect in the region, find out its bounds in screen space and
// subtract it from the screen region.
nsIntRegionRectIterator it(aRegionToSubtract);
while (const nsIntRect* rect = it.Next()) {
gfxRect incompleteRect = aTransform.TransformBounds(gfxRect(*rect));
aRegion.Sub(aRegion, nsIntRect(incompleteRect.x,
incompleteRect.y,
incompleteRect.width,
incompleteRect.height));
}
}
/* static */ void
LayerManagerOGL::ComputeRenderIntegrityInternal(Layer* aLayer,
nsIntRegion& aScreenRegion,
nsIntRegion& aLowPrecisionScreenRegion,
const gfx3DMatrix& aTransform)
{
if (aScreenRegion.IsEmpty() || aLayer->GetOpacity() <= 0.f) {
if (aLayer->GetOpacity() <= 0.f ||
(aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) {
return;
}
@ -1638,7 +1661,7 @@ LayerManagerOGL::ComputeRenderIntegrityInternal(Layer* aLayer,
}
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
ComputeRenderIntegrityInternal(child, aScreenRegion, transform);
ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform);
}
return;
}
@ -1658,19 +1681,27 @@ LayerManagerOGL::ComputeRenderIntegrityInternal(Layer* aLayer,
gfx3DMatrix transformToScreen = aLayer->GetEffectiveTransform();
transformToScreen.PreMultiply(aTransform);
// For each rect in the region, find out its bounds in screen space and
// subtract it from the screen region.
nsIntRegionRectIterator it(incompleteRegion);
while (const nsIntRect* rect = it.Next()) {
gfxRect incompleteRect = transformToScreen.TransformBounds(gfxRect(*rect));
aScreenRegion.Sub(aScreenRegion, nsIntRect(incompleteRect.x,
incompleteRect.y,
incompleteRect.width,
incompleteRect.height));
SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen);
// See if there's any incomplete low-precision rendering
incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidLowPrecisionRegion());
if (!incompleteRegion.IsEmpty()) {
SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen);
}
}
}
static int
GetRegionArea(const nsIntRegion& aRegion)
{
int area = 0;
nsIntRegionRectIterator it(aRegion);
while (const nsIntRect* rect = it.Next()) {
area += rect->width * rect->height;
}
return area;
}
float
LayerManagerOGL::ComputeRenderIntegrity()
{
@ -1683,18 +1714,21 @@ LayerManagerOGL::ComputeRenderIntegrity()
gfx3DMatrix transform;
nsIntRect screenRect(0, 0, mWidgetSize.width, mWidgetSize.height);
nsIntRegion screenRegion(screenRect);
ComputeRenderIntegrityInternal(GetRoot(), screenRegion, transform);
nsIntRegion lowPrecisionScreenRegion(screenRect);
ComputeRenderIntegrityInternal(GetRoot(), screenRegion,
lowPrecisionScreenRegion, transform);
if (!screenRegion.IsEqual(screenRect)) {
// Calculate the area of the region. All rects in an nsRegion are
// non-overlapping.
int area = 0;
nsIntRegionRectIterator it(screenRegion);
while (const nsIntRect* rect = it.Next()) {
area += rect->width * rect->height;
float screenArea = screenRect.width * screenRect.height;
float highPrecisionIntegrity = GetRegionArea(screenRegion) / screenArea;
float lowPrecisionIntegrity = 1.f;
if (!lowPrecisionScreenRegion.IsEqual(screenRect)) {
lowPrecisionIntegrity = GetRegionArea(lowPrecisionScreenRegion) / screenArea;
}
return area / (float)(screenRect.width * screenRect.height);
return (highPrecisionIntegrity + lowPrecisionIntegrity) / 2.f;
}
return 1.f;

View File

@ -399,11 +399,13 @@ private:
/**
* Recursive helper method for use by ComputeRenderIntegrity. Subtracts
* any incomplete rendering on aLayer from aScreenRegion. aTransform is the
* any incomplete rendering on aLayer from aScreenRegion. Any low-precision
* rendering is included in aLowPrecisionScreenRegion. aTransform is the
* accumulated transform of intermediate surfaces beneath aLayer.
*/
static void ComputeRenderIntegrityInternal(Layer* aLayer,
nsIntRegion& aScreenRegion,
nsIntRegion& aLowPrecisionScreenRegion,
const gfx3DMatrix& aTransform);
/* Thebes layer callbacks; valid at the end of a transaciton,

View File

@ -113,6 +113,9 @@ public:
TiledThebesLayerOGL(LayerManagerOGL *aManager);
virtual ~TiledThebesLayerOGL();
// Layer implementation
const nsIntRegion& GetValidLowPrecisionRegion() const { return mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion(); }
// LayerOGL impl
void Destroy() {}
Layer* GetLayer() { return this; }