bool ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, gfx::Rect& aViewport, float& aScaleX, float& aScaleY, bool aDrawingCritical) { aScaleX = aScaleY = 1.0; #ifdef MOZ_WIDGET_ANDROID Layer* primaryScrollable = GetPrimaryScrollableLayer(); if (primaryScrollable) { const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); // This is derived from the code in // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. const gfx3DMatrix& rootTransform = GetRoot()->GetTransform(); CSSToLayerScale paintScale = metrics.mDevPixelsPerCSSPixel / LayerToLayoutDeviceScale(rootTransform.GetXScale(), rootTransform.GetYScale()); const CSSRect& metricsDisplayPort = (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ? metrics.mCriticalDisplayPort : metrics.mDisplayPort; LayerRect displayPort = (metricsDisplayPort + metrics.mScrollOffset) * paintScale; return AndroidBridge::Bridge()->ProgressiveUpdateCallback( aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, aViewport, aScaleX, aScaleY); } #endif return false; }
bool ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, ParentLayerRect& aCompositionBounds, CSSToParentLayerScale& aZoom, bool aDrawingCritical) { aZoom.scale = 1.0; #ifdef MOZ_WIDGET_ANDROID Layer* primaryScrollable = GetPrimaryScrollableLayer(); if (primaryScrollable) { const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); // This is derived from the code in // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. CSSToLayerScale paintScale = metrics.LayersPixelsPerCSSPixel(); const CSSRect& metricsDisplayPort = (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ? metrics.mCriticalDisplayPort : metrics.mDisplayPort; LayerRect displayPort = (metricsDisplayPort + metrics.GetScrollOffset()) * paintScale; return AndroidBridge::Bridge()->ProgressiveUpdateCallback( aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, aCompositionBounds, aZoom); } #endif return false; }
bool ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, gfx::Rect& aViewport, float& aScaleX, float& aScaleY, bool aDrawingCritical) { #ifdef MOZ_WIDGET_ANDROID Layer* primaryScrollable = GetPrimaryScrollableLayer(); if (primaryScrollable) { const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); // This is derived from the code in // gfx/layers/ipc/CompositorParent.cpp::TransformShadowTree. const gfx3DMatrix& rootTransform = GetRoot()->GetTransform(); float devPixelRatioX = 1 / rootTransform.GetXScale(); float devPixelRatioY = 1 / rootTransform.GetYScale(); const gfx::Rect& metricsDisplayPort = (aDrawingCritical && !metrics.mCriticalDisplayPort.IsEmpty()) ? metrics.mCriticalDisplayPort : metrics.mDisplayPort; gfx::Rect displayPort((metricsDisplayPort.x + metrics.mScrollOffset.x) * devPixelRatioX, (metricsDisplayPort.y + metrics.mScrollOffset.y) * devPixelRatioY, metricsDisplayPort.width * devPixelRatioX, metricsDisplayPort.height * devPixelRatioY); return AndroidBridge::Bridge()->ProgressiveUpdateCallback( aHasPendingNewThebesContent, displayPort, devPixelRatioX, aDrawingCritical, aViewport, aScaleX, aScaleY); } #endif return false; }
void CompositorParent::TransformShadowTree() { Layer* layer = GetPrimaryScrollableLayer(); ShadowLayer* shadow = layer->AsShadowLayer(); ContainerLayer* container = layer->AsContainerLayer(); const FrameMetrics* metrics = &container->GetFrameMetrics(); const gfx3DMatrix& rootTransform = mLayerManager->GetRoot()->GetTransform(); const gfx3DMatrix& currentTransform = layer->GetTransform(); float rootScaleX = rootTransform.GetXScale(); float rootScaleY = rootTransform.GetYScale(); if (mIsFirstPaint && metrics) { nsIntPoint scrollOffset = metrics->mViewportScrollOffset; mContentSize = metrics->mContentSize; SetFirstPaintViewport(scrollOffset.x, scrollOffset.y, 1/rootScaleX, mContentSize.width, mContentSize.height, metrics->mCSSContentSize.width, metrics->mCSSContentSize.height); mIsFirstPaint = false; } else if (metrics && (metrics->mContentSize != mContentSize)) { mContentSize = metrics->mContentSize; SetPageSize(1/rootScaleX, mContentSize.width, mContentSize.height, metrics->mCSSContentSize.width, metrics->mCSSContentSize.height); } // We synchronise the viewport information with Java after sending the above // notifications, so that Java can take these into account in its response. if (metrics) { // Calculate the absolute display port to send to Java nsIntRect displayPort = metrics->mDisplayPort; nsIntPoint scrollOffset = metrics->mViewportScrollOffset; displayPort.x += scrollOffset.x; displayPort.y += scrollOffset.y; SyncViewportInfo(displayPort, 1/rootScaleX, mLayersUpdated, mScrollOffset, mXScale, mYScale); mLayersUpdated = false; } // Handle transformations for asynchronous panning and zooming. We determine the // zoom used by Gecko from the transformation set on the root layer, and we // determine the scroll offset used by Gecko from the frame metrics of the // primary scrollable layer. We compare this to the desired zoom and scroll // offset in the view transform we obtained from Java in order to compute the // transformation we need to apply. if (metrics) { float tempScaleDiffX = rootScaleX * mXScale; float tempScaleDiffY = rootScaleY * mYScale; nsIntPoint metricsScrollOffset(0, 0); if (metrics->IsScrollable()) metricsScrollOffset = metrics->mViewportScrollOffset; nsIntPoint scrollCompensation( (mScrollOffset.x / tempScaleDiffX - metricsScrollOffset.x) * mXScale, (mScrollOffset.y / tempScaleDiffY - metricsScrollOffset.y) * mYScale); ViewTransform treeTransform(-scrollCompensation, mXScale, mYScale); shadow->SetShadowTransform(gfx3DMatrix(treeTransform) * currentTransform); } else { ViewTransform treeTransform(nsIntPoint(0,0), mXScale, mYScale); shadow->SetShadowTransform(gfx3DMatrix(treeTransform) * currentTransform); } }
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; }
void CompositorParent::TransformShadowTree() { Layer* layer = GetPrimaryScrollableLayer(); ShadowLayer* shadow = layer->AsShadowLayer(); ContainerLayer* container = layer->AsContainerLayer(); const FrameMetrics& metrics = container->GetFrameMetrics(); const gfx3DMatrix& rootTransform = mLayerManager->GetRoot()->GetTransform(); const gfx3DMatrix& currentTransform = layer->GetTransform(); float rootScaleX = rootTransform.GetXScale(); float rootScaleY = rootTransform.GetYScale(); if (mIsFirstPaint) { mContentRect = metrics.mContentRect; SetFirstPaintViewport(metrics.mViewportScrollOffset, 1/rootScaleX, mContentRect, metrics.mCSSContentRect); mIsFirstPaint = false; } else if (!metrics.mContentRect.IsEqualEdges(mContentRect)) { mContentRect = metrics.mContentRect; SetPageRect(1/rootScaleX, mContentRect, metrics.mCSSContentRect); } // We synchronise the viewport information with Java after sending the above // notifications, so that Java can take these into account in its response. // Calculate the absolute display port to send to Java nsIntRect displayPort = metrics.mDisplayPort; nsIntPoint scrollOffset = metrics.mViewportScrollOffset; displayPort.x += scrollOffset.x; displayPort.y += scrollOffset.y; SyncViewportInfo(displayPort, 1/rootScaleX, mLayersUpdated, mScrollOffset, mXScale, mYScale); mLayersUpdated = false; // Handle transformations for asynchronous panning and zooming. We determine the // zoom used by Gecko from the transformation set on the root layer, and we // determine the scroll offset used by Gecko from the frame metrics of the // primary scrollable layer. We compare this to the desired zoom and scroll // offset in the view transform we obtained from Java in order to compute the // transformation we need to apply. float tempScaleDiffX = rootScaleX * mXScale; float tempScaleDiffY = rootScaleY * mYScale; nsIntPoint metricsScrollOffset(0, 0); if (metrics.IsScrollable()) metricsScrollOffset = metrics.mViewportScrollOffset; nsIntPoint scrollCompensation( (mScrollOffset.x / tempScaleDiffX - metricsScrollOffset.x) * mXScale, (mScrollOffset.y / tempScaleDiffY - metricsScrollOffset.y) * mYScale); ViewTransform treeTransform(-scrollCompensation, mXScale, mYScale); shadow->SetShadowTransform(gfx3DMatrix(treeTransform) * currentTransform); // Alter the scroll offset so that fixed position layers remain within // the page area. float offsetX = mScrollOffset.x / tempScaleDiffX; float offsetY = mScrollOffset.y / tempScaleDiffY; offsetX = NS_MAX((float)mContentRect.x, NS_MIN(offsetX, (float)(mContentRect.XMost() - mWidgetSize.width))); offsetY = NS_MAX((float)mContentRect.y, NS_MIN(offsetY, (float)(mContentRect.YMost() - mWidgetSize.height))); gfxPoint reverseViewTranslation(offsetX - metricsScrollOffset.x, offsetY - metricsScrollOffset.y); TranslateFixedLayers(layer, reverseViewTranslation); }