Bug 1098495 - Retain a container's intermediate surface's content. r=mattwoodrow

--HG--
extra : rebase_source : cdb691c1127445eeeb2e4fda5a0ef4f2223703fc
This commit is contained in:
Benoit Girard 2014-11-18 17:33:36 -05:00
parent c85c042474
commit 2d7740df64
5 changed files with 61 additions and 28 deletions

View File

@ -151,13 +151,7 @@ struct LayerPropertiesBase : public LayerProperties
result = OldTransformedBounds();
AddRegion(result, NewTransformedBounds());
// If we don't have to generate invalidations separately for child
// layers then we can just stop here since we've already invalidated the entire
// old and new bounds.
if (!aCallback) {
ClearInvalidations(mLayer);
return result;
}
// We can't bail out early because we need to update mChildrenChanged.
}
AddRegion(result, ComputeChangeInternal(aCallback, aGeometryChanged));
@ -227,19 +221,16 @@ struct ContainerLayerProperties : public LayerPropertiesBase
ContainerLayer* container = mLayer->AsContainerLayer();
nsIntRegion result;
bool childrenChanged = false;
if (mPreXScale != container->GetPreXScale() ||
mPreYScale != container->GetPreYScale()) {
aGeometryChanged = true;
result = OldTransformedBounds();
AddRegion(result, NewTransformedBounds());
childrenChanged = true;
// If we don't have to generate invalidations separately for child
// layers then we can just stop here since we've already invalidated the entire
// old and new bounds.
if (!aCallback) {
ClearInvalidations(mLayer);
return result;
}
// Can't bail out early, we need to update the child container layers
}
// A low frame rate is especially visible to users when scrolling, so we
@ -270,13 +261,18 @@ struct ContainerLayerProperties : public LayerPropertiesBase
// encounter them in the new list):
for (uint32_t j = i; j < childsOldIndex; ++j) {
AddRegion(result, mChildren[j]->OldTransformedBounds());
childrenChanged |= true;
}
// Invalidate any regions of the child that have changed:
AddRegion(result, mChildren[childsOldIndex]->ComputeChange(aCallback, aGeometryChanged));
// Invalidate any regions of the child that have changed:
nsIntRegion region = mChildren[childsOldIndex]->ComputeChange(aCallback, aGeometryChanged);
i = childsOldIndex + 1;
if (!region.IsEmpty()) {
AddRegion(result, region);
childrenChanged |= true;
}
} else {
// We've already seen this child in mChildren (which means it must
// have been reordered) and invalidated its old area. We need to
// have been reordered) and invalidated its old area. We need to
// invalidate its new area too:
invalidateChildsCurrentArea = true;
}
@ -297,10 +293,12 @@ struct ContainerLayerProperties : public LayerPropertiesBase
ClearInvalidations(child);
}
}
childrenChanged |= invalidateChildsCurrentArea;
}
// Process remaining removed children.
while (i < mChildren.Length()) {
childrenChanged |= true;
AddRegion(result, mChildren[i]->OldTransformedBounds());
i++;
}
@ -309,7 +307,12 @@ struct ContainerLayerProperties : public LayerPropertiesBase
aCallback(container, result);
}
if (childrenChanged) {
container->SetChildrenChanged(true);
}
result.Transform(gfx::To3DMatrix(mLayer->GetLocalTransform()));
return result;
}

View File

@ -830,7 +830,8 @@ ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
mInheritedYScale(1.0f),
mUseIntermediateSurface(false),
mSupportsComponentAlphaChildren(false),
mMayHaveReadbackChild(false)
mMayHaveReadbackChild(false),
mChildrenChanged(false)
{
mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
}

View File

@ -1889,6 +1889,10 @@ public:
*/
static bool HasOpaqueAncestorLayer(Layer* aLayer);
void SetChildrenChanged(bool aVal) {
mChildrenChanged = aVal;
}
protected:
friend class ReadbackProcessor;
@ -1931,6 +1935,9 @@ protected:
bool mUseIntermediateSurface;
bool mSupportsComponentAlphaChildren;
bool mMayHaveReadbackChild;
// This is updated by ComputeDifferences. This will be true if we need to invalidate
// the intermediate surface.
bool mChildrenChanged;
};
/**

View File

@ -91,6 +91,15 @@ static void DrawLayerInfo(const RenderTargetIntRect& aClipRect,
maxWidth);
}
template<class ContainerT>
static gfx::IntRect ContainerVisibleRect(ContainerT* aContainer)
{
nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y,
visibleRect.width, visibleRect.height);
return surfaceRect;
}
static void PrintUniformityInfo(Layer* aLayer)
{
#ifdef MOZ_ENABLE_PROFILER_SPS
@ -179,14 +188,28 @@ ContainerPrepare(ContainerT* aContainer,
// DefaultComputeSupportsComponentAlphaChildren can mutate aContainer so call it unconditionally
aContainer->DefaultComputeSupportsComponentAlphaChildren(&surfaceCopyNeeded);
if (aContainer->UseIntermediateSurface()) {
MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface\n", aContainer);
if (!surfaceCopyNeeded) {
// If we don't need a copy we can render to the intermediate now to avoid
// unecessary render target switching. This brings a big perf boost on mobile gpus.
RefPtr<CompositingRenderTarget> surface = CreateTemporaryTarget(aContainer, aManager);
RenderIntermediate(aContainer, aManager, RenderTargetPixel::ToUntyped(aClipRect), surface);
RefPtr<CompositingRenderTarget> surface = nullptr;
RefPtr<CompositingRenderTarget>& lastSurf = aContainer->mLastIntermediateSurface;
gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
if (lastSurf && !aContainer->mChildrenChanged && lastSurf->GetRect().IsEqualEdges(surfaceRect)) {
surface = lastSurf;
}
if (!surface) {
// If we don't need a copy we can render to the intermediate now to avoid
// unecessary render target switching. This brings a big perf boost on mobile gpus.
surface = CreateOrRecycleTarget(aContainer, aManager);
MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface rendering\n", aContainer);
RenderIntermediate(aContainer, aManager, RenderTargetPixel::ToUntyped(aClipRect), surface);
aContainer->SetChildrenChanged(false);
}
aContainer->mPrepared->mTmpTarget = surface;
} else {
MOZ_PERFORMANCE_WARNING("gfx", "[%p] Container layer requires intermediate surface copy\n", aContainer);
aContainer->mPrepared->mNeedsSurfaceCopy = true;
aContainer->mLastIntermediateSurface = nullptr;
}
@ -269,14 +292,12 @@ RenderLayers(ContainerT* aContainer,
}
template<class ContainerT> RefPtr<CompositingRenderTarget>
CreateTemporaryTarget(ContainerT* aContainer,
CreateOrRecycleTarget(ContainerT* aContainer,
LayerManagerComposite* aManager)
{
Compositor* compositor = aManager->GetCompositor();
nsIntRect visibleRect = aContainer->GetEffectiveVisibleRegion().GetBounds();
SurfaceInitMode mode = INIT_MODE_CLEAR;
gfx::IntRect surfaceRect = gfx::IntRect(visibleRect.x, visibleRect.y,
visibleRect.width, visibleRect.height);
gfx::IntRect surfaceRect = ContainerVisibleRect(aContainer);
if (aContainer->GetEffectiveVisibleRegion().GetNumRects() == 1 &&
(aContainer->GetContentFlags() & Layer::CONTENT_OPAQUE))
{
@ -534,3 +555,4 @@ RefLayerComposite::CleanupResources()
} /* layers */
} /* mozilla */

View File

@ -48,7 +48,7 @@ class ContainerLayerComposite : public ContainerLayer,
const RenderTargetIntRect& aClipRect);
template<class ContainerT>
friend RefPtr<CompositingRenderTarget>
CreateTemporaryTarget(ContainerT* aContainer,
CreateOrRecycleTarget(ContainerT* aContainer,
LayerManagerComposite* aManager,
const RenderTargetIntRect& aClipRect);