Bug 1013385 - Add the layer bounds to the layers API and use it for checkerboarding. r=mattwoodrow,BenWa

This commit is contained in:
Kartikaya Gupta 2014-09-15 16:09:52 -04:00
parent 999a08b6c5
commit 6b0862f4b0
9 changed files with 100 additions and 2 deletions

View File

@ -1467,6 +1467,9 @@ Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
if (!mTransform.IsIdentity()) {
AppendToString(aStream, mTransform, " [transform=", "]");
}
if (!mLayerBounds.IsEmpty()) {
AppendToString(aStream, mLayerBounds, " [bounds=", "]");
}
if (!mVisibleRegion.IsEmpty()) {
AppendToString(aStream, mVisibleRegion, " [visible=", "]");
} else {

View File

@ -805,6 +805,24 @@ public:
Mutated();
}
}
/**
* CONSTRUCTION PHASE ONLY
* The union of the bounds of all the display item that got flattened
* into this layer. This is intended to be an approximation to the
* size of the layer if the nearest scrollable ancestor had an infinitely
* large displayport. Computing this more exactly is too expensive,
* but this approximation is sufficient for what we need to use it for.
*/
virtual void SetLayerBounds(const nsIntRect& aLayerBounds)
{
if (!mLayerBounds.IsEqualEdges(aLayerBounds)) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) LayerBounds", this));
mLayerBounds = aLayerBounds;
Mutated();
}
}
/**
* CONSTRUCTION PHASE ONLY
* Tell this layer which region will be visible. The visible region
@ -1178,6 +1196,7 @@ public:
gfx::CompositionOp GetMixBlendMode() const { return mMixBlendMode; }
const nsIntRect* GetClipRect() { return mUseClipRect ? &mClipRect : nullptr; }
uint32_t GetContentFlags() { return mContentFlags; }
const nsIntRect& GetLayerBounds() const { return mLayerBounds; }
const nsIntRegion& GetVisibleRegion() const { return mVisibleRegion; }
const FrameMetrics& GetFrameMetrics(uint32_t aIndex) const;
uint32_t GetFrameMetricsCount() const { return mFrameMetrics.Length(); }
@ -1589,6 +1608,7 @@ protected:
void* mImplData;
nsRefPtr<Layer> mMaskLayer;
gfx::UserData mUserData;
nsIntRect mLayerBounds;
nsIntRegion mVisibleRegion;
nsTArray<FrameMetrics> mFrameMetrics;
EventRegions mEventRegions;

View File

@ -2620,6 +2620,19 @@ Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
Matrix4x4().Scale(zoomChange, zoomChange, 1);
}
bool AsyncPanZoomController::IsCurrentlyCheckerboarding() const {
ReentrantMonitorAutoEnter lock(mMonitor);
if (!gfxPrefs::APZAllowCheckerboarding()) {
return false;
}
CSSPoint currentScrollOffset = mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset;
CSSRect painted = mLastContentPaintMetrics.mDisplayPort + mLastContentPaintMetrics.GetScrollOffset();
CSSRect visible = CSSRect(currentScrollOffset, mFrameMetrics.CalculateCompositedSizeInCssPixels());
return !painted.Contains(visible);
}
void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) {
AssertOnCompositorThread();

View File

@ -240,6 +240,14 @@ public:
*/
Matrix4x4 GetTransformToLastDispatchedPaint() const;
/**
* Returns whether or not the APZC is currently in a state of checkerboarding.
* This is a simple computation based on the last-painted content and whether
* the async transform has pushed it so far that it doesn't fully contain the
* composition bounds.
*/
bool IsCurrentlyCheckerboarding() const;
/**
* Recalculates the displayport. Ideally, this should paint an area bigger
* than the composite-to dimensions so that when you scroll down, you don't

View File

@ -48,6 +48,24 @@ namespace layers {
using namespace gfx;
static bool
LayerHasCheckerboardingAPZC(Layer* aLayer, gfxRGBA* aOutColor)
{
for (LayerMetricsWrapper i(aLayer, LayerMetricsWrapper::StartAt::BOTTOM); i; i = i.GetParent()) {
if (!i.Metrics().IsScrollable()) {
continue;
}
if (i.GetApzc() && i.GetApzc()->IsCurrentlyCheckerboarding()) {
if (aOutColor) {
*aOutColor = i.Metrics().GetBackgroundColor();
}
return true;
}
break;
}
return false;
}
/**
* Returns a rectangle of content painted opaquely by aLayer. Very consertative;
* bails by returning an empty rect in any tricky situations.
@ -180,12 +198,14 @@ ContainerPrepare(ContainerT* aContainer,
if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty() &&
!layerToRender->GetLayer()->AsContainerLayer()) {
CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer());
continue;
}
RenderTargetIntRect clipRect = layerToRender->GetLayer()->
CalculateScissorRect(aClipRect);
if (clipRect.IsEmpty()) {
CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
continue;
}
@ -195,7 +215,9 @@ ContainerPrepare(ContainerT* aContainer,
Compositor* compositor = aManager->GetCompositor();
if (!layerToRender->GetLayer()->AsContainerLayer() &&
!quad.Intersects(compositor->ClipRectInLayersCoordinates(layerToRender->GetLayer(), clipRect))) {
!quad.Intersects(compositor->ClipRectInLayersCoordinates(layerToRender->GetLayer(), clipRect)) &&
!LayerHasCheckerboardingAPZC(layerToRender->GetLayer(), nullptr)) {
CULLING_LOG("Sublayer %p is clipped entirely\n", layerToRender->GetLayer());
continue;
}
@ -269,6 +291,24 @@ RenderLayers(ContainerT* aContainer,
PreparedLayer& preparedData = aContainer->mPrepared->mLayers[i];
LayerComposite* layerToRender = preparedData.mLayer;
const RenderTargetIntRect& clipRect = preparedData.mClipRect;
Layer* layer = layerToRender->GetLayer();
gfxRGBA color;
if (LayerHasCheckerboardingAPZC(layer, &color)) {
// Ideally we would want to intersect the checkerboard region from the APZ with the layer bounds
// and only fill in that area. However the layer bounds takes into account the base translation
// for the thebes layer whereas the checkerboard region does not. One does not simply
// intersect areas in different coordinate spaces. So we do this a little more permissively
// and only fill in the background when we know there is checkerboard, which in theory
// should only occur transiently.
nsIntRect layerBounds = layer->GetLayerBounds();
EffectChain effectChain(layer);
effectChain.mPrimaryEffect = new EffectSolidColor(ToColor(color));
aManager->GetCompositor()->DrawQuad(gfx::Rect(layerBounds.x, layerBounds.y, layerBounds.width, layerBounds.height),
gfx::Rect(clipRect.ToUnknownRect()),
effectChain, layer->GetEffectiveOpacity(),
layer->GetEffectiveTransform());
}
if (layerToRender->HasLayerBeenComposited()) {
// Composer2D will compose this layer so skip GPU composition
@ -290,7 +330,6 @@ RenderLayers(ContainerT* aContainer,
layerToRender->SetShadowVisibleRegion(preparedData.mSavedVisibleRegion);
}
Layer* layer = layerToRender->GetLayer();
if (gfxPrefs::UniformityInfo()) {
PrintUniformityInfo(layer);
}

View File

@ -294,6 +294,7 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
const LayerAttributes& attrs = osla.attrs();
const CommonLayerAttributes& common = attrs.common();
layer->SetLayerBounds(common.layerBounds());
layer->SetVisibleRegion(common.visibleRegion());
layer->SetEventRegions(common.eventRegions());
layer->SetContentFlags(common.contentFlags());

View File

@ -190,6 +190,7 @@ struct Animation {
// Change a layer's attributes
struct CommonLayerAttributes {
nsIntRect layerBounds;
nsIntRegion visibleRegion;
EventRegions eventRegions;
TransformMatrix transform;

View File

@ -574,6 +574,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
LayerAttributes attrs;
CommonLayerAttributes& common = attrs.common();
common.layerBounds() = mutant->GetLayerBounds();
common.visibleRegion() = mutant->GetVisibleRegion();
common.eventRegions() = mutant->GetEventRegions();
common.postXScale() = mutant->GetPostXScale();

View File

@ -500,6 +500,10 @@ public:
* in mItemClip).
*/
void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip);
/**
* The union of all the bounds of the display items in this layer.
*/
nsIntRegion mBounds;
private:
/**
@ -2165,6 +2169,10 @@ ContainerState::PopThebesLayerData()
SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion);
}
nsIntRect layerBounds = data->mBounds.GetBounds();
layerBounds.MoveBy(-GetTranslationForThebesLayer(data->mLayer));
layer->SetLayerBounds(layerBounds);
#ifdef MOZ_DUMP_PAINTING
layer->AddExtraDumpInfo(nsCString(data->mLog));
#endif
@ -2325,6 +2333,10 @@ ThebesLayerData::Accumulate(ContainerState* aState,
{
FLB_LOG_THEBES_DECISION(this, "Accumulating dp=%s(%p), f=%p against tld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
bool snap;
nsRect itemBounds = aItem->GetBounds(aState->mBuilder, &snap);
mBounds.OrWith(aState->ScaleToOutsidePixels(itemBounds, snap));
if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(aItem)) {
mForceTransparentSurface = true;
}