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 #include "Caches.h"
     18 
     19 #include "GammaFontRenderer.h"
     20 #include "LayerRenderer.h"
     21 #include "Properties.h"
     22 #include "renderstate/RenderState.h"
     23 #include "ShadowTessellator.h"
     24 #ifdef BUGREPORT_FONT_CACHE_USAGE
     25 #include "font/FontCacheHistoryTracker.h"
     26 #endif
     27 #include "utils/GLUtils.h"
     28 
     29 #include <cutils/properties.h>
     30 #include <utils/Log.h>
     31 #include <utils/String8.h>
     32 
     33 namespace android {
     34 namespace uirenderer {
     35 
     36 Caches* Caches::sInstance = nullptr;
     37 
     38 ///////////////////////////////////////////////////////////////////////////////
     39 // Macros
     40 ///////////////////////////////////////////////////////////////////////////////
     41 
     42 #if DEBUG_CACHE_FLUSH
     43     #define FLUSH_LOGD(...) ALOGD(__VA_ARGS__)
     44 #else
     45     #define FLUSH_LOGD(...)
     46 #endif
     47 
     48 ///////////////////////////////////////////////////////////////////////////////
     49 // Constructors/destructor
     50 ///////////////////////////////////////////////////////////////////////////////
     51 
     52 Caches::Caches(RenderState& renderState)
     53         : gradientCache(mExtensions)
     54         , patchCache(renderState)
     55         , programCache(mExtensions)
     56         , dither(*this)
     57         , mRenderState(&renderState)
     58         , mInitialized(false) {
     59     INIT_LOGD("Creating OpenGL renderer caches");
     60     init();
     61     initConstraints();
     62     initStaticProperties();
     63     initExtensions();
     64 }
     65 
     66 bool Caches::init() {
     67     if (mInitialized) return false;
     68 
     69     ATRACE_NAME("Caches::init");
     70 
     71     mRegionMesh = nullptr;
     72     mProgram = nullptr;
     73 
     74     patchCache.init();
     75 
     76     mInitialized = true;
     77 
     78     mPixelBufferState = new PixelBufferState();
     79     mTextureState = new TextureState();
     80     mTextureState->constructTexture(*this);
     81 
     82     return true;
     83 }
     84 
     85 void Caches::initExtensions() {
     86     if (mExtensions.hasDebugMarker()) {
     87         eventMark = glInsertEventMarkerEXT;
     88 
     89         startMark = glPushGroupMarkerEXT;
     90         endMark = glPopGroupMarkerEXT;
     91     } else {
     92         eventMark = eventMarkNull;
     93         startMark = startMarkNull;
     94         endMark = endMarkNull;
     95     }
     96 }
     97 
     98 void Caches::initConstraints() {
     99     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
    100 }
    101 
    102 void Caches::initStaticProperties() {
    103     // OpenGL ES 3.0+ specific features
    104     gpuPixelBuffersEnabled = mExtensions.hasPixelBufferObjects()
    105             && property_get_bool(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, true);
    106 }
    107 
    108 void Caches::terminate() {
    109     if (!mInitialized) return;
    110     mRegionMesh.reset(nullptr);
    111 
    112     fboCache.clear();
    113 
    114     programCache.clear();
    115     mProgram = nullptr;
    116 
    117     patchCache.clear();
    118 
    119     clearGarbage();
    120 
    121     delete mPixelBufferState;
    122     mPixelBufferState = nullptr;
    123     delete mTextureState;
    124     mTextureState = nullptr;
    125     mInitialized = false;
    126 }
    127 
    128 void Caches::setProgram(const ProgramDescription& description) {
    129     setProgram(programCache.get(description));
    130 }
    131 
    132 void Caches::setProgram(Program* program) {
    133     if (!program || !program->isInUse()) {
    134         if (mProgram) {
    135             mProgram->remove();
    136         }
    137         if (program) {
    138             program->use();
    139         }
    140         mProgram = program;
    141     }
    142 }
    143 
    144 ///////////////////////////////////////////////////////////////////////////////
    145 // Debug
    146 ///////////////////////////////////////////////////////////////////////////////
    147 
    148 uint32_t Caches::getOverdrawColor(uint32_t amount) const {
    149     static uint32_t sOverdrawColors[2][4] = {
    150             { 0x2f0000ff, 0x2f00ff00, 0x3fff0000, 0x7fff0000 },
    151             { 0x2f0000ff, 0x4fffff00, 0x5fff8ad8, 0x7fff0000 }
    152     };
    153     if (amount < 1) amount = 1;
    154     if (amount > 4) amount = 4;
    155 
    156     int overdrawColorIndex = static_cast<int>(Properties::overdrawColorSet);
    157     return sOverdrawColors[overdrawColorIndex][amount - 1];
    158 }
    159 
    160 void Caches::dumpMemoryUsage() {
    161     String8 stringLog;
    162     dumpMemoryUsage(stringLog);
    163     ALOGD("%s", stringLog.string());
    164 }
    165 
    166 void Caches::dumpMemoryUsage(String8 &log) {
    167     uint32_t total = 0;
    168     log.appendFormat("Current memory usage / total memory usage (bytes):\n");
    169     log.appendFormat("  TextureCache         %8d / %8d\n",
    170             textureCache.getSize(), textureCache.getMaxSize());
    171     log.appendFormat("  LayerCache           %8d / %8d (numLayers = %zu)\n",
    172             layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
    173     if (mRenderState) {
    174         int memused = 0;
    175         for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
    176                 it != mRenderState->mActiveLayers.end(); it++) {
    177             const Layer* layer = *it;
    178             log.appendFormat("    Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
    179                     layer->getWidth(), layer->getHeight(),
    180                     layer->isTextureLayer(), layer->getTextureId(),
    181                     layer->getFbo(), layer->getStrongCount());
    182             memused += layer->getWidth() * layer->getHeight() * 4;
    183         }
    184         log.appendFormat("  Layers total   %8d (numLayers = %zu)\n",
    185                 memused, mRenderState->mActiveLayers.size());
    186         total += memused;
    187     }
    188     log.appendFormat("  RenderBufferCache    %8d / %8d\n",
    189             renderBufferCache.getSize(), renderBufferCache.getMaxSize());
    190     log.appendFormat("  GradientCache        %8d / %8d\n",
    191             gradientCache.getSize(), gradientCache.getMaxSize());
    192     log.appendFormat("  PathCache            %8d / %8d\n",
    193             pathCache.getSize(), pathCache.getMaxSize());
    194     log.appendFormat("  TessellationCache    %8d / %8d\n",
    195             tessellationCache.getSize(), tessellationCache.getMaxSize());
    196     log.appendFormat("  TextDropShadowCache  %8d / %8d\n", dropShadowCache.getSize(),
    197             dropShadowCache.getMaxSize());
    198     log.appendFormat("  PatchCache           %8d / %8d\n",
    199             patchCache.getSize(), patchCache.getMaxSize());
    200 
    201     fontRenderer.dumpMemoryUsage(log);
    202 
    203     log.appendFormat("Other:\n");
    204     log.appendFormat("  FboCache             %8d / %8d\n",
    205             fboCache.getSize(), fboCache.getMaxSize());
    206 
    207     total += textureCache.getSize();
    208     total += renderBufferCache.getSize();
    209     total += gradientCache.getSize();
    210     total += pathCache.getSize();
    211     total += tessellationCache.getSize();
    212     total += dropShadowCache.getSize();
    213     total += patchCache.getSize();
    214     total += fontRenderer.getSize();
    215 
    216     log.appendFormat("Total memory usage:\n");
    217     log.appendFormat("  %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
    218 
    219 #ifdef BUGREPORT_FONT_CACHE_USAGE
    220     fontRenderer.getFontRenderer().historyTracker().dump(log);
    221 #endif
    222 }
    223 
    224 ///////////////////////////////////////////////////////////////////////////////
    225 // Memory management
    226 ///////////////////////////////////////////////////////////////////////////////
    227 
    228 void Caches::clearGarbage() {
    229     textureCache.clearGarbage();
    230     pathCache.clearGarbage();
    231     patchCache.clearGarbage();
    232 }
    233 
    234 void Caches::flush(FlushMode mode) {
    235     FLUSH_LOGD("Flushing caches (mode %d)", mode);
    236 
    237     switch (mode) {
    238         case FlushMode::Full:
    239             textureCache.clear();
    240             patchCache.clear();
    241             dropShadowCache.clear();
    242             gradientCache.clear();
    243             fontRenderer.clear();
    244             fboCache.clear();
    245             dither.clear();
    246             // fall through
    247         case FlushMode::Moderate:
    248             fontRenderer.flush();
    249             textureCache.flush();
    250             pathCache.clear();
    251             tessellationCache.clear();
    252             // fall through
    253         case FlushMode::Layers:
    254             layerCache.clear();
    255             renderBufferCache.clear();
    256             break;
    257     }
    258 
    259     clearGarbage();
    260     glFinish();
    261     // Errors during cleanup should be considered non-fatal, dump them and
    262     // and move on. TODO: All errors or just errors like bad surface?
    263     GLUtils::dumpGLErrors();
    264 }
    265 
    266 ///////////////////////////////////////////////////////////////////////////////
    267 // Regions
    268 ///////////////////////////////////////////////////////////////////////////////
    269 
    270 TextureVertex* Caches::getRegionMesh() {
    271     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
    272     if (!mRegionMesh) {
    273         mRegionMesh.reset(new TextureVertex[kMaxNumberOfQuads * 4]);
    274     }
    275 
    276     return mRegionMesh.get();
    277 }
    278 
    279 ///////////////////////////////////////////////////////////////////////////////
    280 // Temporary Properties
    281 ///////////////////////////////////////////////////////////////////////////////
    282 
    283 }; // namespace uirenderer
    284 }; // namespace android
    285