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

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

Merge "Clean up tessellation cache in prep for other tesselation types"

parents b593539f 6ac174b9
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