1 /*
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
25 namespace android {
26 namespace 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
RenderBufferCache()43 RenderBufferCache::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
~RenderBufferCache()54 RenderBufferCache::~RenderBufferCache() {
55 clear();
56 }
57
58 ///////////////////////////////////////////////////////////////////////////////
59 // Size management
60 ///////////////////////////////////////////////////////////////////////////////
61
getSize()62 uint32_t RenderBufferCache::getSize() {
63 return mSize;
64 }
65
getMaxSize()66 uint32_t RenderBufferCache::getMaxSize() {
67 return mMaxSize;
68 }
69
setMaxSize(uint32_t maxSize)70 void RenderBufferCache::setMaxSize(uint32_t maxSize) {
71 clear();
72 mMaxSize = maxSize;
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////
76 // Caching
77 ///////////////////////////////////////////////////////////////////////////////
78
compare(const RenderBufferCache::RenderBufferEntry & lhs,const RenderBufferCache::RenderBufferEntry & rhs)79 int 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
deleteBuffer(RenderBuffer * buffer)91 void 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
clear()102 void 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
get(GLenum format,const uint32_t width,const uint32_t height)110 RenderBuffer* 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
put(RenderBuffer * buffer)138 bool 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
167