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