diff options
| author | 2013-01-18 16:42:51 -0800 | |
|---|---|---|
| committer | 2013-01-18 16:42:51 -0800 | |
| commit | 2055abaa0a590c35e27e1ae2e7d7cfccdfb98b59 (patch) | |
| tree | 1e302d08b6aa3714048a4d8435aa44f155c998c9 /libs/hwui | |
| parent | f25febf01453733e8bdd1ac241ecd9d3bcbef475 (diff) | |
Allow layers with a stencil buffer to be resized on the fly
Bug #7146141
This change moves the resizeLayer() from LayerCache (where it should
never have been anyway) to Layer. This makes a little more sense.
Change-Id: I8b2f9c19c558e738405a58b9e71ec5799fc6be88
Diffstat (limited to 'libs/hwui')
| -rw-r--r-- | libs/hwui/Layer.cpp | 45 | ||||
| -rw-r--r-- | libs/hwui/Layer.h | 31 | ||||
| -rw-r--r-- | libs/hwui/LayerCache.cpp | 25 | ||||
| -rw-r--r-- | libs/hwui/LayerCache.h | 15 | ||||
| -rw-r--r-- | libs/hwui/LayerRenderer.cpp | 2 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 9 |
6 files changed, 83 insertions, 44 deletions
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 1d85b704e5ad..79dbfb0fc3a5 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -54,6 +54,51 @@ Layer::~Layer() { deleteTexture(); } +uint32_t Layer::computeIdealWidth(uint32_t layerWidth) { + return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); +} + +uint32_t Layer::computeIdealHeight(uint32_t layerHeight) { + return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); +} + +bool Layer::resize(const uint32_t width, const uint32_t height) { + uint32_t desiredWidth = computeIdealWidth(width); + uint32_t desiredHeight = computeIdealWidth(height); + + if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) { + return true; + } + + uint32_t oldWidth = getWidth(); + uint32_t oldHeight = getHeight(); + + setSize(desiredWidth, desiredHeight); + + if (fbo) { + Caches::getInstance().activeTexture(0); + bindTexture(); + allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); + + if (glGetError() != GL_NO_ERROR) { + setSize(oldWidth, oldHeight); + return false; + } + } + + if (stencil) { + bindStencilRenderBuffer(); + allocateStencilRenderBuffer(); + + if (glGetError() != GL_NO_ERROR) { + setSize(oldWidth, oldHeight); + return false; + } + } + + return true; +} + void Layer::removeFbo(bool flush) { if (stencil) { // TODO: recycle & cache instead of simply deleting diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 9ef48945df23..a551b3f21000 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -48,6 +48,9 @@ struct Layer { Layer(const uint32_t layerWidth, const uint32_t layerHeight); ~Layer(); + static uint32_t computeIdealWidth(uint32_t layerWidth); + static uint32_t computeIdealHeight(uint32_t layerHeight); + /** * Calling this method will remove (either by recycling or * destroying) the associated FBO, if present, and any render @@ -91,6 +94,17 @@ struct Layer { return texture.height; } + /** + * Resize the layer and its texture if needed. + * + * @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(const uint32_t width, const uint32_t height); + void setSize(uint32_t width, uint32_t height) { texture.width = width; texture.height = height; @@ -203,6 +217,12 @@ struct Layer { } } + inline void bindStencilRenderBuffer() { + if (stencil) { + glBindRenderbuffer(GL_RENDERBUFFER, stencil); + } + } + inline void generateTexture() { if (!texture.id) { glGenTextures(1, &texture.id); @@ -229,7 +249,16 @@ struct Layer { #if DEBUG_LAYERS ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); #endif - glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL); + if (texture.id) { + glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, + format, storage, NULL); + } + } + + inline void allocateStencilRenderBuffer() { + if (stencil) { + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight()); + } } inline mat4& getTexTransform() { diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index cfc5b04f2183..427846459162 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -136,31 +136,6 @@ void LayerCache::dump() { } } -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->getWidth() && entry.mHeight <= layer->getHeight()) { - return true; - } - - uint32_t oldWidth = layer->getWidth(); - uint32_t oldHeight = layer->getHeight(); - - Caches::getInstance().activeTexture(0); - layer->bindTexture(); - layer->setSize(entry.mWidth, entry.mHeight); - layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); - - if (glGetError() != GL_NO_ERROR) { - layer->setSize(oldWidth, oldHeight); - return false; - } - - return true; -} - bool LayerCache::put(Layer* layer) { if (!layer->isCacheable()) return false; diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index fc2cd9104804..7720b4232ae9 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -72,17 +72,6 @@ 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. @@ -108,8 +97,8 @@ public: } LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(NULL) { - mWidth = uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE); - mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE); + mWidth = Layer::computeIdealWidth(layerWidth); + mHeight = Layer::computeIdealHeight(layerHeight); } LayerEntry(Layer* layer): diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index ba59bb391f1d..61bedbb0f388 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -264,7 +264,7 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { if (layer) { LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height); - if (Caches::getInstance().layerCache.resize(layer, width, height)) { + if (layer->resize(width, height)) { layer->layer.set(0.0f, 0.0f, width, height); layer->texCoords.set(0.0f, height / float(layer->getHeight()), width / float(layer->getWidth()), 0.0f); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index be34b40ee42f..f55bc9d2a381 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1248,11 +1248,12 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) { // TODO: See Layer::removeFbo(). The stencil renderbuffer should be cached GLuint buffer; glGenRenderbuffers(1, &buffer); - glBindRenderbuffer(GL_RENDERBUFFER, buffer); - glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, - layer->getWidth(), layer->getHeight()); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer); + layer->setStencilRenderBuffer(buffer); + layer->bindStencilRenderBuffer(); + layer->allocateStencilRenderBuffer(); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer); } } |