Bug 805028 - Add LayerManagerOGL::ComputeRenderIntegrity. r=bgirard

Add a function to LayerManagerOGL that can compute how much of the last
rendered area was incomplete (i.e. is pending update when progressive tile
drawing is enabled).
This commit is contained in:
Chris Lord 2012-10-25 17:23:42 +01:00
Родитель c09613205b
Коммит 0206c993d6
2 изменённых файлов: 100 добавлений и 0 удалений

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

@ -1453,5 +1453,87 @@ LayerManagerOGL::CreateDrawTarget(const IntSize &aSize,
return LayerManager::CreateDrawTarget(aSize, aFormat); return LayerManager::CreateDrawTarget(aSize, aFormat);
} }
/* static */ void
LayerManagerOGL::ComputeRenderIntegrityInternal(Layer* aLayer,
nsIntRegion& aScreenRegion,
const gfx3DMatrix& aTransform)
{
if (aScreenRegion.IsEmpty() || aLayer->GetOpacity() <= 0.f) {
return;
}
// If the layer's a container, recurse into all of its children
ContainerLayer* container = aLayer->AsContainerLayer();
if (container) {
// Accumulate the transform of intermediate surfaces
gfx3DMatrix transform = aTransform;
if (container->UseIntermediateSurface()) {
transform = aLayer->GetEffectiveTransform();
transform.PreMultiply(aTransform);
}
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
ComputeRenderIntegrityInternal(child, aScreenRegion, transform);
}
return;
}
// Only thebes layers can be incomplete
ThebesLayer* thebesLayer = aLayer->AsThebesLayer();
if (!thebesLayer) {
return;
}
// See if there's any incomplete rendering
nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion();
incompleteRegion.Sub(incompleteRegion, thebesLayer->GetValidRegion());
if (!incompleteRegion.IsEmpty()) {
// Calculate the transform to get between screen and layer space
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));
}
}
}
float
LayerManagerOGL::ComputeRenderIntegrity()
{
// We only ever have incomplete rendering when progressive tiles are enabled.
if (!gfxPlatform::UseProgressiveTilePainting() || !GetRoot()) {
return 1.f;
}
// XXX We assume that mWidgetSize represents the 'screen' area.
gfx3DMatrix transform;
nsIntRect screenRect(0, 0, mWidgetSize.width, mWidgetSize.height);
nsIntRegion screenRegion(screenRect);
ComputeRenderIntegrityInternal(GetRoot(), screenRegion, 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;
}
return area / (float)(screenRect.width * screenRect.height);
}
return 1.f;
}
} /* layers */ } /* layers */
} /* mozilla */ } /* mozilla */

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

@ -361,6 +361,15 @@ public:
CreateDrawTarget(const mozilla::gfx::IntSize &aSize, CreateDrawTarget(const mozilla::gfx::IntSize &aSize,
mozilla::gfx::SurfaceFormat aFormat); mozilla::gfx::SurfaceFormat aFormat);
/**
* Calculates the 'completeness' of the rendering that intersected with the
* screen on the last render. This is only useful when progressive tile
* drawing is enabled, otherwise this will always return 1.0.
* This function's expense scales with the size of the layer tree and the
* complexity of individual layers' valid regions.
*/
float ComputeRenderIntegrity();
private: private:
/** Widget associated with this layer manager */ /** Widget associated with this layer manager */
nsIWidget *mWidget; nsIWidget *mWidget;
@ -440,6 +449,15 @@ private:
*/ */
void AddPrograms(gl::ShaderProgramType aType); void AddPrograms(gl::ShaderProgramType aType);
/**
* Recursive helper method for use by ComputeRenderIntegrity. Subtracts
* any incomplete rendering on aLayer from aScreenRegion. aTransform is the
* accumulated transform of intermediate surfaces beneath aLayer.
*/
static void ComputeRenderIntegrityInternal(Layer* aLayer,
nsIntRegion& aScreenRegion,
const gfx3DMatrix& aTransform);
/* Thebes layer callbacks; valid at the end of a transaciton, /* Thebes layer callbacks; valid at the end of a transaciton,
* while rendering */ * while rendering */
DrawThebesLayerCallback mThebesLayerCallback; DrawThebesLayerCallback mThebesLayerCallback;