Bug 814437 - Fix checkerboard measurement when using a critical displayport. r=bgirard

The checkerboard measurement depended on the displayport coverage of the
viewport, which was calculated in LayerRenderer. When using a critical
displayport, this value changes, but this was not being accounted for.

We have all the context we need for this Gecko-side, so move this code into
LayerManagerOGL::ComputeRenderIntegrity and account for displayport coverage
correctly.
This commit is contained in:
Chris Lord 2012-11-29 12:03:38 +00:00
Родитель 7d410314ef
Коммит 53958037df
2 изменённых файлов: 76 добавлений и 46 удалений

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

@ -1702,20 +1702,87 @@ GetRegionArea(const nsIntRegion& aRegion)
return area;
}
static float
GetDisplayportCoverage(const gfx::Rect& aDisplayPort,
const gfx3DMatrix& aTransformToScreen,
const nsIntRect& aScreenRect)
{
gfxRect transformedDisplayport =
aTransformToScreen.TransformBounds(gfxRect(aDisplayPort.x,
aDisplayPort.y,
aDisplayPort.width,
aDisplayPort.height));
transformedDisplayport.RoundOut();
nsIntRect displayport = nsIntRect(transformedDisplayport.x,
transformedDisplayport.y,
transformedDisplayport.width,
transformedDisplayport.height);
if (!displayport.Contains(aScreenRect)) {
nsIntRegion coveredRegion;
coveredRegion.And(aScreenRect, displayport);
return GetRegionArea(coveredRegion) / (float)(aScreenRect.width * aScreenRect.height);
}
return 1.0f;
}
float
LayerManagerOGL::ComputeRenderIntegrity()
{
// We only ever have incomplete rendering when progressive tiles are enabled.
if (!gfxPlatform::UseProgressiveTilePainting() || !GetRoot()) {
Layer* root = GetRoot();
if (!gfxPlatform::UseProgressiveTilePainting() || !root) {
return 1.f;
}
// XXX We assume that mWidgetSize represents the 'screen' area.
gfx3DMatrix transform;
nsIntRect screenRect(0, 0, mWidgetSize.width, mWidgetSize.height);
const FrameMetrics& rootMetrics = root->AsContainerLayer()->GetFrameMetrics();
nsIntRect screenRect(rootMetrics.mCompositionBounds.x,
rootMetrics.mCompositionBounds.y,
rootMetrics.mCompositionBounds.width,
rootMetrics.mCompositionBounds.height);
float lowPrecisionMultiplier = 1.0f;
float highPrecisionMultiplier = 1.0f;
#ifdef MOZ_ANDROID_OMTC
// Use the transform on the primary scrollable layer and its FrameMetrics
// to find out how much of the viewport the current displayport covers
bool hasLowPrecision = true;
Layer* primaryScrollable = GetPrimaryScrollableLayer();
if (primaryScrollable) {
// This is derived from the code in
// gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree.
const gfx3DMatrix& rootTransform = root->GetTransform();
float devPixelRatioX = 1 / rootTransform.GetXScale();
float devPixelRatioY = 1 / rootTransform.GetYScale();
gfx3DMatrix transform = primaryScrollable->GetEffectiveTransform();
transform.ScalePost(devPixelRatioX, devPixelRatioY, 1);
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
// Work out how much of the critical display-port covers the screen
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
hasLowPrecision = true;
highPrecisionMultiplier =
GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect);
}
// Work out how much of the display-port covers the screen
if (!metrics.mDisplayPort.IsEmpty()) {
if (hasLowPrecision) {
lowPrecisionMultiplier =
GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
} else {
highPrecisionMultiplier =
GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect);
}
}
}
#endif
nsIntRegion screenRegion(screenRect);
nsIntRegion lowPrecisionScreenRegion(screenRect);
ComputeRenderIntegrityInternal(GetRoot(), screenRegion,
gfx3DMatrix transform;
ComputeRenderIntegrityInternal(root, screenRegion,
lowPrecisionScreenRegion, transform);
if (!screenRegion.IsEqual(screenRect)) {
@ -1728,7 +1795,8 @@ LayerManagerOGL::ComputeRenderIntegrity()
lowPrecisionIntegrity = GetRegionArea(lowPrecisionScreenRegion) / screenArea;
}
return (highPrecisionIntegrity + lowPrecisionIntegrity) / 2.f;
return ((highPrecisionIntegrity * highPrecisionMultiplier) +
(lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2.f;
}
return 1.f;

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

@ -598,46 +598,8 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
Layer rootLayer = mView.getLayerClient().getRoot();
if ((rootLayer != null) &&
(mProfileRender || PanningPerfAPI.isRecordingCheckerboard())) {
// Find out how much of the viewport area is valid
Rect viewport = RectUtils.round(mPageContext.viewport);
Region validRegion = rootLayer.getValidRegion(mPageContext);
/* restrict the viewport to page bounds so we don't
* count overscroll as checkerboard */
if (!viewport.intersect(mAbsolutePageRect)) {
/* if the rectangles don't intersect
intersect() doesn't change viewport
so we set it to empty by hand */
viewport.setEmpty();
}
validRegion.op(viewport, Region.Op.INTERSECT);
// Check if we have total checkerboarding (there's visible
// page area and the valid region doesn't intersect with the
// viewport).
int screenArea = viewport.width() * viewport.height();
float checkerboard = (screenArea > 0 &&
validRegion.quickReject(viewport)) ? 1.0f : 0.0f;
if (screenArea > 0 && checkerboard < 1.0f) {
validRegion.op(viewport, Region.Op.REVERSE_DIFFERENCE);
// XXX The assumption here is that a Region never has overlapping
// rects. This is true, as evidenced by reading the SkRegion
// source, but is not mentioned in the Android documentation,
// and so is liable to change.
// If it does change, this code will need to be reevaluated.
Rect r = new Rect();
int checkerboardArea = 0;
for (RegionIterator i = new RegionIterator(validRegion); i.next(r);) {
checkerboardArea += r.width() * r.height();
}
checkerboard = checkerboardArea / (float)screenArea;
// Add any incomplete rendering in the screen area
checkerboard += (1.0 - checkerboard) * (1.0 - GeckoAppShell.computeRenderIntegrity());
}
// Calculate the incompletely rendered area of the page
float checkerboard = 1.0f - GeckoAppShell.computeRenderIntegrity();
PanningPerfAPI.recordCheckerboard(checkerboard);