blob: 39e0dbf4f1e1220c6e1541c4f7595a8ed6a0b051 [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
Romain Guy8d4aeb72013-02-12 16:08:55 -080017#include <utils/Log.h>
18
19#include "Debug.h"
20#include "Properties.h"
21#include "RenderBufferCache.h"
22
23namespace android {
24namespace uirenderer {
25
26///////////////////////////////////////////////////////////////////////////////
27// Defines
28///////////////////////////////////////////////////////////////////////////////
29
30// Debug
31#if DEBUG_RENDER_BUFFERS
32 #define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
33#else
34 #define RENDER_BUFFER_LOGD(...)
35#endif
36
37///////////////////////////////////////////////////////////////////////////////
38// Constructors/destructor
39///////////////////////////////////////////////////////////////////////////////
40
41RenderBufferCache::RenderBufferCache(): mSize(0), mMaxSize(MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE)) {
42 char property[PROPERTY_VALUE_MAX];
Chris Craikd41c4d82015-01-05 15:51:13 -080043 if (property_get(PROPERTY_RENDER_BUFFER_CACHE_SIZE, property, nullptr) > 0) {
Romain Guy8d4aeb72013-02-12 16:08:55 -080044 INIT_LOGD(" Setting render buffer cache size to %sMB", property);
45 setMaxSize(MB(atof(property)));
46 } else {
47 INIT_LOGD(" Using default render buffer cache size of %.2fMB",
48 DEFAULT_RENDER_BUFFER_CACHE_SIZE);
49 }
50}
51
52RenderBufferCache::~RenderBufferCache() {
53 clear();
54}
55
56///////////////////////////////////////////////////////////////////////////////
57// Size management
58///////////////////////////////////////////////////////////////////////////////
59
60uint32_t RenderBufferCache::getSize() {
61 return mSize;
62}
63
64uint32_t RenderBufferCache::getMaxSize() {
65 return mMaxSize;
66}
67
68void RenderBufferCache::setMaxSize(uint32_t maxSize) {
69 clear();
70 mMaxSize = maxSize;
71}
72
73///////////////////////////////////////////////////////////////////////////////
74// Caching
75///////////////////////////////////////////////////////////////////////////////
76
77int RenderBufferCache::RenderBufferEntry::compare(
78 const RenderBufferCache::RenderBufferEntry& lhs,
79 const RenderBufferCache::RenderBufferEntry& rhs) {
80 int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
81 if (deltaInt != 0) return deltaInt;
82
83 deltaInt = int(lhs.mHeight) - int(rhs.mHeight);
84 if (deltaInt != 0) return deltaInt;
85
86 return int(lhs.mFormat) - int(rhs.mFormat);
87}
88
89void RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
90 if (buffer) {
91 RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
92 RenderBuffer::formatName(buffer->getFormat()),
93 buffer->getWidth(), buffer->getHeight());
94
95 mSize -= buffer->getSize();
96 delete buffer;
97 }
98}
99
100void RenderBufferCache::clear() {
101 size_t count = mCache.size();
102 for (size_t i = 0; i < count; i++) {
103 deleteBuffer(mCache.itemAt(i).mBuffer);
104 }
105 mCache.clear();
106}
107
108RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
Chris Craikd41c4d82015-01-05 15:51:13 -0800109 RenderBuffer* buffer = nullptr;
Romain Guy8d4aeb72013-02-12 16:08:55 -0800110
111 RenderBufferEntry entry(format, width, height);
112 ssize_t index = mCache.indexOf(entry);
113
114 if (index >= 0) {
115 entry = mCache.itemAt(index);
116 mCache.removeAt(index);
117
118 buffer = entry.mBuffer;
119 mSize -= buffer->getSize();
120
121 RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)",
122 RenderBuffer::formatName(format), width, height);
123 } else {
124 buffer = new RenderBuffer(format, width, height);
125
126 RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)",
127 RenderBuffer::formatName(format), width, height);
128 }
129
130 buffer->bind();
131 buffer->allocate();
132
133 return buffer;
134}
135
136bool RenderBufferCache::put(RenderBuffer* buffer) {
137 if (!buffer) return false;
138
139 const uint32_t size = buffer->getSize();
140 if (size < mMaxSize) {
141 while (mSize + size > mMaxSize) {
142 size_t position = 0;
143
144 RenderBuffer* victim = mCache.itemAt(position).mBuffer;
145 deleteBuffer(victim);
146 mCache.removeAt(position);
147 }
148
149 RenderBufferEntry entry(buffer);
150
151 mCache.add(entry);
152 mSize += size;
153
154 RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
155 RenderBuffer::formatName(buffer->getFormat()),
156 buffer->getWidth(), buffer->getHeight());
157
158 return true;
Samsunge11f3ab2014-09-24 10:52:13 -0700159 } else {
160 RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d",
161 RenderBuffer::formatName(buffer->getFormat()),
162 buffer->getWidth(), buffer->getHeight(), size, mMaxSize);
163 delete buffer;
Romain Guy8d4aeb72013-02-12 16:08:55 -0800164 }
165 return false;
166}
167
168}; // namespace uirenderer
169}; // namespace android