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