Loading libs/hwui/FontRenderer.cpp +31 −4 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include "Caches.h" #include "Debug.h" #include "Extensions.h" #include "FontRenderer.h" #include "Rect.h" Loading Loading @@ -375,34 +376,60 @@ 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; 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()) { // Can't copy inner rect; glTexSubimage expects pointer to deal with entire buffer // of data. So expand the dirty rect to the encompassing horizontal stripe. const Rect* dirtyRect = cacheTexture->getDirtyRect(); uint32_t x = 0; 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; void* textureData = cacheTexture->getTexture() + y * width + x; 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 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); } } // Reset to default unpack row length to avoid affecting texture // uploads in other parts of the renderer if (hasUnpackRowLength) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } mUploadTexture = false; } Loading libs/hwui/Layer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ bool Layer::resize(const uint32_t width, const uint32_t height) { if (fbo) { Caches::getInstance().activeTexture(0); bindTexture(); allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); allocateTexture(); if (glGetError() != GL_NO_ERROR) { setSize(oldWidth, oldHeight); Loading libs/hwui/Layer.h +4 −3 Original line number Diff line number Diff line Loading @@ -255,13 +255,14 @@ struct Layer { texture.id = 0; } inline void allocateTexture(GLenum format, GLenum storage) { inline void allocateTexture() { #if DEBUG_LAYERS ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); #endif if (texture.id) { glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } } Loading libs/hwui/LayerRenderer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -256,7 +256,7 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque // Initialize the texture if needed if (layer->isEmpty()) { layer->setEmpty(false); layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); layer->allocateTexture(); // This should only happen if we run out of memory if (glGetError() != GL_NO_ERROR) { Loading libs/hwui/OpenGLRenderer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -922,7 +922,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLui // Initialize the texture if needed if (layer->isEmpty()) { layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); layer->allocateTexture(); layer->setEmpty(false); } Loading Loading
libs/hwui/FontRenderer.cpp +31 −4 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #include "Caches.h" #include "Debug.h" #include "Extensions.h" #include "FontRenderer.h" #include "Rect.h" Loading Loading @@ -375,34 +376,60 @@ 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; 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()) { // Can't copy inner rect; glTexSubimage expects pointer to deal with entire buffer // of data. So expand the dirty rect to the encompassing horizontal stripe. const Rect* dirtyRect = cacheTexture->getDirtyRect(); uint32_t x = 0; 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; void* textureData = cacheTexture->getTexture() + y * width + x; 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 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); } } // Reset to default unpack row length to avoid affecting texture // uploads in other parts of the renderer if (hasUnpackRowLength) { glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } mUploadTexture = false; } Loading
libs/hwui/Layer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -90,7 +90,7 @@ bool Layer::resize(const uint32_t width, const uint32_t height) { if (fbo) { Caches::getInstance().activeTexture(0); bindTexture(); allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); allocateTexture(); if (glGetError() != GL_NO_ERROR) { setSize(oldWidth, oldHeight); Loading
libs/hwui/Layer.h +4 −3 Original line number Diff line number Diff line Loading @@ -255,13 +255,14 @@ struct Layer { texture.id = 0; } inline void allocateTexture(GLenum format, GLenum storage) { inline void allocateTexture() { #if DEBUG_LAYERS ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); #endif if (texture.id) { glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } } Loading
libs/hwui/LayerRenderer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -256,7 +256,7 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque // Initialize the texture if needed if (layer->isEmpty()) { layer->setEmpty(false); layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); layer->allocateTexture(); // This should only happen if we run out of memory if (glGetError() != GL_NO_ERROR) { Loading
libs/hwui/OpenGLRenderer.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -922,7 +922,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip, GLui // Initialize the texture if needed if (layer->isEmpty()) { layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); layer->allocateTexture(); layer->setEmpty(false); } Loading