Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2010 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 #include <utils/String8.h>
     21 
     22 #include "Caches.h"
     23 #include "Properties.h"
     24 #include "LayerRenderer.h"
     25 
     26 namespace android {
     27 
     28 #ifdef USE_OPENGL_RENDERER
     29 using namespace uirenderer;
     30 ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
     31 #endif
     32 
     33 namespace uirenderer {
     34 
     35 ///////////////////////////////////////////////////////////////////////////////
     36 // Macros
     37 ///////////////////////////////////////////////////////////////////////////////
     38 
     39 #if DEBUG_CACHE_FLUSH
     40     #define FLUSH_LOGD(...) LOGD(__VA_ARGS__)
     41 #else
     42     #define FLUSH_LOGD(...)
     43 #endif
     44 
     45 ///////////////////////////////////////////////////////////////////////////////
     46 // Constructors/destructor
     47 ///////////////////////////////////////////////////////////////////////////////
     48 
     49 Caches::Caches(): Singleton<Caches>(), mInitialized(false) {
     50     GLint maxTextureUnits;
     51     glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
     52     if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
     53         LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
     54     }
     55 
     56     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
     57 
     58     init();
     59 
     60     mDebugLevel = readDebugLevel();
     61     LOGD("Enabling debug mode %d", mDebugLevel);
     62 
     63 #if RENDER_LAYERS_AS_REGIONS
     64     INIT_LOGD("Layers will be composited as regions");
     65 #endif
     66 }
     67 
     68 void Caches::init() {
     69     if (mInitialized) return;
     70 
     71     glGenBuffers(1, &meshBuffer);
     72     glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
     73     glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
     74 
     75     mCurrentBuffer = meshBuffer;
     76     mRegionMesh = NULL;
     77 
     78     blend = false;
     79     lastSrcMode = GL_ZERO;
     80     lastDstMode = GL_ZERO;
     81     currentProgram = NULL;
     82 
     83     mInitialized = true;
     84 }
     85 
     86 void Caches::terminate() {
     87     if (!mInitialized) return;
     88 
     89     glDeleteBuffers(1, &meshBuffer);
     90     mCurrentBuffer = 0;
     91 
     92     glDeleteBuffers(1, &mRegionMeshIndices);
     93     delete[] mRegionMesh;
     94     mRegionMesh = NULL;
     95 
     96     fboCache.clear();
     97 
     98     programCache.clear();
     99     currentProgram = NULL;
    100 
    101     mInitialized = false;
    102 }
    103 
    104 ///////////////////////////////////////////////////////////////////////////////
    105 // Debug
    106 ///////////////////////////////////////////////////////////////////////////////
    107 
    108 void Caches::dumpMemoryUsage() {
    109     String8 stringLog;
    110     dumpMemoryUsage(stringLog);
    111     LOGD("%s", stringLog.string());
    112 }
    113 
    114 void Caches::dumpMemoryUsage(String8 &log) {
    115     log.appendFormat("Current memory usage / total memory usage (bytes):\n");
    116     log.appendFormat("  TextureCache         %8d / %8d\n",
    117             textureCache.getSize(), textureCache.getMaxSize());
    118     log.appendFormat("  LayerCache           %8d / %8d\n",
    119             layerCache.getSize(), layerCache.getMaxSize());
    120     log.appendFormat("  GradientCache        %8d / %8d\n",
    121             gradientCache.getSize(), gradientCache.getMaxSize());
    122     log.appendFormat("  PathCache            %8d / %8d\n",
    123             pathCache.getSize(), pathCache.getMaxSize());
    124     log.appendFormat("  CircleShapeCache     %8d / %8d\n",
    125             circleShapeCache.getSize(), circleShapeCache.getMaxSize());
    126     log.appendFormat("  OvalShapeCache       %8d / %8d\n",
    127             ovalShapeCache.getSize(), ovalShapeCache.getMaxSize());
    128     log.appendFormat("  RoundRectShapeCache  %8d / %8d\n",
    129             roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
    130     log.appendFormat("  RectShapeCache       %8d / %8d\n",
    131             rectShapeCache.getSize(), rectShapeCache.getMaxSize());
    132     log.appendFormat("  ArcShapeCache        %8d / %8d\n",
    133             arcShapeCache.getSize(), arcShapeCache.getMaxSize());
    134     log.appendFormat("  TextDropShadowCache  %8d / %8d\n", dropShadowCache.getSize(),
    135             dropShadowCache.getMaxSize());
    136     for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
    137         const uint32_t size = fontRenderer.getFontRendererSize(i);
    138         log.appendFormat("  FontRenderer %d       %8d / %8d\n", i, size, size);
    139     }
    140     log.appendFormat("Other:\n");
    141     log.appendFormat("  FboCache             %8d / %8d\n",
    142             fboCache.getSize(), fboCache.getMaxSize());
    143     log.appendFormat("  PatchCache           %8d / %8d\n",
    144             patchCache.getSize(), patchCache.getMaxSize());
    145 
    146     uint32_t total = 0;
    147     total += textureCache.getSize();
    148     total += layerCache.getSize();
    149     total += gradientCache.getSize();
    150     total += pathCache.getSize();
    151     total += dropShadowCache.getSize();
    152     total += roundRectShapeCache.getSize();
    153     total += circleShapeCache.getSize();
    154     total += ovalShapeCache.getSize();
    155     total += rectShapeCache.getSize();
    156     total += arcShapeCache.getSize();
    157     for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
    158         total += fontRenderer.getFontRendererSize(i);
    159     }
    160 
    161     log.appendFormat("Total memory usage:\n");
    162     log.appendFormat("  %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
    163 }
    164 
    165 ///////////////////////////////////////////////////////////////////////////////
    166 // Memory management
    167 ///////////////////////////////////////////////////////////////////////////////
    168 
    169 void Caches::clearGarbage() {
    170     textureCache.clearGarbage();
    171     pathCache.clearGarbage();
    172 
    173     Mutex::Autolock _l(mGarbageLock);
    174 
    175     size_t count = mLayerGarbage.size();
    176     for (size_t i = 0; i < count; i++) {
    177         Layer* layer = mLayerGarbage.itemAt(i);
    178         LayerRenderer::destroyLayer(layer);
    179     }
    180     mLayerGarbage.clear();
    181 }
    182 
    183 void Caches::deleteLayerDeferred(Layer* layer) {
    184     Mutex::Autolock _l(mGarbageLock);
    185     mLayerGarbage.push(layer);
    186 }
    187 
    188 void Caches::flush(FlushMode mode) {
    189     FLUSH_LOGD("Flushing caches (mode %d)", mode);
    190 
    191     clearGarbage();
    192 
    193     switch (mode) {
    194         case kFlushMode_Full:
    195             textureCache.clear();
    196             patchCache.clear();
    197             dropShadowCache.clear();
    198             gradientCache.clear();
    199             fontRenderer.clear();
    200             // fall through
    201         case kFlushMode_Moderate:
    202             fontRenderer.flush();
    203             textureCache.flush();
    204             pathCache.clear();
    205             roundRectShapeCache.clear();
    206             circleShapeCache.clear();
    207             ovalShapeCache.clear();
    208             rectShapeCache.clear();
    209             arcShapeCache.clear();
    210             // fall through
    211         case kFlushMode_Layers:
    212             layerCache.clear();
    213             break;
    214     }
    215 }
    216 
    217 ///////////////////////////////////////////////////////////////////////////////
    218 // VBO
    219 ///////////////////////////////////////////////////////////////////////////////
    220 
    221 void Caches::bindMeshBuffer() {
    222     bindMeshBuffer(meshBuffer);
    223 }
    224 
    225 void Caches::bindMeshBuffer(const GLuint buffer) {
    226     if (mCurrentBuffer != buffer) {
    227         glBindBuffer(GL_ARRAY_BUFFER, buffer);
    228         mCurrentBuffer = buffer;
    229     }
    230 }
    231 
    232 void Caches::unbindMeshBuffer() {
    233     if (mCurrentBuffer) {
    234         glBindBuffer(GL_ARRAY_BUFFER, 0);
    235         mCurrentBuffer = 0;
    236     }
    237 }
    238 
    239 TextureVertex* Caches::getRegionMesh() {
    240     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
    241     if (!mRegionMesh) {
    242         mRegionMesh = new TextureVertex[REGION_MESH_QUAD_COUNT * 4];
    243 
    244         uint16_t* regionIndices = new uint16_t[REGION_MESH_QUAD_COUNT * 6];
    245         for (int i = 0; i < REGION_MESH_QUAD_COUNT; i++) {
    246             uint16_t quad = i * 4;
    247             int index = i * 6;
    248             regionIndices[index    ] = quad;       // top-left
    249             regionIndices[index + 1] = quad + 1;   // top-right
    250             regionIndices[index + 2] = quad + 2;   // bottom-left
    251             regionIndices[index + 3] = quad + 2;   // bottom-left
    252             regionIndices[index + 4] = quad + 1;   // top-right
    253             regionIndices[index + 5] = quad + 3;   // bottom-right
    254         }
    255 
    256         glGenBuffers(1, &mRegionMeshIndices);
    257         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mRegionMeshIndices);
    258         glBufferData(GL_ELEMENT_ARRAY_BUFFER, REGION_MESH_QUAD_COUNT * 6 * sizeof(uint16_t),
    259                 regionIndices, GL_STATIC_DRAW);
    260 
    261         delete[] regionIndices;
    262     } else {
    263         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mRegionMeshIndices);
    264     }
    265 
    266     return mRegionMesh;
    267 }
    268 
    269 }; // namespace uirenderer
    270 }; // namespace android
    271