OSDN Git Service

am fd395ce7: am d0077829: am fb397cf8: (-s ours) Merge "Frameworks/base: Support...
[android-x86/frameworks-base.git] / libs / hwui / Caches.cpp
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 "DisplayListRenderer.h"
22 #include "GammaFontRenderer.h"
23 #include "LayerRenderer.h"
24 #include "Properties.h"
25 #include "renderstate/RenderState.h"
26 #include "ShadowTessellator.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     initProperties();
62     initStaticProperties();
63     initExtensions();
64     initTempProperties();
65
66     mDebugLevel = readDebugLevel();
67     ALOGD_IF(mDebugLevel != kDebugDisabled,
68             "Enabling debug mode %d", mDebugLevel);
69 }
70
71 bool Caches::init() {
72     if (mInitialized) return false;
73
74     ATRACE_NAME("Caches::init");
75
76     mRegionMesh = nullptr;
77     mProgram = nullptr;
78
79     mFunctorsCount = 0;
80
81     debugLayersUpdates = false;
82     debugOverdraw = false;
83     debugStencilClip = kStencilHide;
84
85     patchCache.init();
86
87     mInitialized = true;
88
89     mPixelBufferState = new PixelBufferState();
90     mTextureState = new TextureState();
91
92     return true;
93 }
94
95 void Caches::initFont() {
96     fontRenderer = GammaFontRenderer::createRenderer();
97 }
98
99 void Caches::initExtensions() {
100     if (mExtensions.hasDebugMarker()) {
101         eventMark = glInsertEventMarkerEXT;
102
103         startMark = glPushGroupMarkerEXT;
104         endMark = glPopGroupMarkerEXT;
105     } else {
106         eventMark = eventMarkNull;
107         startMark = startMarkNull;
108         endMark = endMarkNull;
109     }
110 }
111
112 void Caches::initConstraints() {
113     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
114 }
115
116 void Caches::initStaticProperties() {
117     gpuPixelBuffersEnabled = false;
118
119     // OpenGL ES 3.0+ specific features
120     if (mExtensions.hasPixelBufferObjects()) {
121         char property[PROPERTY_VALUE_MAX];
122         if (property_get(PROPERTY_ENABLE_GPU_PIXEL_BUFFERS, property, "true") > 0) {
123             gpuPixelBuffersEnabled = !strcmp(property, "true");
124         }
125     }
126 }
127
128 bool Caches::initProperties() {
129     bool prevDebugLayersUpdates = debugLayersUpdates;
130     bool prevDebugOverdraw = debugOverdraw;
131     StencilClipDebug prevDebugStencilClip = debugStencilClip;
132
133     char property[PROPERTY_VALUE_MAX];
134     if (property_get(PROPERTY_DEBUG_LAYERS_UPDATES, property, nullptr) > 0) {
135         INIT_LOGD("  Layers updates debug enabled: %s", property);
136         debugLayersUpdates = !strcmp(property, "true");
137     } else {
138         debugLayersUpdates = false;
139     }
140
141     debugOverdraw = false;
142     if (property_get(PROPERTY_DEBUG_OVERDRAW, property, nullptr) > 0) {
143         INIT_LOGD("  Overdraw debug enabled: %s", property);
144         if (!strcmp(property, "show")) {
145             debugOverdraw = true;
146             mOverdrawDebugColorSet = kColorSet_Default;
147         } else if (!strcmp(property, "show_deuteranomaly")) {
148             debugOverdraw = true;
149             mOverdrawDebugColorSet = kColorSet_Deuteranomaly;
150         }
151     }
152
153     // See Properties.h for valid values
154     if (property_get(PROPERTY_DEBUG_STENCIL_CLIP, property, nullptr) > 0) {
155         INIT_LOGD("  Stencil clip debug enabled: %s", property);
156         if (!strcmp(property, "hide")) {
157             debugStencilClip = kStencilHide;
158         } else if (!strcmp(property, "highlight")) {
159             debugStencilClip = kStencilShowHighlight;
160         } else if (!strcmp(property, "region")) {
161             debugStencilClip = kStencilShowRegion;
162         }
163     } else {
164         debugStencilClip = kStencilHide;
165     }
166
167     if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) {
168         drawDeferDisabled = !strcasecmp(property, "true");
169         INIT_LOGD("  Draw defer %s", drawDeferDisabled ? "disabled" : "enabled");
170     } else {
171         drawDeferDisabled = false;
172         INIT_LOGD("  Draw defer enabled");
173     }
174
175     if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) {
176         drawReorderDisabled = !strcasecmp(property, "true");
177         INIT_LOGD("  Draw reorder %s", drawReorderDisabled ? "disabled" : "enabled");
178     } else {
179         drawReorderDisabled = false;
180         INIT_LOGD("  Draw reorder enabled");
181     }
182
183     return (prevDebugLayersUpdates != debugLayersUpdates)
184             || (prevDebugOverdraw != debugOverdraw)
185             || (prevDebugStencilClip != debugStencilClip);
186 }
187
188 void Caches::terminate() {
189     if (!mInitialized) return;
190     mRegionMesh.release();
191
192     fboCache.clear();
193
194     programCache.clear();
195     mProgram = nullptr;
196
197     patchCache.clear();
198
199     clearGarbage();
200
201     delete mPixelBufferState;
202     mPixelBufferState = nullptr;
203     delete mTextureState;
204     mTextureState = nullptr;
205     mInitialized = false;
206 }
207
208 void Caches::setProgram(const ProgramDescription& description) {
209     setProgram(programCache.get(description));
210 }
211
212 void Caches::setProgram(Program* program) {
213     if (!program || !program->isInUse()) {
214         if (mProgram) {
215             mProgram->remove();
216         }
217         if (program) {
218             program->use();
219         }
220         mProgram = program;
221     }
222 }
223
224 ///////////////////////////////////////////////////////////////////////////////
225 // Debug
226 ///////////////////////////////////////////////////////////////////////////////
227
228 uint32_t Caches::getOverdrawColor(uint32_t amount) const {
229     static uint32_t sOverdrawColors[2][4] = {
230             { 0x2f0000ff, 0x2f00ff00, 0x3fff0000, 0x7fff0000 },
231             { 0x2f0000ff, 0x4fffff00, 0x5fff8ad8, 0x7fff0000 }
232     };
233     if (amount < 1) amount = 1;
234     if (amount > 4) amount = 4;
235     return sOverdrawColors[mOverdrawDebugColorSet][amount - 1];
236 }
237
238 void Caches::dumpMemoryUsage() {
239     String8 stringLog;
240     dumpMemoryUsage(stringLog);
241     ALOGD("%s", stringLog.string());
242 }
243
244 void Caches::dumpMemoryUsage(String8 &log) {
245     uint32_t total = 0;
246     log.appendFormat("Current memory usage / total memory usage (bytes):\n");
247     log.appendFormat("  TextureCache         %8d / %8d\n",
248             textureCache.getSize(), textureCache.getMaxSize());
249     log.appendFormat("  LayerCache           %8d / %8d (numLayers = %zu)\n",
250             layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount());
251     if (mRenderState) {
252         int memused = 0;
253         for (std::set<Layer*>::iterator it = mRenderState->mActiveLayers.begin();
254                 it != mRenderState->mActiveLayers.end(); it++) {
255             const Layer* layer = *it;
256             log.appendFormat("    Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n",
257                     layer->getWidth(), layer->getHeight(),
258                     layer->isTextureLayer(), layer->getTextureId(),
259                     layer->getFbo(), layer->getStrongCount());
260             memused += layer->getWidth() * layer->getHeight() * 4;
261         }
262         log.appendFormat("  Layers total   %8d (numLayers = %zu)\n",
263                 memused, mRenderState->mActiveLayers.size());
264         total += memused;
265     }
266     log.appendFormat("  RenderBufferCache    %8d / %8d\n",
267             renderBufferCache.getSize(), renderBufferCache.getMaxSize());
268     log.appendFormat("  GradientCache        %8d / %8d\n",
269             gradientCache.getSize(), gradientCache.getMaxSize());
270     log.appendFormat("  PathCache            %8d / %8d\n",
271             pathCache.getSize(), pathCache.getMaxSize());
272     log.appendFormat("  TessellationCache    %8d / %8d\n",
273             tessellationCache.getSize(), tessellationCache.getMaxSize());
274     log.appendFormat("  TextDropShadowCache  %8d / %8d\n", dropShadowCache.getSize(),
275             dropShadowCache.getMaxSize());
276     log.appendFormat("  PatchCache           %8d / %8d\n",
277             patchCache.getSize(), patchCache.getMaxSize());
278     for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
279         const uint32_t sizeA8 = fontRenderer->getFontRendererSize(i, GL_ALPHA);
280         const uint32_t sizeRGBA = fontRenderer->getFontRendererSize(i, GL_RGBA);
281         log.appendFormat("  FontRenderer %d A8    %8d / %8d\n", i, sizeA8, sizeA8);
282         log.appendFormat("  FontRenderer %d RGBA  %8d / %8d\n", i, sizeRGBA, sizeRGBA);
283         log.appendFormat("  FontRenderer %d total %8d / %8d\n", i, sizeA8 + sizeRGBA,
284                 sizeA8 + sizeRGBA);
285     }
286     log.appendFormat("Other:\n");
287     log.appendFormat("  FboCache             %8d / %8d\n",
288             fboCache.getSize(), fboCache.getMaxSize());
289
290     total += textureCache.getSize();
291     total += renderBufferCache.getSize();
292     total += gradientCache.getSize();
293     total += pathCache.getSize();
294     total += tessellationCache.getSize();
295     total += dropShadowCache.getSize();
296     total += patchCache.getSize();
297     for (uint32_t i = 0; i < fontRenderer->getFontRendererCount(); i++) {
298         total += fontRenderer->getFontRendererSize(i, GL_ALPHA);
299         total += fontRenderer->getFontRendererSize(i, GL_RGBA);
300     }
301
302     log.appendFormat("Total memory usage:\n");
303     log.appendFormat("  %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
304 }
305
306 ///////////////////////////////////////////////////////////////////////////////
307 // Memory management
308 ///////////////////////////////////////////////////////////////////////////////
309
310 void Caches::clearGarbage() {
311     textureCache.clearGarbage();
312     pathCache.clearGarbage();
313     patchCache.clearGarbage();
314 }
315
316 void Caches::flush(FlushMode mode) {
317     FLUSH_LOGD("Flushing caches (mode %d)", mode);
318
319     // We must stop tasks before clearing caches
320     if (mode > kFlushMode_Layers) {
321         tasks.stop();
322     }
323
324     switch (mode) {
325         case kFlushMode_Full:
326             textureCache.clear();
327             patchCache.clear();
328             dropShadowCache.clear();
329             gradientCache.clear();
330             fontRenderer->clear();
331             fboCache.clear();
332             dither.clear();
333             // fall through
334         case kFlushMode_Moderate:
335             fontRenderer->flush();
336             textureCache.flush();
337             pathCache.clear();
338             tessellationCache.clear();
339             // fall through
340         case kFlushMode_Layers:
341             layerCache.clear();
342             renderBufferCache.clear();
343             break;
344     }
345
346     clearGarbage();
347     glFinish();
348 }
349
350 ///////////////////////////////////////////////////////////////////////////////
351 // Tiling
352 ///////////////////////////////////////////////////////////////////////////////
353
354 void Caches::startTiling(GLuint x, GLuint y, GLuint width, GLuint height, bool discard) {
355     if (mExtensions.hasTiledRendering() && !debugOverdraw) {
356         glStartTilingQCOM(x, y, width, height, (discard ? GL_NONE : GL_COLOR_BUFFER_BIT0_QCOM));
357     }
358 }
359
360 void Caches::endTiling() {
361     if (mExtensions.hasTiledRendering() && !debugOverdraw) {
362         glEndTilingQCOM(GL_COLOR_BUFFER_BIT0_QCOM);
363     }
364 }
365
366 bool Caches::hasRegisteredFunctors() {
367     return mFunctorsCount > 0;
368 }
369
370 void Caches::registerFunctors(uint32_t functorCount) {
371     mFunctorsCount += functorCount;
372 }
373
374 void Caches::unregisterFunctors(uint32_t functorCount) {
375     if (functorCount > mFunctorsCount) {
376         mFunctorsCount = 0;
377     } else {
378         mFunctorsCount -= functorCount;
379     }
380 }
381
382 ///////////////////////////////////////////////////////////////////////////////
383 // Regions
384 ///////////////////////////////////////////////////////////////////////////////
385
386 TextureVertex* Caches::getRegionMesh() {
387     // Create the mesh, 2 triangles and 4 vertices per rectangle in the region
388     if (!mRegionMesh) {
389         mRegionMesh.reset(new TextureVertex[kMaxNumberOfQuads * 4]);
390     }
391
392     return mRegionMesh.get();
393 }
394
395 ///////////////////////////////////////////////////////////////////////////////
396 // Temporary Properties
397 ///////////////////////////////////////////////////////////////////////////////
398
399 void Caches::initTempProperties() {
400     propertyLightRadius = -1.0f;
401     propertyLightPosY = -1.0f;
402     propertyLightPosZ = -1.0f;
403     propertyAmbientRatio = -1.0f;
404     propertyAmbientShadowStrength = -1;
405     propertySpotShadowStrength = -1;
406 }
407
408 void Caches::setTempProperty(const char* name, const char* value) {
409     ALOGD("setting property %s to %s", name, value);
410     if (!strcmp(name, "ambientRatio")) {
411         propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0);
412         ALOGD("ambientRatio = %.2f", propertyAmbientRatio);
413         return;
414     } else if (!strcmp(name, "lightRadius")) {
415         propertyLightRadius = fmin(fmax(atof(value), 0.0), 3000.0);
416         ALOGD("lightRadius = %.2f", propertyLightRadius);
417         return;
418     } else if (!strcmp(name, "lightPosY")) {
419         propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
420         ALOGD("lightPos Y = %.2f", propertyLightPosY);
421         return;
422     } else if (!strcmp(name, "lightPosZ")) {
423         propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
424         ALOGD("lightPos Z = %.2f", propertyLightPosZ);
425         return;
426     } else if (!strcmp(name, "ambientShadowStrength")) {
427         propertyAmbientShadowStrength = atoi(value);
428         ALOGD("ambient shadow strength = 0x%x out of 0xff", propertyAmbientShadowStrength);
429         return;
430     } else if (!strcmp(name, "spotShadowStrength")) {
431         propertySpotShadowStrength = atoi(value);
432         ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength);
433         return;
434     }
435     ALOGD("    failed");
436 }
437
438 }; // namespace uirenderer
439 }; // namespace android