blob: 8beed2540e1c521936c6bf1ede3d4744aadd4bfa [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() {
John Reckbef837d2015-07-29 16:51:05 -0700101 for (auto entry : mCache) {
102 deleteBuffer(entry.mBuffer);
Romain Guy8d4aeb72013-02-12 16:08:55 -0800103 }
104 mCache.clear();
105}
106
107RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
Chris Craikd41c4d82015-01-05 15:51:13 -0800108 RenderBuffer* buffer = nullptr;
Romain Guy8d4aeb72013-02-12 16:08:55 -0800109
110 RenderBufferEntry entry(format, width, height);
John Reckbef837d2015-07-29 16:51:05 -0700111 auto iter = mCache.find(entry);
Romain Guy8d4aeb72013-02-12 16:08:55 -0800112
John Reckbef837d2015-07-29 16:51:05 -0700113 if (iter != mCache.end()) {
114 entry = *iter;
115 mCache.erase(iter);
Romain Guy8d4aeb72013-02-12 16:08:55 -0800116
117 buffer = entry.mBuffer;
118 mSize -= buffer->getSize();
119
120 RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)",
121 RenderBuffer::formatName(format), width, height);
122 } else {
123 buffer = new RenderBuffer(format, width, height);
124
125 RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)",
126 RenderBuffer::formatName(format), width, height);
127 }
128
129 buffer->bind();
130 buffer->allocate();
131
132 return buffer;
133}
134
135bool RenderBufferCache::put(RenderBuffer* buffer) {
136 if (!buffer) return false;
137
138 const uint32_t size = buffer->getSize();
139 if (size < mMaxSize) {
140 while (mSize + size > mMaxSize) {
John Reckbef837d2015-07-29 16:51:05 -0700141 RenderBuffer* victim = mCache.begin()->mBuffer;
Romain Guy8d4aeb72013-02-12 16:08:55 -0800142 deleteBuffer(victim);
John Reckbef837d2015-07-29 16:51:05 -0700143 mCache.erase(mCache.begin());
Romain Guy8d4aeb72013-02-12 16:08:55 -0800144 }
145
146 RenderBufferEntry entry(buffer);
147
John Reckbef837d2015-07-29 16:51:05 -0700148 mCache.insert(entry);
Romain Guy8d4aeb72013-02-12 16:08:55 -0800149 mSize += size;
150
151 RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
152 RenderBuffer::formatName(buffer->getFormat()),
153 buffer->getWidth(), buffer->getHeight());
154
155 return true;
Samsunge11f3ab2014-09-24 10:52:13 -0700156 } else {
157 RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d",
158 RenderBuffer::formatName(buffer->getFormat()),
159 buffer->getWidth(), buffer->getHeight(), size, mMaxSize);
160 delete buffer;
Romain Guy8d4aeb72013-02-12 16:08:55 -0800161 }
162 return false;
163}
164
165}; // namespace uirenderer
166}; // namespace android