diff options
author | Chris Craik <ccraik@google.com> | 2014-03-06 17:45:28 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-03-06 17:45:29 +0000 |
commit | ef8c07c86fb810d4052fa9fa62751c46234299e9 (patch) | |
tree | ca510e7ad86ea1dfb854c70d23c25383835665a3 /libs/hwui/DisplayList.cpp | |
parent | 46b8d00b1e28c5b527de4d281db9f288499889db (diff) | |
parent | 8b6f2df48e10de35d43621ce174eb3dde394725c (diff) | |
download | frameworks_base-ef8c07c86fb810d4052fa9fa62751c46234299e9.zip frameworks_base-ef8c07c86fb810d4052fa9fa62751c46234299e9.tar.gz frameworks_base-ef8c07c86fb810d4052fa9fa62751c46234299e9.tar.bz2 |
Merge "Draw shadows from casters together if the Z values are similar"
Diffstat (limited to 'libs/hwui/DisplayList.cpp')
-rw-r--r-- | libs/hwui/DisplayList.cpp | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index bdb2f8d..c3aa733 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -488,6 +488,8 @@ void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) { replayStruct.mDrawGlStatus); } +#define SHADOW_DELTA 2.0f + template <class T> void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler, const int level) { @@ -501,34 +503,66 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); LinearAllocator& alloc = handler.allocator(); ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight, - SkRegion::kIntersect_Op); // clip to 3d root bounds for now + SkRegion::kIntersect_Op); // clip to 3d root bounds handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds); - for (size_t i = 0; i < m3dNodes.size(); i++) { - const float zValue = m3dNodes[i].key; - DrawDisplayListOp* childOp = m3dNodes[i].value; + /** + * Draw shadows and (potential) casters mostly in order, but allow the shadows of casters + * with very similar Z heights to draw together. + * + * 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); + size_t drawIndex, shadowIndex, endIndex; + if (mode == kNegativeZChildren) { + drawIndex = 0; + endIndex = nonNegativeIndex; + shadowIndex = endIndex; // draw no shadows + } else { + drawIndex = nonNegativeIndex; + endIndex = m3dNodes.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; + DisplayList* caster = casterOp->mDisplayList; + const float casterZ = m3dNodes[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); + + DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix, + caster->mAlpha, &(caster->mOutline), caster->mWidth, caster->mHeight); + handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds); + } + + lastCasterZ = casterZ; // must do this even if current caster not casting a shadow + shadowIndex++; + continue; + } + } - if (mode == kPositiveZChildren && zValue < 0.0f) continue; - if (mode == kNegativeZChildren && zValue > 0.0f) break; + // only the actual child DL draw needs to be in save/restore, + // since it modifies the renderer's matrix + int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag); + DrawDisplayListOp* childOp = m3dNodes[drawIndex].value; DisplayList* child = childOp->mDisplayList; - if (mode == kPositiveZChildren && zValue > 0.0f - && child->mCastsShadow && child->mAlpha > 0.0f) { - /* draw shadow with parent matrix applied, passing in the child's total matrix - * TODO: consider depth in more complex scenarios (neg z, added shadow depth) - */ - mat4 shadowMatrix(childOp->mTransformFromCompositingAncestor); - child->applyViewPropertyTransforms(shadowMatrix); - - DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix, - child->mAlpha, &(child->mOutline), child->mWidth, child->mHeight); - handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds); - } renderer.concatMatrix(childOp->mTransformFromCompositingAncestor); childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone handler(childOp, renderer.getSaveCount() - 1, mClipToBounds); childOp->mSkipInOrderDraw = true; + + renderer.restoreToCount(restoreTo); + drawIndex++; } handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, mClipToBounds); } |