/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "OpenGLRenderer"
#include <utils/Log.h>
#include "Debug.h"
#include "Properties.h"
#include "RenderBufferCache.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////////////////
// Debug
#if DEBUG_RENDER_BUFFERS
#define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
#else
#define RENDER_BUFFER_LOGD(...)
#endif
///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////
RenderBufferCache::RenderBufferCache(): mSize(0), mMaxSize(MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE)) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_RENDER_BUFFER_CACHE_SIZE, property, NULL) > 0) {
INIT_LOGD(" Setting render buffer cache size to %sMB", property);
setMaxSize(MB(atof(property)));
} else {
INIT_LOGD(" Using default render buffer cache size of %.2fMB",
DEFAULT_RENDER_BUFFER_CACHE_SIZE);
}
}
RenderBufferCache::~RenderBufferCache() {
clear();
}
///////////////////////////////////////////////////////////////////////////////
// Size management
///////////////////////////////////////////////////////////////////////////////
uint32_t RenderBufferCache::getSize() {
return mSize;
}
uint32_t RenderBufferCache::getMaxSize() {
return mMaxSize;
}
void RenderBufferCache::setMaxSize(uint32_t maxSize) {
clear();
mMaxSize = maxSize;
}
///////////////////////////////////////////////////////////////////////////////
// Caching
///////////////////////////////////////////////////////////////////////////////
int RenderBufferCache::RenderBufferEntry::compare(
const RenderBufferCache::RenderBufferEntry& lhs,
const RenderBufferCache::RenderBufferEntry& rhs) {
int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
if (deltaInt != 0) return deltaInt;
deltaInt = int(lhs.mHeight) - int(rhs.mHeight);
if (deltaInt != 0) return deltaInt;
return int(lhs.mFormat) - int(rhs.mFormat);
}
void RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
if (buffer) {
RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
RenderBuffer::formatName(buffer->getFormat()),
buffer->getWidth(), buffer->getHeight());
mSize -= buffer->getSize();
delete buffer;
}
}
void RenderBufferCache::clear() {
size_t count = mCache.size();
for (size_t i = 0; i < count; i++) {
deleteBuffer(mCache.itemAt(i).mBuffer);
}
mCache.clear();
}
RenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
RenderBuffer* buffer = NULL;
RenderBufferEntry entry(format, width, height);
ssize_t index = mCache.indexOf(entry);
if (index >= 0) {
entry = mCache.itemAt(index);
mCache.removeAt(index);
buffer = entry.mBuffer;
mSize -= buffer->getSize();
RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)",
RenderBuffer::formatName(format), width, height);
} else {
buffer = new RenderBuffer(format, width, height);
RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)",
RenderBuffer::formatName(format), width, height);
}
buffer->bind();
buffer->allocate();
return buffer;
}
bool RenderBufferCache::put(RenderBuffer* buffer) {
if (!buffer) return false;
const uint32_t size = buffer->getSize();
if (size < mMaxSize) {
while (mSize + size > mMaxSize) {
size_t position = 0;
RenderBuffer* victim = mCache.itemAt(position).mBuffer;
deleteBuffer(victim);
mCache.removeAt(position);
}
RenderBufferEntry entry(buffer);
mCache.add(entry);
mSize += size;
RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
RenderBuffer::formatName(buffer->getFormat()),
buffer->getWidth(), buffer->getHeight());
return true;
}
return false;
}
}; // namespace uirenderer
}; // namespace android