summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2014-08-21 17:41:57 -0700
committerChris Craik <ccraik@google.com>2014-08-25 15:35:40 -0700
commit8afd0f245cc0c4a0366f39f41b5f78e47ee83be3 (patch)
tree220f6cac192fe822650d4676ef3996da5fb02ad9
parentcc3e5d5cd197ad45e051e31fd85af28588af4cf7 (diff)
downloadframeworks_base-8afd0f245cc0c4a0366f39f41b5f78e47ee83be3.zip
frameworks_base-8afd0f245cc0c4a0366f39f41b5f78e47ee83be3.tar.gz
frameworks_base-8afd0f245cc0c4a0366f39f41b5f78e47ee83be3.tar.bz2
Create z reordering boundaries around dispatchDraw
bug:16012254 This means rendernodes with a Z will no longer be drawn at the end of their parent's DisplayList, but at the end of the associated reorder region (DisplayListData::Chunk). Change-Id: Ia033fee9d9a4db567b2a8d5e90fc57a4d0a64544
-rw-r--r--core/java/android/view/GLES20Canvas.java12
-rw-r--r--core/java/android/view/ViewGroup.java3
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp7
-rw-r--r--graphics/java/android/graphics/Canvas.java6
-rw-r--r--libs/hwui/DisplayList.cpp6
-rw-r--r--libs/hwui/DisplayList.h37
-rw-r--r--libs/hwui/DisplayListOp.h8
-rw-r--r--libs/hwui/DisplayListRenderer.cpp96
-rw-r--r--libs/hwui/DisplayListRenderer.h31
-rw-r--r--libs/hwui/RenderNode.cpp55
-rw-r--r--libs/hwui/RenderNode.h5
11 files changed, 187 insertions, 79 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index a410aa9..ceea9f8 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -179,6 +179,18 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nSetHighContrastText(long renderer, boolean highContrastText);
@Override
+ public void insertReorderBarrier() {
+ nInsertReorderBarrier(mRenderer, true);
+ }
+
+ @Override
+ public void insertInorderBarrier() {
+ nInsertReorderBarrier(mRenderer, false);
+ }
+
+ private static native void nInsertReorderBarrier(long renderer, boolean enableReorder);
+
+ @Override
public int onPreDraw(Rect dirty) {
if (dirty != null) {
return nPrepareDirty(mRenderer, dirty.left, dirty.top, dirty.right, dirty.bottom,
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 19dd583..854e6be 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3072,7 +3072,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
boolean more = false;
final long drawingTime = getDrawingTime();
-
+ if (usingRenderNodeProperties) canvas.insertReorderBarrier();
// Only use the preordered list if not HW accelerated, since the HW pipeline will do the
// draw reordering internally
final ArrayList<View> preorderedList = usingRenderNodeProperties
@@ -3099,6 +3099,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
more |= drawChild(canvas, child, drawingTime);
}
}
+ if (usingRenderNodeProperties) canvas.insertInorderBarrier();
if (debugDraw()) {
onDebugDraw(canvas);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index afcfaf6..6080f2a 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -104,6 +104,12 @@ static void android_view_GLES20Canvas_setHighContrastText(JNIEnv* env, jobject c
renderer->setHighContrastText(highContrastText);
}
+static void android_view_GLES20Canvas_insertReorderBarrier(JNIEnv* env, jobject clazz,
+ jlong rendererPtr, jboolean reorderEnable) {
+ DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+ renderer->insertReorderBarrier(reorderEnable);
+}
+
static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
jlong rendererPtr, jboolean opaque) {
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
@@ -859,6 +865,7 @@ static JNINativeMethod gMethods[] = {
{ "nDestroyRenderer", "(J)V", (void*) android_view_GLES20Canvas_destroyRenderer },
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
{ "nSetHighContrastText","(JZ)V", (void*) android_view_GLES20Canvas_setHighContrastText },
+ { "nInsertReorderBarrier","(JZ)V", (void*) android_view_GLES20Canvas_insertReorderBarrier },
{ "nPrepare", "(JZ)I", (void*) android_view_GLES20Canvas_prepare },
{ "nPrepareDirty", "(JIIIIZ)I", (void*) android_view_GLES20Canvas_prepareDirty },
{ "nFinish", "(J)V", (void*) android_view_GLES20Canvas_finish },
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f3af8f6..f18694b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -243,6 +243,12 @@ public class Canvas {
/** @hide */
public void setHighContrastText(boolean highContrastText) {}
+ /** @hide */
+ public void insertReorderBarrier() {}
+
+ /** @hide */
+ public void insertInorderBarrier() {}
+
/**
* @hide
*/
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 6461ee7..d8932ce 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -89,11 +89,9 @@ void DisplayListData::cleanupResources() {
layers.clear();
}
-void DisplayListData::addChild(DrawRenderNodeOp* op) {
- LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawRenderNodeOp with no render node!");
-
- mChildren.push(op);
+size_t DisplayListData::addChild(DrawRenderNodeOp* op) {
mReferenceHolders.push(op->renderNode());
+ return mChildren.add(op);
}
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index acfa98e..dea109c 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -115,13 +115,24 @@ public:
* Data structure that holds the list of commands used in display list stream
*/
class DisplayListData {
+ friend class DisplayListRenderer;
public:
+ struct Chunk {
+ // range of included ops in DLD::displayListOps
+ size_t beginOpIndex;
+ size_t endOpIndex;
+
+ // range of included children in DLD::mChildren
+ size_t beginChildIndex;
+ size_t endChildIndex;
+
+ // whether children with non-zero Z in the chunk should be reordered
+ bool reorderChildren;
+ };
+
DisplayListData();
~DisplayListData();
- // allocator into which all ops were allocated
- LinearAllocator allocator;
-
// pointers to all ops within display list, pointing into allocator data
Vector<DisplayListOp*> displayListOps;
@@ -138,13 +149,12 @@ public:
Vector<const SkRegion*> regions;
Vector<Layer*> layers;
Vector<Functor*> functors;
- bool hasDrawOps;
- bool isEmpty() {
- return !displayListOps.size();
+ const Vector<Chunk>& getChunks() const {
+ return chunks;
}
- void addChild(DrawRenderNodeOp* childOp);
+ size_t addChild(DrawRenderNodeOp* childOp);
const Vector<DrawRenderNodeOp*>& children() { return mChildren; }
void refProperty(CanvasPropertyPrimitive* prop) {
@@ -155,12 +165,25 @@ public:
mReferenceHolders.push(prop);
}
+ size_t getUsedSize() {
+ return allocator.usedSize();
+ }
+ bool isEmpty() {
+ return !hasDrawOps;
+ }
+
private:
Vector< sp<VirtualLightRefBase> > mReferenceHolders;
// list of children display lists for quick, non-drawing traversal
Vector<DrawRenderNodeOp*> mChildren;
+ Vector<Chunk> chunks;
+
+ // allocator into which all ops were allocated
+ LinearAllocator allocator;
+ bool hasDrawOps;
+
void cleanupResources();
};
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5f533a7..8818510 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1445,6 +1445,7 @@ private:
class DrawRenderNodeOp : public DrawBoundedOp {
friend class RenderNode; // grant RenderNode access to info of child
+ friend class DisplayListData; // grant DisplayListData access to info of child
public:
DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
: DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
@@ -1452,13 +1453,14 @@ public:
virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
bool useQuickReject) {
- if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+ if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
mRenderNode->defer(deferStruct, level + 1);
}
}
+
virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
bool useQuickReject) {
- if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+ if (mRenderNode->isRenderable() && !mSkipInOrderDraw) {
mRenderNode->replay(replayStruct, level + 1);
}
}
@@ -1469,7 +1471,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw Display List %p, flags %#x", mRenderNode, mFlags);
+ OP_LOG("Draw RenderNode %p %s, flags %#x", mRenderNode, mRenderNode->getName(), mFlags);
if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
mRenderNode->output(level + 1);
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 9a9c544..5892978 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -33,10 +33,10 @@ namespace uirenderer {
DisplayListRenderer::DisplayListRenderer()
: mCaches(Caches::getInstance())
- , mDisplayListData(0)
+ , mDisplayListData(NULL)
, mTranslateX(0.0f)
, mTranslateY(0.0f)
- , mHasTranslate(false)
+ , mDeferredBarrierType(kBarrier_None)
, mHighContrastText(false)
, mRestoreSaveCount(-1) {
}
@@ -68,6 +68,7 @@ status_t DisplayListRenderer::prepareDirty(float left, float top,
initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
+ mDeferredBarrierType = kBarrier_InOrder;
mDirtyClip = opaque;
mRestoreSaveCount = -1;
@@ -75,8 +76,8 @@ status_t DisplayListRenderer::prepareDirty(float left, float top,
}
void DisplayListRenderer::finish() {
- insertRestoreToCount();
- insertTranslate();
+ flushRestoreToCount();
+ flushTranslate();
}
void DisplayListRenderer::interrupt() {
@@ -104,13 +105,13 @@ void DisplayListRenderer::restore() {
}
mRestoreSaveCount--;
- insertTranslate();
+ flushTranslate();
StatefulBaseRenderer::restore();
}
void DisplayListRenderer::restoreToCount(int saveCount) {
mRestoreSaveCount = saveCount;
- insertTranslate();
+ flushTranslate();
StatefulBaseRenderer::restoreToCount(saveCount);
}
@@ -123,10 +124,10 @@ int DisplayListRenderer::saveLayer(float left, float top, float right, float bot
void DisplayListRenderer::translate(float dx, float dy, float dz) {
// ignore dz, not used at defer time
- mHasTranslate = true;
+ mHasDeferredTranslate = true;
mTranslateX += dx;
mTranslateY += dy;
- insertRestoreToCount();
+ flushRestoreToCount();
StatefulBaseRenderer::translate(dx, dy, dz);
}
@@ -174,16 +175,12 @@ bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
}
status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
+ LOG_ALWAYS_FATAL_IF(!renderNode, "missing rendernode");
+
// dirty is an out parameter and should not be recorded,
// it matters only when replaying the display list
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
- int opIndex = addDrawOp(op);
- mDisplayListData->addChild(op);
-
- if (renderNode->stagingProperties().isProjectionReceiver()) {
- // use staging property, since recording on UI thread
- mDisplayListData->projectionReceiveIndex = opIndex;
- }
+ addRenderNodeOp(op);
return DrawGlInfo::kStatusDone;
}
@@ -428,30 +425,60 @@ void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
addStateOp(new (alloc()) SetupPaintFilterOp(clearBits, setBits));
}
-void DisplayListRenderer::insertRestoreToCount() {
+void DisplayListRenderer::insertReorderBarrier(bool enableReorder) {
+ flushRestoreToCount();
+ flushTranslate();
+ mDeferredBarrierType = enableReorder ? kBarrier_OutOfOrder : kBarrier_InOrder;
+}
+
+void DisplayListRenderer::flushRestoreToCount() {
if (mRestoreSaveCount >= 0) {
- DisplayListOp* op = new (alloc()) RestoreToCountOp(mRestoreSaveCount);
- mDisplayListData->displayListOps.add(op);
+ addOpAndUpdateChunk(new (alloc()) RestoreToCountOp(mRestoreSaveCount));
mRestoreSaveCount = -1;
}
}
-void DisplayListRenderer::insertTranslate() {
- if (mHasTranslate) {
+void DisplayListRenderer::flushTranslate() {
+ if (mHasDeferredTranslate) {
if (mTranslateX != 0.0f || mTranslateY != 0.0f) {
- DisplayListOp* op = new (alloc()) TranslateOp(mTranslateX, mTranslateY);
- mDisplayListData->displayListOps.add(op);
+ addOpAndUpdateChunk(new (alloc()) TranslateOp(mTranslateX, mTranslateY));
mTranslateX = mTranslateY = 0.0f;
}
- mHasTranslate = false;
+ mHasDeferredTranslate = false;
}
}
-int DisplayListRenderer::addStateOp(StateOp* op) {
- return addOpInternal(op);
+size_t DisplayListRenderer::addOpAndUpdateChunk(DisplayListOp* op) {
+ int insertIndex = mDisplayListData->displayListOps.add(op);
+ if (mDeferredBarrierType != kBarrier_None) {
+ // op is first in new chunk
+ mDisplayListData->chunks.push();
+ DisplayListData::Chunk& newChunk = mDisplayListData->chunks.editTop();
+ newChunk.beginOpIndex = insertIndex;
+ newChunk.endOpIndex = insertIndex + 1;
+ newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
+
+ int nextChildIndex = mDisplayListData->children().size();
+ newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
+ mDeferredBarrierType = kBarrier_None;
+ } else {
+ // standard case - append to existing chunk
+ mDisplayListData->chunks.editTop().endOpIndex = insertIndex + 1;
+ }
+ return insertIndex;
}
-int DisplayListRenderer::addDrawOp(DrawOp* op) {
+size_t DisplayListRenderer::flushAndAddOp(DisplayListOp* op) {
+ flushRestoreToCount();
+ flushTranslate();
+ return addOpAndUpdateChunk(op);
+}
+
+size_t DisplayListRenderer::addStateOp(StateOp* op) {
+ return flushAndAddOp(op);
+}
+
+size_t DisplayListRenderer::addDrawOp(DrawOp* op) {
Rect localBounds;
if (op->getLocalBounds(localBounds)) {
bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
@@ -460,7 +487,22 @@ int DisplayListRenderer::addDrawOp(DrawOp* op) {
}
mDisplayListData->hasDrawOps = true;
- return addOpInternal(op);
+ return flushAndAddOp(op);
+}
+
+size_t DisplayListRenderer::addRenderNodeOp(DrawRenderNodeOp* op) {
+ int opIndex = addDrawOp(op);
+ int childIndex = mDisplayListData->addChild(op);
+
+ // update the chunk's child indices
+ DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop();
+ chunk.endChildIndex = childIndex + 1;
+
+ if (op->renderNode()->stagingProperties().isProjectionReceiver()) {
+ // use staging property, since recording on UI thread
+ mDisplayListData->projectionReceiveIndex = opIndex;
+ }
+ return opIndex;
}
}; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index b5c0159..7350082 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -57,6 +57,8 @@ public:
DisplayListRenderer();
virtual ~DisplayListRenderer();
+ void insertReorderBarrier(bool enableReorder);
+
DisplayListData* finishRecording();
// ----------------------------------------------------------------------------
@@ -154,19 +156,27 @@ public:
mHighContrastText = highContrastText;
}
private:
- void insertRestoreToCount();
- void insertTranslate();
+ enum DeferredBarrierType {
+ kBarrier_None,
+ kBarrier_InOrder,
+ kBarrier_OutOfOrder,
+ };
+
+ void flushRestoreToCount();
+ void flushTranslate();
+ void flushReorderBarrier();
LinearAllocator& alloc() { return mDisplayListData->allocator; }
// Each method returns final index of op
- int addStateOp(StateOp* op);
- int addDrawOp(DrawOp* op);
- int addOpInternal(DisplayListOp* op) {
- insertRestoreToCount();
- insertTranslate();
- return mDisplayListData->displayListOps.add(op);
- }
+ size_t addOpAndUpdateChunk(DisplayListOp* op);
+ // flushes any deferred operations, and appends the op
+ size_t flushAndAddOp(DisplayListOp* op);
+
+ size_t addStateOp(StateOp* op);
+ size_t addDrawOp(DrawOp* op);
+ size_t addRenderNodeOp(DrawRenderNodeOp* op);
+
template<class T>
inline const T* refBuffer(const T* srcBuffer, int32_t count) {
@@ -277,7 +287,8 @@ private:
float mTranslateX;
float mTranslateY;
- bool mHasTranslate;
+ bool mHasDeferredTranslate;
+ DeferredBarrierType mDeferredBarrierType;
bool mHighContrastText;
int mRestoreSaveCount;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 977744f..658265d 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -95,6 +95,7 @@ void RenderNode::output(uint32_t level) {
properties().debugOutputProperties(level);
int flags = DisplayListOp::kOpLogFlag_Recurse;
if (mDisplayListData) {
+ // TODO: consider printing the chunk boundaries here
for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
mDisplayListData->displayListOps[i]->output(level, flags);
}
@@ -106,10 +107,10 @@ void RenderNode::output(uint32_t level) {
int RenderNode::getDebugSize() {
int size = sizeof(RenderNode);
if (mStagingDisplayListData) {
- size += mStagingDisplayListData->allocator.usedSize();
+ size += mStagingDisplayListData->getUsedSize();
}
if (mDisplayListData && mDisplayListData != mStagingDisplayListData) {
- size += mDisplayListData->allocator.usedSize();
+ size += mDisplayListData->getUsedSize();
}
return size;
}
@@ -593,15 +594,16 @@ void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}
-void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
- if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
+void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk,
+ Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
+ if (chunk.beginChildIndex == chunk.endChildIndex) return;
- for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
+ for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) {
DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
RenderNode* child = childOp->mRenderNode;
float childZ = child->properties().getZ();
- if (!MathUtils::isZero(childZ)) {
+ if (!MathUtils::isZero(childZ) && chunk.reorderChildren) {
zTranslatedNodes.add(ZDrawRenderNodeOpPair(childZ, childOp));
childOp->mSkipInOrderDraw = true;
} else if (!child->properties().getProjectBackwards()) {
@@ -610,7 +612,7 @@ void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslate
}
}
- // Z sort 3d children (stable-ness makes z compare fall back to standard drawing order)
+ // Z sort any 3d children (stable-ness makes z compare fall back to standard drawing order)
std::stable_sort(zTranslatedNodes.begin(), zTranslatedNodes.end());
}
@@ -871,32 +873,35 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
renderer.getSaveCount() - 1, properties().getClipToBounds());
} else {
- Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
- buildZSortedChildList(zTranslatedNodes);
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+ for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
+ const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
- // for 3d root, draw children with negative z values
- int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes, renderer, handler);
+ Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
+ buildZSortedChildList(chunk, zTranslatedNodes);
- DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
- const int saveCountOffset = renderer.getSaveCount() - 1;
- const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
- const int size = static_cast<int>(mDisplayListData->displayListOps.size());
- for (int i = 0; i < size; i++) {
- DisplayListOp *op = mDisplayListData->displayListOps[i];
+ // for 3d root, draw children with negative z values
+ int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes,
+ renderer, handler);
+ const int saveCountOffset = renderer.getSaveCount() - 1;
+ const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
+ for (int opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
+ DisplayListOp *op = mDisplayListData->displayListOps[opIndex];
#if DEBUG_DISPLAY_LIST
- op->output(level + 1);
+ op->output(level + 1);
#endif
- logBuffer.writeCommand(level, op->name());
- handler(op, saveCountOffset, properties().getClipToBounds());
+ logBuffer.writeCommand(level, op->name());
+ handler(op, saveCountOffset, properties().getClipToBounds());
- if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
- issueOperationsOfProjectedChildren(renderer, handler);
+ if (CC_UNLIKELY(!mProjectedNodes.isEmpty() && opIndex == projectionReceiveIndex)) {
+ issueOperationsOfProjectedChildren(renderer, handler);
+ }
}
- }
- // for 3d root, draw children with positive z values
- issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+ // for 3d root, draw children with positive z values
+ issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
+ }
}
}
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index afa17d5..18402b2 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -114,7 +114,7 @@ public:
ANDROID_API int getDebugSize();
bool isRenderable() const {
- return mDisplayListData && mDisplayListData->hasDrawOps;
+ return mDisplayListData && !mDisplayListData->isEmpty();
}
bool hasProjectionReceiver() const {
@@ -199,7 +199,8 @@ private:
template <class T>
inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
- void buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
+ void buildZSortedChildList(const DisplayListData::Chunk& chunk,
+ Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
template<class T>
inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);