Loading libs/hwui/LayerCache.cpp +47 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <GLES2/gl2.h> #include <utils/Log.h> #include "LayerCache.h" namespace android { Loading Loading @@ -84,11 +86,55 @@ void LayerCache::clear() { mCache.setOnEntryRemovedListener(NULL); } Layer* LayerCache::get(LayerSize& size) { Layer* LayerCache::get(LayerSize& size, GLuint previousFbo) { Layer* layer = mCache.remove(size); if (layer) { LAYER_LOGD("Reusing layer"); mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4; } else { LAYER_LOGD("Creating new layer"); layer = new Layer; layer->blend = true; // Generate the FBO and attach the texture glGenFramebuffers(1, &layer->fbo); glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); // Generate the texture in which the FBO will draw glGenTextures(1, &layer->texture); glBindTexture(GL_TEXTURE_2D, layer->texture); // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); // Bind texture to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->texture, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGE("Framebuffer incomplete (GL error code 0x%x)", status); glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; return NULL; } } return layer; } Loading libs/hwui/LayerCache.h +32 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,24 @@ namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// // Debug #define DEBUG_LAYERS 0 // Debug #if DEBUG_LAYERS #define LAYER_LOGD(...) LOGD(__VA_ARGS__) #else #define LAYER_LOGD(...) #endif /////////////////////////////////////////////////////////////////////////////// // Cache /////////////////////////////////////////////////////////////////////////////// class LayerCache: public OnEntryRemoved<LayerSize, Layer*> { public: LayerCache(uint32_t maxByteSize); Loading @@ -35,13 +53,25 @@ public: void operator()(LayerSize& bitmap, Layer*& texture); /** * Returns the layer of specified dimensions, NULL if cannot be found. * Returns the layer of specified dimensions. If not suitable layer * can be found, a new one is created and returned. If creating a new * layer fails, NULL is returned. * * When a layer is obtained from the cache, it is removed and the total * size of the cache goes down. * * @param size The dimensions of the desired layer * @param previousFbo The name of the FBO to bind to if creating a new * layer fails */ Layer* get(LayerSize& size); Layer* get(LayerSize& size, GLuint previousFbo); /** * Adds the layer to the cache. The layer will not be added if there is * not enough space available. * * @param size The dimensions of the layer * @param layer The layer to add to the cache * * @return True if the layer was added, false otherwise. */ bool put(LayerSize& size, Layer* layer); Loading libs/hwui/OpenGLRenderer.cpp +10 −61 Original line number Diff line number Diff line Loading @@ -34,9 +34,6 @@ namespace uirenderer { // Defines /////////////////////////////////////////////////////////////////////////////// // Debug #define DEBUG_LAYERS 0 // These properties are defined in mega-bytes #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size" #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size" Loading @@ -51,13 +48,6 @@ namespace uirenderer { #define SV(x, y) { { x, y } } #define FV(x, y, u, v) { { x, y }, { u, v } } // Debug #if DEBUG_LAYERS #define LAYER_LOGD(...) LOGD(__VA_ARGS__) #else #define LAYER_LOGD(...) #endif /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -253,6 +243,8 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { layer->texture, layer->alpha, layer->mode, layer->blend, true); LayerSize size(rect.getWidth(), rect.getHeight()); // Failing to add the layer to the cache should happen only if the // layer is too large if (!mLayerCache.put(size, layer)) { LAYER_LOGD("Deleting layer"); Loading Loading @@ -300,62 +292,19 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) { LayerSize size(right - left, bottom - top); Layer* layer = mLayerCache.get(size); LAYER_LOGD("Requesting layer %dx%d", size.width, size.height); LAYER_LOGD("Layer cache size = %d", mLayerCache.getSize()); if (!layer) { LAYER_LOGD("Creating new layer"); layer = new Layer; layer->blend = true; // Generate the FBO and attach the texture glGenFramebuffers(1, &layer->fbo); glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); // Generate the texture in which the FBO will draw glGenTextures(1, &layer->texture); glBindTexture(GL_TEXTURE_2D, layer->texture); // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // TODO VERY IMPORTANT: Fix TextView to not call saveLayer() all the time const GLsizei width = right - left; const GLsizei height = bottom - top; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); // Bind texture to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->texture, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGD("Framebuffer incomplete (GL error code 0x%x)", status); GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0; glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; 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; } } else { LAYER_LOGD("Reusing layer"); glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); } // Clear the FBO glDisable(GL_SCISSOR_TEST); Loading Loading
libs/hwui/LayerCache.cpp +47 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ #include <GLES2/gl2.h> #include <utils/Log.h> #include "LayerCache.h" namespace android { Loading Loading @@ -84,11 +86,55 @@ void LayerCache::clear() { mCache.setOnEntryRemovedListener(NULL); } Layer* LayerCache::get(LayerSize& size) { Layer* LayerCache::get(LayerSize& size, GLuint previousFbo) { Layer* layer = mCache.remove(size); if (layer) { LAYER_LOGD("Reusing layer"); mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4; } else { LAYER_LOGD("Creating new layer"); layer = new Layer; layer->blend = true; // Generate the FBO and attach the texture glGenFramebuffers(1, &layer->fbo); glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); // Generate the texture in which the FBO will draw glGenTextures(1, &layer->texture); glBindTexture(GL_TEXTURE_2D, layer->texture); // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width, size.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); // Bind texture to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->texture, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGE("Framebuffer incomplete (GL error code 0x%x)", status); glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; return NULL; } } return layer; } Loading
libs/hwui/LayerCache.h +32 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,24 @@ namespace android { namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// // Debug #define DEBUG_LAYERS 0 // Debug #if DEBUG_LAYERS #define LAYER_LOGD(...) LOGD(__VA_ARGS__) #else #define LAYER_LOGD(...) #endif /////////////////////////////////////////////////////////////////////////////// // Cache /////////////////////////////////////////////////////////////////////////////// class LayerCache: public OnEntryRemoved<LayerSize, Layer*> { public: LayerCache(uint32_t maxByteSize); Loading @@ -35,13 +53,25 @@ public: void operator()(LayerSize& bitmap, Layer*& texture); /** * Returns the layer of specified dimensions, NULL if cannot be found. * Returns the layer of specified dimensions. If not suitable layer * can be found, a new one is created and returned. If creating a new * layer fails, NULL is returned. * * When a layer is obtained from the cache, it is removed and the total * size of the cache goes down. * * @param size The dimensions of the desired layer * @param previousFbo The name of the FBO to bind to if creating a new * layer fails */ Layer* get(LayerSize& size); Layer* get(LayerSize& size, GLuint previousFbo); /** * Adds the layer to the cache. The layer will not be added if there is * not enough space available. * * @param size The dimensions of the layer * @param layer The layer to add to the cache * * @return True if the layer was added, false otherwise. */ bool put(LayerSize& size, Layer* layer); Loading
libs/hwui/OpenGLRenderer.cpp +10 −61 Original line number Diff line number Diff line Loading @@ -34,9 +34,6 @@ namespace uirenderer { // Defines /////////////////////////////////////////////////////////////////////////////// // Debug #define DEBUG_LAYERS 0 // These properties are defined in mega-bytes #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size" #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size" Loading @@ -51,13 +48,6 @@ namespace uirenderer { #define SV(x, y) { { x, y } } #define FV(x, y, u, v) { { x, y }, { u, v } } // Debug #if DEBUG_LAYERS #define LAYER_LOGD(...) LOGD(__VA_ARGS__) #else #define LAYER_LOGD(...) #endif /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -253,6 +243,8 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { layer->texture, layer->alpha, layer->mode, layer->blend, true); LayerSize size(rect.getWidth(), rect.getHeight()); // Failing to add the layer to the cache should happen only if the // layer is too large if (!mLayerCache.put(size, layer)) { LAYER_LOGD("Deleting layer"); Loading Loading @@ -300,62 +292,19 @@ int OpenGLRenderer::saveLayerAlpha(float left, float top, float right, float bot bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode,int flags) { LayerSize size(right - left, bottom - top); Layer* layer = mLayerCache.get(size); LAYER_LOGD("Requesting layer %dx%d", size.width, size.height); LAYER_LOGD("Layer cache size = %d", mLayerCache.getSize()); if (!layer) { LAYER_LOGD("Creating new layer"); layer = new Layer; layer->blend = true; // Generate the FBO and attach the texture glGenFramebuffers(1, &layer->fbo); glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); // Generate the texture in which the FBO will draw glGenTextures(1, &layer->texture); glBindTexture(GL_TEXTURE_2D, layer->texture); // The FBO will not be scaled, so we can use lower quality filtering glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // TODO VERY IMPORTANT: Fix TextView to not call saveLayer() all the time const GLsizei width = right - left; const GLsizei height = bottom - top; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, 0); // Bind texture to FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->texture, 0); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { LOGD("Framebuffer incomplete (GL error code 0x%x)", status); GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0; glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; 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; } } else { LAYER_LOGD("Reusing layer"); glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); } // Clear the FBO glDisable(GL_SCISSOR_TEST); Loading