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

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

Add tessellation path for points

bug:4351353
bug:8185479

Point tessellation is similar to line special case, except that we
only tessellate one point (as a circle or rect) and duplicate it
across other instances.

Additionally:

Fixes square caps for AA=false lines

Cleanup in CanvasCompare, disabling interpolation on zoomed-in
comparison view

Change-Id: I0756fcc4b20f77878fed0d8057297c80e82ed9dc
parent 0ace0aa7
Loading
Loading
Loading
Loading
+12 −65
Original line number Original line Diff line number Diff line
@@ -1703,11 +1703,6 @@ void OpenGLRenderer::setupDrawAA() {
    mDescription.isAA = true;
    mDescription.isAA = true;
}
}


void OpenGLRenderer::setupDrawPoint(float pointSize) {
    mDescription.isPoint = true;
    mDescription.pointSize = pointSize;
}

void OpenGLRenderer::setupDrawColor(int color, int alpha) {
void OpenGLRenderer::setupDrawColor(int color, int alpha) {
    mColorA = alpha / 255.0f;
    mColorA = alpha / 255.0f;
    mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f;
    mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f;
@@ -1822,11 +1817,6 @@ void OpenGLRenderer::setupDrawModelView(float left, float top, float right, floa
    }
    }
}
}


void OpenGLRenderer::setupDrawPointUniforms() {
    int slot = mCaches.currentProgram->getUniform("pointSize");
    glUniform1f(slot, mDescription.pointSize);
}

void OpenGLRenderer::setupDrawColorUniforms() {
void OpenGLRenderer::setupDrawColorUniforms() {
    if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
    if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
        mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
        mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
@@ -2409,7 +2399,7 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,


status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint,
status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint,
        bool useOffset) {
        bool useOffset) {
    if (!vertexBuffer.getSize()) {
    if (!vertexBuffer.getVertexCount()) {
        // no vertices to draw
        // no vertices to draw
        return DrawGlInfo::kStatusDone;
        return DrawGlInfo::kStatusDone;
    }
    }
@@ -2447,7 +2437,7 @@ status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPa
        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
        glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
    }
    }


    glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getSize());
    glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());


    if (isAA) {
    if (isAA) {
        glDisableVertexAttribArray(alphaSlot);
        glDisableVertexAttribArray(alphaSlot);
@@ -2510,65 +2500,22 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
}
}


status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
status_t OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
    if (mSnapshot->isIgnored()) return DrawGlInfo::kStatusDone;
    if (mSnapshot->isIgnored() || count < 2) return DrawGlInfo::kStatusDone;

    // TODO: The paint's cap style defines whether the points are square or circular
    // TODO: Handle AA for round points

    // A stroke width of 0 has a special meaning in Skia:
    // it draws an unscaled 1px point
    float strokeWidth = paint->getStrokeWidth();
    const bool isHairLine = paint->getStrokeWidth() == 0.0f;
    if (isHairLine) {
        // Now that we know it's hairline, we can set the effective width, to be used later
        strokeWidth = 1.0f;
    }
    const float halfWidth = strokeWidth / 2;

    int alpha;
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);


    int verticesCount = count >> 1;
    count &= ~0x1; // round down to nearest two
    int generatedVerticesCount = 0;


    TextureVertex pointsData[verticesCount];
    VertexBuffer buffer;
    TextureVertex* vertex = &pointsData[0];
    SkRect bounds;

    PathTessellator::tessellatePoints(points, count, paint, mSnapshot->transform, bounds, buffer);
    // TODO: We should optimize this method to not generate vertices for points
    // that lie outside of the clip.
    mCaches.enableScissor();

    setupDraw();
    setupDrawNoTexture();
    setupDrawPoint(strokeWidth);
    setupDrawColor(paint->getColor(), alpha);
    setupDrawColorFilter();
    setupDrawShader();
    setupDrawBlending(mode);
    setupDrawProgram();
    setupDrawModelViewIdentity(true);
    setupDrawColorUniforms();
    setupDrawColorFilterUniforms();
    setupDrawPointUniforms();
    setupDrawShaderIdentityUniforms();
    setupDrawMesh(vertex);

    for (int i = 0; i < count; i += 2) {
        TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
        generatedVerticesCount++;

        float left = points[i] - halfWidth;
        float right = points[i] + halfWidth;
        float top = points[i + 1] - halfWidth;
        float bottom = points [i + 1] + halfWidth;


        dirtyLayer(left, top, right, bottom, currentTransform());
    if (quickReject(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom)) {
        return DrawGlInfo::kStatusDone;
    }
    }


    glDrawArrays(GL_POINTS, 0, generatedVerticesCount);
    dirtyLayer(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, currentTransform());


    return DrawGlInfo::kStatusDrew;
    bool useOffset = !paint->isAntiAlias();
    return drawVertexBuffer(buffer, paint, useOffset);
}
}


status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
status_t OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
+0 −2
Original line number Original line Diff line number Diff line
@@ -927,7 +927,6 @@ private:
    void setupDrawWithExternalTexture();
    void setupDrawWithExternalTexture();
    void setupDrawNoTexture();
    void setupDrawNoTexture();
    void setupDrawAA();
    void setupDrawAA();
    void setupDrawPoint(float pointSize);
    void setupDrawColor(int color, int alpha);
    void setupDrawColor(int color, int alpha);
    void setupDrawColor(float r, float g, float b, float a);
    void setupDrawColor(float r, float g, float b, float a);
    void setupDrawAlpha8Color(int color, int alpha);
    void setupDrawAlpha8Color(int color, int alpha);
@@ -945,7 +944,6 @@ private:
            bool ignoreTransform = false, bool ignoreModelView = false);
            bool ignoreTransform = false, bool ignoreModelView = false);
    void setupDrawModelViewTranslate(float left, float top, float right, float bottom,
    void setupDrawModelViewTranslate(float left, float top, float right, float bottom,
            bool ignoreTransform = false);
            bool ignoreTransform = false);
    void setupDrawPointUniforms();
    void setupDrawColorUniforms();
    void setupDrawColorUniforms();
    void setupDrawPureColorUniforms();
    void setupDrawPureColorUniforms();
    void setupDrawShaderIdentityUniforms();
    void setupDrawShaderIdentityUniforms();
+101 −44
Original line number Original line Diff line number Diff line
@@ -66,11 +66,11 @@ void PathTessellator::expandBoundsForStroke(SkRect& bounds, const SkPaint* paint
    }
    }
}
}


inline void copyVertex(Vertex* destPtr, const Vertex* srcPtr) {
inline static void copyVertex(Vertex* destPtr, const Vertex* srcPtr) {
    Vertex::set(destPtr, srcPtr->position[0], srcPtr->position[1]);
    Vertex::set(destPtr, srcPtr->position[0], srcPtr->position[1]);
}
}


inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) {
inline static void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) {
    AlphaVertex::set(destPtr, srcPtr->position[0], srcPtr->position[1], srcPtr->alpha);
    AlphaVertex::set(destPtr, srcPtr->position[0], srcPtr->position[1], srcPtr->alpha);
}
}


@@ -84,7 +84,7 @@ inline void copyAlphaVertex(AlphaVertex* destPtr, const AlphaVertex* srcPtr) {
 *
 *
 * NOTE: assumes angles between normals 90 degrees or less
 * NOTE: assumes angles between normals 90 degrees or less
 */
 */
inline vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) {
inline static vec2 totalOffsetFromNormals(const vec2& normalA, const vec2& normalB) {
    return (normalA + normalB) / (1 + fabs(normalA.dot(normalB)));
    return (normalA + normalB) / (1 + fabs(normalA.dot(normalB)));
}
}


@@ -224,6 +224,20 @@ void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo, const Vector<Ver
    DEBUG_DUMP_BUFFER();
    DEBUG_DUMP_BUFFER();
}
}


static inline void storeBeginEnd(const PaintInfo& paintInfo, const Vertex& center,
        const vec2& normal, Vertex* buffer, int& currentIndex, bool begin) {
    vec2 strokeOffset = normal;
    paintInfo.scaleOffsetForStrokeWidth(strokeOffset);

    vec2 referencePoint(center.position[0], center.position[1]);
    if (paintInfo.cap == SkPaint::kSquare_Cap) {
        referencePoint += vec2(-strokeOffset.y, strokeOffset.x) * (begin ? -1 : 1);
    }

    Vertex::set(&buffer[currentIndex++], referencePoint + strokeOffset);
    Vertex::set(&buffer[currentIndex++], referencePoint - strokeOffset);
}

/**
/**
 * Fills a vertexBuffer with non-alpha vertices similar to getStrokeVerticesFromPerimeter, except:
 * Fills a vertexBuffer with non-alpha vertices similar to getStrokeVerticesFromPerimeter, except:
 *
 *
@@ -235,19 +249,17 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
        const Vector<Vertex>& vertices, VertexBuffer& vertexBuffer) {
        const Vector<Vertex>& vertices, VertexBuffer& vertexBuffer) {
    const int extra = paintInfo.capExtraDivisions();
    const int extra = paintInfo.capExtraDivisions();
    const int allocSize = (vertices.size() + extra) * 2;
    const int allocSize = (vertices.size() + extra) * 2;

    Vertex* buffer = vertexBuffer.alloc<Vertex>(allocSize);
    Vertex* buffer = vertexBuffer.alloc<Vertex>(allocSize);


    const int lastIndex = vertices.size() - 1;
    if (extra > 0) {
    if (extra > 0) {
        // tessellate both round caps
        // tessellate both round caps
        const int last = vertices.size() - 1;
        float beginTheta = atan2(
        float beginTheta = atan2(
                    - (vertices[0].position[0] - vertices[1].position[0]),
                    - (vertices[0].position[0] - vertices[1].position[0]),
                    vertices[0].position[1] - vertices[1].position[1]);
                    vertices[0].position[1] - vertices[1].position[1]);
        float endTheta = atan2(
        float endTheta = atan2(
                - (vertices[last].position[0] - vertices[last - 1].position[0]),
                    - (vertices[lastIndex].position[0] - vertices[lastIndex - 1].position[0]),
                vertices[last].position[1] - vertices[last - 1].position[1]);
                    vertices[lastIndex].position[1] - vertices[lastIndex - 1].position[1]);

        const float dTheta = PI / (extra + 1);
        const float dTheta = PI / (extra + 1);
        const float radialScale = 2.0f / (1 + cos(dTheta));
        const float radialScale = 2.0f / (1 + cos(dTheta));


@@ -270,49 +282,38 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo,
            vec2 endRadialOffset(cos(endTheta), sin(endTheta));
            vec2 endRadialOffset(cos(endTheta), sin(endTheta));
            paintInfo.scaleOffsetForStrokeWidth(endRadialOffset);
            paintInfo.scaleOffsetForStrokeWidth(endRadialOffset);
            Vertex::set(&buffer[allocSize - 1 - capOffset],
            Vertex::set(&buffer[allocSize - 1 - capOffset],
                    vertices[last].position[0] + endRadialOffset.x,
                    vertices[lastIndex].position[0] + endRadialOffset.x,
                    vertices[last].position[1] + endRadialOffset.y);
                    vertices[lastIndex].position[1] + endRadialOffset.y);
        }
        }
    }
    }


    int currentIndex = extra;
    int currentIndex = extra;
    const Vertex* current = &(vertices[0]);
    const Vertex* last = &(vertices[0]);
    vec2 lastNormal;
    const Vertex* current = &(vertices[1]);
    for (unsigned int i = 0; i < vertices.size() - 1; i++) {
    vec2 lastNormal(current->position[1] - last->position[1],
                last->position[0] - current->position[0]);
    lastNormal.normalize();

    storeBeginEnd(paintInfo, vertices[0], lastNormal, buffer, currentIndex, true);

    for (unsigned int i = 1; i < vertices.size() - 1; i++) {
        const Vertex* next = &(vertices[i + 1]);
        const Vertex* next = &(vertices[i + 1]);
        vec2 nextNormal(next->position[1] - current->position[1],
        vec2 nextNormal(next->position[1] - current->position[1],
                current->position[0] - next->position[0]);
                current->position[0] - next->position[0]);
        nextNormal.normalize();
        nextNormal.normalize();


        vec2 totalOffset;
        vec2 strokeOffset  = totalOffsetFromNormals(lastNormal, nextNormal);
        if (i == 0) {
        paintInfo.scaleOffsetForStrokeWidth(strokeOffset);
            totalOffset = nextNormal;
        } else {
            totalOffset = totalOffsetFromNormals(lastNormal, nextNormal);
        }
        paintInfo.scaleOffsetForStrokeWidth(totalOffset);

        Vertex::set(&buffer[currentIndex++],
                current->position[0] + totalOffset.x,
                current->position[1] + totalOffset.y);


        Vertex::set(&buffer[currentIndex++],
        vec2 center(current->position[0], current->position[1]);
                current->position[0] - totalOffset.x,
        Vertex::set(&buffer[currentIndex++], center + strokeOffset);
                current->position[1] - totalOffset.y);
        Vertex::set(&buffer[currentIndex++], center - strokeOffset);


        current = next;
        current = next;
        lastNormal = nextNormal;
        lastNormal = nextNormal;
    }
    }


    vec2 totalOffset = lastNormal;
    storeBeginEnd(paintInfo, vertices[lastIndex], lastNormal, buffer, currentIndex, false);
    paintInfo.scaleOffsetForStrokeWidth(totalOffset);

    Vertex::set(&buffer[currentIndex++],
            current->position[0] + totalOffset.x,
            current->position[1] + totalOffset.y);
    Vertex::set(&buffer[currentIndex++],
            current->position[0] - totalOffset.x,
            current->position[1] - totalOffset.y);


    DEBUG_DUMP_BUFFER();
    DEBUG_DUMP_BUFFER();
}
}
@@ -389,7 +390,7 @@ void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo, const Vector<Ver
 * For explanation of constants and general methodoloyg, see comments for
 * For explanation of constants and general methodoloyg, see comments for
 * getStrokeVerticesFromUnclosedVerticesAA() below.
 * getStrokeVerticesFromUnclosedVerticesAA() below.
 */
 */
inline void storeCapAA(const PaintInfo& paintInfo, const Vector<Vertex>& vertices,
inline static void storeCapAA(const PaintInfo& paintInfo, const Vector<Vertex>& vertices,
        AlphaVertex* buffer, bool isFirst, vec2 normal, int offset) {
        AlphaVertex* buffer, bool isFirst, vec2 normal, int offset) {
    const int extra = paintInfo.capExtraDivisions();
    const int extra = paintInfo.capExtraDivisions();
    const int extraOffset = (extra + 1) / 2;
    const int extraOffset = (extra + 1) / 2;
@@ -772,11 +773,67 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint,
    }
    }
}
}


static void expandRectToCoverVertex(SkRect& rect, float x, float y) {
    rect.fLeft = fminf(rect.fLeft, x);
    rect.fTop = fminf(rect.fTop, y);
    rect.fRight = fmaxf(rect.fRight, x);
    rect.fBottom = fmaxf(rect.fBottom, y);
}
static void expandRectToCoverVertex(SkRect& rect, const Vertex& vertex) {
static void expandRectToCoverVertex(SkRect& rect, const Vertex& vertex) {
    rect.fLeft = fminf(rect.fLeft, vertex.position[0]);
    expandRectToCoverVertex(rect, vertex.position[0], vertex.position[1]);
    rect.fTop = fminf(rect.fTop, vertex.position[1]);
}
    rect.fRight = fmaxf(rect.fRight, vertex.position[0]);

    rect.fBottom = fmaxf(rect.fBottom, vertex.position[1]);
template <class TYPE>
static void instanceVertices(VertexBuffer& srcBuffer, VertexBuffer& dstBuffer,
        const float* points, int count, SkRect& bounds) {
    bounds.set(points[0], points[1], points[0], points[1]);

    int numPoints = count / 2;
    int verticesPerPoint = srcBuffer.getVertexCount();
    dstBuffer.alloc<TYPE>(numPoints * verticesPerPoint + (numPoints - 1) * 2);

    for (int i = 0; i < count; i += 2) {
        expandRectToCoverVertex(bounds, points[i + 0], points[i + 1]);
        dstBuffer.copyInto<TYPE>(srcBuffer, points[i + 0], points[i + 1]);
    }
    dstBuffer.createDegenerateSeparators<TYPE>(verticesPerPoint);
}

void PathTessellator::tessellatePoints(const float* points, int count, SkPaint* paint,
        const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer) {
    const PaintInfo paintInfo(paint, transform);

    // determine point shape
    SkPath path;
    float radius = paintInfo.halfStrokeWidth;
    if (radius == 0.0f) radius = 0.25f;

    if (paintInfo.cap == SkPaint::kRound_Cap) {
        path.addCircle(0, 0, radius);
    } else {
        path.addRect(-radius, -radius, radius, radius);
    }

    // calculate outline
    Vector<Vertex> outlineVertices;
    approximatePathOutlineVertices(path, true,
            paintInfo.inverseScaleX * paintInfo.inverseScaleX,
            paintInfo.inverseScaleY * paintInfo.inverseScaleY, outlineVertices);

    if (!outlineVertices.size()) return;

    // tessellate, then duplicate outline across points
    int numPoints = count / 2;
    VertexBuffer tempBuffer;
    if (!paintInfo.isAA) {
        getFillVerticesFromPerimeter(outlineVertices, tempBuffer);
        instanceVertices<Vertex>(tempBuffer, vertexBuffer, points, count, bounds);
    } else {
        getFillVerticesFromPerimeterAA(paintInfo, outlineVertices, tempBuffer);
        instanceVertices<AlphaVertex>(tempBuffer, vertexBuffer, points, count, bounds);
    }

    expandBoundsForStroke(bounds, paint, true); // force-expand bounds to incorporate stroke
}
}


void PathTessellator::tessellateLines(const float* points, int count, SkPaint* paint,
void PathTessellator::tessellateLines(const float* points, int count, SkPaint* paint,
+25 −10
Original line number Original line Diff line number Diff line
@@ -30,7 +30,7 @@ class VertexBuffer {
public:
public:
    VertexBuffer():
    VertexBuffer():
        mBuffer(0),
        mBuffer(0),
        mSize(0),
        mVertexCount(0),
        mCleanupMethod(NULL)
        mCleanupMethod(NULL)
    {}
    {}


@@ -44,30 +44,42 @@ public:
       multiple regions within a single VertexBuffer, such as with PathTessellator::tesselateLines()
       multiple regions within a single VertexBuffer, such as with PathTessellator::tesselateLines()
     */
     */
    template <class TYPE>
    template <class TYPE>
    TYPE* alloc(int size) {
    TYPE* alloc(int vertexCount) {
        if (mSize) {
        if (mVertexCount) {
            TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
            TYPE* reallocBuffer = (TYPE*)mReallocBuffer;
            // already have allocated the buffer, re-allocate space within
            // already have allocated the buffer, re-allocate space within
            if (mReallocBuffer != mBuffer) {
            if (mReallocBuffer != mBuffer) {
                // not first re-allocation, leave space for degenerate triangles to separate strips
                // not first re-allocation, leave space for degenerate triangles to separate strips
                reallocBuffer += 2;
                reallocBuffer += 2;
            }
            }
            mReallocBuffer = reallocBuffer + size;
            mReallocBuffer = reallocBuffer + vertexCount;
            return reallocBuffer;
            return reallocBuffer;
        }
        }
        mSize = size;
        mVertexCount = vertexCount;
        mReallocBuffer = mBuffer = (void*)new TYPE[size];
        mReallocBuffer = mBuffer = (void*)new TYPE[vertexCount];
        mCleanupMethod = &(cleanup<TYPE>);
        mCleanupMethod = &(cleanup<TYPE>);


        return (TYPE*)mBuffer;
        return (TYPE*)mBuffer;
    }
    }


    void* getBuffer() const { return mBuffer; }
    template <class TYPE>
    unsigned int getSize() const { return mSize; }
    void copyInto(const VertexBuffer& srcBuffer, float xOffset, float yOffset) {
        int verticesToCopy = srcBuffer.getVertexCount();

        TYPE* dst = alloc<TYPE>(verticesToCopy);
        TYPE* src = (TYPE*)srcBuffer.getBuffer();

        for (int i = 0; i < verticesToCopy; i++) {
            TYPE::copyWithOffset(&dst[i], src[i], xOffset, yOffset);
        }
    }

    void* getBuffer() const { return mBuffer; } // shouldn't be const, since not a const ptr?
    unsigned int getVertexCount() const { return mVertexCount; }


    template <class TYPE>
    template <class TYPE>
    void createDegenerateSeparators(int allocSize) {
    void createDegenerateSeparators(int allocSize) {
        TYPE* end = (TYPE*)mBuffer + mSize;
        TYPE* end = (TYPE*)mBuffer + mVertexCount;
        for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
        for (TYPE* degen = (TYPE*)mBuffer + allocSize; degen < end; degen += 2 + allocSize) {
            memcpy(degen, degen - 1, sizeof(TYPE));
            memcpy(degen, degen - 1, sizeof(TYPE));
            memcpy(degen + 1, degen + 2, sizeof(TYPE));
            memcpy(degen + 1, degen + 2, sizeof(TYPE));
@@ -81,7 +93,7 @@ private:
    }
    }


    void* mBuffer;
    void* mBuffer;
    unsigned int mSize;
    unsigned int mVertexCount;


    void* mReallocBuffer; // used for multi-allocation
    void* mReallocBuffer; // used for multi-allocation


@@ -95,6 +107,9 @@ public:
    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);


    static void tessellatePoints(const float* points, int count, SkPaint* paint,
            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);

    static void tessellateLines(const float* points, int count, SkPaint* paint,
    static void tessellateLines(const float* points, int count, SkPaint* paint,
            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);
            const mat4* transform, SkRect& bounds, VertexBuffer& vertexBuffer);


+9 −18
Original line number Original line Diff line number Diff line
@@ -68,24 +68,22 @@ namespace uirenderer {
#define PROGRAM_BITMAP_WRAPS_SHIFT 9
#define PROGRAM_BITMAP_WRAPS_SHIFT 9
#define PROGRAM_BITMAP_WRAPT_SHIFT 11
#define PROGRAM_BITMAP_WRAPT_SHIFT 11


#define PROGRAM_GRADIENT_TYPE_SHIFT 33
#define PROGRAM_GRADIENT_TYPE_SHIFT 33 // 2 bits for gradient type
#define PROGRAM_MODULATE_SHIFT 35
#define PROGRAM_MODULATE_SHIFT 35


#define PROGRAM_IS_POINT_SHIFT 36
#define PROGRAM_HAS_AA_SHIFT 36


#define PROGRAM_HAS_AA_SHIFT 37
#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 37
#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 38


#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38
#define PROGRAM_HAS_GAMMA_CORRECTION 39
#define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39


#define PROGRAM_HAS_GAMMA_CORRECTION 40
#define PROGRAM_IS_SIMPLE_GRADIENT 40


#define PROGRAM_IS_SIMPLE_GRADIENT 41
#define PROGRAM_HAS_COLORS 41


#define PROGRAM_HAS_COLORS 42
#define PROGRAM_HAS_DEBUG_HIGHLIGHT 42

#define PROGRAM_EMULATE_STENCIL 43
#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43
#define PROGRAM_EMULATE_STENCIL 44


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Types
// Types
@@ -157,9 +155,6 @@ struct ProgramDescription {
    SkXfermode::Mode framebufferMode;
    SkXfermode::Mode framebufferMode;
    bool swapSrcDst;
    bool swapSrcDst;


    bool isPoint;
    float pointSize;

    bool hasGammaCorrection;
    bool hasGammaCorrection;
    float gamma;
    float gamma;


@@ -201,9 +196,6 @@ struct ProgramDescription {
        framebufferMode = SkXfermode::kClear_Mode;
        framebufferMode = SkXfermode::kClear_Mode;
        swapSrcDst = false;
        swapSrcDst = false;


        isPoint = false;
        pointSize = 0.0f;

        hasGammaCorrection = false;
        hasGammaCorrection = false;
        gamma = 2.2f;
        gamma = 2.2f;


@@ -269,7 +261,6 @@ struct ProgramDescription {
        key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
        key |= (framebufferMode & PROGRAM_MAX_XFERMODE) << PROGRAM_XFERMODE_FRAMEBUFFER_SHIFT;
        if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
        if (swapSrcDst) key |= PROGRAM_KEY_SWAP_SRC_DST;
        if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
        if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT;
        if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT;
        if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
        if (isAA) key |= programid(0x1) << PROGRAM_HAS_AA_SHIFT;
        if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
        if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT;
        if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
        if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
Loading