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

Commit 6820ac8b authored by Romain Guy's avatar Romain Guy
Browse files

Fix 9patch rendering.

Change-Id: Ic4c18ff483cca95fbabcb10843f7714efe488adb
parent 93227750
Loading
Loading
Loading
Loading
+9 −12
Original line number Diff line number Diff line
@@ -399,7 +399,7 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {

    drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
            1.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
            &mMeshVertices[0].texture[0], NULL, 0, true, true);
            &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, true, true);

    resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);

@@ -574,13 +574,12 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
    Patch* mesh = mCaches.patchCache.get(patch);
    mesh->updateVertices(bitmap, left, top, right, bottom,
            &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs);
    mesh->dump();

    // Specify right and bottom as +1.0f from left/top to prevent scaling since the
    // patch mesh already defines the final size
    drawTextureMesh(left, top, left + 1.0f, top + 1.0f, texture->id, alpha / 255.0f,
            mode, texture->blend, &mesh->vertices[0].position[0],
            &mesh->vertices[0].texture[0], mesh->indices, mesh->indicesCount);
            &mesh->vertices[0].texture[0], GL_TRIANGLES, mesh->verticesCount);
}

void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -956,19 +955,21 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
    SkXfermode::Mode mode;
    getAlphaAndMode(paint, &alpha, &mode);

    drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend,
            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
    drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode,
            texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
            GL_TRIANGLE_STRIP, gMeshCount);
}

void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
    drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
            &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
            GL_TRIANGLE_STRIP, gMeshCount);
}

void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend,
        GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount,
        GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
        bool swapSrcDst, bool ignoreTransform) {
    clearLayerRegions();

@@ -1010,11 +1011,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
        mColorFilter->setupProgram(mCaches.currentProgram);
    }

    if (!indices) {
        glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
    } else {
        glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices);
    }
    glDrawArrays(drawMode, 0, elementsCount);
    glDisableVertexAttribArray(texCoordsSlot);
}

+1 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ private:
     */
    void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
            float alpha, SkXfermode::Mode mode, bool blend,
            GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0,
            GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
            bool swapSrcDst = false, bool ignoreTransform = false);

    /**
+70 −97
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define LOG_TAG "OpenGLRenderer"

#include <cstring>
#include <cmath>

#include <utils/Log.h>

@@ -29,38 +30,14 @@ namespace uirenderer {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////

Patch::Patch(const uint32_t xCount, const uint32_t yCount):
        xCount(xCount + 2), yCount(yCount + 2) {
    verticesCount = (xCount + 2) * (yCount + 2);
    vertices = new TextureVertex[verticesCount];

Patch::Patch(const uint32_t xCount, const uint32_t yCount) {
    // 2 triangles per patch, 3 vertices per triangle
    indicesCount = (xCount + 1) * (yCount + 1) * 2 * 3;
    indices = new uint16_t[indicesCount];

    const uint32_t xNum = xCount + 1;
    const uint32_t yNum = yCount + 1;

    uint16_t* startIndices = indices;
    uint32_t n = 0;
    for (uint32_t y = 0; y < yNum; y++) {
        for (uint32_t x = 0; x < xNum; x++) {
            *startIndices++ = n;
            *startIndices++ = n + 1;
            *startIndices++ = n + xNum + 2;

            *startIndices++ = n;
            *startIndices++ = n + xNum + 2;
            *startIndices++ = n + xNum + 1;

            n += 1;
        }
        n += 1;
    }
    verticesCount = (xCount + 1) * (yCount + 1) * 2 * 3;
    vertices = new TextureVertex[verticesCount];
    memset(vertices, 0, sizeof(TextureVertex) * verticesCount);
}

Patch::~Patch() {
    delete indices;
    delete vertices;
}

@@ -74,10 +51,8 @@ void Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float
    const uint32_t xStretchCount = (width + 1) >> 1;
    const uint32_t yStretchCount = (height + 1) >> 1;

    float xStretch = 0;
    float yStretch = 0;
    float xStretchTex = 0;
    float yStretchTex = 0;
    float stretchX = 0.0f;
    float stretchY = 0.0;

    const float meshWidth = right - left;

@@ -89,9 +64,10 @@ void Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float
        for (uint32_t i = 1; i < width; i += 2) {
            stretchSize += xDivs[i] - xDivs[i - 1];
        }
        xStretchTex = (stretchSize / bitmapWidth) / xStretchCount;
        const float xStretchTex = stretchSize;
        const float fixed = bitmapWidth - stretchSize;
        xStretch = (right - left - fixed) / xStretchCount;
        const float xStretch = right - left - fixed;
        stretchX = xStretch / xStretchTex;
    }

    if (yStretchCount > 0) {
@@ -99,89 +75,86 @@ void Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float
        for (uint32_t i = 1; i < height; i += 2) {
            stretchSize += yDivs[i] - yDivs[i - 1];
        }
        yStretchTex = (stretchSize / bitmapHeight) / yStretchCount;
        const float yStretchTex = stretchSize;
        const float fixed = bitmapHeight - stretchSize;
        yStretch = (bottom - top - fixed) / yStretchCount;
        const float yStretch = bottom - top - fixed;
        stretchY = yStretch / yStretchTex;
    }

    float vy = 0.0f;
    float ty = 0.0f;
    TextureVertex* vertex = vertices;

    generateVertices(vertex, 0.0f, 0.0f, xDivs, width, xStretch, xStretchTex,
            meshWidth, bitmapWidth);
    vertex += width + 2;
    float previousStepY = 0.0f;

    float y1 = 0.0f;
    float v1 = 0.0f;

    for (uint32_t i = 0; i < height; i++) {
        float stepY = yDivs[i];

    for (uint32_t y = 0; y < height; y++) {
        if (y & 1) {
            vy += yStretch;
            ty += yStretchTex;
        float y2 = 0.0f;
        if (i & 1) {
            const float segment = stepY - previousStepY;
            y2 = y1 + segment * stretchY;
        } else {
            const float step = float(yDivs[y]);
            vy += step;
            ty += step / bitmapHeight;
            y2 = y1 + stepY - previousStepY;
        }
        generateVertices(vertex, vy, ty, xDivs, width, xStretch, xStretchTex,
                meshWidth, bitmapWidth);
        vertex += width + 2;
        float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight;

        generateRow(vertex, y1, y2, v1, v2, xDivs, width, stretchX,
                right - left, bitmapWidth);

        y1 = y2;
        v1 = (stepY + 0.5f) / bitmapHeight;

        previousStepY = stepY;
    }

    generateVertices(vertex, bottom - top, 1.0f, xDivs, width, xStretch, xStretchTex,
            meshWidth, bitmapWidth);
    generateRow(vertex, y1, bottom - top, v1, 1.0f, xDivs, width, stretchX,
            right - left, bitmapWidth);
}

inline void Patch::generateVertices(TextureVertex* vertex, float y, float v,
        const int32_t xDivs[], uint32_t xCount, float xStretch, float xStretchTex,
        float width, float widthTex) {
    float vx = 0.0f;
    float tx = 0.0f;
inline void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2,
        const int32_t xDivs[], uint32_t xCount, float stretchX, float width, float bitmapWidth) {
    float previousStepX = 0.0f;

    TextureVertex::set(vertex, vx, y, tx, v);
    vertex++;
    float x1 = 0.0f;
    float u1 = 0.0f;

    for (uint32_t x = 0; x < xCount; x++) {
        if (x & 1) {
            vx += xStretch;
            tx += xStretchTex;
    // Generate the row quad by quad
    for (uint32_t i = 0; i < xCount; i++) {
        float stepX = xDivs[i];

        float x2 = 0.0f;
        if (i & 1) {
            const float segment = stepX - previousStepX;
            x2 = x1 + segment * stretchX;
        } else {
            const float step = float(xDivs[x]);
            vx += step;
            tx += step / widthTex;
            x2 = x1 + stepX - previousStepX;
        }
        float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;

        generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2);

        x1 = x2;
        u1 = (stepX + 0.5f) / bitmapWidth;

        TextureVertex::set(vertex, vx, y, tx, v);
        vertex++;
        previousStepX = stepX;
    }

    TextureVertex::set(vertex, width, y, 1.0f, v);
    vertex++;
    generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2);
}

///////////////////////////////////////////////////////////////////////////////
// Debug tools
///////////////////////////////////////////////////////////////////////////////
inline void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
            float u1, float v1, float u2, float v2) {
    // Left triangle
    TextureVertex::set(vertex++, x1, y1, u1, v1);
    TextureVertex::set(vertex++, x2, y1, u2, v1);
    TextureVertex::set(vertex++, x1, y2, u1, v2);

void Patch::dump() {
    LOGD("Vertices [");
    for (uint32_t y = 0; y < yCount; y++) {
        char buffer[512];
        buffer[0] = '\0';
        uint32_t offset = 0;
        for (uint32_t x = 0; x < xCount; x++) {
            TextureVertex* v = &vertices[y * xCount + x];
            offset += sprintf(&buffer[offset], " (%.4f,%.4f)-(%.4f,%.4f)",
                    v->position[0], v->position[1], v->texture[0], v->texture[1]);
        }
        LOGD("  [%s ]", buffer);
    }
    LOGD("]\nIndices [ ");
    char buffer[4096];
    buffer[0] = '\0';
    uint32_t offset = 0;
    for (uint32_t i = 0; i < indicesCount; i++) {
        offset += sprintf(&buffer[offset], "%d ", indices[i]);
    }
    LOGD("  %s\n]", buffer);
    // Right triangle
    TextureVertex::set(vertex++, x1, y2, u1, v2);
    TextureVertex::set(vertex++, x2, y1, u2, v1);
    TextureVertex::set(vertex++, x2, y2, u2, v2);
}

}; // namespace uirenderer
+5 −10
Original line number Diff line number Diff line
@@ -62,21 +62,16 @@ struct Patch {
    void updateVertices(const SkBitmap* bitmap, float left, float top, float right, float bottom,
            const int32_t* xDivs,  const int32_t* yDivs,
            const uint32_t width, const uint32_t height);
    void dump();

    uint32_t xCount;
    uint32_t yCount;

    uint16_t* indices;
    uint32_t indicesCount;

    TextureVertex* vertices;
    uint32_t verticesCount;

private:
    static inline void generateVertices(TextureVertex* vertex, float y, float v,
            const int32_t xDivs[], uint32_t xCount, float xStretch, float xStretchTex,
            float width, float widthTex);
    static inline void generateRow(TextureVertex*& vertex, float y1, float y2,
            float v1, float v2, const int32_t xDivs[], uint32_t xCount,
            float stretchX, float width, float bitmapWidth);
    static inline void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
            float u1, float v1, float u2, float v2);
}; // struct Patch

}; // namespace uirenderer
+2.8 KiB
Loading image diff...
Loading