blob: 868290bf0f8b16fa540f029d1fc795ad880ecf0a [file] [log] [blame]
Romain Guy4aa90572010-09-26 18:40:37 -07001/*
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 "DisplayListRenderer.h"
20
21namespace android {
22namespace uirenderer {
23
24///////////////////////////////////////////////////////////////////////////////
Romain Guyb051e892010-09-28 19:09:36 -070025// Display list
26///////////////////////////////////////////////////////////////////////////////
27
Romain Guyffac7fc2011-01-13 17:21:49 -080028const char* DisplayList::OP_NAMES[] = {
Romain Guyffac7fc2011-01-13 17:21:49 -080029 "Save",
30 "Restore",
31 "RestoreToCount",
32 "SaveLayer",
33 "SaveLayerAlpha",
34 "Translate",
35 "Rotate",
36 "Scale",
Romain Guy4cf6e2f2011-01-23 11:35:13 -080037 "Skew",
Romain Guyffac7fc2011-01-13 17:21:49 -080038 "SetMatrix",
39 "ConcatMatrix",
40 "ClipRect",
41 "DrawDisplayList",
42 "DrawLayer",
43 "DrawBitmap",
44 "DrawBitmapMatrix",
45 "DrawBitmapRect",
Romain Guy5a7b4662011-01-20 19:09:30 -080046 "DrawBitmapMesh",
Romain Guyffac7fc2011-01-13 17:21:49 -080047 "DrawPatch",
48 "DrawColor",
49 "DrawRect",
Romain Guy01d58e42011-01-19 21:54:02 -080050 "DrawRoundRect",
51 "DrawCircle",
Romain Guyc1cd9ba32011-01-23 14:18:41 -080052 "DrawOval",
Romain Guy8b2f5262011-01-23 16:15:02 -080053 "DrawArc",
Romain Guyffac7fc2011-01-13 17:21:49 -080054 "DrawPath",
55 "DrawLines",
56 "DrawText",
57 "ResetShader",
58 "SetupShader",
59 "ResetColorFilter",
60 "SetupColorFilter",
61 "ResetShadow",
Chet Haasedaf98e92011-01-10 14:10:36 -080062 "SetupShadow",
63 "DrawGLFunction"
Romain Guyffac7fc2011-01-13 17:21:49 -080064};
65
Romain Guyb051e892010-09-28 19:09:36 -070066DisplayList::DisplayList(const DisplayListRenderer& recorder) {
Chet Haase5977baa2011-01-05 18:01:22 -080067 initFromDisplayListRenderer(recorder);
68}
69
70DisplayList::~DisplayList() {
Chet Haased63cbd12011-02-03 16:32:46 -080071 clearResources();
72}
73
74void DisplayList::clearResources() {
Chet Haase5977baa2011-01-05 18:01:22 -080075 sk_free((void*) mReader.base());
76
77 Caches& caches = Caches::getInstance();
78
79 for (size_t i = 0; i < mBitmapResources.size(); i++) {
80 caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
81 }
82 mBitmapResources.clear();
83
Romain Guy24c00212011-01-14 15:31:00 -080084 for (size_t i = 0; i < mShaders.size(); i++) {
Romain Guy43ccf462011-01-14 18:51:01 -080085 caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
Chet Haase5977baa2011-01-05 18:01:22 -080086 }
Romain Guy24c00212011-01-14 15:31:00 -080087 mShaders.clear();
Chet Haase5977baa2011-01-05 18:01:22 -080088
89 for (size_t i = 0; i < mPaints.size(); i++) {
90 delete mPaints.itemAt(i);
91 }
92 mPaints.clear();
93
Romain Guy2fc941e2011-02-03 15:06:05 -080094 for (size_t i = 0; i < mPaths.size(); i++) {
95 delete mPaths.itemAt(i);
96 }
97 mPaths.clear();
Chet Haase5a7e8282011-02-04 12:50:55 -080098 for (size_t i = 0; i < mOriginalPaths.size(); i++) {
99 caches.resourceCache.decrementRefcount(mOriginalPaths.itemAt(i));
100 }
101 mOriginalPaths.clear();
Romain Guy2fc941e2011-02-03 15:06:05 -0800102
Chet Haase5977baa2011-01-05 18:01:22 -0800103 for (size_t i = 0; i < mMatrices.size(); i++) {
104 delete mMatrices.itemAt(i);
105 }
106 mMatrices.clear();
Chet Haase5977baa2011-01-05 18:01:22 -0800107}
108
Chet Haased63cbd12011-02-03 16:32:46 -0800109void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
Romain Guyb051e892010-09-28 19:09:36 -0700110 const SkWriter32& writer = recorder.writeStream();
111 init();
112
113 if (writer.size() == 0) {
114 return;
115 }
116
Chet Haased63cbd12011-02-03 16:32:46 -0800117 if (reusing) {
118 // re-using display list - clear out previous allocations
119 clearResources();
120 }
121
Romain Guyb051e892010-09-28 19:09:36 -0700122 size_t size = writer.size();
123 void* buffer = sk_malloc_throw(size);
124 writer.flatten(buffer);
125 mReader.setMemory(buffer, size);
126
Chet Haase5c13d892010-10-08 08:37:55 -0700127 Caches& caches = Caches::getInstance();
Romain Guyb051e892010-09-28 19:09:36 -0700128
Chet Haase5c13d892010-10-08 08:37:55 -0700129 const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources();
130 for (size_t i = 0; i < bitmapResources.size(); i++) {
131 SkBitmap* resource = bitmapResources.itemAt(i);
132 mBitmapResources.add(resource);
133 caches.resourceCache.incrementRefcount(resource);
Romain Guyb051e892010-09-28 19:09:36 -0700134 }
Chet Haased98aa2d2010-10-25 15:47:32 -0700135
Romain Guy24c00212011-01-14 15:31:00 -0800136 const Vector<SkiaShader*> &shaders = recorder.getShaders();
137 for (size_t i = 0; i < shaders.size(); i++) {
Romain Guy43ccf462011-01-14 18:51:01 -0800138 SkiaShader* shader = shaders.itemAt(i);
139 mShaders.add(shader);
140 caches.resourceCache.incrementRefcount(shader);
Romain Guyb051e892010-09-28 19:09:36 -0700141 }
142
Chet Haased98aa2d2010-10-25 15:47:32 -0700143 const Vector<SkPaint*> &paints = recorder.getPaints();
144 for (size_t i = 0; i < paints.size(); i++) {
145 mPaints.add(paints.itemAt(i));
146 }
147
Romain Guy2fc941e2011-02-03 15:06:05 -0800148 const Vector<SkPath*> &paths = recorder.getPaths();
149 for (size_t i = 0; i < paths.size(); i++) {
150 mPaths.add(paths.itemAt(i));
151 }
152
Chet Haase5a7e8282011-02-04 12:50:55 -0800153 const Vector<SkPath*> &originalPaths = recorder.getOriginalPaths();
154 for (size_t i = 0; i < originalPaths.size(); i++) {
155 SkPath* path = originalPaths.itemAt(i);
156 mOriginalPaths.add(path);
157 caches.resourceCache.incrementRefcount(path);
158 }
159
Chet Haased98aa2d2010-10-25 15:47:32 -0700160 const Vector<SkMatrix*> &matrices = recorder.getMatrices();
161 for (size_t i = 0; i < matrices.size(); i++) {
162 mMatrices.add(matrices.itemAt(i));
163 }
Romain Guyb051e892010-09-28 19:09:36 -0700164}
165
Romain Guyb051e892010-09-28 19:09:36 -0700166void DisplayList::init() {
Romain Guyb051e892010-09-28 19:09:36 -0700167}
168
Romain Guycabfcc12011-03-07 18:06:46 -0800169bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800170 bool needsInvalidate = false;
Romain Guyb051e892010-09-28 19:09:36 -0700171 TextContainer text;
172 mReader.rewind();
173
Romain Guyffac7fc2011-01-13 17:21:49 -0800174#if DEBUG_DISPLAY_LIST
175 uint32_t count = (level + 1) * 2;
176 char indent[count + 1];
177 for (uint32_t i = 0; i < count; i++) {
178 indent[i] = ' ';
179 }
180 indent[count] = '\0';
181 DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
182#endif
Romain Guyb051e892010-09-28 19:09:36 -0700183
Romain Guyffac7fc2011-01-13 17:21:49 -0800184 int saveCount = renderer.getSaveCount() - 1;
Romain Guyb051e892010-09-28 19:09:36 -0700185 while (!mReader.eof()) {
Romain Guy5b3b3522010-10-27 18:57:51 -0700186 int op = mReader.readInt();
Romain Guyffac7fc2011-01-13 17:21:49 -0800187
Romain Guy5b3b3522010-10-27 18:57:51 -0700188 switch (op) {
Chet Haasedaf98e92011-01-10 14:10:36 -0800189 case DrawGLFunction: {
190 Functor *functor = (Functor *) getInt();
191 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
Romain Guycabfcc12011-03-07 18:06:46 -0800192 needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
Chet Haasedaf98e92011-01-10 14:10:36 -0800193 }
194 break;
Romain Guyb051e892010-09-28 19:09:36 -0700195 case Save: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800196 int rendererNum = getInt();
197 DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
198 renderer.save(rendererNum);
Romain Guyb051e892010-09-28 19:09:36 -0700199 }
200 break;
201 case Restore: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800202 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guyb051e892010-09-28 19:09:36 -0700203 renderer.restore();
204 }
205 break;
206 case RestoreToCount: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800207 int restoreCount = saveCount + getInt();
208 DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
209 renderer.restoreToCount(restoreCount);
Romain Guyb051e892010-09-28 19:09:36 -0700210 }
211 break;
212 case SaveLayer: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800213 float f1 = getFloat();
214 float f2 = getFloat();
215 float f3 = getFloat();
216 float f4 = getFloat();
217 SkPaint* paint = getPaint();
218 int flags = getInt();
219 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
220 OP_NAMES[op], f1, f2, f3, f4, paint, flags);
221 renderer.saveLayer(f1, f2, f3, f4, paint, flags);
Romain Guyb051e892010-09-28 19:09:36 -0700222 }
223 break;
Romain Guy5b3b3522010-10-27 18:57:51 -0700224 case SaveLayerAlpha: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800225 float f1 = getFloat();
226 float f2 = getFloat();
227 float f3 = getFloat();
228 float f4 = getFloat();
229 int alpha = getInt();
230 int flags = getInt();
231 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
232 OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
233 renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags);
Romain Guy5b3b3522010-10-27 18:57:51 -0700234 }
235 break;
Romain Guyb051e892010-09-28 19:09:36 -0700236 case Translate: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800237 float f1 = getFloat();
238 float f2 = getFloat();
239 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
240 renderer.translate(f1, f2);
Romain Guyb051e892010-09-28 19:09:36 -0700241 }
242 break;
243 case Rotate: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800244 float rotation = getFloat();
245 DISPLAY_LIST_LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
246 renderer.rotate(rotation);
Romain Guyb051e892010-09-28 19:09:36 -0700247 }
248 break;
249 case Scale: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800250 float sx = getFloat();
251 float sy = getFloat();
252 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
253 renderer.scale(sx, sy);
Romain Guyb051e892010-09-28 19:09:36 -0700254 }
255 break;
Romain Guy807daf72011-01-18 11:19:19 -0800256 case Skew: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800257 float sx = getFloat();
258 float sy = getFloat();
259 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
260 renderer.skew(sx, sy);
Romain Guy807daf72011-01-18 11:19:19 -0800261 }
262 break;
Romain Guyb051e892010-09-28 19:09:36 -0700263 case SetMatrix: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800264 SkMatrix* matrix = getMatrix();
265 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
266 renderer.setMatrix(matrix);
Romain Guyb051e892010-09-28 19:09:36 -0700267 }
268 break;
269 case ConcatMatrix: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800270 SkMatrix* matrix = getMatrix();
271 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
272 renderer.concatMatrix(matrix);
Romain Guyb051e892010-09-28 19:09:36 -0700273 }
274 break;
275 case ClipRect: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800276 float f1 = getFloat();
277 float f2 = getFloat();
278 float f3 = getFloat();
279 float f4 = getFloat();
280 int regionOp = getInt();
281 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
282 f1, f2, f3, f4, regionOp);
283 renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
Romain Guyb051e892010-09-28 19:09:36 -0700284 }
285 break;
Romain Guy0fe478e2010-11-08 12:08:41 -0800286 case DrawDisplayList: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800287 DisplayList* displayList = getDisplayList();
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700288 uint32_t width = getUInt();
289 uint32_t height = getUInt();
290 DISPLAY_LIST_LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
291 displayList, width, height, level + 1);
292 needsInvalidate |= renderer.drawDisplayList(displayList, width, height,
293 dirty, level + 1);
Romain Guy0fe478e2010-11-08 12:08:41 -0800294 }
295 break;
Romain Guy6c319ca2011-01-11 14:29:25 -0800296 case DrawLayer: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800297 Layer* layer = (Layer*) getInt();
298 float x = getFloat();
299 float y = getFloat();
300 SkPaint* paint = getPaint();
301 DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
302 layer, x, y, paint);
303 renderer.drawLayer(layer, x, y, paint);
Romain Guy6c319ca2011-01-11 14:29:25 -0800304 }
305 break;
Romain Guyb051e892010-09-28 19:09:36 -0700306 case DrawBitmap: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800307 SkBitmap* bitmap = getBitmap();
308 float x = getFloat();
309 float y = getFloat();
310 SkPaint* paint = getPaint();
311 DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
312 bitmap, x, y, paint);
313 renderer.drawBitmap(bitmap, x, y, paint);
Romain Guyb051e892010-09-28 19:09:36 -0700314 }
315 break;
316 case DrawBitmapMatrix: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800317 SkBitmap* bitmap = getBitmap();
318 SkMatrix* matrix = getMatrix();
319 SkPaint* paint = getPaint();
320 DISPLAY_LIST_LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
321 bitmap, matrix, paint);
322 renderer.drawBitmap(bitmap, matrix, paint);
Romain Guyb051e892010-09-28 19:09:36 -0700323 }
324 break;
325 case DrawBitmapRect: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800326 SkBitmap* bitmap = getBitmap();
327 float f1 = getFloat();
328 float f2 = getFloat();
329 float f3 = getFloat();
330 float f4 = getFloat();
331 float f5 = getFloat();
332 float f6 = getFloat();
333 float f7 = getFloat();
334 float f8 = getFloat();
335 SkPaint* paint = getPaint();
336 DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
337 (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
338 renderer.drawBitmap(bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
Romain Guyb051e892010-09-28 19:09:36 -0700339 }
340 break;
Romain Guy5a7b4662011-01-20 19:09:30 -0800341 case DrawBitmapMesh: {
342 int verticesCount = 0;
343 uint32_t colorsCount = 0;
344
345 SkBitmap* bitmap = getBitmap();
346 uint32_t meshWidth = getInt();
347 uint32_t meshHeight = getInt();
348 float* vertices = getFloats(verticesCount);
349 bool hasColors = getInt();
350 int* colors = hasColors ? getInts(colorsCount) : NULL;
351
Chet Haasedaf98e92011-01-10 14:10:36 -0800352 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guy5a7b4662011-01-20 19:09:30 -0800353 renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
354 }
Romain Guya566b7c2011-01-23 16:36:11 -0800355 break;
Romain Guyb051e892010-09-28 19:09:36 -0700356 case DrawPatch: {
357 int32_t* xDivs = NULL;
358 int32_t* yDivs = NULL;
Romain Guy4bb94202010-10-12 15:59:26 -0700359 uint32_t* colors = NULL;
Romain Guyb051e892010-09-28 19:09:36 -0700360 uint32_t xDivsCount = 0;
361 uint32_t yDivsCount = 0;
Romain Guy4bb94202010-10-12 15:59:26 -0700362 int8_t numColors = 0;
Romain Guyb051e892010-09-28 19:09:36 -0700363
364 SkBitmap* bitmap = getBitmap();
365
366 xDivs = getInts(xDivsCount);
367 yDivs = getInts(yDivsCount);
Romain Guy4bb94202010-10-12 15:59:26 -0700368 colors = getUInts(numColors);
Romain Guyb051e892010-09-28 19:09:36 -0700369
Chet Haasedaf98e92011-01-10 14:10:36 -0800370 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guy4bb94202010-10-12 15:59:26 -0700371 renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
372 numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
Romain Guyb051e892010-09-28 19:09:36 -0700373 }
374 break;
375 case DrawColor: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800376 int color = getInt();
377 int xferMode = getInt();
378 DISPLAY_LIST_LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
379 renderer.drawColor(color, (SkXfermode::Mode) xferMode);
Romain Guyb051e892010-09-28 19:09:36 -0700380 }
381 break;
382 case DrawRect: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800383 float f1 = getFloat();
384 float f2 = getFloat();
385 float f3 = getFloat();
386 float f4 = getFloat();
387 SkPaint* paint = getPaint();
388 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
389 f1, f2, f3, f4, paint);
390 renderer.drawRect(f1, f2, f3, f4, paint);
Romain Guyb051e892010-09-28 19:09:36 -0700391 }
392 break;
Romain Guy01d58e42011-01-19 21:54:02 -0800393 case DrawRoundRect: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800394 float f1 = getFloat();
395 float f2 = getFloat();
396 float f3 = getFloat();
397 float f4 = getFloat();
398 float f5 = getFloat();
399 float f6 = getFloat();
400 SkPaint* paint = getPaint();
401 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
402 (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
403 renderer.drawRoundRect(f1, f2, f3, f4, f5, f6, paint);
Romain Guy01d58e42011-01-19 21:54:02 -0800404 }
405 break;
406 case DrawCircle: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800407 float f1 = getFloat();
408 float f2 = getFloat();
409 float f3 = getFloat();
410 SkPaint* paint = getPaint();
411 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %p",
412 (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
413 renderer.drawCircle(f1, f2, f3, paint);
Romain Guy01d58e42011-01-19 21:54:02 -0800414 }
415 break;
Romain Guyc1cd9ba32011-01-23 14:18:41 -0800416 case DrawOval: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800417 float f1 = getFloat();
418 float f2 = getFloat();
419 float f3 = getFloat();
420 float f4 = getFloat();
421 SkPaint* paint = getPaint();
422 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
423 (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
424 renderer.drawOval(f1, f2, f3, f4, paint);
Romain Guyc1cd9ba32011-01-23 14:18:41 -0800425 }
426 break;
Romain Guy8b2f5262011-01-23 16:15:02 -0800427 case DrawArc: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800428 float f1 = getFloat();
429 float f2 = getFloat();
430 float f3 = getFloat();
431 float f4 = getFloat();
432 float f5 = getFloat();
433 float f6 = getFloat();
434 int i1 = getInt();
435 SkPaint* paint = getPaint();
436 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
437 (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
438 renderer.drawArc(f1, f2, f3, f4, f5, f6, i1 == 1, paint);
Romain Guy8b2f5262011-01-23 16:15:02 -0800439 }
440 break;
Romain Guyb051e892010-09-28 19:09:36 -0700441 case DrawPath: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800442 SkPath* path = getPath();
443 SkPaint* paint = getPaint();
444 DISPLAY_LIST_LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
445 renderer.drawPath(path, paint);
Romain Guyb051e892010-09-28 19:09:36 -0700446 }
447 break;
448 case DrawLines: {
449 int count = 0;
450 float* points = getFloats(count);
Chet Haasedaf98e92011-01-10 14:10:36 -0800451 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guyb051e892010-09-28 19:09:36 -0700452 renderer.drawLines(points, count, getPaint());
453 }
454 break;
455 case DrawText: {
456 getText(&text);
Chet Haasedaf98e92011-01-10 14:10:36 -0800457 int count = getInt();
458 float x = getFloat();
459 float y = getFloat();
460 SkPaint* paint = getPaint();
461 DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
462 text.text(), text.length(), count, x, y, paint);
463 renderer.drawText(text.text(), text.length(), count, x, y, paint);
Romain Guyb051e892010-09-28 19:09:36 -0700464 }
465 break;
466 case ResetShader: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800467 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guyb051e892010-09-28 19:09:36 -0700468 renderer.resetShader();
469 }
470 break;
471 case SetupShader: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800472 SkiaShader* shader = getShader();
473 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
474 renderer.setupShader(shader);
Romain Guyb051e892010-09-28 19:09:36 -0700475 }
476 break;
477 case ResetColorFilter: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800478 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guyb051e892010-09-28 19:09:36 -0700479 renderer.resetColorFilter();
480 }
481 break;
482 case SetupColorFilter: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800483 SkiaColorFilter *colorFilter = getColorFilter();
484 DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
485 renderer.setupColorFilter(colorFilter);
Romain Guyb051e892010-09-28 19:09:36 -0700486 }
487 break;
488 case ResetShadow: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800489 DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
Romain Guyb051e892010-09-28 19:09:36 -0700490 renderer.resetShadow();
491 }
492 break;
493 case SetupShadow: {
Chet Haasedaf98e92011-01-10 14:10:36 -0800494 float radius = getFloat();
495 float dx = getFloat();
496 float dy = getFloat();
497 int color = getInt();
498 DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
499 radius, dx, dy, color);
500 renderer.setupShadow(radius, dx, dy, color);
Romain Guyb051e892010-09-28 19:09:36 -0700501 }
502 break;
Chet Haasedaf98e92011-01-10 14:10:36 -0800503 default:
504 DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
505 (char*) indent, OP_NAMES[op]);
506 break;
Romain Guyb051e892010-09-28 19:09:36 -0700507 }
508 }
Romain Guyffac7fc2011-01-13 17:21:49 -0800509
Chet Haasedaf98e92011-01-10 14:10:36 -0800510 DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate);
511 return needsInvalidate;
Romain Guyb051e892010-09-28 19:09:36 -0700512}
513
514///////////////////////////////////////////////////////////////////////////////
Romain Guy4aa90572010-09-26 18:40:37 -0700515// Base structure
516///////////////////////////////////////////////////////////////////////////////
517
Romain Guy2fc941e2011-02-03 15:06:05 -0800518DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
Chet Haase5977baa2011-01-05 18:01:22 -0800519 mDisplayList = NULL;
Romain Guy4aa90572010-09-26 18:40:37 -0700520}
521
522DisplayListRenderer::~DisplayListRenderer() {
523 reset();
524}
525
526void DisplayListRenderer::reset() {
Romain Guy4aa90572010-09-26 18:40:37 -0700527 mWriter.reset();
Chet Haase5c13d892010-10-08 08:37:55 -0700528
529 Caches& caches = Caches::getInstance();
530 for (size_t i = 0; i < mBitmapResources.size(); i++) {
531 SkBitmap* resource = mBitmapResources.itemAt(i);
532 caches.resourceCache.decrementRefcount(resource);
533 }
534 mBitmapResources.clear();
Chet Haased98aa2d2010-10-25 15:47:32 -0700535
Chet Haase5a7e8282011-02-04 12:50:55 -0800536 for (size_t i = 0; i < mOriginalPaths.size(); i++) {
537 SkPath* resource = mOriginalPaths.itemAt(i);
538 caches.resourceCache.decrementRefcount(resource);
539 }
540 mOriginalPaths.clear();
541
Romain Guy43ccf462011-01-14 18:51:01 -0800542 for (size_t i = 0; i < mShaders.size(); i++) {
543 caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
544 }
Romain Guy24c00212011-01-14 15:31:00 -0800545 mShaders.clear();
546 mShaderMap.clear();
Romain Guy43ccf462011-01-14 18:51:01 -0800547
548 mPaints.clear();
549 mPaintMap.clear();
Romain Guy2fc941e2011-02-03 15:06:05 -0800550 mPaths.clear();
551 mPathMap.clear();
Chet Haased98aa2d2010-10-25 15:47:32 -0700552 mMatrices.clear();
Romain Guy4aa90572010-09-26 18:40:37 -0700553}
554
555///////////////////////////////////////////////////////////////////////////////
556// Operations
557///////////////////////////////////////////////////////////////////////////////
558
Chet Haase5977baa2011-01-05 18:01:22 -0800559DisplayList* DisplayListRenderer::getDisplayList() {
560 if (mDisplayList == NULL) {
561 mDisplayList = new DisplayList(*this);
562 } else {
Chet Haased63cbd12011-02-03 16:32:46 -0800563 mDisplayList->initFromDisplayListRenderer(*this, true);
Chet Haase5977baa2011-01-05 18:01:22 -0800564 }
565 return mDisplayList;
566}
567
Romain Guyb051e892010-09-28 19:09:36 -0700568void DisplayListRenderer::setViewport(int width, int height) {
569 mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
570
571 mWidth = width;
572 mHeight = height;
573}
574
Romain Guy7d7b5492011-01-24 16:33:45 -0800575void DisplayListRenderer::prepareDirty(float left, float top,
576 float right, float bottom, bool opaque) {
Romain Guyb051e892010-09-28 19:09:36 -0700577 mSnapshot = new Snapshot(mFirstSnapshot,
578 SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
579 mSaveCount = 1;
580 mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
Romain Guy27454a42011-01-23 12:01:41 -0800581 mRestoreSaveCount = -1;
582}
583
584void DisplayListRenderer::finish() {
585 insertRestoreToCount();
586 OpenGLRenderer::finish();
Romain Guyb051e892010-09-28 19:09:36 -0700587}
588
Chet Haasedaf98e92011-01-10 14:10:36 -0800589void DisplayListRenderer::interrupt() {
Chet Haasedaf98e92011-01-10 14:10:36 -0800590}
Romain Guy2b1847e2011-01-26 13:43:01 -0800591
Chet Haasedaf98e92011-01-10 14:10:36 -0800592void DisplayListRenderer::resume() {
Romain Guy4aa90572010-09-26 18:40:37 -0700593}
594
Romain Guycabfcc12011-03-07 18:06:46 -0800595bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
596 // Ignore dirty during recording, it matters only when we replay
Chet Haasedaf98e92011-01-10 14:10:36 -0800597 addOp(DisplayList::DrawGLFunction);
598 addInt((int) functor);
599 return false; // No invalidate needed at record-time
600}
601
Romain Guy4aa90572010-09-26 18:40:37 -0700602int DisplayListRenderer::save(int flags) {
Romain Guyb051e892010-09-28 19:09:36 -0700603 addOp(DisplayList::Save);
Romain Guy4aa90572010-09-26 18:40:37 -0700604 addInt(flags);
605 return OpenGLRenderer::save(flags);
606}
607
608void DisplayListRenderer::restore() {
Romain Guyb051e892010-09-28 19:09:36 -0700609 addOp(DisplayList::Restore);
Romain Guy4aa90572010-09-26 18:40:37 -0700610 OpenGLRenderer::restore();
611}
612
613void DisplayListRenderer::restoreToCount(int saveCount) {
Romain Guy27454a42011-01-23 12:01:41 -0800614 mRestoreSaveCount = saveCount;
Romain Guy4aa90572010-09-26 18:40:37 -0700615 OpenGLRenderer::restoreToCount(saveCount);
616}
617
618int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
Chet Haase5c13d892010-10-08 08:37:55 -0700619 SkPaint* p, int flags) {
Romain Guyb051e892010-09-28 19:09:36 -0700620 addOp(DisplayList::SaveLayer);
Romain Guy4aa90572010-09-26 18:40:37 -0700621 addBounds(left, top, right, bottom);
622 addPaint(p);
623 addInt(flags);
Romain Guyb051e892010-09-28 19:09:36 -0700624 return OpenGLRenderer::save(flags);
Romain Guy4aa90572010-09-26 18:40:37 -0700625}
626
Romain Guy5b3b3522010-10-27 18:57:51 -0700627int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
628 int alpha, int flags) {
629 addOp(DisplayList::SaveLayerAlpha);
630 addBounds(left, top, right, bottom);
631 addInt(alpha);
632 addInt(flags);
633 return OpenGLRenderer::save(flags);
634}
635
Romain Guy4aa90572010-09-26 18:40:37 -0700636void DisplayListRenderer::translate(float dx, float dy) {
Romain Guyb051e892010-09-28 19:09:36 -0700637 addOp(DisplayList::Translate);
Romain Guy4aa90572010-09-26 18:40:37 -0700638 addPoint(dx, dy);
639 OpenGLRenderer::translate(dx, dy);
640}
641
642void DisplayListRenderer::rotate(float degrees) {
Romain Guyb051e892010-09-28 19:09:36 -0700643 addOp(DisplayList::Rotate);
Romain Guy4aa90572010-09-26 18:40:37 -0700644 addFloat(degrees);
645 OpenGLRenderer::rotate(degrees);
646}
647
648void DisplayListRenderer::scale(float sx, float sy) {
Romain Guyb051e892010-09-28 19:09:36 -0700649 addOp(DisplayList::Scale);
Romain Guy4aa90572010-09-26 18:40:37 -0700650 addPoint(sx, sy);
651 OpenGLRenderer::scale(sx, sy);
652}
653
Romain Guy807daf72011-01-18 11:19:19 -0800654void DisplayListRenderer::skew(float sx, float sy) {
655 addOp(DisplayList::Skew);
656 addPoint(sx, sy);
657 OpenGLRenderer::skew(sx, sy);
658}
659
Romain Guy4aa90572010-09-26 18:40:37 -0700660void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
Romain Guyb051e892010-09-28 19:09:36 -0700661 addOp(DisplayList::SetMatrix);
Romain Guy4aa90572010-09-26 18:40:37 -0700662 addMatrix(matrix);
663 OpenGLRenderer::setMatrix(matrix);
664}
665
666void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
Romain Guyb051e892010-09-28 19:09:36 -0700667 addOp(DisplayList::ConcatMatrix);
Romain Guy4aa90572010-09-26 18:40:37 -0700668 addMatrix(matrix);
669 OpenGLRenderer::concatMatrix(matrix);
670}
671
672bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
673 SkRegion::Op op) {
Romain Guyb051e892010-09-28 19:09:36 -0700674 addOp(DisplayList::ClipRect);
Romain Guy4aa90572010-09-26 18:40:37 -0700675 addBounds(left, top, right, bottom);
676 addInt(op);
677 return OpenGLRenderer::clipRect(left, top, right, bottom, op);
678}
679
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700680bool DisplayListRenderer::drawDisplayList(DisplayList* displayList,
681 uint32_t width, uint32_t height, Rect& dirty, uint32_t level) {
Romain Guycabfcc12011-03-07 18:06:46 -0800682 // dirty is an out parameter and should not be recorded,
683 // it matters only when replaying the display list
Romain Guy0fe478e2010-11-08 12:08:41 -0800684 addOp(DisplayList::DrawDisplayList);
685 addDisplayList(displayList);
Romain Guy7b5b6ab2011-03-14 18:05:08 -0700686 addSize(width, height);
Chet Haasedaf98e92011-01-10 14:10:36 -0800687 return false;
Romain Guy0fe478e2010-11-08 12:08:41 -0800688}
689
Romain Guyada830f2011-01-13 12:13:20 -0800690void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
Romain Guy6c319ca2011-01-11 14:29:25 -0800691 addOp(DisplayList::DrawLayer);
Romain Guyada830f2011-01-13 12:13:20 -0800692 addInt((int) layer);
693 addPoint(x, y);
Romain Guy6c319ca2011-01-11 14:29:25 -0800694 addPaint(paint);
695}
696
Romain Guy4aa90572010-09-26 18:40:37 -0700697void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
Chet Haase5c13d892010-10-08 08:37:55 -0700698 SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700699 addOp(DisplayList::DrawBitmap);
Romain Guy4aa90572010-09-26 18:40:37 -0700700 addBitmap(bitmap);
701 addPoint(left, top);
702 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700703}
704
Chet Haase5c13d892010-10-08 08:37:55 -0700705void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
706 SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700707 addOp(DisplayList::DrawBitmapMatrix);
Romain Guy4aa90572010-09-26 18:40:37 -0700708 addBitmap(bitmap);
709 addMatrix(matrix);
710 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700711}
712
713void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
714 float srcRight, float srcBottom, float dstLeft, float dstTop,
Chet Haase5c13d892010-10-08 08:37:55 -0700715 float dstRight, float dstBottom, SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700716 addOp(DisplayList::DrawBitmapRect);
Romain Guy4aa90572010-09-26 18:40:37 -0700717 addBitmap(bitmap);
718 addBounds(srcLeft, srcTop, srcRight, srcBottom);
719 addBounds(dstLeft, dstTop, dstRight, dstBottom);
720 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700721}
722
Romain Guy5a7b4662011-01-20 19:09:30 -0800723void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
724 float* vertices, int* colors, SkPaint* paint) {
725 addOp(DisplayList::DrawBitmapMesh);
726 addBitmap(bitmap);
727 addInt(meshWidth);
728 addInt(meshHeight);
729 addFloats(vertices, (meshWidth + 1) * (meshHeight + 1) * 2);
730 if (colors) {
731 addInt(1);
732 addInts(colors, (meshWidth + 1) * (meshHeight + 1));
733 } else {
734 addInt(0);
735 }
736 addPaint(paint);
737}
738
Romain Guy4aa90572010-09-26 18:40:37 -0700739void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
Romain Guy4bb94202010-10-12 15:59:26 -0700740 const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
Chet Haase5c13d892010-10-08 08:37:55 -0700741 float left, float top, float right, float bottom, SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700742 addOp(DisplayList::DrawPatch);
Romain Guy4aa90572010-09-26 18:40:37 -0700743 addBitmap(bitmap);
744 addInts(xDivs, width);
745 addInts(yDivs, height);
Romain Guy4bb94202010-10-12 15:59:26 -0700746 addUInts(colors, numColors);
Romain Guy4aa90572010-09-26 18:40:37 -0700747 addBounds(left, top, right, bottom);
748 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700749}
750
751void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
Romain Guyb051e892010-09-28 19:09:36 -0700752 addOp(DisplayList::DrawColor);
Romain Guy4aa90572010-09-26 18:40:37 -0700753 addInt(color);
754 addInt(mode);
Romain Guy4aa90572010-09-26 18:40:37 -0700755}
756
757void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
Chet Haase5c13d892010-10-08 08:37:55 -0700758 SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700759 addOp(DisplayList::DrawRect);
Romain Guy4aa90572010-09-26 18:40:37 -0700760 addBounds(left, top, right, bottom);
761 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700762}
763
Romain Guy01d58e42011-01-19 21:54:02 -0800764void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
765 float rx, float ry, SkPaint* paint) {
766 addOp(DisplayList::DrawRoundRect);
767 addBounds(left, top, right, bottom);
768 addPoint(rx, ry);
769 addPaint(paint);
770}
771
772void DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
773 addOp(DisplayList::DrawCircle);
774 addPoint(x, y);
775 addFloat(radius);
776 addPaint(paint);
777}
778
Romain Guyc1cd9ba32011-01-23 14:18:41 -0800779void DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
780 SkPaint* paint) {
781 addOp(DisplayList::DrawOval);
782 addBounds(left, top, right, bottom);
783 addPaint(paint);
784}
785
Romain Guy8b2f5262011-01-23 16:15:02 -0800786void DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
787 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
Romain Guy82d41a52011-01-24 21:53:42 -0800788 addOp(DisplayList::DrawArc);
Romain Guy8b2f5262011-01-23 16:15:02 -0800789 addBounds(left, top, right, bottom);
790 addPoint(startAngle, sweepAngle);
791 addInt(useCenter ? 1 : 0);
792 addPaint(paint);
793}
794
Romain Guy4aa90572010-09-26 18:40:37 -0700795void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700796 addOp(DisplayList::DrawPath);
Romain Guy4aa90572010-09-26 18:40:37 -0700797 addPath(path);
798 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700799}
800
Chet Haase5c13d892010-10-08 08:37:55 -0700801void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700802 addOp(DisplayList::DrawLines);
Romain Guy4aa90572010-09-26 18:40:37 -0700803 addFloats(points, count);
804 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700805}
806
807void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
808 float x, float y, SkPaint* paint) {
Romain Guyb051e892010-09-28 19:09:36 -0700809 addOp(DisplayList::DrawText);
Romain Guy4aa90572010-09-26 18:40:37 -0700810 addText(text, bytesCount);
811 addInt(count);
812 addPoint(x, y);
813 addPaint(paint);
Romain Guy4aa90572010-09-26 18:40:37 -0700814}
815
816void DisplayListRenderer::resetShader() {
Romain Guyb051e892010-09-28 19:09:36 -0700817 addOp(DisplayList::ResetShader);
Romain Guy4aa90572010-09-26 18:40:37 -0700818}
819
820void DisplayListRenderer::setupShader(SkiaShader* shader) {
Chet Haase5c13d892010-10-08 08:37:55 -0700821 addOp(DisplayList::SetupShader);
822 addShader(shader);
Romain Guy4aa90572010-09-26 18:40:37 -0700823}
824
825void DisplayListRenderer::resetColorFilter() {
Romain Guyb051e892010-09-28 19:09:36 -0700826 addOp(DisplayList::ResetColorFilter);
Romain Guy4aa90572010-09-26 18:40:37 -0700827}
828
829void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
Chet Haasead93c2b2010-10-22 16:17:12 -0700830 addOp(DisplayList::SetupColorFilter);
831 addColorFilter(filter);
Romain Guy4aa90572010-09-26 18:40:37 -0700832}
833
834void DisplayListRenderer::resetShadow() {
Romain Guyb051e892010-09-28 19:09:36 -0700835 addOp(DisplayList::ResetShadow);
Romain Guy4aa90572010-09-26 18:40:37 -0700836}
837
838void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
Romain Guyb051e892010-09-28 19:09:36 -0700839 addOp(DisplayList::SetupShadow);
Romain Guy4aa90572010-09-26 18:40:37 -0700840 addFloat(radius);
841 addPoint(dx, dy);
842 addInt(color);
Romain Guy4aa90572010-09-26 18:40:37 -0700843}
844
Romain Guy4aa90572010-09-26 18:40:37 -0700845}; // namespace uirenderer
846}; // namespace android