Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f40b8a93 authored by Chris Craik's avatar Chris Craik Committed by Android (Google) Code Review
Browse files

Merge "Fully deferred displaylist replay" into jb-mr2-dev

parents 30527267 ff78583d
Loading
Loading
Loading
Loading
+2 −7
Original line number Diff line number Diff line
@@ -103,14 +103,9 @@ void Caches::initFont() {
void Caches::initExtensions() {
    if (mExtensions.hasDebugMarker()) {
        eventMark = glInsertEventMarkerEXT;
        if ((drawDeferDisabled || drawReorderDisabled)) {

        startMark = glPushGroupMarkerEXT;
        endMark = glPopGroupMarkerEXT;
        } else {
            startMark = startMarkNull;
            endMark = endMarkNull;
        }

    } else {
        eventMark = eventMarkNull;
        startMark = startMarkNull;
+243 −37
Original line number Diff line number Diff line
@@ -32,15 +32,15 @@
namespace android {
namespace uirenderer {

/////////////////////////////////////////////////////////////////////////////////
// Operation Batches
/////////////////////////////////////////////////////////////////////////////////

class DrawOpBatch {
public:
    DrawOpBatch() {
        mOps.clear();
    }
    DrawOpBatch() { mOps.clear(); }

    ~DrawOpBatch() {
        mOps.clear();
    }
    virtual ~DrawOpBatch() { mOps.clear(); }

    void add(DrawOp* op) {
        // NOTE: ignore empty bounds special case, since we don't merge across those ops
@@ -48,8 +48,9 @@ public:
        mOps.add(op);
    }

    bool intersects(Rect& rect) {
    virtual bool intersects(Rect& rect) {
        if (!rect.intersects(mBounds)) return false;

        for (unsigned int i = 0; i < mOps.size(); i++) {
            if (rect.intersects(mOps[i]->state.mBounds)) {
#if DEBUG_DEFER
@@ -64,27 +65,217 @@ public:
        return false;
    }

    Vector<DrawOp*> mOps;
    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
        DEFER_LOGD("replaying draw batch %p", this);

        status_t status = DrawGlInfo::kStatusDone;
        DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
        for (unsigned int i = 0; i < mOps.size(); i++) {
            DrawOp* op = mOps[i];

            renderer.restoreDisplayState(op->state, kStateDeferFlag_Draw);

#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
            renderer.eventMark(strlen(op->name()), op->name());
#endif
            status |= op->applyDraw(renderer, dirty, 0, op->state.mMultipliedAlpha);
            logBuffer.writeCommand(0, op->name());
        }
        return status;
    }

    inline int count() const { return mOps.size(); }
private:
    Vector<DrawOp*> mOps;
    Rect mBounds;
};

void DeferredDisplayList::clear() {
class StateOpBatch : public DrawOpBatch {
public:
    // creates a single operation batch
    StateOpBatch(StateOp* op) : mOp(op) {}

    bool intersects(Rect& rect) {
        // if something checks for intersection, it's trying to go backwards across a state op,
        // something not currently supported - state ops are always barriers
        CRASH();
        return false;
    }

    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
        DEFER_LOGD("replaying state op batch %p", this);
        renderer.restoreDisplayState(mOp->state, 0);

        // use invalid save count because it won't be used at flush time - RestoreToCountOp is the
        // only one to use it, and we don't use that class at flush time, instead calling
        // renderer.restoreToCount directly
        int saveCount = -1;
        mOp->applyState(renderer, saveCount);
        return DrawGlInfo::kStatusDone;
    }

private:
    StateOp* mOp;
};

class RestoreToCountBatch : public DrawOpBatch {
public:
    RestoreToCountBatch(int restoreCount) : mRestoreCount(restoreCount) {}

    bool intersects(Rect& rect) {
        // if something checks for intersection, it's trying to go backwards across a state op,
        // something not currently supported - state ops are always barriers
        CRASH();
        return false;
    }

    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty) {
        DEFER_LOGD("batch %p restoring to count %d", this, mRestoreCount);
        renderer.restoreToCount(mRestoreCount);

        return DrawGlInfo::kStatusDone;
    }

private:
    /*
     * The count used here represents the flush() time saveCount. This is as opposed to the
     * DisplayList record time, or defer() time values (which are RestoreToCountOp's mCount, and
     * (saveCount + mCount) respectively). Since the count is different from the original
     * RestoreToCountOp, we don't store a pointer to the op, as elsewhere.
     */
    const int mRestoreCount;
};

/////////////////////////////////////////////////////////////////////////////////
// DeferredDisplayList
/////////////////////////////////////////////////////////////////////////////////

void DeferredDisplayList::resetBatchingState() {
    for (int i = 0; i < kOpBatch_Count; i++) {
        mBatchIndices[i] = -1;
    }
}

void DeferredDisplayList::clear() {
    resetBatchingState();
    mComplexClipStackStart = -1;

    for (unsigned int i = 0; i < mBatches.size(); i++) {
        delete mBatches[i];
    }
    mBatches.clear();
    mSaveStack.clear();
}

void DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
    if (CC_UNLIKELY(disallowReorder)) {
        if (!mBatches.isEmpty()) {
            mBatches[0]->add(op);
/////////////////////////////////////////////////////////////////////////////////
// Operation adding
/////////////////////////////////////////////////////////////////////////////////

int DeferredDisplayList::getStateOpDeferFlags() const {
    // For both clipOp and save(Layer)Op, we don't want to save drawing info, and only want to save
    // the clip if we aren't recording a complex clip (and can thus trust it to be a rect)
    return recordingComplexClip() ? 0 : kStateDeferFlag_Clip;
}

int DeferredDisplayList::getDrawOpDeferFlags() const {
    return kStateDeferFlag_Draw | getStateOpDeferFlags();
}

/**
 * When an clipping operation occurs that could cause a complex clip, record the operation and all
 * subsequent clipOps, save/restores (if the clip flag is set). During a flush, instead of loading
 * the clip from deferred state, we play back all of the relevant state operations that generated
 * the complex clip.
 *
 * Note that we don't need to record the associated restore operation, since operations at defer
 * time record whether they should store the renderer's current clip
 */
void DeferredDisplayList::addClip(OpenGLRenderer& renderer, ClipOp* op) {
    if (recordingComplexClip() || op->canCauseComplexClip() || !renderer.hasRectToRectTransform()) {
        DEFER_LOGD("%p Received complex clip operation %p", this, op);

        // NOTE: defer clip op before setting mComplexClipStackStart so previous clip is recorded
        storeStateOpBarrier(renderer, op);

        if (!recordingComplexClip()) {
            mComplexClipStackStart = renderer.getSaveCount() - 1;
            DEFER_LOGD("    Starting complex clip region, start is %d", mComplexClipStackStart);
        }
    }
}

/**
 * For now, we record save layer operations as barriers in the batch list, preventing drawing
 * operations from reordering around the saveLayer and it's associated restore()
 *
 * In the future, we should send saveLayer commands (if they can be played out of order) and their
 * contained drawing operations to a seperate list of batches, so that they may draw at the
 * beginning of the frame. This would avoid targetting and removing an FBO in the middle of a frame.
 *
 * saveLayer operations should be pulled to the beginning of the frame if the canvas doesn't have a
 * complex clip, and if the flags (kClip_SaveFlag & kClipToLayer_SaveFlag) are set.
 */
void DeferredDisplayList::addSaveLayer(OpenGLRenderer& renderer,
        SaveLayerOp* op, int newSaveCount) {
    DEFER_LOGD("%p adding saveLayerOp %p, flags %x, new count %d",
            this, op, op->getFlags(), newSaveCount);

    storeStateOpBarrier(renderer, op);
    mSaveStack.push(newSaveCount);
}

/**
 * Takes save op and it's return value - the new save count - and stores it into the stream as a
 * barrier if it's needed to properly modify a complex clip
 */
void DeferredDisplayList::addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount) {
    int saveFlags = op->getFlags();
    DEFER_LOGD("%p adding saveOp %p, flags %x, new count %d", this, op, saveFlags, newSaveCount);

    if (recordingComplexClip() && (saveFlags & SkCanvas::kClip_SaveFlag)) {
        // store and replay the save operation, as it may be needed to correctly playback the clip
        DEFER_LOGD("    adding save barrier with new save count %d", newSaveCount);
        storeStateOpBarrier(renderer, op);
        mSaveStack.push(newSaveCount);
    }
}

/**
 * saveLayer() commands must be associated with a restoreToCount batch that will clean up and draw
 * the layer in the deferred list
 *
 * other save() commands which occur as children of a snapshot with complex clip will be deferred,
 * and must be restored
 *
 * Either will act as a barrier to draw operation reordering, as we want to play back layer
 * save/restore and complex canvas modifications (including save/restore) in order.
 */
void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount) {
    DEFER_LOGD("%p addRestoreToCount %d", this, newSaveCount);

    if (recordingComplexClip() && newSaveCount <= mComplexClipStackStart) {
        mComplexClipStackStart = -1;
        resetBatchingState();
    }

    if (mSaveStack.isEmpty() || newSaveCount > mSaveStack.top()) {
        return;
    }

    while (!mSaveStack.isEmpty() && mSaveStack.top() >= newSaveCount) mSaveStack.pop();

    storeRestoreToCountBarrier(mSaveStack.size() + 1);
}

void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
    if (renderer.storeDisplayState(op->state, getDrawOpDeferFlags())) {
        return; // quick rejected
    }

    op->onDrawOpDeferred(renderer);

    if (CC_UNLIKELY(renderer.getCaches().drawReorderDisabled)) {
        // TODO: elegant way to reuse batches?
        DrawOpBatch* b = new DrawOpBatch();
        b->add(op);
        mBatches.add(b);
@@ -138,9 +329,41 @@ void DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
    targetBatch->add(op);
}

status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
        uint32_t level) {
    ATRACE_CALL();
void DeferredDisplayList::storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op) {
    DEFER_LOGD("%p adding state op barrier at pos %d", this, mBatches.size());

    renderer.storeDisplayState(op->state, getStateOpDeferFlags());
    mBatches.add(new StateOpBatch(op));
    resetBatchingState();
}

void DeferredDisplayList::storeRestoreToCountBarrier(int newSaveCount) {
    DEFER_LOGD("%p adding restore to count %d barrier, pos %d",
            this, newSaveCount, mBatches.size());

    mBatches.add(new RestoreToCountBatch(newSaveCount));
    resetBatchingState();
}

/////////////////////////////////////////////////////////////////////////////////
// Replay / flush
/////////////////////////////////////////////////////////////////////////////////

static status_t replayBatchList(Vector<DrawOpBatch*>& batchList,
        OpenGLRenderer& renderer, Rect& dirty) {
    status_t status = DrawGlInfo::kStatusDone;

    int opCount = 0;
    for (unsigned int i = 0; i < batchList.size(); i++) {
        status |= batchList[i]->replay(renderer, dirty);
        opCount += batchList[i]->count();
    }
    DEFER_LOGD("--flushed, drew %d batches (total %d ops)", batchList.size(), opCount);
    return status;
}

status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) {
    ATRACE_NAME("flush drawing commands");
    status_t status = DrawGlInfo::kStatusDone;

    if (isEmpty()) return status; // nothing to flush
@@ -148,29 +371,12 @@ status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32
    DEFER_LOGD("--flushing");
    renderer.eventMark("Flush");

    DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
    int opCount = 0;
    for (unsigned int i = 0; i < mBatches.size(); i++) {
        DrawOpBatch* batch = mBatches[i];
        for (unsigned int j = 0; j < batch->mOps.size(); j++) {
            DrawOp* op = batch->mOps[j];
    renderer.restoreToCount(1);

            renderer.restoreDisplayState(op->state);

#if DEBUG_DEFER
            op->output(2);
#endif
            status |= op->applyDraw(renderer, dirty, level,
                    op->state.mMultipliedAlpha >= 0, op->state.mMultipliedAlpha);
            opCount++;
        }
    }
    status |= replayBatchList(mBatches, renderer, dirty);

    DEFER_LOGD("--flushed, drew %d batches (total %d ops)", mBatches.size(), opCount);
    DEFER_LOGD("--flush complete, returning %x", status);

    renderer.restoreToCount(restoreTo);
    renderer.setDrawModifiers(restoreDrawModifiers);
    clear();
    return status;
}
+31 −4
Original line number Diff line number Diff line
@@ -26,10 +26,13 @@
namespace android {
namespace uirenderer {

class ClipOp;
class DrawOp;
class SaveOp;
class SaveLayerOp;
class StateOp;
class DrawOpBatch;
class OpenGLRenderer;
class SkiaShader;

class DeferredDisplayList {
public:
@@ -55,18 +58,42 @@ public:
     * Plays back all of the draw ops recorded into batches to the renderer.
     * Adjusts the state of the renderer as necessary, and restores it when complete
     */
    status_t flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
            uint32_t level);
    status_t flush(OpenGLRenderer& renderer, Rect& dirty);

    void addClip(OpenGLRenderer& renderer, ClipOp* op);
    void addSaveLayer(OpenGLRenderer& renderer, SaveLayerOp* op, int newSaveCount);
    void addSave(OpenGLRenderer& renderer, SaveOp* op, int newSaveCount);
    void addRestoreToCount(OpenGLRenderer& renderer, int newSaveCount);

    /**
     * Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
     * disallowReorder is false, respecting draw order when overlaps occur
     */
    void add(DrawOp* op, bool disallowReorder);
    void addDrawOp(OpenGLRenderer& renderer, DrawOp* op);

private:
    /*
     * Resets the batching back-pointers, creating a barrier in the operation stream so that no ops
     * added in the future will be inserted into a batch that already exist.
     */
    void resetBatchingState();

    void clear();

    void storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* op);
    void storeRestoreToCountBarrier(int newSaveCount);

    bool recordingComplexClip() const { return mComplexClipStackStart >= 0; }

    int getStateOpDeferFlags() const;
    int getDrawOpDeferFlags() const;

    /*
     *
     * at defer time, stores the savecount of save/saveLayer ops that were 
     */
    Vector<int> mSaveStack;
    int mComplexClipStackStart;

    Vector<DrawOpBatch*> mBatches;
    int mBatchIndices[kOpBatch_Count];
+103 −48
Original line number Diff line number Diff line
@@ -61,6 +61,12 @@ void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {

void DisplayList::clearResources() {
    mDisplayListData = NULL;

    mClipRectOp = NULL;
    mSaveLayerOp = NULL;
    mSaveOp = NULL;
    mRestoreToCountOp = NULL;

    delete mTransformMatrix;
    delete mTransformCamera;
    delete mTransformMatrix3D;
@@ -156,6 +162,13 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
        return;
    }

    // allocate reusable ops for state-deferral
    LinearAllocator& alloc = mDisplayListData->allocator;
    mClipRectOp = new (alloc) ClipRectOp();
    mSaveLayerOp = new (alloc) SaveLayerOp();
    mSaveOp = new (alloc) SaveOp();
    mRestoreToCountOp = new (alloc) RestoreToCountOp();

    mFunctorCount = recorder.getFunctorCount();

    Caches& caches = Caches::getInstance();
@@ -318,7 +331,7 @@ void DisplayList::updateMatrix() {
    }
}

void DisplayList::outputViewProperties(uint32_t level) {
void DisplayList::outputViewProperties(const int level) {
    updateMatrix();
    if (mLeft != 0 || mTop != 0) {
        ALOGD("%*sTranslate (left, top) %d, %d", level * 2, "", mLeft, mTop);
@@ -358,10 +371,17 @@ void DisplayList::outputViewProperties(uint32_t level) {
    }
}

status_t DisplayList::setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
        int32_t flags, uint32_t level, DeferredDisplayList* deferredList) {
    status_t status = DrawGlInfo::kStatusDone;
#if DEBUG_DISPLAYLIST
/*
 * For property operations, we pass a savecount of 0, since the operations aren't part of the
 * displaylist, and thus don't have to compensate for the record-time/playback-time discrepancy in
 * base saveCount (i.e., how RestoreToCount uses saveCount + mCount)
 */
#define PROPERTY_SAVECOUNT 0

template <class T>
void DisplayList::setViewProperties(OpenGLRenderer& renderer, T& handler,
        const int level) {
#if DEBUG_DISPLAY_LIST
    outputViewProperties(level);
#endif
    updateMatrix();
@@ -381,86 +401,121 @@ status_t DisplayList::setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
        }
    }
    if (mAlpha < 1 && !mCaching) {
        if (deferredList) {
            // flush since we'll either enter a Layer, or set alpha, both not supported in deferral
            status |= deferredList->flush(renderer, dirty, flags, level);
        }

        if (!mHasOverlappingRendering) {
            renderer.setAlpha(mAlpha);
        } else {
            // TODO: should be able to store the size of a DL at record time and not
            // have to pass it into this call. In fact, this information might be in the
            // location/size info that we store with the new native transform data.
            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
            int saveFlags = SkCanvas::kHasAlphaLayer_SaveFlag;
            if (mClipChildren) {
                flags |= SkCanvas::kClipToLayer_SaveFlag;
                saveFlags |= SkCanvas::kClipToLayer_SaveFlag;
            }
            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
                    mMultipliedAlpha, flags);
            handler(mSaveLayerOp->reinit(0, 0, mRight - mLeft, mBottom - mTop,
                    mMultipliedAlpha, SkXfermode::kSrcOver_Mode, saveFlags), PROPERTY_SAVECOUNT);
        }
    }
    if (mClipChildren && !mCaching) {
        if (deferredList && CC_UNLIKELY(!renderer.hasRectToRectTransform())) {
            // flush, since clip will likely be a region
            status |= deferredList->flush(renderer, dirty, flags, level);
        handler(mClipRectOp->reinit(0, 0, mRight - mLeft, mBottom - mTop, SkRegion::kIntersect_Op),
                PROPERTY_SAVECOUNT);
    }
}

class DeferOperationHandler {
public:
    DeferOperationHandler(DeferStateStruct& deferStruct, int multipliedAlpha, int level)
        : mDeferStruct(deferStruct), mMultipliedAlpha(multipliedAlpha), mLevel(level) {}
    inline void operator()(DisplayListOp* operation, int saveCount) {
        operation->defer(mDeferStruct, saveCount, mLevel, mMultipliedAlpha);
    }
        renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
                SkRegion::kIntersect_Op);
private:
    DeferStateStruct& mDeferStruct;
    const int mMultipliedAlpha;
    const int mLevel;
};

void DisplayList::defer(DeferStateStruct& deferStruct, const int level) {
    DeferOperationHandler handler(deferStruct, mCaching ? mMultipliedAlpha : -1, level);
    iterate<DeferOperationHandler>(deferStruct.mRenderer, handler, level);
}

class ReplayOperationHandler {
public:
    ReplayOperationHandler(ReplayStateStruct& replayStruct, int multipliedAlpha, int level)
        : mReplayStruct(replayStruct), mMultipliedAlpha(multipliedAlpha), mLevel(level) {}
    inline void operator()(DisplayListOp* operation, int saveCount) {
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
        replayStruct.mRenderer.eventMark(operation->name());
#endif
        operation->replay(mReplayStruct, saveCount, mLevel, mMultipliedAlpha);
    }
    return status;
private:
    ReplayStateStruct& mReplayStruct;
    const int mMultipliedAlpha;
    const int mLevel;
};

void DisplayList::replay(ReplayStateStruct& replayStruct, const int level) {
    ReplayOperationHandler handler(replayStruct, mCaching ? mMultipliedAlpha : -1, level);

    replayStruct.mRenderer.startMark(mName.string());
    iterate<ReplayOperationHandler>(replayStruct.mRenderer, handler, level);
    replayStruct.mRenderer.endMark();

    DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
            replayStruct.mDrawGlStatus);
}

status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level,
        DeferredDisplayList* deferredList) {
    status_t drawGlStatus = DrawGlInfo::kStatusDone;
/**
 * This function serves both defer and replay modes, and will organize the displayList's component
 * operations for a single frame:
 *
 * Every 'simple' operation that affects just the matrix and alpha (or other factors of
 * DeferredDisplayState) may be issued directly to the renderer, but complex operations (with custom
 * defer logic) and operations in displayListOps are issued through the 'handler' which handles the
 * defer vs replay logic, per operation
 */
template <class T>
void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level) {
    if (mSize == 0 || mAlpha <= 0) {
        DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
        return;
    }

#if DEBUG_DISPLAY_LIST
    Rect* clipRect = renderer.getClipRect();
    DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
            (level+1)*2, "", this, mName.string(), clipRect->left, clipRect->top,
            level * 2, "", this, mName.string(), clipRect->left, clipRect->top,
            clipRect->right, clipRect->bottom);
#endif

    renderer.startMark(mName.string());
    int restoreTo = renderer.getSaveCount();
    handler(mSaveOp->reinit(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
            PROPERTY_SAVECOUNT);

    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
    DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
    DISPLAY_LIST_LOGD("%*sSave %d %d", (level + 1) * 2, "",
            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);

    drawGlStatus |= setViewProperties(renderer, dirty, flags, level, deferredList);
    setViewProperties<T>(renderer, handler, level + 1);

    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
        DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
        renderer.restoreToCount(restoreTo);
        renderer.endMark();
        return drawGlStatus;
        handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
        return;
    }

    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
    int saveCount = renderer.getSaveCount() - 1;
    for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
        DisplayListOp *op = mDisplayListData->displayListOps[i];
#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
        renderer.eventMark(strlen(op->name()), op->name());
#endif
        drawGlStatus |= op->replay(renderer, dirty, flags,
                saveCount, level, mCaching, mMultipliedAlpha, deferredList);

        handler(op, saveCount);
        logBuffer.writeCommand(level, op->name());
    }

    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
    DISPLAY_LIST_LOGD("%*sRestoreToCount %d", (level + 1) * 2, "", restoreTo);
    handler(mRestoreToCountOp->reinit(restoreTo), PROPERTY_SAVECOUNT);
    renderer.restoreToCount(restoreTo);
    renderer.endMark();

    DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
            drawGlStatus);

    if (!level && CC_LIKELY(deferredList)) {
        drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
    }

    return drawGlStatus;
}

}; // namespace uirenderer
+53 −6

File changed.

Preview size limit exceeded, changes collapsed.

Loading