diff options
author | Romain Guy <romainguy@google.com> | 2010-07-08 11:45:51 -0700 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2010-07-08 11:45:51 -0700 |
commit | f18fd99b5c182329cd8936a9611f0103d8ece44a (patch) | |
tree | c32def6bcb82e2a2019a5a49744dfa34c94d8d81 /libs | |
parent | 132f22590a3cd27ce15a705bdb481675e8fd02bc (diff) | |
download | frameworks_base-f18fd99b5c182329cd8936a9611f0103d8ece44a.zip frameworks_base-f18fd99b5c182329cd8936a9611f0103d8ece44a.tar.gz frameworks_base-f18fd99b5c182329cd8936a9611f0103d8ece44a.tar.bz2 |
Create FBOs in LayerCache.
This moves a bit of code away from OpenGLRenderer and matches
what happens with the TextureCache.
Change-Id: I3c67f54f83d7240770daa015861c0e75a1dd8c42
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/LayerCache.cpp | 48 | ||||
-rw-r--r-- | libs/hwui/LayerCache.h | 34 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 71 |
3 files changed, 89 insertions, 64 deletions
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 882ad83..bcda45e 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -18,6 +18,8 @@ #include <GLES2/gl2.h> +#include <utils/Log.h> + #include "LayerCache.h" namespace android { @@ -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; } diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index 519552d..adc6713 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -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); @@ -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); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ae7719c..027ed79 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -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" @@ -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 /////////////////////////////////////////////////////////////////////////////// @@ -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"); @@ -300,63 +292,20 @@ 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; + GLuint previousFbo = snapshot->previous.get() ? snapshot->previous->fbo : 0; + LayerSize size(right - left, bottom - top); - return false; - } - } else { - LAYER_LOGD("Reusing layer"); - glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); + // TODO VERY IMPORTANT: Fix TextView to not call saveLayer() all the time + Layer* layer = mLayerCache.get(size, previousFbo); + if (!layer) { + return false; } + glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); + // Clear the FBO glDisable(GL_SCISSOR_TEST); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |