IntRect LayerMLGPU::GetClippedBoundingBox(RenderViewMLGPU* aView, const Maybe<gfx::Polygon>& aGeometry) { MOZ_ASSERT(IsPrepared()); Layer* layer = GetLayer(); const Matrix4x4& transform = layer->GetEffectiveTransform(); Rect rect = aGeometry ? aGeometry->BoundingBox() : Rect(layer->GetLocalVisibleRegion().GetBounds().ToUnknownRect()); rect = transform.TransformBounds(rect); rect.MoveBy(-aView->GetTargetOffset()); rect = rect.Intersect(Rect(mComputedClipRect.ToUnknownRect())); IntRect bounds; rect.RoundOut(); rect.ToIntRect(&bounds); return bounds; }
bool BasicContainerLayer::ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect) { Matrix transform; if (!GetEffectiveTransform().CanDraw2D(&transform) || ThebesMatrix(transform).HasNonIntegerTranslation()) return false; nsIntPoint offset(int32_t(transform._31), int32_t(transform._32)); gfx::IntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().GetBounds() + offset); nsIntRegion covered; for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) { if (ToData(l)->IsHidden()) continue; Matrix childTransform; if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) || ThebesMatrix(childTransform).HasNonIntegerTranslation() || l->GetEffectiveOpacity() != 1.0) return false; nsIntRegion childRegion = l->GetEffectiveVisibleRegion(); childRegion.MoveBy(int32_t(childTransform._31), int32_t(childTransform._32)); childRegion.And(childRegion, rect); if (l->GetClipRect()) { childRegion.And(childRegion, ParentLayerIntRect::ToUntyped(*l->GetClipRect()) + offset); } nsIntRegion intersection; intersection.And(covered, childRegion); if (!intersection.IsEmpty()) return false; covered.Or(covered, childRegion); } return covered.Contains(rect); }
bool FrameBuilder::AddLayerToConstantBuffer(ItemInfo& aItem) { LayerMLGPU* layer = aItem.layer; // If this layer could appear multiple times, cache it. if (aItem.geometry) { if (mLayerBufferMap.Get(layer, &aItem.layerIndex)) { return true; } } LayerConstants* info = AllocateLayerInfo(aItem); if (!info) { return false; } // Note we do not use GetEffectiveTransformForBuffer, since we calculate // the correct scaling when we build texture coordinates. Layer* baseLayer = layer->GetLayer(); const gfx::Matrix4x4& transform = baseLayer->GetEffectiveTransform(); memcpy(&info->transform, &transform._11, 64); info->clipRect = gfx::Rect(layer->GetComputedClipRect().ToUnknownRect()); info->maskIndex = 0; if (MaskOperation* op = layer->GetMask()) { // Note: we use 0 as an invalid index, and so indices are offset by 1. gfx::Rect rect = op->ComputeMaskRect(baseLayer); AddMaskRect(rect, &info->maskIndex); } if (aItem.geometry) { mLayerBufferMap.Put(layer, aItem.layerIndex); } return true; }
float LayerManagerComposite::ComputeRenderIntegrity() { // We only ever have incomplete rendering when progressive tiles are enabled. Layer* root = GetRoot(); if (!gfxPlatform::GetPlatform()->UseProgressivePaint() || !root) { return 1.f; } FrameMetrics rootMetrics = LayerMetricsWrapper::TopmostScrollableMetrics(root); if (!rootMetrics.IsScrollable()) { // The root may not have any scrollable metrics, in which case rootMetrics // will just be an empty FrameMetrics. Instead use the actual metrics from // the root layer. rootMetrics = LayerMetricsWrapper(root).Metrics(); } ParentLayerIntRect bounds = RoundedToInt(rootMetrics.GetCompositionBounds()); IntRect screenRect(bounds.x, bounds.y, bounds.width, bounds.height); float lowPrecisionMultiplier = 1.0f; float highPrecisionMultiplier = 1.0f; #ifdef MOZ_WIDGET_ANDROID // Use the transform on the primary scrollable layer and its FrameMetrics // to find out how much of the viewport the current displayport covers nsTArray<Layer*> rootScrollableLayers; GetRootScrollableLayers(rootScrollableLayers); if (rootScrollableLayers.Length() > 0) { // This is derived from the code in // AsyncCompositionManager::TransformScrollableLayer Layer* rootScrollable = rootScrollableLayers[0]; const FrameMetrics& metrics = LayerMetricsWrapper::TopmostScrollableMetrics(rootScrollable); Matrix4x4 transform = rootScrollable->GetEffectiveTransform(); transform.PostScale(metrics.GetPresShellResolution(), metrics.GetPresShellResolution(), 1); // Clip the screen rect to the document bounds Rect documentBounds = transform.TransformBounds(Rect(metrics.GetScrollableRect().x - metrics.GetScrollOffset().x, metrics.GetScrollableRect().y - metrics.GetScrollOffset().y, metrics.GetScrollableRect().width, metrics.GetScrollableRect().height)); documentBounds.RoundOut(); screenRect = screenRect.Intersect(IntRect(documentBounds.x, documentBounds.y, documentBounds.width, documentBounds.height)); // If the screen rect is empty, the user has scrolled entirely into // over-scroll and so we can be considered to have full integrity. if (screenRect.IsEmpty()) { return 1.0f; } // Work out how much of the critical display-port covers the screen bool hasLowPrecision = false; if (!metrics.GetCriticalDisplayPort().IsEmpty()) { hasLowPrecision = true; highPrecisionMultiplier = GetDisplayportCoverage(metrics.GetCriticalDisplayPort(), transform, screenRect); } // Work out how much of the display-port covers the screen if (!metrics.GetDisplayPort().IsEmpty()) { if (hasLowPrecision) { lowPrecisionMultiplier = GetDisplayportCoverage(metrics.GetDisplayPort(), transform, screenRect); } else { lowPrecisionMultiplier = highPrecisionMultiplier = GetDisplayportCoverage(metrics.GetDisplayPort(), transform, screenRect); } } } // If none of the screen is covered, we have zero integrity. if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) { return 0.0f; } #endif // MOZ_WIDGET_ANDROID nsIntRegion screenRegion(screenRect); nsIntRegion lowPrecisionScreenRegion(screenRect); Matrix4x4 transform; ComputeRenderIntegrityInternal(root, screenRegion, lowPrecisionScreenRegion, transform); if (!screenRegion.IsEqual(screenRect)) { // Calculate the area of the region. All rects in an nsRegion are // non-overlapping. float screenArea = screenRect.width * screenRect.height; float highPrecisionIntegrity = screenRegion.Area() / screenArea; float lowPrecisionIntegrity = 1.f; if (!lowPrecisionScreenRegion.IsEqual(screenRect)) { lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea; } return ((highPrecisionIntegrity * highPrecisionMultiplier) + (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2; } return 1.f; }
float LayerManagerComposite::ComputeRenderIntegrity() { // We only ever have incomplete rendering when progressive tiles are enabled. Layer* root = GetRoot(); if (!gfxPrefs::UseProgressiveTilePainting() || !root) { return 1.f; } const FrameMetrics& rootMetrics = root->GetFrameMetrics(); ParentLayerIntRect bounds = RoundedToInt(rootMetrics.mCompositionBounds); nsIntRect screenRect(bounds.x, bounds.y, bounds.width, bounds.height); float lowPrecisionMultiplier = 1.0f; float highPrecisionMultiplier = 1.0f; #ifdef MOZ_ANDROID_OMTC // Use the transform on the primary scrollable layer and its FrameMetrics // to find out how much of the viewport the current displayport covers Layer* primaryScrollable = GetPrimaryScrollableLayer(); if (primaryScrollable) { // This is derived from the code in // AsyncCompositionManager::TransformScrollableLayer const FrameMetrics& metrics = primaryScrollable->GetFrameMetrics(); Matrix4x4 transform = primaryScrollable->GetEffectiveTransform(); transform.ScalePost(metrics.mResolution.scale, metrics.mResolution.scale, 1); // Clip the screen rect to the document bounds Rect documentBounds = transform.TransformBounds(Rect(metrics.mScrollableRect.x - metrics.GetScrollOffset().x, metrics.mScrollableRect.y - metrics.GetScrollOffset().y, metrics.mScrollableRect.width, metrics.mScrollableRect.height)); documentBounds.RoundOut(); screenRect = screenRect.Intersect(nsIntRect(documentBounds.x, documentBounds.y, documentBounds.width, documentBounds.height)); // If the screen rect is empty, the user has scrolled entirely into // over-scroll and so we can be considered to have full integrity. if (screenRect.IsEmpty()) { return 1.0f; } // Work out how much of the critical display-port covers the screen bool hasLowPrecision = false; if (!metrics.mCriticalDisplayPort.IsEmpty()) { hasLowPrecision = true; highPrecisionMultiplier = GetDisplayportCoverage(metrics.mCriticalDisplayPort, transform, screenRect); } // Work out how much of the display-port covers the screen if (!metrics.mDisplayPort.IsEmpty()) { if (hasLowPrecision) { lowPrecisionMultiplier = GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect); } else { lowPrecisionMultiplier = highPrecisionMultiplier = GetDisplayportCoverage(metrics.mDisplayPort, transform, screenRect); } } } // If none of the screen is covered, we have zero integrity. if (highPrecisionMultiplier <= 0.0f && lowPrecisionMultiplier <= 0.0f) { return 0.0f; } #endif // MOZ_ANDROID_OMTC nsIntRegion screenRegion(screenRect); nsIntRegion lowPrecisionScreenRegion(screenRect); Matrix4x4 transform; ComputeRenderIntegrityInternal(root, screenRegion, lowPrecisionScreenRegion, transform); if (!screenRegion.IsEqual(screenRect)) { // Calculate the area of the region. All rects in an nsRegion are // non-overlapping. float screenArea = screenRect.width * screenRect.height; float highPrecisionIntegrity = screenRegion.Area() / screenArea; float lowPrecisionIntegrity = 1.f; if (!lowPrecisionScreenRegion.IsEqual(screenRect)) { lowPrecisionIntegrity = lowPrecisionScreenRegion.Area() / screenArea; } return ((highPrecisionIntegrity * highPrecisionMultiplier) + (lowPrecisionIntegrity * lowPrecisionMultiplier)) / 2; } return 1.f; }