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

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

Merge "Use path outlines to define shadow shapes"

parents cd53c257 15a07a21
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -1589,7 +1589,9 @@ public:
            mWidth(width), mHeight(height) {}
            mWidth(width), mHeight(height) {}


    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
        return renderer.drawShadow(mCasterTransform, mCasterAlpha, mWidth, mHeight);
        SkPath casterOutline; // TODO: drive with path from view
        casterOutline.addRect(0, 0, mWidth, mHeight);
        return renderer.drawShadow(mCasterTransform, mCasterAlpha, &casterOutline);
    }
    }


    virtual void output(int level, uint32_t logFlags) const {
    virtual void output(int level, uint32_t logFlags) const {
+23 −8
Original line number Original line Diff line number Diff line
@@ -3185,28 +3185,43 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, const SkPaint*
}
}


status_t OpenGLRenderer::drawShadow(const mat4& casterTransform, float casterAlpha,
status_t OpenGLRenderer::drawShadow(const mat4& casterTransform, float casterAlpha,
        float width, float height) {
        const SkPath* casterOutline) {
    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;
    if (currentSnapshot()->isIgnored()) return DrawGlInfo::kStatusDone;


    // For now, always and scissor
    // TODO: use quickRejectWithScissor. For now, always force enable scissor.
    // TODO: use quickReject
    mCaches.enableScissor();
    mCaches.enableScissor();


    SkPaint paint;
    SkPaint paint;
    paint.setColor(mCaches.propertyShadowStrength << 24);
    paint.setARGB(mCaches.propertyShadowStrength, 0, 0, 0);
    paint.setAntiAlias(true); // want to use AlphaVertex
    paint.setAntiAlias(true); // want to use AlphaVertex


    // tessellate caster outline into a 2d polygon
    Vector<Vertex> casterVertices2d;
    const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value
    PathTessellator::approximatePathOutlineVertices(*casterOutline,
            casterRefinementThresholdSquared, casterVertices2d);

    // map 2d caster poly into 3d
    const int casterVertexCount = casterVertices2d.size();
    Vector3 casterPolygon[casterVertexCount];
    for (int i = 0; i < casterVertexCount; i++) {
        const Vertex& point2d = casterVertices2d[i];
        casterPolygon[i] = Vector3(point2d.x, point2d.y, 0);
        casterTransform.mapPoint3d(casterPolygon[i]);
    }

    // draw caster's shadows
    VertexBuffer ambientShadowVertexBuffer;
    VertexBuffer ambientShadowVertexBuffer;
    ShadowTessellator::tessellateAmbientShadow(width, height, casterTransform,
    ShadowTessellator::tessellateAmbientShadow(casterPolygon, casterVertexCount,
            ambientShadowVertexBuffer);
            ambientShadowVertexBuffer);
    drawVertexBuffer(ambientShadowVertexBuffer, &paint);
    drawVertexBuffer(ambientShadowVertexBuffer, &paint);


    VertexBuffer spotShadowVertexBuffer;
    VertexBuffer spotShadowVertexBuffer;
    Vector3 lightPosScale(mCaches.propertyLightPosXScale,
    Vector3 lightPosScale(mCaches.propertyLightPosXScale,
            mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
            mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
    ShadowTessellator::tessellateSpotShadow(width, height, lightPosScale,
    ShadowTessellator::tessellateSpotShadow(casterPolygon, casterVertexCount,
            *currentTransform(), getWidth(), getHeight(),
            lightPosScale, *currentTransform(), getWidth(), getHeight(),
            casterTransform, spotShadowVertexBuffer);
            spotShadowVertexBuffer);


    drawVertexBuffer(spotShadowVertexBuffer, &paint);
    drawVertexBuffer(spotShadowVertexBuffer, &paint);


+1 −1
Original line number Original line Diff line number Diff line
@@ -214,7 +214,7 @@ public:
    virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);
    virtual status_t drawRects(const float* rects, int count, const SkPaint* paint);


    status_t drawShadow(const mat4& casterTransform, float casterAlpha,
    status_t drawShadow(const mat4& casterTransform, float casterAlpha,
            float width, float height);
            const SkPath* casterOutline);


    virtual void resetShader();
    virtual void resetShader();
    virtual void setupShader(SkiaShader* shader);
    virtual void setupShader(SkiaShader* shader);
+24 −14
Original line number Original line Diff line number Diff line
@@ -53,7 +53,7 @@
namespace android {
namespace android {
namespace uirenderer {
namespace uirenderer {


#define THRESHOLD 0.5f
#define OUTLINE_REFINE_THRESHOLD_SQUARED (0.5f * 0.5f)
#define ROUND_CAP_THRESH 0.25f
#define ROUND_CAP_THRESH 0.25f
#define PI 3.1415926535897932f
#define PI 3.1415926535897932f


@@ -739,7 +739,8 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
    // force close if we're filling the path, since fill path expects closed perimeter.
    // force close if we're filling the path, since fill path expects closed perimeter.
    bool forceClose = paintInfo.style != SkPaint::kStroke_Style;
    bool forceClose = paintInfo.style != SkPaint::kStroke_Style;
    bool wasClosed = approximatePathOutlineVertices(path, forceClose,
    bool wasClosed = approximatePathOutlineVertices(path, forceClose,
            threshInvScaleX * threshInvScaleX, threshInvScaleY * threshInvScaleY, tempVertices);
            threshInvScaleX * threshInvScaleX, threshInvScaleY * threshInvScaleY,
            OUTLINE_REFINE_THRESHOLD_SQUARED, tempVertices);


    if (!tempVertices.size()) {
    if (!tempVertices.size()) {
        // path was empty, return without allocating vertex buffer
        // path was empty, return without allocating vertex buffer
@@ -824,7 +825,8 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP
    Vector<Vertex> outlineVertices;
    Vector<Vertex> outlineVertices;
    approximatePathOutlineVertices(path, true,
    approximatePathOutlineVertices(path, true,
            paintInfo.inverseScaleX * paintInfo.inverseScaleX,
            paintInfo.inverseScaleX * paintInfo.inverseScaleX,
            paintInfo.inverseScaleY * paintInfo.inverseScaleY, outlineVertices);
            paintInfo.inverseScaleY * paintInfo.inverseScaleY,
            OUTLINE_REFINE_THRESHOLD_SQUARED, outlineVertices);


    if (!outlineVertices.size()) return;
    if (!outlineVertices.size()) return;


@@ -897,6 +899,11 @@ void PathTessellator::tessellateLines(const float* points, int count, const SkPa
// Simple path line approximation
// Simple path line approximation
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////


bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, float thresholdSquared,
        Vector<Vertex>& outputVertices) {
    return approximatePathOutlineVertices(path, true, 1.0f, 1.0f, thresholdSquared, outputVertices);
}

void pushToVector(Vector<Vertex>& vertices, float x, float y) {
void pushToVector(Vector<Vertex>& vertices, float x, float y) {
    // TODO: make this not yuck
    // TODO: make this not yuck
    vertices.push();
    vertices.push();
@@ -905,7 +912,8 @@ void pushToVector(Vector<Vertex>& vertices, float x, float y) {
}
}


bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool forceClose,
bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool forceClose,
        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
        float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
        Vector<Vertex>& outputVertices) {
    ATRACE_CALL();
    ATRACE_CALL();


    // TODO: to support joins other than sharp miter, join vertices should be labelled in the
    // TODO: to support joins other than sharp miter, join vertices should be labelled in the
@@ -932,7 +940,7 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
                        pts[0].x(), pts[0].y(),
                        pts[0].x(), pts[0].y(),
                        pts[2].x(), pts[2].y(),
                        pts[2].x(), pts[2].y(),
                        pts[1].x(), pts[1].y(),
                        pts[1].x(), pts[1].y(),
                        sqrInvScaleX, sqrInvScaleY, outputVertices);
                        sqrInvScaleX, sqrInvScaleY, thresholdSquared, outputVertices);
                break;
                break;
            case SkPath::kCubic_Verb:
            case SkPath::kCubic_Verb:
                ALOGV("kCubic_Verb");
                ALOGV("kCubic_Verb");
@@ -941,7 +949,7 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
                        pts[1].x(), pts[1].y(),
                        pts[1].x(), pts[1].y(),
                        pts[3].x(), pts[3].y(),
                        pts[3].x(), pts[3].y(),
                        pts[2].x(), pts[2].y(),
                        pts[2].x(), pts[2].y(),
                        sqrInvScaleX, sqrInvScaleY, outputVertices);
                        sqrInvScaleX, sqrInvScaleY, thresholdSquared, outputVertices);
                break;
                break;
            default:
            default:
                break;
                break;
@@ -964,7 +972,8 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo
void PathTessellator::recursiveCubicBezierVertices(
void PathTessellator::recursiveCubicBezierVertices(
        float p1x, float p1y, float c1x, float c1y,
        float p1x, float p1y, float c1x, float c1y,
        float p2x, float p2y, float c2x, float c2y,
        float p2x, float p2y, float c2x, float c2y,
        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
        float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
        Vector<Vertex>& outputVertices) {
    float dx = p2x - p1x;
    float dx = p2x - p1x;
    float dy = p2y - p1y;
    float dy = p2y - p1y;
    float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
    float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx);
@@ -973,7 +982,7 @@ void PathTessellator::recursiveCubicBezierVertices(


    // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors
    // multiplying by sqrInvScaleY/X equivalent to multiplying in dimensional scale factors


    if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
    if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
        // below thresh, draw line by adding endpoint
        // below thresh, draw line by adding endpoint
        pushToVector(outputVertices, p2x, p2y);
        pushToVector(outputVertices, p2x, p2y);
    } else {
    } else {
@@ -997,11 +1006,11 @@ void PathTessellator::recursiveCubicBezierVertices(
        recursiveCubicBezierVertices(
        recursiveCubicBezierVertices(
                p1x, p1y, p1c1x, p1c1y,
                p1x, p1y, p1c1x, p1c1y,
                mx, my, p1c1c2x, p1c1c2y,
                mx, my, p1c1c2x, p1c1c2y,
                sqrInvScaleX, sqrInvScaleY, outputVertices);
                sqrInvScaleX, sqrInvScaleY, thresholdSquared, outputVertices);
        recursiveCubicBezierVertices(
        recursiveCubicBezierVertices(
                mx, my, p2c1c2x, p2c1c2y,
                mx, my, p2c1c2x, p2c1c2y,
                p2x, p2y, p2c2x, p2c2y,
                p2x, p2y, p2c2x, p2c2y,
                sqrInvScaleX, sqrInvScaleY, outputVertices);
                sqrInvScaleX, sqrInvScaleY, thresholdSquared, outputVertices);
    }
    }
}
}


@@ -1009,12 +1018,13 @@ void PathTessellator::recursiveQuadraticBezierVertices(
        float ax, float ay,
        float ax, float ay,
        float bx, float by,
        float bx, float by,
        float cx, float cy,
        float cx, float cy,
        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex>& outputVertices) {
        float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
        Vector<Vertex>& outputVertices) {
    float dx = bx - ax;
    float dx = bx - ax;
    float dy = by - ay;
    float dy = by - ay;
    float d = (cx - bx) * dy - (cy - by) * dx;
    float d = (cx - bx) * dy - (cy - by) * dx;


    if (d * d < THRESHOLD * THRESHOLD * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
    if (d * d < thresholdSquared * (dx * dx * sqrInvScaleY + dy * dy * sqrInvScaleX)) {
        // below thresh, draw line by adding endpoint
        // below thresh, draw line by adding endpoint
        pushToVector(outputVertices, bx, by);
        pushToVector(outputVertices, bx, by);
    } else {
    } else {
@@ -1028,9 +1038,9 @@ void PathTessellator::recursiveQuadraticBezierVertices(
        float my = (acy + bcy) * 0.5f;
        float my = (acy + bcy) * 0.5f;


        recursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy,
        recursiveQuadraticBezierVertices(ax, ay, mx, my, acx, acy,
                sqrInvScaleX, sqrInvScaleY, outputVertices);
                sqrInvScaleX, sqrInvScaleY, thresholdSquared, outputVertices);
        recursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy,
        recursiveQuadraticBezierVertices(mx, my, bx, by, bcx, bcy,
                sqrInvScaleX, sqrInvScaleY, outputVertices);
                sqrInvScaleX, sqrInvScaleY, thresholdSquared, outputVertices);
    }
    }
}
}


+49 −3
Original line number Original line Diff line number Diff line
@@ -31,18 +31,64 @@ class PathTessellator {
public:
public:
    static void expandBoundsForStroke(SkRect& bounds, const SkPaint* paint);
    static void expandBoundsForStroke(SkRect& bounds, const SkPaint* paint);


    /**
     * Populates a VertexBuffer with a tessellated approximation of the input convex path, as a single
     * triangle strip. Note: joins are not currently supported.
     *
     * @param path The path to be approximated
     * @param paint The paint the path will be drawn with, indicating AA, painting style
     *        (stroke vs fill), stroke width, stroke cap & join style, etc.
     * @param transform The transform the path is to be drawn with, used to drive stretch-aware path
     *        vertex approximation, and correct AA ramp offsetting.
     * @param vertexBuffer The output buffer
     */
    static void tessellatePath(const SkPath& path, const SkPaint* paint,
    static void tessellatePath(const SkPath& path, const SkPaint* paint,
            const mat4& transform, VertexBuffer& vertexBuffer);
            const mat4& transform, VertexBuffer& vertexBuffer);


    /**
     * Populates a VertexBuffer with a tessellated approximation of points as a single triangle
     * strip (with degenerate tris separating), respecting the shape defined by the paint cap.
     *
     * @param points The center vertices of the points to be drawn
     * @param count The number of floats making up the point vertices
     * @param paint The paint the points will be drawn with indicating AA, stroke width & cap
     * @param transform The transform the points will be drawn with, used to drive stretch-aware path
     *        vertex approximation, and correct AA ramp offsetting
     * @param bounds An output rectangle, which returns the total area covered by the output buffer
     * @param vertexBuffer The output buffer
     */
    static void tessellatePoints(const float* points, int count, const SkPaint* paint,
    static void tessellatePoints(const float* points, int count, const SkPaint* paint,
            const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);
            const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);


    /**
     * Populates a VertexBuffer with a tessellated approximation of lines as a single triangle
     * strip (with degenerate tris separating).
     *
     * @param points Pairs of endpoints defining the lines to be drawn
     * @param count The number of floats making up the line vertices
     * @param paint The paint the lines will be drawn with indicating AA, stroke width & cap
     * @param transform The transform the points will be drawn with, used to drive stretch-aware path
     *        vertex approximation, and correct AA ramp offsetting
     * @param bounds An output rectangle, which returns the total area covered by the output buffer
     * @param vertexBuffer The output buffer
     */
    static void tessellateLines(const float* points, int count, const SkPaint* paint,
    static void tessellateLines(const float* points, int count, const SkPaint* paint,
            const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);
            const mat4& transform, SkRect& bounds, VertexBuffer& vertexBuffer);


    /**
     * Approximates a convex, CW outline into a Vector of 2d vertices.
     *
     * @param path The outline to be approximated
     * @param thresholdSquared The threshold of acceptable error (in pixels) when approximating
     * @param outputVertices An empty Vector which will be populated with the output
     */
    static bool approximatePathOutlineVertices(const SkPath &path, float thresholdSquared,
            Vector<Vertex> &outputVertices);

private:
private:
    static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
    static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose,
        float sqrInvScaleX, float sqrInvScaleY, Vector<Vertex> &outputVertices);
            float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
            Vector<Vertex> &outputVertices);


/*
/*
  endpoints a & b,
  endpoints a & b,
@@ -52,7 +98,7 @@ private:
            float ax, float ay,
            float ax, float ay,
            float bx, float by,
            float bx, float by,
            float cx, float cy,
            float cx, float cy,
            float sqrInvScaleX, float sqrInvScaleY,
            float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
            Vector<Vertex> &outputVertices);
            Vector<Vertex> &outputVertices);


/*
/*
@@ -64,7 +110,7 @@ private:
            float c1x, float c1y,
            float c1x, float c1y,
            float p2x, float p2y,
            float p2x, float p2y,
            float c2x, float c2y,
            float c2x, float c2y,
            float sqrInvScaleX, float sqrInvScaleY,
            float sqrInvScaleX, float sqrInvScaleY, float thresholdSquared,
            Vector<Vertex> &outputVertices);
            Vector<Vertex> &outputVertices);
};
};


Loading