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
This commit is contained in:
@@ -178,6 +178,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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -243,6 +243,12 @@ public class Canvas {
|
||||
/** @hide */
|
||||
public void setHighContrastText(boolean highContrastText) {}
|
||||
|
||||
/** @hide */
|
||||
public void insertReorderBarrier() {}
|
||||
|
||||
/** @hide */
|
||||
public void insertInorderBarrier() {}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
// for 3d root, draw children with negative z values
|
||||
int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes, renderer, handler);
|
||||
|
||||
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 (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) {
|
||||
const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex];
|
||||
|
||||
Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
|
||||
buildZSortedChildList(chunk, zTranslatedNodes);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user