LayerCache.cpp revision 0bb5667b4ef91fefd0500fae0186789d15d54e0e
1dda570201ac851dd85af3861f7e575721d3345daRomain Guy/*
2dda570201ac851dd85af3861f7e575721d3345daRomain Guy * Copyright (C) 2010 The Android Open Source Project
3dda570201ac851dd85af3861f7e575721d3345daRomain Guy *
4dda570201ac851dd85af3861f7e575721d3345daRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5dda570201ac851dd85af3861f7e575721d3345daRomain Guy * you may not use this file except in compliance with the License.
6dda570201ac851dd85af3861f7e575721d3345daRomain Guy * You may obtain a copy of the License at
7dda570201ac851dd85af3861f7e575721d3345daRomain Guy *
8dda570201ac851dd85af3861f7e575721d3345daRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9dda570201ac851dd85af3861f7e575721d3345daRomain Guy *
10dda570201ac851dd85af3861f7e575721d3345daRomain Guy * Unless required by applicable law or agreed to in writing, software
11dda570201ac851dd85af3861f7e575721d3345daRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12dda570201ac851dd85af3861f7e575721d3345daRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dda570201ac851dd85af3861f7e575721d3345daRomain Guy * See the License for the specific language governing permissions and
14dda570201ac851dd85af3861f7e575721d3345daRomain Guy * limitations under the License.
15dda570201ac851dd85af3861f7e575721d3345daRomain Guy */
16dda570201ac851dd85af3861f7e575721d3345daRomain Guy
17dda570201ac851dd85af3861f7e575721d3345daRomain Guy#define LOG_TAG "OpenGLRenderer"
18dda570201ac851dd85af3861f7e575721d3345daRomain Guy
19dda570201ac851dd85af3861f7e575721d3345daRomain Guy#include <GLES2/gl2.h>
20dda570201ac851dd85af3861f7e575721d3345daRomain Guy
21f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy#include <utils/Log.h>
22f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
23dda570201ac851dd85af3861f7e575721d3345daRomain Guy#include "LayerCache.h"
24fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy#include "Properties.h"
25dda570201ac851dd85af3861f7e575721d3345daRomain Guy
26dda570201ac851dd85af3861f7e575721d3345daRomain Guynamespace android {
27dda570201ac851dd85af3861f7e575721d3345daRomain Guynamespace uirenderer {
28dda570201ac851dd85af3861f7e575721d3345daRomain Guy
29dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
30dda570201ac851dd85af3861f7e575721d3345daRomain Guy// Constructors/destructor
31dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
32dda570201ac851dd85af3861f7e575721d3345daRomain Guy
33fb8b763f762ae21923c58d64caa729b012f40e05Romain GuyLayerCache::LayerCache():
34fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity),
35fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        mIdGenerator(1), mSize(0), mMaxSize(MB(DEFAULT_LAYER_CACHE_SIZE)) {
36fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    char property[PROPERTY_VALUE_MAX];
37fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, NULL) > 0) {
38fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        LOGD("  Setting layer cache size to %sMB", property);
39fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        setMaxSize(MB(atof(property)));
40fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    } else {
41fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy        LOGD("  Using default layer cache size of %.2fMB", DEFAULT_LAYER_CACHE_SIZE);
42fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy    }
43fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy}
44fb8b763f762ae21923c58d64caa729b012f40e05Romain Guy
45dda570201ac851dd85af3861f7e575721d3345daRomain GuyLayerCache::LayerCache(uint32_t maxByteSize):
466c81893c626499e58c8eeb20d6c35ec4e1ce808bRomain Guy        mCache(GenerationCache<LayerSize, Layer*>::kUnlimitedCapacity),
476c81893c626499e58c8eeb20d6c35ec4e1ce808bRomain Guy        mIdGenerator(1), mSize(0), mMaxSize(maxByteSize) {
48dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
49dda570201ac851dd85af3861f7e575721d3345daRomain Guy
50dda570201ac851dd85af3861f7e575721d3345daRomain GuyLayerCache::~LayerCache() {
515f0c6a483900f3989f4d2a8f913cf5b6a9777d03Romain Guy    clear();
52dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
53dda570201ac851dd85af3861f7e575721d3345daRomain Guy
54dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
55dda570201ac851dd85af3861f7e575721d3345daRomain Guy// Size management
56dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
57dda570201ac851dd85af3861f7e575721d3345daRomain Guy
58dda570201ac851dd85af3861f7e575721d3345daRomain Guyuint32_t LayerCache::getSize() {
59dda570201ac851dd85af3861f7e575721d3345daRomain Guy    return mSize;
60dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
61dda570201ac851dd85af3861f7e575721d3345daRomain Guy
62dda570201ac851dd85af3861f7e575721d3345daRomain Guyuint32_t LayerCache::getMaxSize() {
63dda570201ac851dd85af3861f7e575721d3345daRomain Guy    return mMaxSize;
64dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
65dda570201ac851dd85af3861f7e575721d3345daRomain Guy
66dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid LayerCache::setMaxSize(uint32_t maxSize) {
67dda570201ac851dd85af3861f7e575721d3345daRomain Guy    mMaxSize = maxSize;
68dda570201ac851dd85af3861f7e575721d3345daRomain Guy    while (mSize > mMaxSize) {
69dda570201ac851dd85af3861f7e575721d3345daRomain Guy        Layer* oldest = mCache.removeOldest();
70dda570201ac851dd85af3861f7e575721d3345daRomain Guy        deleteLayer(oldest);
71dda570201ac851dd85af3861f7e575721d3345daRomain Guy    }
72dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
73dda570201ac851dd85af3861f7e575721d3345daRomain Guy
74dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
75dda570201ac851dd85af3861f7e575721d3345daRomain Guy// Callbacks
76dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
77dda570201ac851dd85af3861f7e575721d3345daRomain Guy
78dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid LayerCache::operator()(LayerSize& size, Layer*& layer) {
79dda570201ac851dd85af3861f7e575721d3345daRomain Guy    deleteLayer(layer);
80dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
81dda570201ac851dd85af3861f7e575721d3345daRomain Guy
82dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
83dda570201ac851dd85af3861f7e575721d3345daRomain Guy// Caching
84dda570201ac851dd85af3861f7e575721d3345daRomain Guy///////////////////////////////////////////////////////////////////////////////
85dda570201ac851dd85af3861f7e575721d3345daRomain Guy
86dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid LayerCache::deleteLayer(Layer* layer) {
87dda570201ac851dd85af3861f7e575721d3345daRomain Guy    if (layer) {
88dda570201ac851dd85af3861f7e575721d3345daRomain Guy        mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4;
89dda570201ac851dd85af3861f7e575721d3345daRomain Guy
90dda570201ac851dd85af3861f7e575721d3345daRomain Guy        glDeleteTextures(1, &layer->texture);
91dda570201ac851dd85af3861f7e575721d3345daRomain Guy        delete layer;
92dda570201ac851dd85af3861f7e575721d3345daRomain Guy    }
93dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
94dda570201ac851dd85af3861f7e575721d3345daRomain Guy
95dda570201ac851dd85af3861f7e575721d3345daRomain Guyvoid LayerCache::clear() {
96dda570201ac851dd85af3861f7e575721d3345daRomain Guy    mCache.setOnEntryRemovedListener(this);
97dda570201ac851dd85af3861f7e575721d3345daRomain Guy    mCache.clear();
98dda570201ac851dd85af3861f7e575721d3345daRomain Guy    mCache.setOnEntryRemovedListener(NULL);
99dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
100dda570201ac851dd85af3861f7e575721d3345daRomain Guy
101f607bdc167f66b3e7003acaa4736ae46d78c1492Romain GuyLayer* LayerCache::get(LayerSize& size) {
102dda570201ac851dd85af3861f7e575721d3345daRomain Guy    Layer* layer = mCache.remove(size);
103dda570201ac851dd85af3861f7e575721d3345daRomain Guy    if (layer) {
104f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        LAYER_LOGD("Reusing layer");
105f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
106dda570201ac851dd85af3861f7e575721d3345daRomain Guy        mSize -= layer->layer.getWidth() * layer->layer.getHeight() * 4;
107f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy    } else {
108f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        LAYER_LOGD("Creating new layer");
109f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
110f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        layer = new Layer;
111f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        layer->blend = true;
11238c85b907a478af96d71b9a5df5a2066b8475311Romain Guy        layer->empty = true;
113f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
114f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        glGenTextures(1, &layer->texture);
115f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        glBindTexture(GL_TEXTURE_2D, layer->texture);
116f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
1170bb5667b4ef91fefd0500fae0186789d15d54e0eRomain Guy        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1180bb5667b4ef91fefd0500fae0186789d15d54e0eRomain Guy
11938c85b907a478af96d71b9a5df5a2066b8475311Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
12038c85b907a478af96d71b9a5df5a2066b8475311Romain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
121f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
122f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
123f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
124dda570201ac851dd85af3861f7e575721d3345daRomain Guy    }
125f18fd99b5c182329cd8936a9611f0103d8ece44aRomain Guy
126dda570201ac851dd85af3861f7e575721d3345daRomain Guy    return layer;
127dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
128dda570201ac851dd85af3861f7e575721d3345daRomain Guy
129dda570201ac851dd85af3861f7e575721d3345daRomain Guybool LayerCache::put(LayerSize& layerSize, Layer* layer) {
130dda570201ac851dd85af3861f7e575721d3345daRomain Guy    const uint32_t size = layerSize.width * layerSize.height * 4;
131dda570201ac851dd85af3861f7e575721d3345daRomain Guy    // Don't even try to cache a layer that's bigger than the cache
132dda570201ac851dd85af3861f7e575721d3345daRomain Guy    if (size < mMaxSize) {
133dda570201ac851dd85af3861f7e575721d3345daRomain Guy        while (mSize + size > mMaxSize) {
134dda570201ac851dd85af3861f7e575721d3345daRomain Guy            Layer* oldest = mCache.removeOldest();
135dda570201ac851dd85af3861f7e575721d3345daRomain Guy            deleteLayer(oldest);
136dda570201ac851dd85af3861f7e575721d3345daRomain Guy        }
137dda570201ac851dd85af3861f7e575721d3345daRomain Guy
1386c81893c626499e58c8eeb20d6c35ec4e1ce808bRomain Guy        layerSize.id = mIdGenerator++;
139dda570201ac851dd85af3861f7e575721d3345daRomain Guy        mCache.put(layerSize, layer);
140dda570201ac851dd85af3861f7e575721d3345daRomain Guy        mSize += size;
141dda570201ac851dd85af3861f7e575721d3345daRomain Guy
142dda570201ac851dd85af3861f7e575721d3345daRomain Guy        return true;
143dda570201ac851dd85af3861f7e575721d3345daRomain Guy    }
144dda570201ac851dd85af3861f7e575721d3345daRomain Guy    return false;
145dda570201ac851dd85af3861f7e575721d3345daRomain Guy}
146dda570201ac851dd85af3861f7e575721d3345daRomain Guy
147dda570201ac851dd85af3861f7e575721d3345daRomain Guy}; // namespace uirenderer
148dda570201ac851dd85af3861f7e575721d3345daRomain Guy}; // namespace android
149