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

Commit 5d116764 authored by Chris Craik's avatar Chris Craik
Browse files

Clean up clipping and deferral logic

bug:8037003

-Merges replay methods
-Bounds checking for DrawBitmapMesh, DrawRects and DrawDisplayList
-Use clip as bounds for otherwise unbounded draw operations

Clip-as-bounds is correct for drawColor and functor, but other draw
operations (pos text, text on path, and layers) still need true bounds
calculation

Change-Id: I5d5149d2c624f01e3fe46628bf156e835e69b9d5
parent ad82f20d
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -955,6 +955,8 @@ class GLES20Canvas extends HardwareCanvas {

    @Override
    public void drawLines(float[] pts, int offset, int count, Paint paint) {
        if (count < 4) return;

        if ((offset | count) < 0 || offset + count > pts.length) {
            throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
        }
@@ -1078,6 +1080,8 @@ class GLES20Canvas extends HardwareCanvas {

    @Override
    public void drawPoints(float[] pts, int offset, int count, Paint paint) {
        if (count < 2) return;

        int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER);
        try {
            nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
+2 −2
Original line number Diff line number Diff line
@@ -1199,7 +1199,7 @@ public class Canvas {
     * meshHeight+1 vertices down. The verts array is accessed in row-major
     * order, so that the first meshWidth+1 vertices are distributed across the
     * top of the bitmap from left to right. A more general version of this
     * methid is drawVertices().
     * method is drawVertices().
     *
     * @param bitmap The bitmap to draw using the mesh
     * @param meshWidth The number of columns in the mesh. Nothing is drawn if
@@ -1208,7 +1208,7 @@ public class Canvas {
     *                   this is 0
     * @param verts Array of x,y pairs, specifying where the mesh should be
     *              drawn. There must be at least
     *              (meshWidth+1) * (meshHeight+1) * 2 + meshOffset values
     *              (meshWidth+1) * (meshHeight+1) * 2 + vertOffset values
     *              in the array
     * @param vertOffset Number of verts elements to skip before drawing
     * @param colors May be null. Specifies a color at each vertex, which is
+2 −7
Original line number Diff line number Diff line
@@ -426,13 +426,8 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
        Caches::getInstance().eventMark(strlen(op->name()), op->name());
#endif

        if (deferredList) {
        drawGlStatus |= op->replay(renderer, dirty, flags,
                    saveCount, level, mCaching, mMultipliedAlpha, *deferredList);
        } else {
            drawGlStatus |= op->replay(renderer, dirty, flags,
                    saveCount, level, mCaching, mMultipliedAlpha);
        }
                saveCount, level, mCaching, mMultipliedAlpha, deferredList);
        logBuffer.writeCommand(level, op->name());
    }

+38 −50
Original line number Diff line number Diff line
@@ -74,14 +74,11 @@ public:
        kOpLogFlag_JSON = 0x2 // TODO: add?
    };

    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha) = 0;

    // same as replay above, but draw operations will defer into the deferredList if possible
    // NOTE: colorfilters, paintfilters, shaders, shadow, and complex clips prevent deferral
    // If a DeferredDisplayList is supplied, DrawOps will be stored until the list is flushed
    // NOTE: complex clips and layers prevent deferral
    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha,
            DeferredDisplayList& deferredList) = 0;
            DeferredDisplayList* deferredList) = 0;

    virtual void output(int level, uint32_t flags = 0) = 0;

@@ -96,22 +93,16 @@ public:

    virtual ~StateOp() {}

    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha) {
        applyState(renderer, saveCount);
        return DrawGlInfo::kStatusDone;
    }

    /**
     * State operations are applied directly to the renderer, but can cause the deferred drawing op
     * list to flush
     */
    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
        status_t status = DrawGlInfo::kStatusDone;
        if (requiresDrawOpFlush()) {
        if (deferredList && requiresDrawOpFlush()) {
            // will be setting renderer state that affects ops in deferredList, so flush list first
            status |= deferredList.flush(renderer, dirty, flags, level);
            status |= deferredList->flush(renderer, dirty, flags, level);
        }
        applyState(renderer, saveCount);
        return status;
@@ -131,23 +122,14 @@ public:
    DrawOp(SkPaint* paint)
            : mPaint(paint), mQuickRejected(false) {}

    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha) {
        if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
            return DrawGlInfo::kStatusDone;
        }

        return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
    }

    /** Draw operations are stored in the deferredList with information necessary for playback */
    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
        if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
            return DrawGlInfo::kStatusDone;
        }

        if (renderer.disallowDeferral()) {
        if (!deferredList || renderer.disallowDeferral()) {
            // dispatch draw immediately, since the renderer's state is too complex for deferral
            return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
        }
@@ -161,7 +143,7 @@ public:

        if (!renderer.storeDisplayState(state)) {
            // op wasn't quick-rejected, so defer
            deferredList.add(this, renderer.disallowReorder());
            deferredList->add(this, renderer.disallowReorder());
        }

        return DrawGlInfo::kStatusDone;
@@ -184,7 +166,6 @@ public:

    float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }

public:
    /**
     * Stores the relevant canvas state of the object between deferral and replay (if the canvas
     * state supports being stored) See OpenGLRenderer::simpleClipAndState()
@@ -204,7 +185,20 @@ public:
    DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
            : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}

    // default constructor for area, to be overridden in child constructor body
    // Calculates bounds as smallest rect encompassing all points
    // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
    // subclass' constructor)
    DrawBoundedOp(const float* points, int count, SkPaint* paint)
            : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
        for (int i = 2; i < count; i += 2) {
            mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
            mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
            mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
            mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
        }
    }

    // default empty constructor for bounds, to be overridden in child constructor body
    DrawBoundedOp(SkPaint* paint)
            : DrawOp(paint) {}

@@ -740,11 +734,12 @@ public:
    }
};

class DrawBitmapMeshOp : public DrawOp {
class DrawBitmapMeshOp : public DrawBoundedOp {
public:
    DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
            float* vertices, int* colors, SkPaint* paint)
            : DrawOp(paint), mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
            : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
            mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
            mVertices(vertices), mColors(colors) {}

    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
@@ -873,10 +868,11 @@ public:
    virtual const char* name() { return "DrawRect"; }
};

class DrawRectsOp : public DrawOp {
class DrawRectsOp : public DrawBoundedOp {
public:
    DrawRectsOp(const float* rects, int count, SkPaint* paint)
            : DrawOp(paint), mRects(rects), mCount(count) {}
            : DrawBoundedOp(rects, count, paint),
            mRects(rects), mCount(count) {}

    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
            bool caching, int multipliedAlpha) {
@@ -1022,13 +1018,8 @@ private:
class DrawLinesOp : public DrawBoundedOp {
public:
    DrawLinesOp(float* points, int count, SkPaint* paint)
            : DrawBoundedOp(paint), mPoints(points), mCount(count) {
        for (int i = 0; i < count; i += 2) {
            mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
            mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
            mLocalBounds.top = fminf(mLocalBounds.top, points[i+1]);
            mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i+1]);
        }
            : DrawBoundedOp(points, count, paint),
            mPoints(points), mCount(count) {
        mLocalBounds.outset(strokeWidthOutset());
    }

@@ -1199,26 +1190,23 @@ private:
    Functor* mFunctor;
};

class DrawDisplayListOp : public DrawOp {
class DrawDisplayListOp : public DrawBoundedOp {
public:
    DrawDisplayListOp(DisplayList* displayList, int flags)
            : DrawOp(0), mDisplayList(displayList), mFlags(flags) {}
            : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
            mDisplayList(displayList), mFlags(flags) {}

    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
        if (mDisplayList && mDisplayList->isRenderable()) {
            return mDisplayList->replay(renderer, dirty, mFlags, level + 1, &deferredList);
            return mDisplayList->replay(renderer, dirty, mFlags, level + 1, deferredList);
        }
        return DrawGlInfo::kStatusDone;
    }

    // NOT USED, since replay is overridden
    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
            bool caching, int multipliedAlpha) {
        if (mDisplayList && mDisplayList->isRenderable()) {
            return mDisplayList->replay(renderer, dirty, mFlags, level + 1);
        }
        return DrawGlInfo::kStatusDone;
    }
            bool caching, int multipliedAlpha) { return DrawGlInfo::kStatusDone; }

    virtual void output(int level, uint32_t flags) {
        OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
+2 −0
Original line number Diff line number Diff line
@@ -1235,6 +1235,8 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state) {
            // quick rejected
            return true;
        }
    } else {
        state.mBounds.set(currentClip);
    }

    state.mClip.set(currentClip);