From e927713a108744aab661abdf0ee4b8d98349a1bd Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Tue, 14 Aug 2012 17:27:47 -0700 Subject: Correctly handle preserve-3d layer ordering bug:6843244 Current implementation only works for HW acceleration. Change-Id: I009090132a8f3859ab9e57e609c1754f9021d4d7 --- .../graphics/android/layers/LayerAndroid.cpp | 96 ++++++++++++++++------ .../graphics/android/layers/LayerAndroid.h | 10 ++- .../graphics/android/rendering/ShaderProgram.cpp | 5 ++ .../android/rendering/SurfaceCollection.cpp | 22 +---- 4 files changed, 86 insertions(+), 47 deletions(-) diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp index 438d96c..67d1259 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.cpp @@ -398,22 +398,27 @@ void LayerAndroid::updateLocalTransformAndClip(const TransformationMatrix& paren { FloatPoint position(getPosition().x() + m_replicatedLayerPosition.x() - getScrollOffset().x(), getPosition().y() + m_replicatedLayerPosition.y() - getScrollOffset().y()); - float originX = getAnchorPoint().x() * getWidth(); - float originY = getAnchorPoint().y() * getHeight(); - - TransformationMatrix localMatrix; if (isPositionFixed()) m_drawTransform.makeIdentity(); else m_drawTransform = parentMatrix; - m_drawTransform.translate3d(originX + position.x(), - originY + position.y(), - anchorPointZ()); - m_drawTransform.multiply(m_transform); - m_drawTransform.translate3d(-originX, - -originY, - -anchorPointZ()); + + if (m_transform.isIdentity()) { + m_drawTransform.translate3d(position.x(), + position.y(), + 0); + } else { + float originX = getAnchorPoint().x() * getWidth(); + float originY = getAnchorPoint().y() * getHeight(); + m_drawTransform.translate3d(originX + position.x(), + originY + position.y(), + anchorPointZ()); + m_drawTransform.multiply(m_transform); + m_drawTransform.translate3d(-originX, + -originY, + -anchorPointZ()); + } m_drawTransformUnfudged = m_drawTransform; if (m_drawTransform.isIdentityOrTranslation() @@ -473,23 +478,19 @@ void LayerAndroid::updateGLPositionsAndScale(const TransformationMatrix& parentM if (!countChildren() || !m_visible) return; - TransformationMatrix localMatrix = m_drawTransformUnfudged; - + TransformationMatrix childMatrix = m_drawTransformUnfudged; // Flatten to 2D if the layer doesn't preserve 3D. if (!preserves3D()) { - localMatrix.setM13(0); - localMatrix.setM23(0); - localMatrix.setM31(0); - localMatrix.setM32(0); - localMatrix.setM33(1); - localMatrix.setM34(0); - localMatrix.setM43(0); + childMatrix.setM13(0); + childMatrix.setM23(0); + childMatrix.setM31(0); + childMatrix.setM32(0); + childMatrix.setM33(1); + childMatrix.setM34(0); + childMatrix.setM43(0); } // now apply it to our children - - TransformationMatrix childMatrix; - childMatrix = localMatrix; childMatrix.translate3d(getScrollOffset().x(), getScrollOffset().y(), 0); if (!m_childrenTransform.isIdentity()) { childMatrix.translate(getSize().width() * 0.5f, getSize().height() * 0.5f); @@ -819,6 +820,55 @@ bool LayerAndroid::drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle st return askScreenUpdate; } +void LayerAndroid::collect3dRenderingContext(Vector& layersInContext) +{ + layersInContext.append(this); + if (preserves3D()) { + int count = countChildren(); + for (int i = 0; i < count; i++) + getChild(i)->collect3dRenderingContext(layersInContext); + } +} + +bool LayerAndroid::drawSurfaceAndChildrenGL() +{ + bool askScreenUpdate = false; + if (surface()->getFirstLayer() == this) + askScreenUpdate |= surface()->drawGL(false); + + // return early, since children will be painted directly by drawTreeSurfacesGL + if (preserves3D()) + return askScreenUpdate; + + int count = countChildren(); + Vector sublayers; + for (int i = 0; i < count; i++) + sublayers.append(getChild(i)); + + std::stable_sort(sublayers.begin(), sublayers.end(), compareLayerZ); + for (int i = 0; i < count; i++) + askScreenUpdate |= sublayers[i]->drawTreeSurfacesGL(); + + return askScreenUpdate; +} + +bool LayerAndroid::drawTreeSurfacesGL() +{ + bool askScreenUpdate = false; + if (preserves3D()) { + // hit a preserve-3d layer, so render the entire 3D rendering context in z order + Vector contextLayers; + collect3dRenderingContext(contextLayers); + std::stable_sort(contextLayers.begin(), contextLayers.end(), compareLayerZ); + + for (unsigned int i = 0; i < contextLayers.size(); i++) + askScreenUpdate |= contextLayers[i]->drawSurfaceAndChildrenGL(); + } else + askScreenUpdate |= drawSurfaceAndChildrenGL(); + + return askScreenUpdate; +} + bool LayerAndroid::drawGL(bool layerTilesDisabled) { if (!layerTilesDisabled && m_imageCRC) { diff --git a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h index b28daef..5a1ef57 100644 --- a/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h +++ b/Source/WebCore/platform/graphics/android/layers/LayerAndroid.h @@ -151,6 +151,9 @@ public: float getScale() { return m_scale; } + // draw the layer tree recursively in draw order, grouping and sorting 3d rendering contexts + bool drawTreeSurfacesGL(); + virtual bool drawGL(bool layerTilesDisabled); virtual bool drawCanvas(SkCanvas* canvas, bool drawChildren, PaintStyle style); bool drawChildrenCanvas(SkCanvas* canvas, PaintStyle style); @@ -312,13 +315,14 @@ private: return contentIsScrollable() || isPositionFixed() || (m_animations.size() != 0); } + // recurse through the current 3d rendering context, adding layers in the context to the vector + void collect3dRenderingContext(Vector& layersInContext); + bool drawSurfaceAndChildrenGL(); + #if DUMP_NAV_CACHE friend class CachedLayer::Debug; // debugging access only #endif - void copyAnimationStartTimes(LayerAndroid* oldLayer); - bool prepareContext(bool force = false); - // ------------------------------------------------------------------- // Fields to be serialized // ------------------------------------------------------------------- diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp index b59b6e2..5920007 100644 --- a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.cpp @@ -274,6 +274,11 @@ ShaderProgram::ShaderProgram() , m_currentScale(1.0f) , m_needsInit(true) { + // initialize the matrix to calculate z values correctly, since it can be + // used for that before setupDrawing is called. + GLUtils::setOrthographicMatrix(m_visibleContentRectProjectionMatrix, + 0,0,1,1, + -1000, 1000); } void ShaderProgram::cleanupGLResources() diff --git a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp index 1c769bf..b675f7d 100644 --- a/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp +++ b/Source/WebCore/platform/graphics/android/rendering/SurfaceCollection.cpp @@ -95,15 +95,6 @@ void SurfaceCollection::prepareGL(const SkRect& visibleContentRect, bool tryToFa m_surfaces[i]->prepareGL(layerTilesDisabled, tryToFastBlit); } -static inline bool compareSurfaceZ(const Surface* a, const Surface* b) -{ - const LayerAndroid* la = a->getFirstLayer(); - const LayerAndroid* lb = b->getFirstLayer(); - - // swap drawing order if zValue suggests it AND the layers are in the same stacking context - return (la->zValue() > lb->zValue()) && (la->getParent() == lb->getParent()); -} - bool SurfaceCollection::drawGL(const SkRect& visibleContentRect) { TRACE_METHOD(); @@ -111,21 +102,10 @@ bool SurfaceCollection::drawGL(const SkRect& visibleContentRect) ClassTracker::instance()->show(); #endif - bool needsRedraw = false; updateLayerPositions(visibleContentRect); bool layerTilesDisabled = m_compositedRoot->state()->isSingleSurfaceRenderingMode(); - // create a duplicate vector of surfaces, sorted by z value - Vector surfaces; - for (unsigned int i = 0; i < m_surfaces.size(); i++) - surfaces.append(m_surfaces[i]); - std::stable_sort(surfaces.begin()+1, surfaces.end(), compareSurfaceZ); - - // draw the sorted vector - for (unsigned int i = 0; i < m_surfaces.size(); i++) - needsRedraw |= surfaces[i]->drawGL(layerTilesDisabled); - - return needsRedraw; + return m_compositedRoot->drawTreeSurfacesGL(); } Color SurfaceCollection::getBackgroundColor() -- cgit v1.1