Caches.cpp revision af102bee518191f1e6ad843f06dcd7a64611462d
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
33namespace android {
34namespace uirenderer {
35
36Caches* 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
52Caches::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
66bool 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
85void 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
98void Caches::initConstraints() {
99    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
100}
101
102void 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
108void 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
128void Caches::setProgram(const ProgramDescription& description) {
129    setProgram(programCache.get(description));
130}
131
132void 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
148uint32_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
160void Caches::dumpMemoryUsage() {
161    String8 stringLog;
162    dumpMemoryUsage(stringLog);
163    ALOGD("%s", stringLog.string());
164}
165
166void 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
228void Caches::clearGarbage() {
229    textureCache.clearGarbage();
230    pathCache.clearGarbage();
231    patchCache.clearGarbage();
232}
233
234void 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
270TextureVertex* 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