blob: 830a13ab28a7cb668695b0503e3455db54f498a0 [file] [log] [blame]
Romain Guy8d4aeb72013-02-12 16:08:55 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
19#include <utils/Log.h>
20
21#include "Debug.h"
22#include "Properties.h"
23#include "RenderBufferCache.h"
24
25namespace android {
26namespace uirenderer {
27
28///////////////////////////////////////////////////////////////////////////////
29// Defines
30///////////////////////////////////////////////////////////////////////////////
31
32// Debug
33#if DEBUG_RENDER_BUFFERS
34 #define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
35#else
36 #define RENDER_BUFFER_LOGD(...)
37#endif
38
39///////////////////////////////////////////////////////////////////////////////
40// Constructors/destructor
41///////////////////////////////////////////////////////////////////////////////
42
43RenderBufferCache::RenderBufferCache(): mSize(0), mMaxSize(MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE)) {
44 char property[PROPERTY_VALUE_MAX];
45 if (property_get(PROPERTY_RENDER_BUFFER_CACHE_SIZE, property, NULL) > 0) {
46 INIT_LOGD(" Setting render buffer cache size to %sMB", property);
47 setMaxSize(MB(atof(property)));
48 } else {
49 INIT_LOGD(" Using default render buffer cache size of %.2fMB",
50 DEFAULT_RENDER_BUFFER_CACHE_SIZE);
51 }
52}
53
54RenderBufferCache::~RenderBufferCache() {
55 clear();
56}
57
58///////////////////////////////////////////////////////////////////////////////
59// Size management
60///////////////////////////////////////////////////////////////////////////////
61
62uint32_t RenderBufferCache::getSize() {
63 return mSize;
64}
65
66uint32_t RenderBufferCache::getMaxSize() {
67 return mMaxSize;
68}
69
70void RenderBufferCache::setMaxSize(uint32_t maxSize) {
71 clear();
72 mMaxSize = maxSize;
73}
74
75///////////////////////////////////////////////////////////////////////////////
76// Caching
77///////////////////////////////////////////////////////////////////////////////
78
79int RenderBufferCache::RenderBufferEntry::compare(
80 const RenderBufferCache::RenderBufferEntry& lhs,
81 const RenderBufferCache::RenderBufferEntry& rhs) {
82 int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
83 if (deltaInt != 0) return deltaInt;
84
85 deltaInt = int(lhs.mHeight) - int(rhs.mHeight);
86 if (deltaInt != 0) return deltaInt;
87
88 return int(lhs.mFormat) - int(rhs.mFormat);
89}
90
91void RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
92 if (buffer) {
93 RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
94 RenderBuffer::formatName(buffer->getFormat()),
95 buffer->getWidth(), buffer->getHeight());
96
97 mSize -= buffer->getSize();
98 delete buffer;
99 }
100}
101
102void RenderBufferCache::clear() {
103 size_t count = mCache.size();
104 for (size_t i = 0; i < count; i++) {
105 deleteBuffer(mCache.itemAt(i).mBuffer);
106 }
107 mCache.clear();
108}
109
110RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
111 RenderBuffer* buffer = NULL;
112
113 RenderBufferEntry entry(format, width, height);
114 ssize_t index = mCache.indexOf(entry);
115
116 if (index >= 0) {
117 entry = mCache.itemAt(index);
118 mCache.removeAt(index);
119
120 buffer = entry.mBuffer;
121 mSize -= buffer->getSize();
122
123 RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)",
124 RenderBuffer::formatName(format), width, height);
125 } else {
126 buffer = new RenderBuffer(format, width, height);
127
128 RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)",
129 RenderBuffer::formatName(format), width, height);
130 }
131
132 buffer->bind();
133 buffer->allocate();
134
135 return buffer;
136}
137
138bool RenderBufferCache::put(RenderBuffer* buffer) {
139 if (!buffer) return false;
140
141 const uint32_t size = buffer->getSize();
142 if (size < mMaxSize) {
143 while (mSize + size > mMaxSize) {
144 size_t position = 0;
145
146 RenderBuffer* victim = mCache.itemAt(position).mBuffer;
147 deleteBuffer(victim);
148 mCache.removeAt(position);
149 }
150
151 RenderBufferEntry entry(buffer);
152
153 mCache.add(entry);
154 mSize += size;
155
156 RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
157 RenderBuffer::formatName(buffer->getFormat()),
158 buffer->getWidth(), buffer->getHeight());
159
160 return true;
161 }
162 return false;
163}
164
165}; // namespace uirenderer
166}; // namespace android