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

Commit 6ac174b9 authored by Chris Craik's avatar Chris Craik
Browse files

Clean up tessellation cache in prep for other tesselation types

bug:15536396

Also fixes compilation warning, avoids SkPaint deep copy

Change-Id: I74334f08b1d34c6789aabf968ff62db5bacbed1b
parent 6b2df21e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1118,8 +1118,8 @@ public:
            const DeferredDisplayState& state) {
        DrawStrokableOp::onDefer(renderer, deferInfo, state);
        if (!mPaint->getPathEffect()) {
            renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix,
                    mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy, mPaint);
            renderer.getCaches().tessellationCache.precacheRoundRect(state.mMatrix, *mPaint,
                    mLocalBounds.getWidth(), mLocalBounds.getHeight(), mRx, mRy);
        }
    }

+4 −0
Original line number Diff line number Diff line
@@ -308,6 +308,10 @@ status_t DisplayListRenderer::drawOval(float left, float top, float right, float

status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
        float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) {
    if (fabs(sweepAngle) > 360.0f) {
        return drawOval(left, top, right, bottom, paint);
    }

    paint = refPaint(paint);
    addDrawOp(new (alloc()) DrawArcOp(left, top, right, bottom,
                    startAngle, sweepAngle, useCenter, paint));
+2 −6
Original line number Diff line number Diff line
@@ -2556,8 +2556,8 @@ status_t OpenGLRenderer::drawRoundRect(float left, float top, float right, float
        return drawShape(left, top, texture, p);
    }

    const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(*currentTransform(),
            right - left, bottom - top, rx, ry, p);
    const VertexBuffer* vertexBuffer = mCaches.tessellationCache.getRoundRect(
            *currentTransform(), *p, right - left, bottom - top, rx, ry);
    return drawVertexBuffer(left, top, *vertexBuffer, p);
}

@@ -2611,10 +2611,6 @@ status_t OpenGLRenderer::drawArc(float left, float top, float right, float botto
        return DrawGlInfo::kStatusDone;
    }

    if (fabs(sweepAngle) >= 360.0f) {
        return drawOval(left, top, right, bottom, p);
    }

    // TODO: support fills (accounting for concavity if useCenter && sweepAngle > 180)
    if (p->getStyle() != SkPaint::kStroke_Style || p->getPathEffect() != 0 || useCenter) {
        mCaches.activeTexture(0);
+54 −58
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ namespace uirenderer {

TessellationCache::Description::Description()
        : type(kNone)
        , scaleX(1.0f)
        , scaleY(1.0f)
        , aa(false)
        , cap(SkPaint::kDefault_Cap)
        , style(SkPaint::kFill_Style)
@@ -46,21 +48,13 @@ TessellationCache::Description::Description()
    memset(&shape, 0, sizeof(Shape));
}

TessellationCache::Description::Description(Type type)
TessellationCache::Description::Description(Type type, const Matrix4& transform, const SkPaint& paint)
        : type(type)
        , aa(false)
        , cap(SkPaint::kDefault_Cap)
        , style(SkPaint::kFill_Style)
        , strokeWidth(1.0f) {
    memset(&shape, 0, sizeof(Shape));
}

TessellationCache::Description::Description(Type type, const SkPaint* paint)
        : type(type)
        , aa(paint->isAntiAlias())
        , cap(paint->getStrokeCap())
        , style(paint->getStyle())
        , strokeWidth(paint->getStrokeWidth()) {
        , aa(paint.isAntiAlias())
        , cap(paint.getStrokeCap())
        , style(paint.getStyle())
        , strokeWidth(paint.getStrokeWidth()) {
    PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY);
    memset(&shape, 0, sizeof(Shape));
}

@@ -70,10 +64,20 @@ hash_t TessellationCache::Description::hash() const {
    hash = JenkinsHashMix(hash, cap);
    hash = JenkinsHashMix(hash, style);
    hash = JenkinsHashMix(hash, android::hash_type(strokeWidth));
    hash = JenkinsHashMix(hash, android::hash_type(scaleX));
    hash = JenkinsHashMix(hash, android::hash_type(scaleY));
    hash = JenkinsHashMixBytes(hash, (uint8_t*) &shape, sizeof(Shape));
    return JenkinsHashWhiten(hash);
}

void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const {
    matrix->loadScale(scaleX, scaleY, 1.0f);
    paint->setAntiAlias(aa);
    paint->setStrokeCap(cap);
    paint->setStyle(style);
    paint->setStrokeWidth(strokeWidth);
}

TessellationCache::ShadowDescription::ShadowDescription()
        : nodeKey(NULL) {
    memset(&matrixData, 0, 16 * sizeof(float));
@@ -96,20 +100,15 @@ hash_t TessellationCache::ShadowDescription::hash() const {

class TessellationCache::TessellationTask : public Task<VertexBuffer*> {
public:
    TessellationTask(Tessellator tessellator, const Description& description,
                const SkPaint* paint)
    TessellationTask(Tessellator tessellator, const Description& description)
        : tessellator(tessellator)
        , description(description)
        , paint(*paint) {
        , description(description) {
    }

    ~TessellationTask() {}

    Tessellator tessellator;
    Description description;

    //copied, since input paint may not be immutable
    const SkPaint paint;
};

class TessellationCache::TessellationProcessor : public TaskProcessor<VertexBuffer*> {
@@ -121,7 +120,7 @@ public:
    virtual void onProcess(const sp<Task<VertexBuffer*> >& task) {
        TessellationTask* t = static_cast<TessellationTask*>(task.get());
        ATRACE_NAME("shape tessellation");
        VertexBuffer* buffer = t->tessellator(t->description, t->paint);
        VertexBuffer* buffer = t->tessellator(t->description);
        t->setResult(buffer);
    }
};
@@ -416,21 +415,12 @@ void TessellationCache::getShadowBuffers(const Matrix4* drawTransform, const Rec
// Tessellation precaching
///////////////////////////////////////////////////////////////////////////////

static VertexBuffer* tessellatePath(const SkPath& path, const SkPaint* paint,
        float scaleX, float scaleY) {
    VertexBuffer* buffer = new VertexBuffer();
    Matrix4 matrix;
    matrix.loadScale(scaleX, scaleY, 1);
    PathTessellator::tessellatePath(path, paint, matrix, *buffer);
    return buffer;
}

TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(
        const Description& entry, Tessellator tessellator, const SkPaint* paint) {
        const Description& entry, Tessellator tessellator) {
    Buffer* buffer = mCache.get(entry);
    if (!buffer) {
        // not cached, enqueue a task to fill the buffer
        sp<TessellationTask> task = new TessellationTask(tessellator, entry, paint);
        sp<TessellationTask> task = new TessellationTask(tessellator, entry);
        buffer = new Buffer(task);

        if (mProcessor == NULL) {
@@ -442,43 +432,49 @@ TessellationCache::Buffer* TessellationCache::getOrCreateBuffer(
    return buffer;
}

static VertexBuffer* tessellatePath(const TessellationCache::Description& description,
        const SkPath& path) {
    Matrix4 matrix;
    SkPaint paint;
    description.setupMatrixAndPaint(&matrix, &paint);
    VertexBuffer* buffer = new VertexBuffer();
    PathTessellator::tessellatePath(path, &paint, matrix, *buffer);
    return buffer;
}

///////////////////////////////////////////////////////////////////////////////
// Rounded rects
// RoundRect
///////////////////////////////////////////////////////////////////////////////

static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description,
        const SkPaint& paint) {
    SkRect rect = SkRect::MakeWH(description.shape.roundRect.mWidth,
            description.shape.roundRect.mHeight);
    float rx = description.shape.roundRect.mRx;
    float ry = description.shape.roundRect.mRy;
    if (paint.getStyle() == SkPaint::kStrokeAndFill_Style) {
        float outset = paint.getStrokeWidth() / 2;
static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& description) {
    SkRect rect = SkRect::MakeWH(description.shape.roundRect.width,
            description.shape.roundRect.height);
    float rx = description.shape.roundRect.rx;
    float ry = description.shape.roundRect.ry;
    if (description.style == SkPaint::kStrokeAndFill_Style) {
        float outset = description.strokeWidth / 2;
        rect.outset(outset, outset);
        rx += outset;
        ry += outset;
    }
    SkPath path;
    path.addRoundRect(rect, rx, ry);
    return tessellatePath(path, &paint,
            description.shape.roundRect.mScaleX, description.shape.roundRect.mScaleY);
}

TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(const Matrix4& transform,
        float width, float height, float rx, float ry, const SkPaint* paint) {
    Description entry(Description::kRoundRect, paint);
    entry.shape.roundRect.mWidth = width;
    entry.shape.roundRect.mHeight = height;
    entry.shape.roundRect.mRx = rx;
    entry.shape.roundRect.mRy = ry;
    PathTessellator::extractTessellationScales(transform,
            &entry.shape.roundRect.mScaleX, &entry.shape.roundRect.mScaleY);

    return getOrCreateBuffer(entry, &tessellateRoundRect, paint);
}
const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform,
        float width, float height, float rx, float ry, const SkPaint* paint) {
    return getRoundRectBuffer(transform, width, height, rx, ry, paint)->getVertexBuffer();
    return tessellatePath(description, path);
}

TessellationCache::Buffer* TessellationCache::getRoundRectBuffer(
        const Matrix4& transform, const SkPaint& paint,
        float width, float height, float rx, float ry) {
    Description entry(Description::kRoundRect, transform, paint);
    entry.shape.roundRect.width = width;
    entry.shape.roundRect.height = height;
    entry.shape.roundRect.rx = rx;
    entry.shape.roundRect.ry = ry;
    return getOrCreateBuffer(entry, &tessellateRoundRect);
}
const VertexBuffer* TessellationCache::getRoundRect(const Matrix4& transform, const SkPaint& paint,
        float width, float height, float rx, float ry) {
    return getRoundRectBuffer(transform, paint, width, height, rx, ry)->getVertexBuffer();
}

}; // namespace uirenderer
+19 −21
Original line number Diff line number Diff line
@@ -50,30 +50,28 @@ public:
        enum Type {
            kNone,
            kRoundRect,
            kAmbientShadow,
            kSpotShadow
        };

        Type type;
        float scaleX;
        float scaleY;
        bool aa;
        SkPaint::Cap cap;
        SkPaint::Style style;
        float strokeWidth;
        union Shape {
            struct RoundRect {
                float mScaleX;
                float mScaleY;
                float mWidth;
                float mHeight;
                float mRx;
                float mRy;
                float width;
                float height;
                float rx;
                float ry;
            } roundRect;
        } shape;

        Description();
        Description(Type type);
        Description(Type type, const SkPaint* paint);
        Description(Type type, const Matrix4& transform, const SkPaint& paint);
        hash_t hash() const;
        void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const;
    };

    struct ShadowDescription {
@@ -123,12 +121,12 @@ public:

    // TODO: precache/get for Oval, Lines, Points, etc.

    void precacheRoundRect(const Matrix4& transform,
            float width, float height, float rx, float ry, const SkPaint* paint) {
        getRoundRectBuffer(transform, width, height, rx, ry, paint);
    void precacheRoundRect(const Matrix4& transform, const SkPaint& paint,
            float width, float height, float rx, float ry) {
        getRoundRectBuffer(transform, paint, width, height, rx, ry);
    }
    const VertexBuffer* getRoundRect(const Matrix4& transform,
            float width, float height, float rx, float ry, const SkPaint* paint);
    const VertexBuffer* getRoundRect(const Matrix4& transform, const SkPaint& paint,
            float width, float height, float rx, float ry);

    void precacheShadows(const Matrix4* drawTransform, const Rect& localClip,
            bool opaque, const SkPath* casterPerimeter,
@@ -146,14 +144,14 @@ private:
    class TessellationTask;
    class TessellationProcessor;

    typedef VertexBuffer* (*Tessellator)(const Description&);

    typedef VertexBuffer* (*Tessellator)(const Description&, const SkPaint&);
    Buffer* getRectBuffer(const Matrix4& transform, const SkPaint& paint,
            float width, float height);
    Buffer* getRoundRectBuffer(const Matrix4& transform, const SkPaint& paint,
            float width, float height, float rx, float ry);

    Buffer* getRoundRectBuffer(const Matrix4& transform,
            float width, float height, float rx, float ry, const SkPaint* paint);

    Buffer* getOrCreateBuffer(const Description& entry,
            Tessellator tessellator, const SkPaint* paint);
    Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator);

    uint32_t mSize;
    uint32_t mMaxSize;
Loading