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

Commit 831e550b authored by Romain Guy's avatar Romain Guy Committed by Android (Google) Code Review
Browse files

Merge "Draw n-patches using OpenGL."

parents 0f399ec6 f7f93556
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
	LayerCache.cpp \
	Matrix.cpp \
	OpenGLRenderer.cpp \
	PatchCache.cpp \
	Program.cpp \
	TextureCache.cpp

+3 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#ifndef ANDROID_UI_LAYER_H
#define ANDROID_UI_LAYER_H

#include <sys/types.h>

#include <GLES2/gl2.h>

#include <SkXfermode.h>
@@ -54,7 +56,7 @@ struct LayerSize {
    bool operator==(const LayerSize& rhs) const {
        return width == rhs.width && height == rhs.height;
    }
};
}; // struct LayerSize

/**
 * A layer has dimensions and is backed by an OpenGL texture.
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ public:
     * Used as a callback when an entry is removed from the cache.
     * Do not invoke directly.
     */
    void operator()(LayerSize& bitmap, Layer*& texture);
    void operator()(LayerSize& size, Layer*& layer);

    /**
     * Returns the layer of specified dimensions. If not suitable layer
+121 −10
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ namespace uirenderer {

#define DEFAULT_TEXTURE_CACHE_SIZE 20
#define DEFAULT_LAYER_CACHE_SIZE 10
#define DEFAULT_PATCH_CACHE_SIZE 100

// Converts a number of mega-bytes into bytes
#define MB(s) s * 1024 * 1024
@@ -95,7 +96,8 @@ static const Blender gBlends[] = {

OpenGLRenderer::OpenGLRenderer():
        mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
        mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)) {
        mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)),
        mPatchCache(DEFAULT_PATCH_CACHE_SIZE) {
    LOGD("Create OpenGLRenderer");

    char property[PROPERTY_VALUE_MAX];
@@ -298,7 +300,6 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
    GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0;
    LayerSize size(right - left, bottom - top);

    // TODO VERY IMPORTANT: Fix TextView to not call saveLayer() all the time
    Layer* layer = mLayerCache.get(size, previousFbo);
    if (!layer) {
        return false;
@@ -472,8 +473,110 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,

void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
        float left, float top, float right, float bottom, const SkPaint* paint) {
    // TODO: Implement
    LOGD("Draw 9patch, paddingLeft=%d", patch->paddingLeft);
    const Texture* texture = mTextureCache.get(bitmap);

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

    const uint32_t width = patch->numXDivs;
    const uint32_t height = patch->numYDivs;

    Patch* mesh = mPatchCache.get(patch);

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

    const int32_t* xDivs = &patch->xDivs[0];
    const int32_t* yDivs = &patch->yDivs[0];

    float xStretch = 0;
    float yStretch = 0;
    float xStretchTex = 0;
    float yStretchTex = 0;

    const float meshWidth = right - left;

    const float bitmapWidth = float(bitmap->width());
    const float bitmapHeight = float(bitmap->height());

    if (xStretchCount > 0) {
        uint32_t stretchSize = 0;
        for (uint32_t i = 1; i < width; i += 2) {
            stretchSize += xDivs[i] - xDivs[i - 1];
        }
        xStretchTex = (stretchSize / bitmapWidth) / xStretchCount;
        const float fixed = bitmapWidth - stretchSize;
        xStretch = (right - left - fixed) / xStretchCount;
    }

    if (yStretchCount > 0) {
        uint32_t stretchSize = 0;
        for (uint32_t i = 1; i < height; i += 2) {
            stretchSize += yDivs[i] - yDivs[i - 1];
        }
        yStretchTex = (stretchSize / bitmapHeight) / yStretchCount;
        const float fixed = bitmapHeight - stretchSize;
        yStretch = (bottom - top - fixed) / yStretchCount;
    }

    float vy = 0.0f;
    float ty = 0.0f;
    TextureVertex* vertex = mesh->vertices;

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

    for (uint32_t y = 0; y < height; y++) {
        if (y & 1) {
            vy += yStretch;
            ty += yStretchTex;
        } else {
            const float step = float(yDivs[y]);
            vy += step;
            ty += step / bitmapHeight;
        }
        generateVertices(vertex, vy, ty, xDivs, width, xStretch, xStretchTex,
                meshWidth, bitmapWidth);
        vertex += width + 2;
    }

    generateVertices(vertex, bottom - top, 1.0f, xDivs, width, xStretch, xStretchTex,
            meshWidth, bitmapWidth);

    // 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, mode, texture->blend,
            true, &mesh->vertices[0].position[0], &mesh->vertices[0].texture[0], mesh->indices,
            mesh->indicesCount);
}

void OpenGLRenderer::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;

    TextureVertex::set(vertex, vx, y, tx, v);
    vertex++;

    for (uint32_t x = 0; x < xCount; x++) {
        if (x & 1) {
            vx += xStretch;
            tx += xStretchTex;
        } else {
            const float step = float(xDivs[x]);
            vx += step;
            tx += step / widthTex;
        }

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

    TextureVertex::set(vertex, width, y, 1.0f, v);
    vertex++;
}

void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -538,6 +641,13 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot

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

void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
        GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied,
        GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount) {
    mModelView.loadTranslate(left, top, 0.0f);
    mModelView.scale(right - left, bottom - top, 1.0f);

@@ -560,20 +670,21 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b
    glActiveTexture(GL_TEXTURE0);
    glUniform1i(mDrawTextureShader->sampler, 0);

    const GLvoid* p = &mDrawTextureVertices[0].position[0];
    const GLvoid* t = &mDrawTextureVertices[0].texture[0];

    glEnableVertexAttribArray(mDrawTextureShader->position);
    glVertexAttribPointer(mDrawTextureShader->position, 2, GL_FLOAT, GL_FALSE,
            gDrawTextureVertexStride, p);
            gDrawTextureVertexStride, vertices);

    glEnableVertexAttribArray(mDrawTextureShader->texCoords);
    glVertexAttribPointer(mDrawTextureShader->texCoords, 2, GL_FLOAT, GL_FALSE,
            gDrawTextureVertexStride, t);
            gDrawTextureVertexStride, texCoords);

    glVertexAttrib4f(mDrawTextureShader->color, 1.0f, 1.0f, 1.0f, alpha);

    if (!indices) {
        glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
    } else {
        glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices);
    }

    glDisableVertexAttribArray(mDrawTextureShader->position);
    glDisableVertexAttribArray(mDrawTextureShader->texCoords);
+16 −19
Original line number Diff line number Diff line
@@ -32,10 +32,10 @@
#include "Program.h"
#include "Rect.h"
#include "Snapshot.h"
#include "Texture.h"
#include "Layer.h"
#include "TextureCache.h"
#include "LayerCache.h"
#include "PatchCache.h"
#include "Vertex.h"

namespace android {
namespace uirenderer {
@@ -44,22 +44,6 @@ namespace uirenderer {
// Support
///////////////////////////////////////////////////////////////////////////////

/**
 * Simple structure to describe a vertex with a position.
 * This is used to draw filled rectangles without a texture.
 */
struct SimpleVertex {
    float position[2];
}; // struct SimpleVertex

/**
 * Simple structure to describe a vertex with a position and a texture.
 */
struct TextureVertex {
    float position[2];
    float texture[2];
}; // struct TextureVertex

/**
 * Structure mapping Skia xfermodes to OpenGL blending factors.
 */
@@ -197,6 +181,13 @@ private:
    void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
            float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = false);

    /**
     * TODO: documentation
     */
    void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
            float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied,
            GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0);

    /**
     * Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
     * back to default is achieved by calling:
@@ -220,6 +211,12 @@ private:
     */
    inline void getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode);

    /**
     * TODO: documentation
     */
    inline void generateVertices(TextureVertex* vertex, float y, float v, const int32_t xDivs[],
            uint32_t xCount, float xStretch, float xStretchTex, float width, float widthTex);

    // Dimensions of the drawing surface
    int mWidth, mHeight;

@@ -243,9 +240,9 @@ private:
    // Used to draw textured quads
    TextureVertex mDrawTextureVertices[4];

    // Used to cache all drawBitmap textures
    TextureCache mTextureCache;
    LayerCache mLayerCache;
    PatchCache mPatchCache;
}; // class OpenGLRenderer

}; // namespace uirenderer
Loading