diff options
Diffstat (limited to 'libs/hwui/LayerRenderer.cpp')
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 128 |
1 files changed, 60 insertions, 68 deletions
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(); + } } } |