Bug 1423528 - Recompute shadow visible rect for ContainerLayerMLGPU in case it has been changed by async animations. r=mstange

This commit is contained in:
Matt Woodrow 2018-02-21 15:45:06 +13:00
Родитель dd015cb66e
Коммит 76a9ef80ff
6 изменённых файлов: 85 добавлений и 50 удалений

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

@ -730,58 +730,11 @@ ContainerLayerComposite::CleanupResources()
}
}
static LayerIntRect
TransformRect(const LayerIntRect& aRect, const Matrix4x4& aTransform)
{
if (aRect.IsEmpty()) {
return LayerIntRect();
}
Rect rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
rect = aTransform.TransformAndClipBounds(rect, Rect::MaxIntRect());
rect.RoundOut();
IntRect intRect;
if (!gfxUtils::GfxRectToIntRect(ThebesRect(rect), &intRect)) {
return LayerIntRect();
}
return ViewAs<LayerPixel>(intRect);
}
static void
AddTransformedRegion(LayerIntRegion& aDest, const LayerIntRegion& aSource, const Matrix4x4& aTransform)
{
for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
aDest.Or(aDest, TransformRect(iter.Get(), aTransform));
}
aDest.SimplifyOutward(20);
}
// Async animations can move child layers without updating our visible region.
// PostProcessLayers will recompute visible regions for layers with an intermediate
// surface, but otherwise we need to do it now.
void
ComputeVisibleRegionForChildren(ContainerLayer* aContainer, LayerIntRegion& aResult)
{
for (Layer* l = aContainer->GetFirstChild(); l; l = l->GetNextSibling()) {
if (l->Extend3DContext()) {
MOZ_ASSERT(l->AsContainerLayer());
ComputeVisibleRegionForChildren(l->AsContainerLayer(), aResult);
} else {
AddTransformedRegion(aResult,
l->GetLocalVisibleRegion(),
l->ComputeTransformToPreserve3DRoot());
}
}
}
const LayerIntRegion&
ContainerLayerComposite::GetShadowVisibleRegion()
{
if (!UseIntermediateSurface()) {
mShadowVisibleRegion.SetEmpty();
ComputeVisibleRegionForChildren(this, mShadowVisibleRegion);
RecomputeShadowVisibleRegionFromChildren();
}
return mShadowVisibleRegion;
@ -791,8 +744,7 @@ const LayerIntRegion&
RefLayerComposite::GetShadowVisibleRegion()
{
if (!UseIntermediateSurface()) {
mShadowVisibleRegion.SetEmpty();
ComputeVisibleRegionForChildren(this, mShadowVisibleRegion);
RecomputeShadowVisibleRegionFromChildren();
}
return mShadowVisibleRegion;

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

@ -1487,6 +1487,63 @@ HostLayer::GetShadowTransform() {
return transform;
}
static LayerIntRect
TransformRect(const LayerIntRect& aRect, const Matrix4x4& aTransform)
{
if (aRect.IsEmpty()) {
return LayerIntRect();
}
Rect rect(aRect.X(), aRect.Y(), aRect.Width(), aRect.Height());
rect = aTransform.TransformAndClipBounds(rect, Rect::MaxIntRect());
rect.RoundOut();
IntRect intRect;
if (!gfxUtils::GfxRectToIntRect(ThebesRect(rect), &intRect)) {
return LayerIntRect();
}
return ViewAs<LayerPixel>(intRect);
}
static void
AddTransformedRegion(LayerIntRegion& aDest, const LayerIntRegion& aSource, const Matrix4x4& aTransform)
{
for (auto iter = aSource.RectIter(); !iter.Done(); iter.Next()) {
aDest.Or(aDest, TransformRect(iter.Get(), aTransform));
}
aDest.SimplifyOutward(20);
}
// Async animations can move child layers without updating our visible region.
// PostProcessLayers will recompute visible regions for layers with an intermediate
// surface, but otherwise we need to do it now.
void
ComputeVisibleRegionForChildren(ContainerLayer* aContainer, LayerIntRegion& aResult)
{
for (Layer* l = aContainer->GetFirstChild(); l; l = l->GetNextSibling()) {
if (l->Extend3DContext()) {
MOZ_ASSERT(l->AsContainerLayer());
ComputeVisibleRegionForChildren(l->AsContainerLayer(), aResult);
} else {
AddTransformedRegion(aResult,
l->GetLocalVisibleRegion(),
l->ComputeTransformToPreserve3DRoot());
}
}
}
void
HostLayer::RecomputeShadowVisibleRegionFromChildren()
{
mShadowVisibleRegion.SetEmpty();
ContainerLayer* container = GetLayer()->AsContainerLayer();
MOZ_ASSERT(container);
if (container) {
ComputeVisibleRegionForChildren(container, mShadowVisibleRegion);
}
}
bool
LayerComposite::HasStaleCompositor() const
{

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

@ -613,6 +613,8 @@ public:
bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; }
bool GetShadowOpacitySetByAnimation() { return mShadowOpacitySetByAnimation; }
void RecomputeShadowVisibleRegionFromChildren();
protected:
HostLayerManager* mCompositorManager;

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

@ -244,5 +244,25 @@ ContainerLayerMLGPU::IsContentOpaque()
return LayerMLGPU::IsContentOpaque();
}
const LayerIntRegion&
ContainerLayerMLGPU::GetShadowVisibleRegion()
{
if (!UseIntermediateSurface()) {
RecomputeShadowVisibleRegionFromChildren();
}
return mShadowVisibleRegion;
}
const LayerIntRegion&
RefLayerMLGPU::GetShadowVisibleRegion()
{
if (!UseIntermediateSurface()) {
RecomputeShadowVisibleRegionFromChildren();
}
return mShadowVisibleRegion;
}
} // namespace layers
} // namespace mozilla

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

@ -35,6 +35,8 @@ public:
void SetInvalidCompositeRect(const gfx::IntRect* aRect) override;
void ClearCachedResources() override;
const LayerIntRegion& GetShadowVisibleRegion() override;
RefPtr<MLGRenderTarget> UpdateRenderTarget(
MLGDevice* aDevice,
MLGRenderTargetFlags aFlags);

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

@ -151,6 +151,8 @@ public:
DefaultComputeEffectiveTransforms(aTransformToSurface);
}
const LayerIntRegion& GetShadowVisibleRegion() override;
MOZ_LAYER_DECL_NAME("RefLayerMLGPU", TYPE_REF)
};