diff options
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 131 |
1 files changed, 121 insertions, 10 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 027ed79..34da572 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -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); - glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount); + if (!indices) { + glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount); + } else { + glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices); + } glDisableVertexAttribArray(mDrawTextureShader->position); glDisableVertexAttribArray(mDrawTextureShader->texCoords); |