Merge "Allocate layers from the layers pool. Bug #3413433" into honeycomb
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 fbo = Caches::getInstance().fboCache.get();
|
||||
if (!fbo) {
|
||||
LOGW("Could not obtain an FBO");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
Layer* layer = Caches::getInstance().layerCache.get(width, height);
|
||||
if (!layer) {
|
||||
LOGW("Could not obtain a layer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glGenTextures(1, &layer->texture);
|
||||
glBindTexture(GL_TEXTURE_2D, layer->texture);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
// 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);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
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, width, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user