Home | History | Annotate | Download | only in hwui
      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