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

Commit 6f72bebe authored by Romain Guy's avatar Romain Guy
Browse files

Update 9patch structure when rendering with different divs/colors.

Bug #3221488

Change-Id: Ifc9e42a991d630feadc9e8032322f37504d09d6d
parent 73066685
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -58,6 +58,8 @@ public:
        mXDivs[0] = mYDivs[0] = 2;
        mXDivs[1] = mYDivs[1] = 3;

        mPatch->copy(mXDivs, mYDivs);

        glGenTextures(1, &mTexture);
        glBindTexture(GL_TEXTURE_2D, mTexture);

@@ -89,8 +91,7 @@ public:
        const float half = lineWidth * 0.5f;

        mPatch->updateVertices(gLineTextureWidth, gLineTextureHeight,
                -gLineAABias, -half - gLineAABias, length + gLineAABias, half + gLineAABias,
                mXDivs, mYDivs, mXDivsCount, mYDivsCount);
                -gLineAABias, -half - gLineAABias, length + gLineAABias, half + gLineAABias);

        tx = -gLineAABias;
        ty = lineWidth <= 1.0f ? -gLineAABias : -half - gLineAABias;
+3 −0
Original line number Diff line number Diff line
@@ -952,6 +952,9 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int
                mode, texture->blend, (GLvoid*) 0, (GLvoid*) gMeshTextureOffset,
                GL_TRIANGLES, mesh->verticesCount, false, false, mesh->meshBuffer,
                true, !mesh->hasEmptyQuads);
    } else {
        PATCH_LOGD("Invisible 9patch, ignoring (%.2f, %.2f, %.2f, %.2f)",
                left, top, right, bottom);
    }
}

+79 −26
Original line number Diff line number Diff line
@@ -30,32 +30,81 @@ namespace uirenderer {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////

Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads) {
Patch::Patch(const uint32_t xCount, const uint32_t yCount, const int8_t emptyQuads):
        mXCount(xCount), mYCount(yCount) {
    // 2 triangles per patch, 3 vertices per triangle
    verticesCount = ((xCount + 1) * (yCount + 1) - emptyQuads) * 2 * 3;
    mVertices = new TextureVertex[verticesCount];
    hasEmptyQuads = emptyQuads > 0;
    mUploaded = false;

    mColorKey = 0;
    mXDivs = new int32_t[mXCount];
    mYDivs = new int32_t[mYCount];

    glGenBuffers(1, &meshBuffer);
}

Patch::~Patch() {
    delete[] mVertices;
    delete[] mXDivs;
    delete[] mYDivs;
    glDeleteBuffers(1, &meshBuffer);
}

///////////////////////////////////////////////////////////////////////////////
// Patch management
///////////////////////////////////////////////////////////////////////////////

void Patch::copy(const int32_t* xDivs, const int32_t* yDivs) {
    memcpy(mXDivs, xDivs, mXCount * sizeof(int32_t));
    memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
}

void Patch::copy(const int32_t* yDivs) {
    memcpy(mYDivs, yDivs, mYCount * sizeof(int32_t));
}

void Patch::updateColorKey(const uint32_t colorKey) {
    mColorKey = colorKey;
}

bool Patch::matches(const int32_t* xDivs, const int32_t* yDivs, const uint32_t colorKey) {
    if (mColorKey != colorKey) {
        updateColorKey(colorKey);
        copy(xDivs, yDivs);
        return false;
    }

    for (uint32_t i = 0; i < mXCount; i++) {
        if (mXDivs[i] != xDivs[i]) {
            // The Y divs may or may not match, copy everything
            copy(xDivs, yDivs);
            return false;
        }
    }

    for (uint32_t i = 0; i < mYCount; i++) {
        if (mYDivs[i] != yDivs[i]) {
            // We know all the X divs match, copy only Y divs
            copy(yDivs);
            return false;
        }
    }

    return true;
}

///////////////////////////////////////////////////////////////////////////////
// Vertices management
///////////////////////////////////////////////////////////////////////////////

void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
        float left, float top, float right, float bottom,
        const int32_t* xDivs, const int32_t* yDivs,
        const uint32_t width, const uint32_t height, const uint32_t colorKey) {
        float left, float top, float right, float bottom) {
    if (hasEmptyQuads) quads.clear();

    const uint32_t xStretchCount = (width + 1) >> 1;
    const uint32_t yStretchCount = (height + 1) >> 1;
    const uint32_t xStretchCount = (mXCount + 1) >> 1;
    const uint32_t yStretchCount = (mYCount + 1) >> 1;

    float stretchX = 0.0f;
    float stretchY = 0.0;
@@ -64,8 +113,8 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,

    if (xStretchCount > 0) {
        uint32_t stretchSize = 0;
        for (uint32_t i = 1; i < width; i += 2) {
            stretchSize += xDivs[i] - xDivs[i - 1];
        for (uint32_t i = 1; i < mXCount; i += 2) {
            stretchSize += mXDivs[i] - mXDivs[i - 1];
        }
        const float xStretchTex = stretchSize;
        const float fixed = bitmapWidth - stretchSize;
@@ -75,8 +124,8 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,

    if (yStretchCount > 0) {
        uint32_t stretchSize = 0;
        for (uint32_t i = 1; i < height; i += 2) {
            stretchSize += yDivs[i] - yDivs[i - 1];
        for (uint32_t i = 1; i < mYCount; i += 2) {
            stretchSize += mYDivs[i] - mYDivs[i - 1];
        }
        const float yStretchTex = stretchSize;
        const float fixed = bitmapHeight - stretchSize;
@@ -92,8 +141,8 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
    float y1 = 0.0f;
    float v1 = 0.0f;

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

        float y2 = 0.0f;
        if (i & 1) {
@@ -104,8 +153,7 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
        }
        float v2 = fmax(0.0f, stepY - 0.5f) / bitmapHeight;

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

        y1 = y2;
        v1 = (stepY + 0.5f) / bitmapHeight;
@@ -113,25 +161,30 @@ void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight,
        previousStepY = stepY;
    }

    generateRow(vertex, y1, bottom - top, v1, 1.0f, xDivs, width, stretchX,
            right - left, bitmapWidth, quadCount, colorKey);
    generateRow(vertex, y1, bottom - top, v1, 1.0f, stretchX, right - left,
            bitmapWidth, quadCount);

    Caches::getInstance().bindMeshBuffer(meshBuffer);
    if (!mUploaded) {
        glBufferData(GL_ARRAY_BUFFER, sizeof(TextureVertex) * verticesCount,
                mVertices, GL_STATIC_DRAW);
                mVertices, GL_DYNAMIC_DRAW);
        mUploaded = true;
    } else {
        glBufferSubData(GL_ARRAY_BUFFER, 0,
                sizeof(TextureVertex) * verticesCount, mVertices);
    }
}

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,
        uint32_t& quadCount, const uint32_t colorKey) {
        float stretchX, float width, float bitmapWidth, uint32_t& quadCount) {
    float previousStepX = 0.0f;

    float x1 = 0.0f;
    float u1 = 0.0f;

    // Generate the row quad by quad
    for (uint32_t i = 0; i < xCount; i++) {
        float stepX = xDivs[i];
    for (uint32_t i = 0; i < mXCount; i++) {
        float stepX = mXDivs[i];

        float x2 = 0.0f;
        if (i & 1) {
@@ -142,7 +195,7 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl
        }
        float u2 = fmax(0.0f, stepX - 0.5f) / bitmapWidth;

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

        x1 = x2;
        u1 = (stepX + 0.5f) / bitmapWidth;
@@ -150,12 +203,12 @@ void Patch::generateRow(TextureVertex*& vertex, float y1, float y2, float v1, fl
        previousStepX = stepX;
    }

    generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount, colorKey);
    generateQuad(vertex, x1, y1, width, y2, u1, v1, 1.0f, v2, quadCount);
}

void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
            float u1, float v1, float u2, float v2, uint32_t& quadCount, const uint32_t colorKey) {
    if (((colorKey >> quadCount++) & 0x1) == 1) {
            float u1, float v1, float u2, float v2, uint32_t& quadCount) {
    if (((mColorKey >> quadCount++) & 0x1) == 1) {
        return;
    }

+17 −57
Original line number Diff line number Diff line
@@ -34,55 +34,6 @@ namespace uirenderer {
// 9-patch structures
///////////////////////////////////////////////////////////////////////////////

/**
 * Description of a patch.
 */
struct PatchDescription {
    PatchDescription(): bitmapWidth(0), bitmapHeight(0), pixelWidth(0), pixelHeight(0),
            xCount(0), yCount(0), emptyCount(0), colorKey(0) { }
    PatchDescription(const float bitmapWidth, const float bitmapHeight,
            const float pixelWidth, const float pixelHeight,
            const uint32_t xCount, const uint32_t yCount,
            const int8_t emptyCount, const uint32_t colorKey):
            bitmapWidth(bitmapWidth), bitmapHeight(bitmapHeight),
            pixelWidth(pixelWidth), pixelHeight(pixelHeight),
            xCount(xCount), yCount(yCount),
            emptyCount(emptyCount), colorKey(colorKey) { }
    PatchDescription(const PatchDescription& description):
            bitmapWidth(description.bitmapWidth), bitmapHeight(description.bitmapHeight),
            pixelWidth(description.pixelWidth), pixelHeight(description.pixelHeight),
            xCount(description.xCount), yCount(description.yCount),
            emptyCount(description.emptyCount), colorKey(description.colorKey) { }

    float bitmapWidth;
    float bitmapHeight;
    float pixelWidth;
    float pixelHeight;
    uint32_t xCount;
    uint32_t yCount;
    int8_t emptyCount;
    uint32_t colorKey;

    bool operator<(const PatchDescription& rhs) const {
        LTE_FLOAT(bitmapWidth) {
            LTE_FLOAT(bitmapHeight) {
                LTE_FLOAT(pixelWidth) {
                    LTE_FLOAT(pixelHeight) {
                        LTE_INT(xCount) {
                            LTE_INT(yCount) {
                                LTE_INT(emptyCount) {
                                    LTE_INT(colorKey) return false;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
}; // struct PatchDescription

/**
 * An OpenGL patch. This contains an array of vertices and an array of
 * indices to render the vertices.
@@ -92,10 +43,11 @@ struct Patch {
    ~Patch();

    void updateVertices(const float bitmapWidth, const float bitmapHeight,
            float left, float top, float right, float bottom,
            const int32_t* xDivs, const int32_t* yDivs,
            const uint32_t width, const uint32_t height,
            const uint32_t colorKey = 0);
            float left, float top, float right, float bottom);

    void updateColorKey(const uint32_t colorKey);
    void copy(const int32_t* xDivs, const int32_t* yDivs);
    bool matches(const int32_t* xDivs, const int32_t* yDivs, const uint32_t colorKey);

    GLuint meshBuffer;
    uint32_t verticesCount;
@@ -104,15 +56,23 @@ struct Patch {

private:
    TextureVertex* mVertices;
    bool mUploaded;

    uint32_t mXCount;
    int32_t* mXDivs;
    uint32_t mYCount;
    int32_t* mYDivs;
    uint32_t mColorKey;

    void copy(const int32_t* yDivs);

    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,
            uint32_t& quadCount, const uint32_t colorKey);
            float v1, float v2, float stretchX, float width, float bitmapWidth,
            uint32_t& quadCount);
    void generateQuad(TextureVertex*& vertex,
            float x1, float y1, float x2, float y2,
            float u1, float v1, float u2, float v2,
            uint32_t& quadCount, const uint32_t colorKey);
            uint32_t& quadCount);
}; // struct Patch

}; // namespace uirenderer
+6 −2
Original line number Diff line number Diff line
@@ -87,8 +87,9 @@ Patch* PatchCache::get(const float bitmapWidth, const float bitmapHeight,
                width, height, pixelWidth, pixelHeight, bitmapWidth, bitmapHeight);

        mesh = new Patch(width, height, transparentQuads);
        mesh->updateVertices(bitmapWidth, bitmapHeight, 0.0f, 0.0f,
                pixelWidth, pixelHeight, xDivs, yDivs, width, height, colorKey);
        mesh->updateColorKey(colorKey);
        mesh->copy(xDivs, yDivs);
        mesh->updateVertices(bitmapWidth, bitmapHeight, 0.0f, 0.0f, pixelWidth, pixelHeight);

        if (mCache.size() >= mMaxEntries) {
            delete mCache.valueAt(mCache.size() - 1);
@@ -96,6 +97,9 @@ Patch* PatchCache::get(const float bitmapWidth, const float bitmapHeight,
        }

        mCache.add(description, mesh);
    } else if (!mesh->matches(xDivs, yDivs, colorKey)) {
        PATCH_LOGD("Patch mesh does not match, refreshing vertices");
        mesh->updateVertices(bitmapWidth, bitmapHeight, 0.0f, 0.0f, pixelWidth, pixelHeight);
    }

    return mesh;
Loading