OSDN Git Service

am c5bd6146: (-s ours) am 8a50ecea: am 82fae621: LayoutLib: translucent sys ui bars...
[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 "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