summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2010-07-08 11:45:51 -0700
committerRomain Guy <romainguy@google.com>2010-07-08 11:45:51 -0700
commitf18fd99b5c182329cd8936a9611f0103d8ece44a (patch)
treec32def6bcb82e2a2019a5a49744dfa34c94d8d81 /libs
parent132f22590a3cd27ce15a705bdb481675e8fd02bc (diff)
downloadframeworks_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.cpp48
-rw-r--r--libs/hwui/LayerCache.h34
-rw-r--r--libs/hwui/OpenGLRenderer.cpp71
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);