18d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy/*
28d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * Copyright (C) 2013 The Android Open Source Project
38d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy *
48d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
58d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * you may not use this file except in compliance with the License.
68d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * You may obtain a copy of the License at
78d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy *
88d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
98d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy *
108d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * Unless required by applicable law or agreed to in writing, software
118d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
128d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * See the License for the specific language governing permissions and
148d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy * limitations under the License.
158d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy */
168d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
178d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#include "RenderBufferCache.h"
181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include "Debug.h"
198dc02f99d09130ace2ee738c2e689db1b3f33181John Reck#include "DeviceInfo.h"
201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include "Properties.h"
218d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
226b50780363d3bb8db600c770183fa07677509ae8John Reck#include <utils/Log.h>
236b50780363d3bb8db600c770183fa07677509ae8John Reck
246b50780363d3bb8db600c770183fa07677509ae8John Reck#include <cstdlib>
256b50780363d3bb8db600c770183fa07677509ae8John Reck
268d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guynamespace android {
278d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guynamespace uirenderer {
288d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
298d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
308d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// Defines
318d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
328d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
338d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// Debug
348d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#if DEBUG_RENDER_BUFFERS
351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDER_BUFFER_LOGD(...) ALOGD(__VA_ARGS__)
368d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#else
371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDER_BUFFER_LOGD(...)
388d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy#endif
398d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
408dc02f99d09130ace2ee738c2e689db1b3f33181John Reckstatic uint32_t calculateRboCacheSize() {
418dc02f99d09130ace2ee738c2e689db1b3f33181John Reck    // TODO: Do we need to use extensions().has4BitStencil() here?
428dc02f99d09130ace2ee738c2e689db1b3f33181John Reck    // The tuning guide recommends it, but all real devices are configured
438dc02f99d09130ace2ee738c2e689db1b3f33181John Reck    // with a larger cache than necessary by 4x, so keep the 2x for now regardless
448dc02f99d09130ace2ee738c2e689db1b3f33181John Reck    return DeviceInfo::multiplyByResolution(2);
458dc02f99d09130ace2ee738c2e689db1b3f33181John Reck}
468dc02f99d09130ace2ee738c2e689db1b3f33181John Reck
478d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
488d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// Constructors/destructor
498d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
508d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John ReckRenderBufferCache::RenderBufferCache() : mSize(0), mMaxSize(calculateRboCacheSize()) {}
528d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
538d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain GuyRenderBufferCache::~RenderBufferCache() {
548d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    clear();
558d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
568d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
578d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
588d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// Size management
598d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
608d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
618d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guyuint32_t RenderBufferCache::getSize() {
628d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    return mSize;
638d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
648d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
658d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guyuint32_t RenderBufferCache::getMaxSize() {
668d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    return mMaxSize;
678d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
688d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
698d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
708d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy// Caching
718d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy///////////////////////////////////////////////////////////////////////////////
728d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
731bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reckint RenderBufferCache::RenderBufferEntry::compare(const RenderBufferCache::RenderBufferEntry& lhs,
741bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                                  const RenderBufferCache::RenderBufferEntry& rhs) {
758d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    int deltaInt = int(lhs.mWidth) - int(rhs.mWidth);
768d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    if (deltaInt != 0) return deltaInt;
778d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
788d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    deltaInt = int(lhs.mHeight) - int(rhs.mHeight);
798d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    if (deltaInt != 0) return deltaInt;
808d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
818d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    return int(lhs.mFormat) - int(rhs.mFormat);
828d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
838d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
848d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guyvoid RenderBufferCache::deleteBuffer(RenderBuffer* buffer) {
858d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    if (buffer) {
868d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d)",
871bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           buffer->getHeight());
898d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
908d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        mSize -= buffer->getSize();
918d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        delete buffer;
928d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    }
938d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
948d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
958d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guyvoid RenderBufferCache::clear() {
96bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck    for (auto entry : mCache) {
97bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        deleteBuffer(entry.mBuffer);
988d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    }
998d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    mCache.clear();
1008d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
1018d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1028d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain GuyRenderBuffer* RenderBufferCache::get(GLenum format, const uint32_t width, const uint32_t height) {
103d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik    RenderBuffer* buffer = nullptr;
1048d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1058d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    RenderBufferEntry entry(format, width, height);
106bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck    auto iter = mCache.find(entry);
1078d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
108bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck    if (iter != mCache.end()) {
109bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        entry = *iter;
110bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        mCache.erase(iter);
1118d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1128d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        buffer = entry.mBuffer;
1138d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        mSize -= buffer->getSize();
1148d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        RENDER_BUFFER_LOGD("Found %s render buffer (%dx%d)", RenderBuffer::formatName(format),
1161bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           width, height);
1178d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    } else {
1188d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        buffer = new RenderBuffer(format, width, height);
1198d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        RENDER_BUFFER_LOGD("Created new %s render buffer (%dx%d)", RenderBuffer::formatName(format),
1211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           width, height);
1228d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    }
1238d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1248d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    buffer->bind();
1258d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    buffer->allocate();
1268d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1278d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    return buffer;
1288d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
1298d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1308d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guybool RenderBufferCache::put(RenderBuffer* buffer) {
1318d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    if (!buffer) return false;
1328d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1338d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    const uint32_t size = buffer->getSize();
1348d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    if (size < mMaxSize) {
1358d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        while (mSize + size > mMaxSize) {
136bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck            RenderBuffer* victim = mCache.begin()->mBuffer;
1378d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy            deleteBuffer(victim);
138bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck            mCache.erase(mCache.begin());
1398d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        }
1408d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1418d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        RenderBufferEntry entry(buffer);
1428d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
143bef837dc57b47fd7fcc17c86d741cf77eac4487bJohn Reck        mCache.insert(entry);
1448d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        mSize += size;
1458d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1468d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        RENDER_BUFFER_LOGD("Added %s render buffer (%dx%d)",
1471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
1481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           buffer->getHeight());
1498d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1508d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        return true;
151e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung    } else {
152e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung        RENDER_BUFFER_LOGD("Deleted %s render buffer (%dx%d) Size=%d, MaxSize=%d",
1531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           RenderBuffer::formatName(buffer->getFormat()), buffer->getWidth(),
1541bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                           buffer->getHeight(), size, mMaxSize);
155e11f3ab000ec8d71e816aea7f266a3ceafebfd56Samsung        delete buffer;
1568d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    }
1578d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    return false;
1588d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
1598d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy
1601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace uirenderer
1611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace android
162