Loading libs/hwui/DisplayList.cpp +70 −53 Original line number Diff line number Diff line Loading @@ -304,8 +304,11 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler, /** * Apply property-based transformations to input matrix * * If true3dTransform is set to true, the transform applied to the input matrix will use true 4x4 * matrix computation instead of the Skia 3x3 matrix + camera hackery. */ void DisplayList::applyViewPropertyTransforms(mat4& matrix) { void DisplayList::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) { if (mLeft != 0 || mTop != 0) { matrix.translate(mLeft, mTop); } Loading @@ -319,15 +322,31 @@ void DisplayList::applyViewPropertyTransforms(mat4& matrix) { if (mMatrixFlags != 0) { updateMatrix(); if (mMatrixFlags == TRANSLATION) { matrix.translate(mTranslationX, mTranslationY, mTranslationZ); matrix.translate(mTranslationX, mTranslationY, true3dTransform ? mTranslationZ : 0.0f); } else { if (!true3dTransform) { matrix.multiply(*mTransformMatrix); } else { mat4 true3dMat; true3dMat.loadTranslate( mPivotX + mTranslationX, mPivotY + mTranslationY, mTranslationZ); true3dMat.rotate(mRotationX, 1, 0, 0); true3dMat.rotate(mRotationY, 0, 1, 0); true3dMat.rotate(mRotation, 0, 0, 1); true3dMat.scale(mScaleX, mScaleY, 1); true3dMat.translate(-mPivotX, -mPivotY); matrix.multiply(true3dMat); } } } } /** * Organizes the DisplayList hierarchy to prepare for Z-based draw order. * Organizes the DisplayList hierarchy to prepare for background projection reordering. * * This should be called before a call to defer() or drawDisplayList() * Loading @@ -336,7 +355,6 @@ void DisplayList::applyViewPropertyTransforms(mat4& matrix) { */ void DisplayList::computeOrdering() { ATRACE_CALL(); m3dNodes.clear(); mProjectedNodes.clear(); // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that Loading @@ -345,40 +363,23 @@ void DisplayList::computeOrdering() { for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { DrawDisplayListOp* childOp = mDisplayListData->children[i]; childOp->mDisplayList->computeOrderingImpl(childOp, &m3dNodes, &mat4::identity(), &mProjectedNodes, &mat4::identity()); } } void DisplayList::computeOrderingImpl( DrawDisplayListOp* opState, Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot, const mat4* transformFrom3dRoot, Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface) { m3dNodes.clear(); mProjectedNodes.clear(); if (mDisplayListData == NULL || mDisplayListData->isEmpty()) return; // TODO: should avoid this calculation in most cases // TODO: just calculate single matrix, down to all leaf composited elements Matrix4 localTransformFrom3dRoot(*transformFrom3dRoot); localTransformFrom3dRoot.multiply(opState->mTransformFromParent); Matrix4 localTransformFromProjectionSurface(*transformFromProjectionSurface); localTransformFromProjectionSurface.multiply(opState->mTransformFromParent); if (mTranslationZ != 0.0f) { // TODO: other signals for 3d compositing, such as custom matrix4 // composited 3d layer, flag for out of order draw and save matrix... opState->mSkipInOrderDraw = true; opState->mTransformFromCompositingAncestor.load(localTransformFrom3dRoot); // ... and insert into current 3d root, keyed with pivot z for later sorting Vector3 pivot(mPivotX, mPivotY, 0.0f); mat4 totalTransform(localTransformFrom3dRoot); applyViewPropertyTransforms(totalTransform); totalTransform.mapPoint3d(pivot); compositedChildrenOf3dRoot->add(ZDrawDisplayListOpPair(pivot.z, opState)); } else if (mProjectBackwards) { if (mProjectBackwards) { // composited projectee, flag for out of order draw, save matrix, and store in proj surface opState->mSkipInOrderDraw = true; opState->mTransformFromCompositingAncestor.load(localTransformFromProjectionSurface); Loading @@ -389,15 +390,6 @@ void DisplayList::computeOrderingImpl( } if (mDisplayListData->children.size() > 0) { if (mIsolatedZVolume) { // create a new 3d space for descendents by collecting them compositedChildrenOf3dRoot = &m3dNodes; transformFrom3dRoot = &mat4::identity(); } else { applyViewPropertyTransforms(localTransformFrom3dRoot); transformFrom3dRoot = &localTransformFrom3dRoot; } const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0; bool haveAppliedPropertiesToProjection = false; for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { Loading @@ -422,9 +414,7 @@ void DisplayList::computeOrderingImpl( projectionChildren = compositedChildrenOfProjectionSurface; projectionTransform = &localTransformFromProjectionSurface; } child->computeOrderingImpl(childOp, compositedChildrenOf3dRoot, transformFrom3dRoot, projectionChildren, projectionTransform); child->computeOrderingImpl(childOp, projectionChildren, projectionTransform); } } Loading Loading @@ -477,14 +467,36 @@ void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) { replayStruct.mDrawGlStatus); } void DisplayList::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) { if (mDisplayListData == NULL || mDisplayListData->children.size() == 0) return; for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { DrawDisplayListOp* childOp = mDisplayListData->children[i]; DisplayList* child = childOp->mDisplayList; float childZ = child->mTranslationZ; if (childZ != 0.0f) { zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp)); childOp->mSkipInOrderDraw = true; } else if (!child->mProjectBackwards) { // regular, in order drawing DisplayList childOp->mSkipInOrderDraw = false; } } // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order) std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end()); } #define SHADOW_DELTA 0.1f template <class T> void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler, const int level) { if (m3dNodes.size() == 0 || (mode == kNegativeZChildren && m3dNodes[0].key > 0.0f) || (mode == kPositiveZChildren && m3dNodes[m3dNodes.size() - 1].key < 0.0f)) { void DisplayList::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes, ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) { const int size = zTranslatedNodes.size(); if (size == 0 || (mode == kNegativeZChildren && zTranslatedNodes[0].key > 0.0f) || (mode == kPositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) { // no 3d children to draw return; } Loading @@ -502,7 +514,7 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are * underneath both, and neither's shadow is drawn on top of the other. */ const size_t nonNegativeIndex = findNonNegativeIndex(m3dNodes); const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes); size_t drawIndex, shadowIndex, endIndex; if (mode == kNegativeZChildren) { drawIndex = 0; Loading @@ -510,24 +522,29 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren shadowIndex = endIndex; // draw no shadows } else { drawIndex = nonNegativeIndex; endIndex = m3dNodes.size(); endIndex = size; shadowIndex = drawIndex; // potentially draw shadow for each pos Z child } float lastCasterZ = 0.0f; while (shadowIndex < endIndex || drawIndex < endIndex) { if (shadowIndex < endIndex) { DrawDisplayListOp* casterOp = m3dNodes[shadowIndex].value; DrawDisplayListOp* casterOp = zTranslatedNodes[shadowIndex].value; DisplayList* caster = casterOp->mDisplayList; const float casterZ = m3dNodes[shadowIndex].key; const float casterZ = zTranslatedNodes[shadowIndex].key; // attempt to render the shadow if the caster about to be drawn is its caster, // OR if its caster's Z value is similar to the previous potential caster if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) { if (caster->mCastsShadow && caster->mAlpha > 0.0f) { mat4 shadowMatrix(casterOp->mTransformFromCompositingAncestor); caster->applyViewPropertyTransforms(shadowMatrix); mat4 shadowMatrixXY(casterOp->mTransformFromParent); caster->applyViewPropertyTransforms(shadowMatrixXY); DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix, // Z matrix needs actual 3d transformation, so mapped z values will be correct mat4 shadowMatrixZ(casterOp->mTransformFromParent); caster->applyViewPropertyTransforms(shadowMatrixZ, true); DisplayListOp* shadowOp = new (alloc) DrawShadowOp( shadowMatrixXY, shadowMatrixZ, caster->mAlpha, &(caster->mOutline), caster->mWidth, caster->mHeight); handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds); } Loading @@ -542,10 +559,10 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren // since it modifies the renderer's matrix int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag); DrawDisplayListOp* childOp = m3dNodes[drawIndex].value; DrawDisplayListOp* childOp = zTranslatedNodes[drawIndex].value; DisplayList* child = childOp->mDisplayList; renderer.concatMatrix(childOp->mTransformFromCompositingAncestor); renderer.concatMatrix(childOp->mTransformFromParent); childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone handler(childOp, renderer.getSaveCount() - 1, mClipToBounds); childOp->mSkipInOrderDraw = true; Loading Loading @@ -617,11 +634,11 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) bool quickRejected = mClipToBounds && renderer.quickRejectConservative(0, 0, mWidth, mHeight); if (!quickRejected) { // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order) std::stable_sort(m3dNodes.begin(), m3dNodes.end()); Vector<ZDrawDisplayListOpPair> zTranslatedNodes; buildZSortedChildList(zTranslatedNodes); // for 3d root, draw children with negative z values iterate3dChildren(kNegativeZChildren, renderer, handler, level); iterate3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler); DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); const int saveCountOffset = renderer.getSaveCount() - 1; Loading @@ -642,7 +659,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) } // for 3d root, draw children with positive z values iterate3dChildren(kPositiveZChildren, renderer, handler, level); iterate3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler); } DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); Loading libs/hwui/DisplayList.h +5 −8 Original line number Diff line number Diff line Loading @@ -573,20 +573,20 @@ private: void outputViewProperties(const int level); void applyViewPropertyTransforms(mat4& matrix); void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false); void computeOrderingImpl(DrawDisplayListOp* opState, Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot, const mat4* transformFrom3dRoot, Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface); template <class T> inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level); void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes); template <class T> inline void iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler, const int level); inline void iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes, ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler); template <class T> inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level); Loading Loading @@ -657,9 +657,6 @@ private: * Draw time state - these properties are only set and used during rendering */ // for 3d roots, contains a z sorted list of all children items Vector<ZDrawDisplayListOpPair> m3dNodes; // for projection surfaces, contains a list of all children items Vector<DrawDisplayListOp*> mProjectedNodes; }; // class DisplayList Loading libs/hwui/DisplayListOp.h +14 −12 Original line number Diff line number Diff line Loading @@ -1534,10 +1534,10 @@ private: const mat4 mTransformFromParent; /** * Holds the transformation between the 3d root OR projection surface ViewGroup and this * DisplayList drawing instance. Represents any translations / transformations done within the * drawing of the compositing ancestor ViewGroup's draw, before the draw of the View represented * by this DisplayList draw instance. * Holds the transformation between the projection surface ViewGroup and this DisplayList * drawing instance. Represents any translations / transformations done within the drawing of * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this * DisplayList draw instance. * * Note: doesn't include any transformation recorded within the DisplayList and its properties. */ Loading @@ -1550,19 +1550,20 @@ private: */ class DrawShadowOp : public DrawOp { public: DrawShadowOp(const mat4& transform, float alpha, const SkPath* outline, DrawShadowOp(const mat4& transformXY, const mat4& transformZ, float alpha, const SkPath* outline, float fallbackWidth, float fallbackHeight) : DrawOp(NULL), mTransform(transform), mAlpha(alpha), mOutline(outline), : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), mAlpha(alpha), mOutline(outline), mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight) {} virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { if (!mOutline->isEmpty()) { return renderer.drawShadow(mTransform, mAlpha, mOutline); } if (mOutline->isEmpty()) { SkPath fakeOutline; fakeOutline.addRect(0, 0, mFallbackWidth, mFallbackHeight); return renderer.drawShadow(mTransform, mAlpha, &fakeOutline); return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, &fakeOutline); } return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, mOutline); } virtual void output(int level, uint32_t logFlags) const { Loading @@ -1572,7 +1573,8 @@ public: virtual const char* name() { return "DrawShadow"; } private: const mat4 mTransform; const mat4 mTransformXY; const mat4 mTransformZ; const float mAlpha; const SkPath* mOutline; const float mFallbackWidth; Loading libs/hwui/Matrix.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -385,9 +385,14 @@ void Matrix4::loadOrtho(float left, float right, float bottom, float top, float mType = kTypeTranslate | kTypeScale | kTypeRectToRect; } float Matrix4::mapZ(const Vector3& orig) const { // duplicates logic for mapPoint3d's z coordinate return orig.x * data[2] + orig.y * data[6] + orig.z * data[kScaleZ] + data[kTranslateZ]; } void Matrix4::mapPoint3d(Vector3& vec) const { //TODO: optimize simple case Vector3 orig(vec); const Vector3 orig(vec); vec.x = orig.x * data[kScaleX] + orig.y * data[kSkewX] + orig.z * data[8] + data[kTranslateX]; vec.y = orig.x * data[kSkewY] + orig.y * data[kScaleY] + orig.z * data[9] + data[kTranslateY]; vec.z = orig.x * data[2] + orig.y * data[6] + orig.z * data[kScaleZ] + data[kTranslateZ]; Loading libs/hwui/Matrix.h +1 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ public: void copyTo(float* v) const; void copyTo(SkMatrix& v) const; float mapZ(const Vector3& orig) const; void mapPoint3d(Vector3& vec) const; void mapPoint(float& x, float& y) const; // 2d only void mapRect(Rect& r) const; // 2d only Loading Loading
libs/hwui/DisplayList.cpp +70 −53 Original line number Diff line number Diff line Loading @@ -304,8 +304,11 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler, /** * Apply property-based transformations to input matrix * * If true3dTransform is set to true, the transform applied to the input matrix will use true 4x4 * matrix computation instead of the Skia 3x3 matrix + camera hackery. */ void DisplayList::applyViewPropertyTransforms(mat4& matrix) { void DisplayList::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) { if (mLeft != 0 || mTop != 0) { matrix.translate(mLeft, mTop); } Loading @@ -319,15 +322,31 @@ void DisplayList::applyViewPropertyTransforms(mat4& matrix) { if (mMatrixFlags != 0) { updateMatrix(); if (mMatrixFlags == TRANSLATION) { matrix.translate(mTranslationX, mTranslationY, mTranslationZ); matrix.translate(mTranslationX, mTranslationY, true3dTransform ? mTranslationZ : 0.0f); } else { if (!true3dTransform) { matrix.multiply(*mTransformMatrix); } else { mat4 true3dMat; true3dMat.loadTranslate( mPivotX + mTranslationX, mPivotY + mTranslationY, mTranslationZ); true3dMat.rotate(mRotationX, 1, 0, 0); true3dMat.rotate(mRotationY, 0, 1, 0); true3dMat.rotate(mRotation, 0, 0, 1); true3dMat.scale(mScaleX, mScaleY, 1); true3dMat.translate(-mPivotX, -mPivotY); matrix.multiply(true3dMat); } } } } /** * Organizes the DisplayList hierarchy to prepare for Z-based draw order. * Organizes the DisplayList hierarchy to prepare for background projection reordering. * * This should be called before a call to defer() or drawDisplayList() * Loading @@ -336,7 +355,6 @@ void DisplayList::applyViewPropertyTransforms(mat4& matrix) { */ void DisplayList::computeOrdering() { ATRACE_CALL(); m3dNodes.clear(); mProjectedNodes.clear(); // TODO: create temporary DDLOp and call computeOrderingImpl on top DisplayList so that Loading @@ -345,40 +363,23 @@ void DisplayList::computeOrdering() { for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { DrawDisplayListOp* childOp = mDisplayListData->children[i]; childOp->mDisplayList->computeOrderingImpl(childOp, &m3dNodes, &mat4::identity(), &mProjectedNodes, &mat4::identity()); } } void DisplayList::computeOrderingImpl( DrawDisplayListOp* opState, Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot, const mat4* transformFrom3dRoot, Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface) { m3dNodes.clear(); mProjectedNodes.clear(); if (mDisplayListData == NULL || mDisplayListData->isEmpty()) return; // TODO: should avoid this calculation in most cases // TODO: just calculate single matrix, down to all leaf composited elements Matrix4 localTransformFrom3dRoot(*transformFrom3dRoot); localTransformFrom3dRoot.multiply(opState->mTransformFromParent); Matrix4 localTransformFromProjectionSurface(*transformFromProjectionSurface); localTransformFromProjectionSurface.multiply(opState->mTransformFromParent); if (mTranslationZ != 0.0f) { // TODO: other signals for 3d compositing, such as custom matrix4 // composited 3d layer, flag for out of order draw and save matrix... opState->mSkipInOrderDraw = true; opState->mTransformFromCompositingAncestor.load(localTransformFrom3dRoot); // ... and insert into current 3d root, keyed with pivot z for later sorting Vector3 pivot(mPivotX, mPivotY, 0.0f); mat4 totalTransform(localTransformFrom3dRoot); applyViewPropertyTransforms(totalTransform); totalTransform.mapPoint3d(pivot); compositedChildrenOf3dRoot->add(ZDrawDisplayListOpPair(pivot.z, opState)); } else if (mProjectBackwards) { if (mProjectBackwards) { // composited projectee, flag for out of order draw, save matrix, and store in proj surface opState->mSkipInOrderDraw = true; opState->mTransformFromCompositingAncestor.load(localTransformFromProjectionSurface); Loading @@ -389,15 +390,6 @@ void DisplayList::computeOrderingImpl( } if (mDisplayListData->children.size() > 0) { if (mIsolatedZVolume) { // create a new 3d space for descendents by collecting them compositedChildrenOf3dRoot = &m3dNodes; transformFrom3dRoot = &mat4::identity(); } else { applyViewPropertyTransforms(localTransformFrom3dRoot); transformFrom3dRoot = &localTransformFrom3dRoot; } const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0; bool haveAppliedPropertiesToProjection = false; for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { Loading @@ -422,9 +414,7 @@ void DisplayList::computeOrderingImpl( projectionChildren = compositedChildrenOfProjectionSurface; projectionTransform = &localTransformFromProjectionSurface; } child->computeOrderingImpl(childOp, compositedChildrenOf3dRoot, transformFrom3dRoot, projectionChildren, projectionTransform); child->computeOrderingImpl(childOp, projectionChildren, projectionTransform); } } Loading Loading @@ -477,14 +467,36 @@ void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) { replayStruct.mDrawGlStatus); } void DisplayList::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) { if (mDisplayListData == NULL || mDisplayListData->children.size() == 0) return; for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) { DrawDisplayListOp* childOp = mDisplayListData->children[i]; DisplayList* child = childOp->mDisplayList; float childZ = child->mTranslationZ; if (childZ != 0.0f) { zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp)); childOp->mSkipInOrderDraw = true; } else if (!child->mProjectBackwards) { // regular, in order drawing DisplayList childOp->mSkipInOrderDraw = false; } } // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order) std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end()); } #define SHADOW_DELTA 0.1f template <class T> void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler, const int level) { if (m3dNodes.size() == 0 || (mode == kNegativeZChildren && m3dNodes[0].key > 0.0f) || (mode == kPositiveZChildren && m3dNodes[m3dNodes.size() - 1].key < 0.0f)) { void DisplayList::iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes, ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) { const int size = zTranslatedNodes.size(); if (size == 0 || (mode == kNegativeZChildren && zTranslatedNodes[0].key > 0.0f) || (mode == kPositiveZChildren && zTranslatedNodes[size - 1].key < 0.0f)) { // no 3d children to draw return; } Loading @@ -502,7 +514,7 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren * This way, if Views A & B have the same Z height and are both casting shadows, the shadows are * underneath both, and neither's shadow is drawn on top of the other. */ const size_t nonNegativeIndex = findNonNegativeIndex(m3dNodes); const size_t nonNegativeIndex = findNonNegativeIndex(zTranslatedNodes); size_t drawIndex, shadowIndex, endIndex; if (mode == kNegativeZChildren) { drawIndex = 0; Loading @@ -510,24 +522,29 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren shadowIndex = endIndex; // draw no shadows } else { drawIndex = nonNegativeIndex; endIndex = m3dNodes.size(); endIndex = size; shadowIndex = drawIndex; // potentially draw shadow for each pos Z child } float lastCasterZ = 0.0f; while (shadowIndex < endIndex || drawIndex < endIndex) { if (shadowIndex < endIndex) { DrawDisplayListOp* casterOp = m3dNodes[shadowIndex].value; DrawDisplayListOp* casterOp = zTranslatedNodes[shadowIndex].value; DisplayList* caster = casterOp->mDisplayList; const float casterZ = m3dNodes[shadowIndex].key; const float casterZ = zTranslatedNodes[shadowIndex].key; // attempt to render the shadow if the caster about to be drawn is its caster, // OR if its caster's Z value is similar to the previous potential caster if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) { if (caster->mCastsShadow && caster->mAlpha > 0.0f) { mat4 shadowMatrix(casterOp->mTransformFromCompositingAncestor); caster->applyViewPropertyTransforms(shadowMatrix); mat4 shadowMatrixXY(casterOp->mTransformFromParent); caster->applyViewPropertyTransforms(shadowMatrixXY); DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix, // Z matrix needs actual 3d transformation, so mapped z values will be correct mat4 shadowMatrixZ(casterOp->mTransformFromParent); caster->applyViewPropertyTransforms(shadowMatrixZ, true); DisplayListOp* shadowOp = new (alloc) DrawShadowOp( shadowMatrixXY, shadowMatrixZ, caster->mAlpha, &(caster->mOutline), caster->mWidth, caster->mHeight); handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds); } Loading @@ -542,10 +559,10 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren // since it modifies the renderer's matrix int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag); DrawDisplayListOp* childOp = m3dNodes[drawIndex].value; DrawDisplayListOp* childOp = zTranslatedNodes[drawIndex].value; DisplayList* child = childOp->mDisplayList; renderer.concatMatrix(childOp->mTransformFromCompositingAncestor); renderer.concatMatrix(childOp->mTransformFromParent); childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone handler(childOp, renderer.getSaveCount() - 1, mClipToBounds); childOp->mSkipInOrderDraw = true; Loading Loading @@ -617,11 +634,11 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) bool quickRejected = mClipToBounds && renderer.quickRejectConservative(0, 0, mWidth, mHeight); if (!quickRejected) { // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order) std::stable_sort(m3dNodes.begin(), m3dNodes.end()); Vector<ZDrawDisplayListOpPair> zTranslatedNodes; buildZSortedChildList(zTranslatedNodes); // for 3d root, draw children with negative z values iterate3dChildren(kNegativeZChildren, renderer, handler, level); iterate3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler); DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance(); const int saveCountOffset = renderer.getSaveCount() - 1; Loading @@ -642,7 +659,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) } // for 3d root, draw children with positive z values iterate3dChildren(kPositiveZChildren, renderer, handler, level); iterate3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler); } DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo); Loading
libs/hwui/DisplayList.h +5 −8 Original line number Diff line number Diff line Loading @@ -573,20 +573,20 @@ private: void outputViewProperties(const int level); void applyViewPropertyTransforms(mat4& matrix); void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false); void computeOrderingImpl(DrawDisplayListOp* opState, Vector<ZDrawDisplayListOpPair>* compositedChildrenOf3dRoot, const mat4* transformFrom3dRoot, Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface); template <class T> inline void setViewProperties(OpenGLRenderer& renderer, T& handler, const int level); void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes); template <class T> inline void iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler, const int level); inline void iterate3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes, ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler); template <class T> inline void iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level); Loading Loading @@ -657,9 +657,6 @@ private: * Draw time state - these properties are only set and used during rendering */ // for 3d roots, contains a z sorted list of all children items Vector<ZDrawDisplayListOpPair> m3dNodes; // for projection surfaces, contains a list of all children items Vector<DrawDisplayListOp*> mProjectedNodes; }; // class DisplayList Loading
libs/hwui/DisplayListOp.h +14 −12 Original line number Diff line number Diff line Loading @@ -1534,10 +1534,10 @@ private: const mat4 mTransformFromParent; /** * Holds the transformation between the 3d root OR projection surface ViewGroup and this * DisplayList drawing instance. Represents any translations / transformations done within the * drawing of the compositing ancestor ViewGroup's draw, before the draw of the View represented * by this DisplayList draw instance. * Holds the transformation between the projection surface ViewGroup and this DisplayList * drawing instance. Represents any translations / transformations done within the drawing of * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this * DisplayList draw instance. * * Note: doesn't include any transformation recorded within the DisplayList and its properties. */ Loading @@ -1550,19 +1550,20 @@ private: */ class DrawShadowOp : public DrawOp { public: DrawShadowOp(const mat4& transform, float alpha, const SkPath* outline, DrawShadowOp(const mat4& transformXY, const mat4& transformZ, float alpha, const SkPath* outline, float fallbackWidth, float fallbackHeight) : DrawOp(NULL), mTransform(transform), mAlpha(alpha), mOutline(outline), : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), mAlpha(alpha), mOutline(outline), mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight) {} virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { if (!mOutline->isEmpty()) { return renderer.drawShadow(mTransform, mAlpha, mOutline); } if (mOutline->isEmpty()) { SkPath fakeOutline; fakeOutline.addRect(0, 0, mFallbackWidth, mFallbackHeight); return renderer.drawShadow(mTransform, mAlpha, &fakeOutline); return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, &fakeOutline); } return renderer.drawShadow(mTransformXY, mTransformZ, mAlpha, mOutline); } virtual void output(int level, uint32_t logFlags) const { Loading @@ -1572,7 +1573,8 @@ public: virtual const char* name() { return "DrawShadow"; } private: const mat4 mTransform; const mat4 mTransformXY; const mat4 mTransformZ; const float mAlpha; const SkPath* mOutline; const float mFallbackWidth; Loading
libs/hwui/Matrix.cpp +6 −1 Original line number Diff line number Diff line Loading @@ -385,9 +385,14 @@ void Matrix4::loadOrtho(float left, float right, float bottom, float top, float mType = kTypeTranslate | kTypeScale | kTypeRectToRect; } float Matrix4::mapZ(const Vector3& orig) const { // duplicates logic for mapPoint3d's z coordinate return orig.x * data[2] + orig.y * data[6] + orig.z * data[kScaleZ] + data[kTranslateZ]; } void Matrix4::mapPoint3d(Vector3& vec) const { //TODO: optimize simple case Vector3 orig(vec); const Vector3 orig(vec); vec.x = orig.x * data[kScaleX] + orig.y * data[kSkewX] + orig.z * data[8] + data[kTranslateX]; vec.y = orig.x * data[kSkewY] + orig.y * data[kScaleY] + orig.z * data[9] + data[kTranslateY]; vec.z = orig.x * data[2] + orig.y * data[6] + orig.z * data[kScaleZ] + data[kTranslateZ]; Loading
libs/hwui/Matrix.h +1 −0 Original line number Diff line number Diff line Loading @@ -199,6 +199,7 @@ public: void copyTo(float* v) const; void copyTo(SkMatrix& v) const; float mapZ(const Vector3& orig) const; void mapPoint3d(Vector3& vec) const; void mapPoint(float& x, float& y) const; // 2d only void mapRect(Rect& r) const; // 2d only Loading