Loading libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) PatchCache.cpp \ PathCache.cpp \ PathTessellator.cpp \ PixelBuffer.cpp \ Program.cpp \ ProgramCache.cpp \ RenderBufferCache.cpp \ Loading libs/hwui/Caches.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ void Caches::init() { mCurrentPositionPointer = this; mCurrentPositionStride = 0; mCurrentTexCoordsPointer = this; mCurrentPixelBuffer = 0; mTexCoordsArrayEnabled = false; Loading Loading @@ -365,6 +366,28 @@ bool Caches::unbindIndicesBuffer() { return false; } /////////////////////////////////////////////////////////////////////////////// // PBO /////////////////////////////////////////////////////////////////////////////// bool Caches::bindPixelBuffer(const GLuint buffer) { if (mCurrentPixelBuffer != buffer) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); mCurrentPixelBuffer = buffer; return true; } return false; } bool Caches::unbindPixelBuffer() { if (mCurrentPixelBuffer) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); mCurrentPixelBuffer = 0; return true; } return false; } /////////////////////////////////////////////////////////////////////////////// // Meshes and textures /////////////////////////////////////////////////////////////////////////////// Loading libs/hwui/Caches.h +11 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,16 @@ public: bool bindIndicesBuffer(const GLuint buffer); bool unbindIndicesBuffer(); /** * Binds the specified buffer as the current GL unpack pixel buffer. */ bool bindPixelBuffer(const GLuint buffer); /** * Resets the current unpack pixel buffer to 0 (default value.) */ bool unbindPixelBuffer(); /** * Binds an attrib to the specified float vertex pointer. * Assumes a stride of gMeshStride and a size of 2. Loading Loading @@ -307,6 +317,7 @@ private: GLuint mCurrentBuffer; GLuint mCurrentIndicesBuffer; GLuint mCurrentPixelBuffer; void* mCurrentPositionPointer; GLsizei mCurrentPositionStride; void* mCurrentTexCoordsPointer; Loading libs/hwui/DeferredDisplayList.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <utils/Trace.h> #include "Caches.h" #include "Debug.h" #include "DisplayListOp.h" #include "OpenGLRenderer.h" Loading Loading @@ -377,6 +378,8 @@ static status_t replayBatchList(Vector<DrawOpBatch*>& batchList, status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) { ATRACE_NAME("flush drawing commands"); Caches::getInstance().fontRenderer->endPrecaching(); status_t status = DrawGlInfo::kStatusDone; if (isEmpty()) return status; // nothing to flush Loading libs/hwui/FontRenderer.cpp +42 −51 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "Debug.h" #include "Extensions.h" #include "FontRenderer.h" #include "PixelBuffer.h" #include "Rect.h" namespace android { Loading Loading @@ -133,26 +134,13 @@ void FontRenderer::flushAllAndInvalidate() { for (uint32_t i = 0; i < mCacheTextures.size(); i++) { mCacheTextures[i]->init(); } #if DEBUG_FONT_RENDERER uint16_t totalGlyphs = 0; for (uint32_t i = 0; i < mCacheTextures.size(); i++) { totalGlyphs += mCacheTextures[i]->getGlyphCount(); // Erase caches, just as a debugging facility if (mCacheTextures[i]->getTexture()) { memset(mCacheTextures[i]->getTexture(), 0, mCacheTextures[i]->getWidth() * mCacheTextures[i]->getHeight()); } } ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs); #endif } void FontRenderer::flushLargeCaches() { // Start from 1; don't deallocate smallest/default texture for (uint32_t i = 1; i < mCacheTextures.size(); i++) { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture->getTexture()) { if (cacheTexture->getPixelBuffer()) { cacheTexture->init(); LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); while (it.next()) { Loading Loading @@ -226,7 +214,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp uint32_t cacheWidth = cacheTexture->getWidth(); if (!cacheTexture->getTexture()) { if (!cacheTexture->getPixelBuffer()) { Caches::getInstance().activeTexture(0); // Large-glyph texture memory is allocated only as needed cacheTexture->allocateTexture(); Loading @@ -239,7 +227,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp // or anti-aliased (8 bits per pixel) SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); uint8_t* cacheBuffer = cacheTexture->getTexture(); uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; // Copy the glyph image, taking the mask format into account Loading Loading @@ -377,56 +365,36 @@ void FontRenderer::checkTextureUpdate() { Caches& caches = Caches::getInstance(); GLuint lastTextureId = 0; // OpenGL ES 3.0+ lets us specify the row length for unpack operations such // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. // With OpenGL ES 2.0 we have to upload entire stripes instead. const bool hasUnpackRowLength = Extensions::getInstance().getMajorGlVersion() >= 3; bool resetPixelStore = false; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Iterate over all the cache textures and see which ones need to be updated for (uint32_t i = 0; i < mCacheTextures.size(); i++) { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture->isDirty() && cacheTexture->getTexture()) { const Rect* dirtyRect = cacheTexture->getDirtyRect(); uint32_t x = hasUnpackRowLength ? dirtyRect->left : 0; uint32_t y = dirtyRect->top; uint32_t width = cacheTexture->getWidth(); uint32_t height = dirtyRect->getHeight(); void* textureData = cacheTexture->getTexture() + y * width + x; if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { if (cacheTexture->getTextureId() != lastTextureId) { lastTextureId = cacheTexture->getTextureId(); caches.activeTexture(0); glBindTexture(GL_TEXTURE_2D, lastTextureId); // The unpack row length only needs to be specified when a new // texture is bound if (hasUnpackRowLength) { glPixelStorei(GL_UNPACK_ROW_LENGTH, width); } } // If we can upload a sub-rectangle, use the dirty rect width // instead of the width of the entire texture if (hasUnpackRowLength) { width = dirtyRect->getWidth(); if (cacheTexture->upload()) { resetPixelStore = true; } #if DEBUG_FONT_RENDERER ALOGD("glTexSubimage for cacheTexture %d: x, y, width height = %d, %d, %d, %d", i, x, y, width, height); #endif glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, textureData); cacheTexture->setDirty(false); } } // Unbind any PBO we might have used to update textures caches.unbindPixelBuffer(); // Reset to default unpack row length to avoid affecting texture // uploads in other parts of the renderer if (hasUnpackRowLength) { if (resetPixelStore) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } Loading Loading @@ -539,13 +507,14 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) { checkInit(); if (!mCurrentFont) { DropShadow image; image.width = 0; image.height = 0; image.image = NULL; image.penX = 0; image.penY = 0; if (!mCurrentFont) { return image; } Loading @@ -559,6 +528,11 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; uint32_t maxSize = Caches::getInstance().maxTextureSize; if (paddedWidth > maxSize || paddedHeight > maxSize) { return image; } // Align buffers for renderscript usage if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; Loading @@ -578,10 +552,12 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); // Unbind any PBO we might have used Caches::getInstance().unbindPixelBuffer(); blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); } DropShadow image; image.width = paddedWidth; image.height = paddedHeight; image.image = dataBuffer; Loading Loading @@ -612,6 +588,10 @@ void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, con font->precache(paint, text, numGlyphs); } void FontRenderer::endPrecaching() { checkTextureUpdate(); } bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds, Functor* functor) { Loading Loading @@ -690,5 +670,16 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int *image = outImage; } uint32_t FontRenderer::getCacheSize() const { uint32_t size = 0; for (uint32_t i = 0; i < mCacheTextures.size(); i++) { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture && cacheTexture->getPixelBuffer()) { size += cacheTexture->getPixelBuffer()->getSize(); } } return size; } }; // namespace uirenderer }; // namespace android Loading
libs/hwui/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) PatchCache.cpp \ PathCache.cpp \ PathTessellator.cpp \ PixelBuffer.cpp \ Program.cpp \ ProgramCache.cpp \ RenderBufferCache.cpp \ Loading
libs/hwui/Caches.cpp +23 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ void Caches::init() { mCurrentPositionPointer = this; mCurrentPositionStride = 0; mCurrentTexCoordsPointer = this; mCurrentPixelBuffer = 0; mTexCoordsArrayEnabled = false; Loading Loading @@ -365,6 +366,28 @@ bool Caches::unbindIndicesBuffer() { return false; } /////////////////////////////////////////////////////////////////////////////// // PBO /////////////////////////////////////////////////////////////////////////////// bool Caches::bindPixelBuffer(const GLuint buffer) { if (mCurrentPixelBuffer != buffer) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer); mCurrentPixelBuffer = buffer; return true; } return false; } bool Caches::unbindPixelBuffer() { if (mCurrentPixelBuffer) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); mCurrentPixelBuffer = 0; return true; } return false; } /////////////////////////////////////////////////////////////////////////////// // Meshes and textures /////////////////////////////////////////////////////////////////////////////// Loading
libs/hwui/Caches.h +11 −0 Original line number Diff line number Diff line Loading @@ -175,6 +175,16 @@ public: bool bindIndicesBuffer(const GLuint buffer); bool unbindIndicesBuffer(); /** * Binds the specified buffer as the current GL unpack pixel buffer. */ bool bindPixelBuffer(const GLuint buffer); /** * Resets the current unpack pixel buffer to 0 (default value.) */ bool unbindPixelBuffer(); /** * Binds an attrib to the specified float vertex pointer. * Assumes a stride of gMeshStride and a size of 2. Loading Loading @@ -307,6 +317,7 @@ private: GLuint mCurrentBuffer; GLuint mCurrentIndicesBuffer; GLuint mCurrentPixelBuffer; void* mCurrentPositionPointer; GLsizei mCurrentPositionStride; void* mCurrentTexCoordsPointer; Loading
libs/hwui/DeferredDisplayList.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <utils/Trace.h> #include "Caches.h" #include "Debug.h" #include "DisplayListOp.h" #include "OpenGLRenderer.h" Loading Loading @@ -377,6 +378,8 @@ static status_t replayBatchList(Vector<DrawOpBatch*>& batchList, status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty) { ATRACE_NAME("flush drawing commands"); Caches::getInstance().fontRenderer->endPrecaching(); status_t status = DrawGlInfo::kStatusDone; if (isEmpty()) return status; // nothing to flush Loading
libs/hwui/FontRenderer.cpp +42 −51 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include "Debug.h" #include "Extensions.h" #include "FontRenderer.h" #include "PixelBuffer.h" #include "Rect.h" namespace android { Loading Loading @@ -133,26 +134,13 @@ void FontRenderer::flushAllAndInvalidate() { for (uint32_t i = 0; i < mCacheTextures.size(); i++) { mCacheTextures[i]->init(); } #if DEBUG_FONT_RENDERER uint16_t totalGlyphs = 0; for (uint32_t i = 0; i < mCacheTextures.size(); i++) { totalGlyphs += mCacheTextures[i]->getGlyphCount(); // Erase caches, just as a debugging facility if (mCacheTextures[i]->getTexture()) { memset(mCacheTextures[i]->getTexture(), 0, mCacheTextures[i]->getWidth() * mCacheTextures[i]->getHeight()); } } ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs); #endif } void FontRenderer::flushLargeCaches() { // Start from 1; don't deallocate smallest/default texture for (uint32_t i = 1; i < mCacheTextures.size(); i++) { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture->getTexture()) { if (cacheTexture->getPixelBuffer()) { cacheTexture->init(); LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); while (it.next()) { Loading Loading @@ -226,7 +214,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp uint32_t cacheWidth = cacheTexture->getWidth(); if (!cacheTexture->getTexture()) { if (!cacheTexture->getPixelBuffer()) { Caches::getInstance().activeTexture(0); // Large-glyph texture memory is allocated only as needed cacheTexture->allocateTexture(); Loading @@ -239,7 +227,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp // or anti-aliased (8 bits per pixel) SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); uint8_t* cacheBuffer = cacheTexture->getTexture(); uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; // Copy the glyph image, taking the mask format into account Loading Loading @@ -377,56 +365,36 @@ void FontRenderer::checkTextureUpdate() { Caches& caches = Caches::getInstance(); GLuint lastTextureId = 0; // OpenGL ES 3.0+ lets us specify the row length for unpack operations such // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. // With OpenGL ES 2.0 we have to upload entire stripes instead. const bool hasUnpackRowLength = Extensions::getInstance().getMajorGlVersion() >= 3; bool resetPixelStore = false; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Iterate over all the cache textures and see which ones need to be updated for (uint32_t i = 0; i < mCacheTextures.size(); i++) { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture->isDirty() && cacheTexture->getTexture()) { const Rect* dirtyRect = cacheTexture->getDirtyRect(); uint32_t x = hasUnpackRowLength ? dirtyRect->left : 0; uint32_t y = dirtyRect->top; uint32_t width = cacheTexture->getWidth(); uint32_t height = dirtyRect->getHeight(); void* textureData = cacheTexture->getTexture() + y * width + x; if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { if (cacheTexture->getTextureId() != lastTextureId) { lastTextureId = cacheTexture->getTextureId(); caches.activeTexture(0); glBindTexture(GL_TEXTURE_2D, lastTextureId); // The unpack row length only needs to be specified when a new // texture is bound if (hasUnpackRowLength) { glPixelStorei(GL_UNPACK_ROW_LENGTH, width); } } // If we can upload a sub-rectangle, use the dirty rect width // instead of the width of the entire texture if (hasUnpackRowLength) { width = dirtyRect->getWidth(); if (cacheTexture->upload()) { resetPixelStore = true; } #if DEBUG_FONT_RENDERER ALOGD("glTexSubimage for cacheTexture %d: x, y, width height = %d, %d, %d, %d", i, x, y, width, height); #endif glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, textureData); cacheTexture->setDirty(false); } } // Unbind any PBO we might have used to update textures caches.unbindPixelBuffer(); // Reset to default unpack row length to avoid affecting texture // uploads in other parts of the renderer if (hasUnpackRowLength) { if (resetPixelStore) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } Loading Loading @@ -539,13 +507,14 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) { checkInit(); if (!mCurrentFont) { DropShadow image; image.width = 0; image.height = 0; image.image = NULL; image.penX = 0; image.penY = 0; if (!mCurrentFont) { return image; } Loading @@ -559,6 +528,11 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; uint32_t maxSize = Caches::getInstance().maxTextureSize; if (paddedWidth > maxSize || paddedHeight > maxSize) { return image; } // Align buffers for renderscript usage if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; Loading @@ -578,10 +552,12 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); // Unbind any PBO we might have used Caches::getInstance().unbindPixelBuffer(); blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); } DropShadow image; image.width = paddedWidth; image.height = paddedHeight; image.image = dataBuffer; Loading Loading @@ -612,6 +588,10 @@ void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, con font->precache(paint, text, numGlyphs); } void FontRenderer::endPrecaching() { checkTextureUpdate(); } bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, const float* positions, Rect* bounds, Functor* functor) { Loading Loading @@ -690,5 +670,16 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int *image = outImage; } uint32_t FontRenderer::getCacheSize() const { uint32_t size = 0; for (uint32_t i = 0; i < mCacheTextures.size(); i++) { CacheTexture* cacheTexture = mCacheTextures[i]; if (cacheTexture && cacheTexture->getPixelBuffer()) { size += cacheTexture->getPixelBuffer()->getSize(); } } return size; } }; // namespace uirenderer }; // namespace android