void ReadbackProcessor::BuildUpdatesForLayer(ReadbackLayer* aLayer) { if (!aLayer->mSink) return; nsIntPoint offset; Layer* newBackground = FindBackgroundLayer(aLayer, &offset); if (!newBackground) { aLayer->SetUnknown(); return; } if (newBackground->GetType() == Layer::TYPE_COLOR) { ColorLayer* colorLayer = static_cast<ColorLayer*>(newBackground); if (aLayer->mBackgroundColor != colorLayer->GetColor()) { aLayer->mBackgroundLayer = nullptr; aLayer->mBackgroundColor = colorLayer->GetColor(); NS_ASSERTION(aLayer->mBackgroundColor.a == 1.f, "Color layer said it was opaque!"); RefPtr<gfxContext> ctx = aLayer->mSink->BeginUpdate(aLayer->GetRect(), aLayer->AllocateSequenceNumber()); if (ctx) { ColorPattern color(ToDeviceColor(aLayer->mBackgroundColor)); IntSize size = aLayer->GetSize(); ctx->GetDrawTarget()->FillRect(Rect(0, 0, size.width, size.height), color); aLayer->mSink->EndUpdate(ctx, aLayer->GetRect()); } } } else { NS_ASSERTION(newBackground->AsPaintedLayer(), "Must be PaintedLayer"); PaintedLayer* paintedLayer = static_cast<PaintedLayer*>(newBackground); // updateRect is relative to the PaintedLayer IntRect updateRect = aLayer->GetRect() - offset; if (paintedLayer != aLayer->mBackgroundLayer || offset != aLayer->mBackgroundLayerOffset) { aLayer->mBackgroundLayer = paintedLayer; aLayer->mBackgroundLayerOffset = offset; aLayer->mBackgroundColor = Color(); paintedLayer->SetUsedForReadback(true); } else { nsIntRegion invalid; invalid.Sub(updateRect, paintedLayer->GetValidRegion()); updateRect = invalid.GetBounds(); } Update update = { aLayer, updateRect, aLayer->AllocateSequenceNumber() }; mAllUpdates.AppendElement(update); } }
/* static */ void LayerManagerComposite::ComputeRenderIntegrityInternal(Layer* aLayer, nsIntRegion& aScreenRegion, nsIntRegion& aLowPrecisionScreenRegion, const Matrix4x4& aTransform) { if (aLayer->GetOpacity() <= 0.f || (aScreenRegion.IsEmpty() && aLowPrecisionScreenRegion.IsEmpty())) { return; } // If the layer's a container, recurse into all of its children ContainerLayer* container = aLayer->AsContainerLayer(); if (container) { // Accumulate the transform of intermediate surfaces Matrix4x4 transform = aTransform; if (container->UseIntermediateSurface()) { transform = aLayer->GetEffectiveTransform(); transform = aTransform * transform; } for (Layer* child = aLayer->GetFirstChild(); child; child = child->GetNextSibling()) { ComputeRenderIntegrityInternal(child, aScreenRegion, aLowPrecisionScreenRegion, transform); } return; } // Only painted layers can be incomplete PaintedLayer* paintedLayer = aLayer->AsPaintedLayer(); if (!paintedLayer) { return; } // See if there's any incomplete rendering nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion(); incompleteRegion.Sub(incompleteRegion, paintedLayer->GetValidRegion()); if (!incompleteRegion.IsEmpty()) { // Calculate the transform to get between screen and layer space Matrix4x4 transformToScreen = aLayer->GetEffectiveTransform(); transformToScreen = aTransform * transformToScreen; SubtractTransformedRegion(aScreenRegion, incompleteRegion, transformToScreen); // See if there's any incomplete low-precision rendering TiledContentHost* composer = nullptr; LayerComposite* shadow = aLayer->AsLayerComposite(); if (shadow) { composer = shadow->GetCompositableHost()->AsTiledContentHost(); if (composer) { incompleteRegion.Sub(incompleteRegion, composer->GetValidLowPrecisionRegion()); if (!incompleteRegion.IsEmpty()) { SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen); } } } // If we can't get a valid low precision region, assume it's the same as // the high precision region. if (!composer) { SubtractTransformedRegion(aLowPrecisionScreenRegion, incompleteRegion, transformToScreen); } } }