diff options
author | Romain Guy <romainguy@google.com> | 2011-02-02 21:05:35 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-02-02 21:05:35 -0800 |
commit | 5bfd1afffe361958682bcb899b763ce35ec00c3a (patch) | |
tree | d54dbfced67448d7f38f82a00bd805976a4a5f4d /libs | |
parent | 1cee14f154aadabcd9990bd73a197fbd744660ad (diff) | |
parent | 09b7c91de73b59aa3f679b3ae3ba299f82ec9f8a (diff) | |
download | frameworks_base-5bfd1afffe361958682bcb899b763ce35ec00c3a.zip frameworks_base-5bfd1afffe361958682bcb899b763ce35ec00c3a.tar.gz frameworks_base-5bfd1afffe361958682bcb899b763ce35ec00c3a.tar.bz2 |
Merge "Allocate layers from the layers pool. Bug #3413433" into honeycomb
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Caches.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/LayerCache.cpp | 25 | ||||
-rw-r--r-- | libs/hwui/LayerCache.h | 11 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 128 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 6 |
5 files changed, 101 insertions, 77 deletions
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index bffab95..ebf7aa0 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -20,6 +20,7 @@ #include "Caches.h" #include "Properties.h" +#include "LayerRenderer.h" namespace android { @@ -116,12 +117,7 @@ void Caches::clearGarbage() { size_t count = mLayerGarbage.size(); for (size_t i = 0; i < count; i++) { Layer* layer = mLayerGarbage.itemAt(i); - if (layer) { - if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo); - if (layer->texture) glDeleteTextures(1, &layer->texture); - - delete layer; - } + LayerRenderer::destroyLayer(layer); } mLayerGarbage.clear(); } diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 7667af5..a9710ad 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -128,6 +128,31 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) { return layer; } +bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) { + // TODO: We should be smarter and see if we have a texture of the appropriate + // size already in the cache, and reuse it instead of creating a new one + + LayerEntry entry(width, height); + if (entry.mWidth <= layer->width && entry.mHeight <= layer->height) { + return true; + } + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, layer->texture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry.mWidth, entry.mHeight, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + if (glGetError() != GL_NO_ERROR) { + return false; + } + + layer->width = entry.mWidth; + layer->height = entry.mHeight; + + return true; +} + bool LayerCache::put(Layer* layer) { const uint32_t size = layer->width * layer->height * 4; // Don't even try to cache a layer that's bigger than the cache diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index 1333a73..d2d5f39 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -76,6 +76,17 @@ public: * Clears the cache. This causes all layers to be deleted. */ void clear(); + /** + * Resize the specified layer if needed. + * + * @param layer The layer to resize + * @param width The new width of the layer + * @param height The new height of the layer + * + * @return True if the layer was resized or nothing happened, false if + * a failure occurred during the resizing operation + */ + bool resize(Layer* layer, const uint32_t width, const uint32_t height); /** * Sets the maximum size of the cache in bytes. diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 60ff0bf..24f9739 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -18,6 +18,7 @@ #include <ui/Rect.h> +#include "LayerCache.h" #include "LayerRenderer.h" #include "Properties.h" #include "Rect.h" @@ -34,21 +35,24 @@ void LayerRenderer::prepareDirty(float left, float top, float right, float botto glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo); + const float width = mLayer->layer.getWidth(); + const float height = mLayer->layer.getHeight(); + #if RENDER_LAYERS_AS_REGIONS Rect dirty(left, top, right, bottom); if (dirty.isEmpty() || (dirty.left <= 0 && dirty.top <= 0 && - dirty.right >= mLayer->width && dirty.bottom >= mLayer->height)) { + dirty.right >= width && dirty.bottom >= height)) { mLayer->region.clear(); - dirty.set(0.0f, 0.0f, mLayer->width, mLayer->height); + dirty.set(0.0f, 0.0f, width, height); } else { - dirty.intersect(0.0f, 0.0f, mLayer->width, mLayer->height); + dirty.intersect(0.0f, 0.0f, width, height); android::Rect r(dirty.left, dirty.top, dirty.right, dirty.bottom); mLayer->region.subtractSelf(r); } OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque); #else - OpenGLRenderer::prepareDirty(0.0f, 0.0f, mLayer->width, mLayer->height, opaque); + OpenGLRenderer::prepareDirty(0.0f, 0.0f, width, height, opaque); #endif } @@ -162,64 +166,56 @@ void LayerRenderer::generateMesh() { Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) { LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height); - Layer* layer = new Layer(width, height); - - GLuint previousFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); - - glGenFramebuffers(1, &layer->fbo); - glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); - - if (glGetError() != GL_NO_ERROR) { - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - glDeleteBuffers(1, &layer->fbo); - return 0; + GLuint fbo = Caches::getInstance().fboCache.get(); + if (!fbo) { + LOGW("Could not obtain an FBO"); + return NULL; } glActiveTexture(GL_TEXTURE0); - glGenTextures(1, &layer->texture); - glBindTexture(GL_TEXTURE_2D, layer->texture); + Layer* layer = Caches::getInstance().layerCache.get(width, height); + if (!layer) { + LOGW("Could not obtain a layer"); + return NULL; + } - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + layer->fbo = fbo; + layer->layer.set(0.0f, 0.0f, width, height); + layer->texCoords.set(0.0f, height / float(layer->height), + width / float(layer->width), 0.0f); + layer->alpha = 255; + layer->mode = SkXfermode::kSrcOver_Mode; + layer->blend = !isOpaque; + layer->colorFilter = NULL; + layer->region.clear(); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GLuint previousFbo; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo); + glBindTexture(GL_TEXTURE_2D, layer->texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); + // Initialize the texture if needed + if (layer->empty) { + layer->empty = false; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, NULL); - if (glGetError() != GL_NO_ERROR) { - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - glDeleteBuffers(1, &layer->fbo); - glDeleteTextures(1, &layer->texture); - delete layer; - return 0; + if (glGetError() != GL_NO_ERROR) { + LOGD("Could not allocate texture"); + glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + glDeleteTextures(1, &layer->texture); + Caches::getInstance().fboCache.put(fbo); + delete layer; + return NULL; + } } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->texture, 0); - if (glGetError() != GL_NO_ERROR) { - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - glDeleteBuffers(1, &layer->fbo); - glDeleteTextures(1, &layer->texture); - delete layer; - return 0; - } - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - layer->layer.set(0.0f, 0.0f, width, height); - layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f); - layer->alpha = 255; - layer->mode = SkXfermode::kSrcOver_Mode; - layer->blend = !isOpaque; - layer->empty = false; - layer->colorFilter = NULL; - return layer; } @@ -227,27 +223,17 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { if (layer) { LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, layer->texture); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - if (glGetError() != GL_NO_ERROR) { - glDeleteBuffers(1, &layer->fbo); - glDeleteTextures(1, &layer->texture); - - layer->width = 0; - layer->height = 0; - layer->fbo = 0; - layer->texture = 0; - + if (Caches::getInstance().layerCache.resize(layer, width, height)) { + layer->layer.set(0.0f, 0.0f, width, height); + layer->texCoords.set(0.0f, height / float(layer->height), + width / float(layer->width), 0.0f); + } else { + if (layer->texture) glDeleteTextures(1, &layer->texture); + delete layer; return false; } - - layer->width = width; - layer->height = height; } + return true; } @@ -255,10 +241,16 @@ void LayerRenderer::destroyLayer(Layer* layer) { if (layer) { LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo); - if (layer->fbo) glDeleteFramebuffers(1, &layer->fbo); - if (layer->texture) glDeleteTextures(1, &layer->texture); + if (layer->fbo) { + Caches::getInstance().fboCache.put(layer->fbo); + } - delete layer; + if (!Caches::getInstance().layerCache.put(layer)) { + if (layer->texture) glDeleteTextures(1, &layer->texture); + delete layer; + } else { + layer->region.clear(); + } } } diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 2f230b5..2d8b6f3 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -64,14 +64,14 @@ enum DebugLevel { // Converts a number of mega-bytes into bytes #define MB(s) s * 1024 * 1024 -#define DEFAULT_TEXTURE_CACHE_SIZE 20.0f -#define DEFAULT_LAYER_CACHE_SIZE 8.0f +#define DEFAULT_TEXTURE_CACHE_SIZE 24.0f +#define DEFAULT_LAYER_CACHE_SIZE 24.0f #define DEFAULT_PATH_CACHE_SIZE 4.0f #define DEFAULT_SHAPE_CACHE_SIZE 1.0f #define DEFAULT_PATCH_CACHE_SIZE 512 #define DEFAULT_GRADIENT_CACHE_SIZE 0.5f #define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f -#define DEFAULT_FBO_CACHE_SIZE 12 +#define DEFAULT_FBO_CACHE_SIZE 16 #define DEFAULT_TEXT_GAMMA 1.4f #define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64 |