• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Caches(RenderState & renderState)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 
init()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 
initExtensions()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 
initConstraints()98 void Caches::initConstraints() {
99     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
100 }
101 
initStaticProperties()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 
terminate()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 
setProgram(const ProgramDescription & description)128 void Caches::setProgram(const ProgramDescription& description) {
129     setProgram(programCache.get(description));
130 }
131 
setProgram(Program * program)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 
getOverdrawColor(uint32_t amount) const148 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 
dumpMemoryUsage()160 void Caches::dumpMemoryUsage() {
161     String8 stringLog;
162     dumpMemoryUsage(stringLog);
163     ALOGD("%s", stringLog.string());
164 }
165 
dumpMemoryUsage(String8 & log)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 
clearGarbage()228 void Caches::clearGarbage() {
229     textureCache.clearGarbage();
230     pathCache.clearGarbage();
231     patchCache.clearGarbage();
232 }
233 
flush(FlushMode mode)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 
getRegionMesh()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