Loading libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \ LayerCache.cpp \ Matrix.cpp \ OpenGLRenderer.cpp \ PatchCache.cpp \ Program.cpp \ TextureCache.cpp Loading libs/hwui/Layer.h +3 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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. Loading libs/hwui/LayerCache.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading libs/hwui/OpenGLRenderer.cpp +121 −10 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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]; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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); Loading libs/hwui/OpenGLRenderer.h +16 −19 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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. */ Loading Loading @@ -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: Loading @@ -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; Loading @@ -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 Loading
libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \ LayerCache.cpp \ Matrix.cpp \ OpenGLRenderer.cpp \ PatchCache.cpp \ Program.cpp \ TextureCache.cpp Loading
libs/hwui/Layer.h +3 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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. Loading
libs/hwui/LayerCache.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
libs/hwui/OpenGLRenderer.cpp +121 −10 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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]; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading @@ -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); Loading
libs/hwui/OpenGLRenderer.h +16 −19 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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. */ Loading Loading @@ -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: Loading @@ -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; Loading @@ -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