Loading libs/hwui/DisplayListOp.h +102 −13 Original line number Diff line number Diff line Loading @@ -751,12 +751,18 @@ public: TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \ texCoordsRect.xDim, texCoordsRect.yDim) /** * This multi-draw operation builds a mesh on the stack by generating a quad * for each bitmap in the batch. This method is also responsible for dirtying * the current layer, if any. */ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, const Vector<DrawOp*>& ops, const Rect& bounds) { renderer.restoreDisplayState(state, true); // restore all but the clip TextureVertex vertices[6 * ops.size()]; TextureVertex* vertex = &vertices[0]; const bool hasLayer = renderer.hasLayer(); bool transformed = false; // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, Loading @@ -778,6 +784,11 @@ public: SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom); if (hasLayer) { const Rect& dirty = ops[i]->state.mBounds; renderer.dirtyLayer(dirty.left, dirty.top, dirty.right, dirty.bottom); } } return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], Loading Loading @@ -921,25 +932,104 @@ private: class DrawPatchOp : public DrawBoundedOp { public: DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) : DrawBoundedOp(left, top, right, bottom, 0), mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode), mGenerationId(0), mMesh(NULL) { float left, float top, float right, float bottom, SkPaint* paint) : DrawBoundedOp(left, top, right, bottom, paint), mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL) { mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap); }; virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { const Patch* getMesh(OpenGLRenderer& renderer) { if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) { PatchCache& cache = renderer.getCaches().patchCache; mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(), mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top, mPatch); mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch); mGenerationId = cache.getGenerationId(); } return mMesh; } /** * This multi-draw operation builds an indexed mesh on the stack by copying * and transforming the vertices of each 9-patch in the batch. This method * is also responsible for dirtying the current layer, if any. */ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, const Vector<DrawOp*>& ops, const Rect& bounds) { renderer.restoreDisplayState(state, true); // Batches will usually contain a small number of items so it's // worth performing a first iteration to count the exact number // of vertices we need in the new mesh uint32_t totalVertices = 0; for (unsigned int i = 0; i < ops.size(); i++) { totalVertices += ((DrawPatchOp*) ops[i])->getMesh(renderer)->verticesCount; } const bool hasLayer = renderer.hasLayer(); uint32_t indexCount = 0; TextureVertex vertices[totalVertices]; TextureVertex* vertex = &vertices[0]; // Create a mesh that contains the transformed vertices for all the // 9-patch objects that are part of the batch. Note that onDefer() // enforces ops drawn by this function to have a pure translate or // identity matrix for (unsigned int i = 0; i < ops.size(); i++) { DrawPatchOp* patchOp = (DrawPatchOp*) ops[i]; const Patch* opMesh = patchOp->getMesh(renderer); uint32_t vertexCount = opMesh->verticesCount; if (vertexCount == 0) continue; // We use the bounds to know where to translate our vertices // Using patchOp->state.mBounds wouldn't work because these // bounds are clipped const float tx = (int) floorf(patchOp->state.mMatrix.getTranslateX() + patchOp->mLocalBounds.left + 0.5f); const float ty = (int) floorf(patchOp->state.mMatrix.getTranslateY() + patchOp->mLocalBounds.top + 0.5f); // Copy & transform all the vertices for the current operation TextureVertex* opVertices = opMesh->vertices; for (uint32_t j = 0; j < vertexCount; j++, opVertices++) { TextureVertex::set(vertex++, opVertices->position[0] + tx, opVertices->position[1] + ty, opVertices->texture[0], opVertices->texture[1]); } // Dirty the current layer if possible. When the 9-patch does not // contain empty quads we can take a shortcut and simply set the // dirty rect to the object's bounds. if (hasLayer) { if (!opMesh->hasEmptyQuads) { renderer.dirtyLayer(tx, ty, tx + patchOp->mLocalBounds.getWidth(), ty + patchOp->mLocalBounds.getHeight()); } else { const size_t count = opMesh->quads.size(); for (size_t i = 0; i < count; i++) { const Rect& quadBounds = opMesh->quads[i]; const float x = tx + quadBounds.left; const float y = ty + quadBounds.top; renderer.dirtyLayer(x, y, x + quadBounds.getWidth(), y + quadBounds.getHeight()); } } } indexCount += opMesh->indexCount; } return renderer.drawPatches(mBitmap, mEntry, &vertices[0], indexCount, getPaint(renderer)); } virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { // We're not calling the public variant of drawPatch() here // This method won't perform the quickReject() since we've already done it at this point return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode); return renderer.drawPatch(mBitmap, getMesh(renderer), mEntry, mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); } virtual void output(int level, uint32_t logFlags) const { Loading @@ -951,7 +1041,8 @@ public: virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch; deferInfo.mergeId = mEntry ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap; deferInfo.mergeable = true; deferInfo.mergeable = state.mMatrix.isPureTranslate() && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque(); } Loading @@ -959,11 +1050,9 @@ private: SkBitmap* mBitmap; Res_png_9patch* mPatch; int mAlpha; SkXfermode::Mode mMode; uint32_t mGenerationId; const Patch* mMesh; AssetAtlas::Entry* mEntry; }; Loading libs/hwui/DisplayListRenderer.cpp +1 −5 Original line number Diff line number Diff line Loading @@ -317,13 +317,9 @@ status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, in status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint) { int alpha; SkXfermode::Mode mode; OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); bitmap = refBitmap(bitmap); addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, alpha, mode)); addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint)); return DrawGlInfo::kStatusDone; } Loading libs/hwui/OpenGLRenderer.cpp +41 −14 Original line number Diff line number Diff line Loading @@ -1191,7 +1191,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { // after we setup drawing in case we need to mess with the // stencil buffer in setupDraw() TextureVertex* mesh = mCaches.getRegionMesh(); GLsizei numQuads = 0; uint32_t numQuads = 0; setupDrawWithTexture(); setupDrawColor(alpha, alpha, alpha, alpha); Loading Loading @@ -2049,6 +2049,11 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform); } /** * Important note: this method is intended to draw batches of bitmaps and * will not set the scissor enable or dirty the current layer, if any. * The caller is responsible for properly dirtying the current layer. */ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices, bool transformed, const Rect& bounds, SkPaint* paint) { mCaches.activeTexture(0); Loading @@ -2071,12 +2076,12 @@ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureV drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(), texture->id, paint != NULL, color, alpha, mode, &vertices[0].position[0], &vertices[0].texture[0], GL_TRIANGLES, bitmapCount * 6, true, true); GL_TRIANGLES, bitmapCount * 6, true, true, false); } else { drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(), texture->id, alpha / 255.0f, mode, texture->blend, &vertices[0].position[0], &vertices[0].texture[0], GL_TRIANGLES, bitmapCount * 6, false, true, 0, true); GL_TRIANGLES, bitmapCount * 6, false, true, 0, true, false); } return DrawGlInfo::kStatusDrew; Loading Loading @@ -2367,10 +2372,6 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint) { int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); if (quickReject(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; } Loading @@ -2379,13 +2380,11 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(), right - left, bottom - top, patch); return drawPatch(bitmap, mesh, entry, left, top, right, bottom, alpha, mode); return drawPatch(bitmap, mesh, entry, left, top, right, bottom, paint); } status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) { status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, SkPaint* paint) { if (quickReject(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; } Loading @@ -2399,6 +2398,10 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, texture->setWrap(GL_CLAMP_TO_EDGE, true); texture->setFilter(GL_LINEAR, true); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); const bool pureTranslate = currentTransform().isPureTranslate(); // Mark the current layer dirty where we are going to draw the patch if (hasLayer() && mesh->hasEmptyQuads) { Loading @@ -2418,8 +2421,6 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, } } alpha *= mSnapshot->alpha; if (CC_LIKELY(pureTranslate)) { const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f); const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f); Loading @@ -2441,6 +2442,32 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, return DrawGlInfo::kStatusDrew; } /** * Important note: this method is intended to draw batches of 9-patch objects and * will not set the scissor enable or dirty the current layer, if any. * The caller is responsible for properly dirtying the current layer. */ status_t OpenGLRenderer::drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry, TextureVertex* vertices, uint32_t indexCount, SkPaint* paint) { mCaches.activeTexture(0); Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap); if (!texture) return DrawGlInfo::kStatusDone; const AutoTexture autoCleanup(texture); texture->setWrap(GL_CLAMP_TO_EDGE, true); texture->setFilter(GL_LINEAR, true); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f, mode, texture->blend, &vertices[0].position[0], &vertices[0].texture[0], GL_TRIANGLES, indexCount, false, true, 0, true, false); return DrawGlInfo::kStatusDrew; } status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint, bool useOffset) { if (!vertexBuffer.getVertexCount()) { Loading libs/hwui/OpenGLRenderer.h +5 −1 Original line number Diff line number Diff line Loading @@ -297,10 +297,12 @@ public: virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint); virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, float* vertices, int* colors, SkPaint* paint); status_t drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry, TextureVertex* vertices, uint32_t indexCount, SkPaint* paint); virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint); status_t drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode); float left, float top, float right, float bottom, SkPaint* paint); virtual status_t drawColor(int color, SkXfermode::Mode mode); virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint); virtual status_t drawRoundRect(float left, float top, float right, float bottom, Loading Loading @@ -1115,6 +1117,8 @@ private: friend class DisplayListRenderer; friend class Layer; friend class TextSetupFunctor; friend class DrawBitmapOp; friend class DrawPatchOp; }; // class OpenGLRenderer Loading libs/hwui/Patch.cpp +13 −13 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// Patch::Patch(): verticesCount(0), indexCount(0), hasEmptyQuads(false) { Patch::Patch(): vertices(NULL), verticesCount(0), indexCount(0), hasEmptyQuads(false) { } Patch::~Patch() { Loading @@ -47,14 +47,14 @@ uint32_t Patch::getSize() const { } TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight, float left, float top, float right, float bottom, const Res_png_9patch* patch) { float width, float height, const Res_png_9patch* patch) { UvMapper mapper; return createMesh(bitmapWidth, bitmapHeight, left, top, right, bottom, mapper, patch); return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch); } TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight, float left, float top, float right, float bottom, const UvMapper& mapper, const Res_png_9patch* patch) { float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) { if (vertices) return vertices; const uint32_t* colors = &patch->colors[0]; const int8_t numColors = patch->numColors; Loading @@ -79,7 +79,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4; if (maxVertices == 0) return NULL; TextureVertex* vertices = new TextureVertex[maxVertices]; vertices = new TextureVertex[maxVertices]; TextureVertex* vertex = vertices; const int32_t* xDivs = patch->xDivs; Loading @@ -101,9 +101,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig } const float xStretchTex = stretchSize; const float fixed = bitmapWidth - stretchSize; const float xStretch = fmaxf(right - left - fixed, 0.0f); const float xStretch = fmaxf(width - fixed, 0.0f); stretchX = xStretch / xStretchTex; rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(right - left, 0.0f) / fixed, 1.0f); rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(width, 0.0f) / fixed, 1.0f); } if (yStretchCount > 0) { Loading @@ -113,9 +113,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig } const float yStretchTex = stretchSize; const float fixed = bitmapHeight - stretchSize; const float yStretch = fmaxf(bottom - top - fixed, 0.0f); const float yStretch = fmaxf(height - fixed, 0.0f); stretchY = yStretch / yStretchTex; rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(bottom - top, 0.0f) / fixed, 1.0f); rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(height, 0.0f) / fixed, 1.0f); } uint32_t quadCount = 0; Loading Loading @@ -144,7 +144,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig if (stepY > 0.0f) { generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX, right - left, bitmapWidth, quadCount); width, bitmapWidth, quadCount); } y1 = y2; Loading @@ -154,9 +154,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig } if (previousStepY != bitmapHeight) { y2 = bottom - top; y2 = height; generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX, right - left, bitmapWidth, quadCount); width, bitmapWidth, quadCount); } return vertices; Loading Loading
libs/hwui/DisplayListOp.h +102 −13 Original line number Diff line number Diff line Loading @@ -751,12 +751,18 @@ public: TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \ texCoordsRect.xDim, texCoordsRect.yDim) /** * This multi-draw operation builds a mesh on the stack by generating a quad * for each bitmap in the batch. This method is also responsible for dirtying * the current layer, if any. */ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, const Vector<DrawOp*>& ops, const Rect& bounds) { renderer.restoreDisplayState(state, true); // restore all but the clip TextureVertex vertices[6 * ops.size()]; TextureVertex* vertex = &vertices[0]; const bool hasLayer = renderer.hasLayer(); bool transformed = false; // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, Loading @@ -778,6 +784,11 @@ public: SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom); if (hasLayer) { const Rect& dirty = ops[i]->state.mBounds; renderer.dirtyLayer(dirty.left, dirty.top, dirty.right, dirty.bottom); } } return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], Loading Loading @@ -921,25 +932,104 @@ private: class DrawPatchOp : public DrawBoundedOp { public: DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) : DrawBoundedOp(left, top, right, bottom, 0), mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode), mGenerationId(0), mMesh(NULL) { float left, float top, float right, float bottom, SkPaint* paint) : DrawBoundedOp(left, top, right, bottom, paint), mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL) { mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap); }; virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { const Patch* getMesh(OpenGLRenderer& renderer) { if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) { PatchCache& cache = renderer.getCaches().patchCache; mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(), mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top, mPatch); mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch); mGenerationId = cache.getGenerationId(); } return mMesh; } /** * This multi-draw operation builds an indexed mesh on the stack by copying * and transforming the vertices of each 9-patch in the batch. This method * is also responsible for dirtying the current layer, if any. */ virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, const Vector<DrawOp*>& ops, const Rect& bounds) { renderer.restoreDisplayState(state, true); // Batches will usually contain a small number of items so it's // worth performing a first iteration to count the exact number // of vertices we need in the new mesh uint32_t totalVertices = 0; for (unsigned int i = 0; i < ops.size(); i++) { totalVertices += ((DrawPatchOp*) ops[i])->getMesh(renderer)->verticesCount; } const bool hasLayer = renderer.hasLayer(); uint32_t indexCount = 0; TextureVertex vertices[totalVertices]; TextureVertex* vertex = &vertices[0]; // Create a mesh that contains the transformed vertices for all the // 9-patch objects that are part of the batch. Note that onDefer() // enforces ops drawn by this function to have a pure translate or // identity matrix for (unsigned int i = 0; i < ops.size(); i++) { DrawPatchOp* patchOp = (DrawPatchOp*) ops[i]; const Patch* opMesh = patchOp->getMesh(renderer); uint32_t vertexCount = opMesh->verticesCount; if (vertexCount == 0) continue; // We use the bounds to know where to translate our vertices // Using patchOp->state.mBounds wouldn't work because these // bounds are clipped const float tx = (int) floorf(patchOp->state.mMatrix.getTranslateX() + patchOp->mLocalBounds.left + 0.5f); const float ty = (int) floorf(patchOp->state.mMatrix.getTranslateY() + patchOp->mLocalBounds.top + 0.5f); // Copy & transform all the vertices for the current operation TextureVertex* opVertices = opMesh->vertices; for (uint32_t j = 0; j < vertexCount; j++, opVertices++) { TextureVertex::set(vertex++, opVertices->position[0] + tx, opVertices->position[1] + ty, opVertices->texture[0], opVertices->texture[1]); } // Dirty the current layer if possible. When the 9-patch does not // contain empty quads we can take a shortcut and simply set the // dirty rect to the object's bounds. if (hasLayer) { if (!opMesh->hasEmptyQuads) { renderer.dirtyLayer(tx, ty, tx + patchOp->mLocalBounds.getWidth(), ty + patchOp->mLocalBounds.getHeight()); } else { const size_t count = opMesh->quads.size(); for (size_t i = 0; i < count; i++) { const Rect& quadBounds = opMesh->quads[i]; const float x = tx + quadBounds.left; const float y = ty + quadBounds.top; renderer.dirtyLayer(x, y, x + quadBounds.getWidth(), y + quadBounds.getHeight()); } } } indexCount += opMesh->indexCount; } return renderer.drawPatches(mBitmap, mEntry, &vertices[0], indexCount, getPaint(renderer)); } virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { // We're not calling the public variant of drawPatch() here // This method won't perform the quickReject() since we've already done it at this point return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode); return renderer.drawPatch(mBitmap, getMesh(renderer), mEntry, mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); } virtual void output(int level, uint32_t logFlags) const { Loading @@ -951,7 +1041,8 @@ public: virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch; deferInfo.mergeId = mEntry ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap; deferInfo.mergeable = true; deferInfo.mergeable = state.mMatrix.isPureTranslate() && OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque(); } Loading @@ -959,11 +1050,9 @@ private: SkBitmap* mBitmap; Res_png_9patch* mPatch; int mAlpha; SkXfermode::Mode mMode; uint32_t mGenerationId; const Patch* mMesh; AssetAtlas::Entry* mEntry; }; Loading
libs/hwui/DisplayListRenderer.cpp +1 −5 Original line number Diff line number Diff line Loading @@ -317,13 +317,9 @@ status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, in status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint) { int alpha; SkXfermode::Mode mode; OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode); bitmap = refBitmap(bitmap); addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, alpha, mode)); addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint)); return DrawGlInfo::kStatusDone; } Loading
libs/hwui/OpenGLRenderer.cpp +41 −14 Original line number Diff line number Diff line Loading @@ -1191,7 +1191,7 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { // after we setup drawing in case we need to mess with the // stencil buffer in setupDraw() TextureVertex* mesh = mCaches.getRegionMesh(); GLsizei numQuads = 0; uint32_t numQuads = 0; setupDrawWithTexture(); setupDrawColor(alpha, alpha, alpha, alpha); Loading Loading @@ -2049,6 +2049,11 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform); } /** * Important note: this method is intended to draw batches of bitmaps and * will not set the scissor enable or dirty the current layer, if any. * The caller is responsible for properly dirtying the current layer. */ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureVertex* vertices, bool transformed, const Rect& bounds, SkPaint* paint) { mCaches.activeTexture(0); Loading @@ -2071,12 +2076,12 @@ status_t OpenGLRenderer::drawBitmaps(SkBitmap* bitmap, int bitmapCount, TextureV drawAlpha8TextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(), texture->id, paint != NULL, color, alpha, mode, &vertices[0].position[0], &vertices[0].texture[0], GL_TRIANGLES, bitmapCount * 6, true, true); GL_TRIANGLES, bitmapCount * 6, true, true, false); } else { drawTextureMesh(x, y, x + bounds.getWidth(), y + bounds.getHeight(), texture->id, alpha / 255.0f, mode, texture->blend, &vertices[0].position[0], &vertices[0].texture[0], GL_TRIANGLES, bitmapCount * 6, false, true, 0, true); GL_TRIANGLES, bitmapCount * 6, false, true, 0, true, false); } return DrawGlInfo::kStatusDrew; Loading Loading @@ -2367,10 +2372,6 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint) { int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); if (quickReject(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; } Loading @@ -2379,13 +2380,11 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, const Patch* mesh = mCaches.patchCache.get(entry, bitmap->width(), bitmap->height(), right - left, bottom - top, patch); return drawPatch(bitmap, mesh, entry, left, top, right, bottom, alpha, mode); return drawPatch(bitmap, mesh, entry, left, top, right, bottom, paint); } status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) { status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, SkPaint* paint) { if (quickReject(left, top, right, bottom)) { return DrawGlInfo::kStatusDone; } Loading @@ -2399,6 +2398,10 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, texture->setWrap(GL_CLAMP_TO_EDGE, true); texture->setFilter(GL_LINEAR, true); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); const bool pureTranslate = currentTransform().isPureTranslate(); // Mark the current layer dirty where we are going to draw the patch if (hasLayer() && mesh->hasEmptyQuads) { Loading @@ -2418,8 +2421,6 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, } } alpha *= mSnapshot->alpha; if (CC_LIKELY(pureTranslate)) { const float x = (int) floorf(left + currentTransform().getTranslateX() + 0.5f); const float y = (int) floorf(top + currentTransform().getTranslateY() + 0.5f); Loading @@ -2441,6 +2442,32 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const Patch* mesh, return DrawGlInfo::kStatusDrew; } /** * Important note: this method is intended to draw batches of 9-patch objects and * will not set the scissor enable or dirty the current layer, if any. * The caller is responsible for properly dirtying the current layer. */ status_t OpenGLRenderer::drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry, TextureVertex* vertices, uint32_t indexCount, SkPaint* paint) { mCaches.activeTexture(0); Texture* texture = entry ? entry->texture : mCaches.textureCache.get(bitmap); if (!texture) return DrawGlInfo::kStatusDone; const AutoTexture autoCleanup(texture); texture->setWrap(GL_CLAMP_TO_EDGE, true); texture->setFilter(GL_LINEAR, true); int alpha; SkXfermode::Mode mode; getAlphaAndMode(paint, &alpha, &mode); drawIndexedTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f, mode, texture->blend, &vertices[0].position[0], &vertices[0].texture[0], GL_TRIANGLES, indexCount, false, true, 0, true, false); return DrawGlInfo::kStatusDrew; } status_t OpenGLRenderer::drawVertexBuffer(const VertexBuffer& vertexBuffer, SkPaint* paint, bool useOffset) { if (!vertexBuffer.getVertexCount()) { Loading
libs/hwui/OpenGLRenderer.h +5 −1 Original line number Diff line number Diff line Loading @@ -297,10 +297,12 @@ public: virtual status_t drawBitmapData(SkBitmap* bitmap, float left, float top, SkPaint* paint); virtual status_t drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight, float* vertices, int* colors, SkPaint* paint); status_t drawPatches(SkBitmap* bitmap, AssetAtlas::Entry* entry, TextureVertex* vertices, uint32_t indexCount, SkPaint* paint); virtual status_t drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, float left, float top, float right, float bottom, SkPaint* paint); status_t drawPatch(SkBitmap* bitmap, const Patch* mesh, AssetAtlas::Entry* entry, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode); float left, float top, float right, float bottom, SkPaint* paint); virtual status_t drawColor(int color, SkXfermode::Mode mode); virtual status_t drawRect(float left, float top, float right, float bottom, SkPaint* paint); virtual status_t drawRoundRect(float left, float top, float right, float bottom, Loading Loading @@ -1115,6 +1117,8 @@ private: friend class DisplayListRenderer; friend class Layer; friend class TextSetupFunctor; friend class DrawBitmapOp; friend class DrawPatchOp; }; // class OpenGLRenderer Loading
libs/hwui/Patch.cpp +13 −13 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// Patch::Patch(): verticesCount(0), indexCount(0), hasEmptyQuads(false) { Patch::Patch(): vertices(NULL), verticesCount(0), indexCount(0), hasEmptyQuads(false) { } Patch::~Patch() { Loading @@ -47,14 +47,14 @@ uint32_t Patch::getSize() const { } TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight, float left, float top, float right, float bottom, const Res_png_9patch* patch) { float width, float height, const Res_png_9patch* patch) { UvMapper mapper; return createMesh(bitmapWidth, bitmapHeight, left, top, right, bottom, mapper, patch); return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch); } TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight, float left, float top, float right, float bottom, const UvMapper& mapper, const Res_png_9patch* patch) { float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) { if (vertices) return vertices; const uint32_t* colors = &patch->colors[0]; const int8_t numColors = patch->numColors; Loading @@ -79,7 +79,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4; if (maxVertices == 0) return NULL; TextureVertex* vertices = new TextureVertex[maxVertices]; vertices = new TextureVertex[maxVertices]; TextureVertex* vertex = vertices; const int32_t* xDivs = patch->xDivs; Loading @@ -101,9 +101,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig } const float xStretchTex = stretchSize; const float fixed = bitmapWidth - stretchSize; const float xStretch = fmaxf(right - left - fixed, 0.0f); const float xStretch = fmaxf(width - fixed, 0.0f); stretchX = xStretch / xStretchTex; rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(right - left, 0.0f) / fixed, 1.0f); rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(width, 0.0f) / fixed, 1.0f); } if (yStretchCount > 0) { Loading @@ -113,9 +113,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig } const float yStretchTex = stretchSize; const float fixed = bitmapHeight - stretchSize; const float yStretch = fmaxf(bottom - top - fixed, 0.0f); const float yStretch = fmaxf(height - fixed, 0.0f); stretchY = yStretch / yStretchTex; rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(bottom - top, 0.0f) / fixed, 1.0f); rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(height, 0.0f) / fixed, 1.0f); } uint32_t quadCount = 0; Loading Loading @@ -144,7 +144,7 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig if (stepY > 0.0f) { generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX, right - left, bitmapWidth, quadCount); width, bitmapWidth, quadCount); } y1 = y2; Loading @@ -154,9 +154,9 @@ TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeig } if (previousStepY != bitmapHeight) { y2 = bottom - top; y2 = height; generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX, right - left, bitmapWidth, quadCount); width, bitmapWidth, quadCount); } return vertices; Loading