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