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 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 54 RenderBufferCache::~RenderBufferCache() { 55 clear(); 56 } 57 58 /////////////////////////////////////////////////////////////////////////////// 59 // Size management 60 /////////////////////////////////////////////////////////////////////////////// 61 62 uint32_t RenderBufferCache::getSize() { 63 return mSize; 64 } 65 66 uint32_t RenderBufferCache::getMaxSize() { 67 return mMaxSize; 68 } 69 70 void RenderBufferCache::setMaxSize(uint32_t maxSize) { 71 clear(); 72 mMaxSize = maxSize; 73 } 74 75 /////////////////////////////////////////////////////////////////////////////// 76 // Caching 77 /////////////////////////////////////////////////////////////////////////////// 78 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 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 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 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 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