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 #include "Debug.h"
18 #include "Properties.h"
19 #include "RenderBufferCache.h"
20
21 #include <utils/Log.h>
22
23 #include <cstdlib>
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()
44 : mSize(0)
45 , mMaxSize(Properties::renderBufferCacheSize) {}
46
~RenderBufferCache()47 RenderBufferCache::~RenderBufferCache() {
48 clear();
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52 // Size management
53 ///////////////////////////////////////////////////////////////////////////////
54
getSize()55 uint32_t RenderBufferCache::getSize() {
56 return mSize;
57 }
58
getMaxSize()59 uint32_t RenderBufferCache::getMaxSize() {
60 return mMaxSize;
61 }
62
63 ///////////////////////////////////////////////////////////////////////////////
64 // Caching
65 ///////////////////////////////////////////////////////////////////////////////
66
compare(const RenderBufferCache::RenderBufferEntry & lhs,const RenderBufferCache::RenderBufferEntry & rhs)67 int RenderBufferCache::RenderBufferEntry::compare(
68 const RenderBufferCache::RenderBufferEntry& lhs,
69 const RenderBufferCache::RenderBufferEntry& rhs) {
70 int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
71 if (deltaInt != 0) return deltaInt;
72
73 deltaInt = int(lhs.mHeight) - int(rhs.mHeight);
74 if (deltaInt != 0) return deltaInt;
75
76 return int(lhs.mFormat) - int(rhs.mFormat);
77 }
78
deleteBuffer(RenderBuffer * buffer)79 void RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
80 if (buffer) {
81 RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
82 RenderBuffer::formatName(buffer->getFormat()),
83 buffer->getWidth(), buffer->getHeight());
84
85 mSize -= buffer->getSize();
86 delete buffer;
87 }
88 }
89
clear()90 void RenderBufferCache::clear() {
91 for (auto entry : mCache) {
92 deleteBuffer(entry.mBuffer);
93 }
94 mCache.clear();
95 }
96
get(GLenum format,const uint32_t width,const uint32_t height)97 RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
98 RenderBuffer* buffer = nullptr;
99
100 RenderBufferEntry entry(format, width, height);
101 auto iter = mCache.find(entry);
102
103 if (iter != mCache.end()) {
104 entry = *iter;
105 mCache.erase(iter);
106
107 buffer = entry.mBuffer;
108 mSize -= buffer->getSize();
109
110 RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)",
111 RenderBuffer::formatName(format), width, height);
112 } else {
113 buffer = new RenderBuffer(format, width, height);
114
115 RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)",
116 RenderBuffer::formatName(format), width, height);
117 }
118
119 buffer->bind();
120 buffer->allocate();
121
122 return buffer;
123 }
124
put(RenderBuffer * buffer)125 bool RenderBufferCache::put(RenderBuffer* buffer) {
126 if (!buffer) return false;
127
128 const uint32_t size = buffer->getSize();
129 if (size < mMaxSize) {
130 while (mSize + size > mMaxSize) {
131 RenderBuffer* victim = mCache.begin()->mBuffer;
132 deleteBuffer(victim);
133 mCache.erase(mCache.begin());
134 }
135
136 RenderBufferEntry entry(buffer);
137
138 mCache.insert(entry);
139 mSize += size;
140
141 RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
142 RenderBuffer::formatName(buffer->getFormat()),
143 buffer->getWidth(), buffer->getHeight());
144
145 return true;
146 } else {
147 RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d",
148 RenderBuffer::formatName(buffer->getFormat()),
149 buffer->getWidth(), buffer->getHeight(), size, mMaxSize);
150 delete buffer;
151 }
152 return false;
153 }
154
155 }; // namespace uirenderer
156 }; // namespace android
157