Bug 1275694 - Use the local visible region to decide when to cull a layer in CalculateScissorRect(). r=kats
We still take care not to cull a layer if we need to draw a checkerboarding
background for it.
MozReview-Commit-ID: 3EuXEFB2wF9
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -799,25 +799,23 @@ Layer::CalculateScissorRect(const Render
} else {
currentClip = aCurrentScissorRect;
}
if (!clipLayer->GetLocalClipRect()) {
return currentClip;
}
- if (GetVisibleRegion().IsEmpty()) {
+ if (GetLocalVisibleRegion().IsEmpty() &&
+ !(AsLayerComposite() && AsLayerComposite()->NeedToDrawCheckerboarding())) {
// When our visible region is empty, our parent may not have created the
// intermediate surface that we would require for correct clipping; however,
// this does not matter since we are invisible.
- // Note that we do not use GetLocalVisibleRegion(), because that can be
- // empty for a layer whose rendered contents have been async-scrolled
- // completely offscreen, but for which we still need to draw a
- // checkerboarding backround color, and calculating an empty scissor rect
- // for such a layer would prevent that (see bug 1247452 comment 10).
+ // Make sure we still compute a clip rect if we want to draw checkboarding
+ // for this layer, since we want to do this even if the layer is invisible.
return RenderTargetIntRect(currentClip.TopLeft(), RenderTargetIntSize(0, 0));
}
const RenderTargetIntRect clipRect =
ViewAs<RenderTargetPixel>(*clipLayer->GetLocalClipRect(),
PixelCastJustification::RenderTargetIsParentLayerForRoot);
if (clipRect.IsEmpty()) {
// We might have a non-translation transform in the container so we can't
--- a/gfx/layers/composite/ContainerLayerComposite.cpp
+++ b/gfx/layers/composite/ContainerLayerComposite.cpp
@@ -48,34 +48,16 @@
#define XY(k) (k).x, (k).y
#define WH(k) (k).width, (k).height
namespace mozilla {
namespace layers {
using namespace gfx;
-static bool
-LayerHasCheckerboardingAPZC(Layer* aLayer, Color* 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.Metadata().GetBackgroundColor();
- }
- return true;
- }
- break;
- }
- return false;
-}
-
static void DrawLayerInfo(const RenderTargetIntRect& aClipRect,
LayerManagerComposite* aManager,
Layer* aLayer)
{
if (aLayer->GetType() == Layer::LayerType::TYPE_CONTAINER) {
// XXX - should figure out a way to render this, but for now this
// is hard to do, since it will often get superimposed over the first
@@ -352,25 +334,16 @@ ContainerRenderVR(ContainerT* aContainer
// full rect, not just the visible one. Luckily, right now, VR distortion is only
// rendered when the element is fullscreen, so the visibleRect will be right anyway.
aManager->GetCompositor()->DrawQuad(Rect(rect), clipRect, vrEffect, opacity,
scaleTransform);
DUMP("<<< ContainerRenderVR [%p]\n", aContainer);
}
-static bool
-NeedToDrawCheckerboardingForLayer(Layer* aLayer, Color* aOutCheckerboardingColor)
-{
- return (aLayer->Manager()->AsyncPanZoomEnabled() &&
- aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
- aLayer->IsOpaqueForVisibility() &&
- LayerHasCheckerboardingAPZC(aLayer, aOutCheckerboardingColor);
-}
-
/* all of the prepared data that we need in RenderLayer() */
struct PreparedData
{
RefPtr<CompositingRenderTarget> mTmpTarget;
AutoTArray<PreparedLayer, 12> mLayers;
bool mNeedsSurfaceCopy;
};
@@ -407,17 +380,17 @@ ContainerPrepare(ContainerT* aContainer,
if (layerToRender->GetLayer()->IsBackfaceHidden()) {
continue;
}
// We don't want to skip container layers because otherwise their mPrepared
// may be null which is not allowed.
if (!layerToRender->GetLayer()->AsContainerLayer()) {
if (!layerToRender->GetLayer()->IsVisible() &&
- !NeedToDrawCheckerboardingForLayer(layerToRender->GetLayer(), nullptr)) {
+ !layerToRender->NeedToDrawCheckerboarding(nullptr)) {
CULLING_LOG("Sublayer %p has no effective visible region\n", layerToRender->GetLayer());
continue;
}
if (clipRect.IsEmpty()) {
CULLING_LOG("Sublayer %p has an empty world clip rect\n", layerToRender->GetLayer());
continue;
}
@@ -621,17 +594,17 @@ RenderLayers(ContainerT* aContainer,
const RenderTargetIntRect& clipRect = preparedData.mClipRect;
Layer* layer = layerToRender->GetLayer();
if (layerToRender->HasStaleCompositor()) {
continue;
}
Color color;
- if (NeedToDrawCheckerboardingForLayer(layer, &color)) {
+ if (layerToRender->NeedToDrawCheckerboarding(&color)) {
if (gfxPrefs::APZHighlightCheckerboardedAreas()) {
color = Color(255 / 255.f, 188 / 255.f, 217 / 255.f, 1.f); // "Cotton Candy"
}
// 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 painted 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
@@ -951,17 +924,16 @@ RefLayerComposite::RenderLayer(const gfx
}
void
RefLayerComposite::Prepare(const RenderTargetIntRect& aClipRect)
{
ContainerPrepare(this, mCompositeManager, aClipRect);
}
-
void
RefLayerComposite::CleanupResources()
{
mLastIntermediateSurface = nullptr;
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/composite/LayerManagerComposite.cpp
+++ b/gfx/layers/composite/LayerManagerComposite.cpp
@@ -17,16 +17,17 @@
#include "ImageLayerComposite.h" // for ImageLayerComposite
#include "Layers.h" // for Layer, ContainerLayer, etc
#include "LayerScope.h" // for LayerScope Tool
#include "protobuf/LayerScopePacket.pb.h" // for protobuf (LayerScope)
#include "PaintedLayerComposite.h" // for PaintedLayerComposite
#include "TiledContentHost.h"
#include "Units.h" // for ScreenIntRect
#include "UnitTransforms.h" // for ViewAs
+#include "apz/src/AsyncPanZoomController.h" // for AsyncPanZoomController
#include "gfxPrefs.h" // for gfxPrefs
#ifdef XP_MACOSX
#include "gfxPlatformMac.h"
#endif
#include "gfxRect.h" // for gfxRect
#include "gfxUtils.h" // for frame color util
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed
@@ -1584,16 +1585,45 @@ LayerComposite::GetShadowTransform() {
}
bool
LayerComposite::HasStaleCompositor() const
{
return mCompositeManager->GetCompositor() != mCompositor;
}
+static bool
+LayerHasCheckerboardingAPZC(Layer* aLayer, Color* aOutColor)
+{
+ bool answer = false;
+ 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.Metadata().GetBackgroundColor();
+ }
+ answer = true;
+ break;
+ }
+ break;
+ }
+ return answer;
+}
+
+bool
+LayerComposite::NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor)
+{
+ return GetLayer()->Manager()->AsyncPanZoomEnabled() &&
+ (GetLayer()->GetContentFlags() & Layer::CONTENT_OPAQUE) &&
+ GetLayer()->IsOpaqueForVisibility() &&
+ LayerHasCheckerboardingAPZC(GetLayer(), aOutCheckerboardingColor);
+}
+
#ifndef MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS
/*static*/ bool
LayerManagerComposite::SupportsDirectTexturing()
{
return false;
}
--- a/gfx/layers/composite/LayerManagerComposite.h
+++ b/gfx/layers/composite/LayerManagerComposite.h
@@ -551,16 +551,22 @@ public:
/**
* Return the part of the visible region that has been fully rendered.
* While progressive drawing is in progress this region will be
* a subset of the shadow visible region.
*/
virtual nsIntRegion GetFullyRenderedRegion();
+ /**
+ * Return true if a checkerboarding background color needs to be drawn
+ * for this layer.
+ */
+ bool NeedToDrawCheckerboarding(gfx::Color* aOutCheckerboardingColor = nullptr);
+
protected:
gfx::Matrix4x4 mShadowTransform;
LayerIntRegion mShadowVisibleRegion;
Maybe<ParentLayerIntRect> mShadowClipRect;
LayerManagerComposite* mCompositeManager;
RefPtr<Compositor> mCompositor;
float mShadowOpacity;
bool mShadowTransformSetByAnimation;