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.0, "Color layer said it was opaque!"); nsRefPtr<gfxContext> ctx = aLayer->mSink->BeginUpdate(aLayer->GetRect(), aLayer->AllocateSequenceNumber()); if (ctx) { ctx->SetColor(aLayer->mBackgroundColor); nsIntSize size = aLayer->GetSize(); ctx->Rectangle(gfxRect(0, 0, size.width, size.height)); ctx->Fill(); aLayer->mSink->EndUpdate(ctx, aLayer->GetRect()); } } } else { NS_ASSERTION(newBackground->AsThebesLayer(), "Must be ThebesLayer"); ThebesLayer* thebesLayer = static_cast<ThebesLayer*>(newBackground); // updateRect is relative to the ThebesLayer nsIntRect updateRect = aLayer->GetRect() - offset; if (thebesLayer != aLayer->mBackgroundLayer || offset != aLayer->mBackgroundLayerOffset) { aLayer->mBackgroundLayer = thebesLayer; aLayer->mBackgroundLayerOffset = offset; aLayer->mBackgroundColor = gfxRGBA(0,0,0,0); thebesLayer->SetUsedForReadback(true); } else { nsIntRegion invalid; invalid.Sub(updateRect, thebesLayer->GetValidRegion()); updateRect = invalid.GetBounds(); } Update update = { aLayer, updateRect, aLayer->AllocateSequenceNumber() }; mAllUpdates.AppendElement(update); } }
void ContainerLayer::DidRemoveChild(Layer* aLayer) { ThebesLayer* tl = aLayer->AsThebesLayer(); if (tl && tl->UsedForReadback()) { for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) { if (l->GetType() == TYPE_READBACK) { static_cast<ReadbackLayer*>(l)->NotifyThebesLayerRemoved(tl); } } } if (aLayer->GetType() == TYPE_READBACK) { static_cast<ReadbackLayer*>(aLayer)->NotifyRemoved(); } }
/* 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 thebes layers can be incomplete ThebesLayer* thebesLayer = aLayer->AsThebesLayer(); if (!thebesLayer) { return; } // See if there's any incomplete rendering nsIntRegion incompleteRegion = aLayer->GetEffectiveVisibleRegion(); incompleteRegion.Sub(incompleteRegion, thebesLayer->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 TiledLayerComposer* composer = nullptr; LayerComposite* shadow = aLayer->AsLayerComposite(); if (shadow) { composer = shadow->GetTiledLayerComposer(); 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); } } }