DisplayListRenderer.cpp revision c511bee87cda99a252d1a62487f47c8f05aee78c
105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Copyright (C) 2010 The Android Open Source Project
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang *
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Licensed under the Apache License, Version 2.0 (the "License");
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang * you may not use this file except in compliance with the License.
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang * You may obtain a copy of the License at
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang *
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang *      http://www.apache.org/licenses/LICENSE-2.0
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang *
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * Unless required by applicable law or agreed to in writing, software
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang * distributed under the License is distributed on an "AS IS" BASIS,
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang * See the License for the specific language governing permissions and
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang * limitations under the License.
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang */
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define LOG_TAG "OpenGLRenderer"
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "DisplayListLogBuffer.h"
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "DisplayListRenderer.h"
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <utils/String8.h>
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "Caches.h"
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wangnamespace android {
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wangnamespace uirenderer {
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang///////////////////////////////////////////////////////////////////////////////
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang// Display list
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang///////////////////////////////////////////////////////////////////////////////
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wangconst char* DisplayList::OP_NAMES[] = {
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    "Save",
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    "Restore",
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    "RestoreToCount",
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    "SaveLayer",
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    "SaveLayerAlpha",
39    "Translate",
40    "Rotate",
41    "Scale",
42    "Skew",
43    "SetMatrix",
44    "ConcatMatrix",
45    "ClipRect",
46    "DrawDisplayList",
47    "DrawLayer",
48    "DrawBitmap",
49    "DrawBitmapMatrix",
50    "DrawBitmapRect",
51    "DrawBitmapMesh",
52    "DrawPatch",
53    "DrawColor",
54    "DrawRect",
55    "DrawRoundRect",
56    "DrawCircle",
57    "DrawOval",
58    "DrawArc",
59    "DrawPath",
60    "DrawLines",
61    "DrawPoints",
62    "DrawText",
63    "ResetShader",
64    "SetupShader",
65    "ResetColorFilter",
66    "SetupColorFilter",
67    "ResetShadow",
68    "SetupShadow",
69    "DrawGLFunction"
70};
71
72void DisplayList::outputLogBuffer(int fd) {
73    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
74    if (logBuffer.isEmpty()) {
75        return;
76    }
77
78    FILE *file = fdopen(fd, "a");
79
80    fprintf(file, "\nRecent DisplayList operations\n");
81    logBuffer.outputCommands(file, OP_NAMES);
82
83    String8 cachesLog;
84    Caches::getInstance().dumpMemoryUsage(cachesLog);
85    fprintf(file, "\nCaches:\n%s", cachesLog.string());
86    fprintf(file, "\n");
87
88    fflush(file);
89}
90
91DisplayList::DisplayList(const DisplayListRenderer& recorder) {
92    initFromDisplayListRenderer(recorder);
93}
94
95DisplayList::~DisplayList() {
96    clearResources();
97}
98
99void DisplayList::clearResources() {
100    sk_free((void*) mReader.base());
101
102    Caches& caches = Caches::getInstance();
103
104    for (size_t i = 0; i < mBitmapResources.size(); i++) {
105        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
106    }
107    mBitmapResources.clear();
108
109    for (size_t i = 0; i < mFilterResources.size(); i++) {
110        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
111    }
112    mFilterResources.clear();
113
114    for (size_t i = 0; i < mShaders.size(); i++) {
115        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
116        caches.resourceCache.destructor(mShaders.itemAt(i));
117    }
118    mShaders.clear();
119
120    for (size_t i = 0; i < mPaints.size(); i++) {
121        delete mPaints.itemAt(i);
122    }
123    mPaints.clear();
124
125    for (size_t i = 0; i < mPaths.size(); i++) {
126        SkPath* path = mPaths.itemAt(i);
127        caches.pathCache.remove(path);
128        delete path;
129    }
130    mPaths.clear();
131
132    for (size_t i = 0; i < mMatrices.size(); i++) {
133        delete mMatrices.itemAt(i);
134    }
135    mMatrices.clear();
136}
137
138void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
139    const SkWriter32& writer = recorder.writeStream();
140    init();
141
142    if (writer.size() == 0) {
143        return;
144    }
145
146    if (reusing) {
147        // re-using display list - clear out previous allocations
148        clearResources();
149    }
150
151    mSize = writer.size();
152    void* buffer = sk_malloc_throw(mSize);
153    writer.flatten(buffer);
154    mReader.setMemory(buffer, mSize);
155
156    Caches& caches = Caches::getInstance();
157
158    const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources();
159    for (size_t i = 0; i < bitmapResources.size(); i++) {
160        SkBitmap* resource = bitmapResources.itemAt(i);
161        mBitmapResources.add(resource);
162        caches.resourceCache.incrementRefcount(resource);
163    }
164
165    const Vector<SkiaColorFilter*> &filterResources = recorder.getFilterResources();
166    for (size_t i = 0; i < filterResources.size(); i++) {
167        SkiaColorFilter* resource = filterResources.itemAt(i);
168        mFilterResources.add(resource);
169        caches.resourceCache.incrementRefcount(resource);
170    }
171
172    const Vector<SkiaShader*> &shaders = recorder.getShaders();
173    for (size_t i = 0; i < shaders.size(); i++) {
174        SkiaShader* resource = shaders.itemAt(i);
175        mShaders.add(resource);
176        caches.resourceCache.incrementRefcount(resource);
177    }
178
179    const Vector<SkPaint*> &paints = recorder.getPaints();
180    for (size_t i = 0; i < paints.size(); i++) {
181        mPaints.add(paints.itemAt(i));
182    }
183
184    const Vector<SkPath*> &paths = recorder.getPaths();
185    for (size_t i = 0; i < paths.size(); i++) {
186        mPaths.add(paths.itemAt(i));
187    }
188
189    const Vector<SkMatrix*> &matrices = recorder.getMatrices();
190    for (size_t i = 0; i < matrices.size(); i++) {
191        mMatrices.add(matrices.itemAt(i));
192    }
193}
194
195void DisplayList::init() {
196    mSize = 0;
197    mIsRenderable = true;
198}
199
200size_t DisplayList::getSize() {
201    return mSize;
202}
203
204/**
205 * This function is a simplified version of replay(), where we simply retrieve and log the
206 * display list. This function should remain in sync with the replay() function.
207 */
208void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
209    TextContainer text;
210
211    uint32_t count = (level + 1) * 2;
212    char indent[count + 1];
213    for (uint32_t i = 0; i < count; i++) {
214        indent[i] = ' ';
215    }
216    indent[count] = '\0';
217    LOGD("%sStart display list (%p)", (char*) indent + 2, this);
218
219    int saveCount = renderer.getSaveCount() - 1;
220
221    mReader.rewind();
222
223    while (!mReader.eof()) {
224        int op = mReader.readInt();
225
226        switch (op) {
227            case DrawGLFunction: {
228                Functor *functor = (Functor *) getInt();
229                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
230            }
231            break;
232            case Save: {
233                int rendererNum = getInt();
234                LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
235            }
236            break;
237            case Restore: {
238                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
239            }
240            break;
241            case RestoreToCount: {
242                int restoreCount = saveCount + getInt();
243                LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
244            }
245            break;
246            case SaveLayer: {
247                float f1 = getFloat();
248                float f2 = getFloat();
249                float f3 = getFloat();
250                float f4 = getFloat();
251                SkPaint* paint = getPaint();
252                int flags = getInt();
253                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
254                    OP_NAMES[op], f1, f2, f3, f4, paint, flags);
255            }
256            break;
257            case SaveLayerAlpha: {
258                float f1 = getFloat();
259                float f2 = getFloat();
260                float f3 = getFloat();
261                float f4 = getFloat();
262                int alpha = getInt();
263                int flags = getInt();
264                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
265                    OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
266            }
267            break;
268            case Translate: {
269                float f1 = getFloat();
270                float f2 = getFloat();
271                LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
272            }
273            break;
274            case Rotate: {
275                float rotation = getFloat();
276                LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
277            }
278            break;
279            case Scale: {
280                float sx = getFloat();
281                float sy = getFloat();
282                LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
283            }
284            break;
285            case Skew: {
286                float sx = getFloat();
287                float sy = getFloat();
288                LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
289            }
290            break;
291            case SetMatrix: {
292                SkMatrix* matrix = getMatrix();
293                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
294            }
295            break;
296            case ConcatMatrix: {
297                SkMatrix* matrix = getMatrix();
298                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
299            }
300            break;
301            case ClipRect: {
302                float f1 = getFloat();
303                float f2 = getFloat();
304                float f3 = getFloat();
305                float f4 = getFloat();
306                int regionOp = getInt();
307                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
308                    f1, f2, f3, f4, regionOp);
309            }
310            break;
311            case DrawDisplayList: {
312                DisplayList* displayList = getDisplayList();
313                uint32_t width = getUInt();
314                uint32_t height = getUInt();
315                LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
316                    displayList, width, height, level + 1);
317                renderer.outputDisplayList(displayList, level + 1);
318            }
319            break;
320            case DrawLayer: {
321                Layer* layer = (Layer*) getInt();
322                float x = getFloat();
323                float y = getFloat();
324                SkPaint* paint = getPaint();
325                LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
326                    layer, x, y, paint);
327            }
328            break;
329            case DrawBitmap: {
330                SkBitmap* bitmap = getBitmap();
331                float x = getFloat();
332                float y = getFloat();
333                SkPaint* paint = getPaint();
334                LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
335                    bitmap, x, y, paint);
336            }
337            break;
338            case DrawBitmapMatrix: {
339                SkBitmap* bitmap = getBitmap();
340                SkMatrix* matrix = getMatrix();
341                SkPaint* paint = getPaint();
342                LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
343                    bitmap, matrix, paint);
344            }
345            break;
346            case DrawBitmapRect: {
347                SkBitmap* bitmap = getBitmap();
348                float f1 = getFloat();
349                float f2 = getFloat();
350                float f3 = getFloat();
351                float f4 = getFloat();
352                float f5 = getFloat();
353                float f6 = getFloat();
354                float f7 = getFloat();
355                float f8 = getFloat();
356                SkPaint* paint = getPaint();
357                LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
358                    (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
359            }
360            break;
361            case DrawBitmapMesh: {
362                int verticesCount = 0;
363                uint32_t colorsCount = 0;
364                SkBitmap* bitmap = getBitmap();
365                uint32_t meshWidth = getInt();
366                uint32_t meshHeight = getInt();
367                float* vertices = getFloats(verticesCount);
368                bool hasColors = getInt();
369                int* colors = hasColors ? getInts(colorsCount) : NULL;
370                SkPaint* paint = getPaint();
371                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
372            }
373            break;
374            case DrawPatch: {
375                int32_t* xDivs = NULL;
376                int32_t* yDivs = NULL;
377                uint32_t* colors = NULL;
378                uint32_t xDivsCount = 0;
379                uint32_t yDivsCount = 0;
380                int8_t numColors = 0;
381                SkBitmap* bitmap = getBitmap();
382                xDivs = getInts(xDivsCount);
383                yDivs = getInts(yDivsCount);
384                colors = getUInts(numColors);
385                float left = getFloat();
386                float top = getFloat();
387                float right = getFloat();
388                float bottom = getFloat();
389                SkPaint* paint = getPaint();
390                LOGD("%s%s %.2f, %.2f, %.2f, %.2f", (char*) indent, OP_NAMES[op],
391                        left, top, right, bottom);
392            }
393            break;
394            case DrawColor: {
395                int color = getInt();
396                int xferMode = getInt();
397                LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
398            }
399            break;
400            case DrawRect: {
401                float f1 = getFloat();
402                float f2 = getFloat();
403                float f3 = getFloat();
404                float f4 = getFloat();
405                SkPaint* paint = getPaint();
406                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
407                    f1, f2, f3, f4, paint);
408            }
409            break;
410            case DrawRoundRect: {
411                float f1 = getFloat();
412                float f2 = getFloat();
413                float f3 = getFloat();
414                float f4 = getFloat();
415                float f5 = getFloat();
416                float f6 = getFloat();
417                SkPaint* paint = getPaint();
418                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
419                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
420            }
421            break;
422            case DrawCircle: {
423                float f1 = getFloat();
424                float f2 = getFloat();
425                float f3 = getFloat();
426                SkPaint* paint = getPaint();
427                LOGD("%s%s %.2f, %.2f, %.2f, %p",
428                    (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
429            }
430            break;
431            case DrawOval: {
432                float f1 = getFloat();
433                float f2 = getFloat();
434                float f3 = getFloat();
435                float f4 = getFloat();
436                SkPaint* paint = getPaint();
437                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
438                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
439            }
440            break;
441            case DrawArc: {
442                float f1 = getFloat();
443                float f2 = getFloat();
444                float f3 = getFloat();
445                float f4 = getFloat();
446                float f5 = getFloat();
447                float f6 = getFloat();
448                int i1 = getInt();
449                SkPaint* paint = getPaint();
450                LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
451                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
452            }
453            break;
454            case DrawPath: {
455                SkPath* path = getPath();
456                SkPaint* paint = getPaint();
457                LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
458            }
459            break;
460            case DrawLines: {
461                int count = 0;
462                float* points = getFloats(count);
463                SkPaint* paint = getPaint();
464                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
465            }
466            break;
467            case DrawPoints: {
468                int count = 0;
469                float* points = getFloats(count);
470                SkPaint* paint = getPaint();
471                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
472            }
473            break;
474            case DrawText: {
475                getText(&text);
476                int count = getInt();
477                float x = getFloat();
478                float y = getFloat();
479                SkPaint* paint = getPaint();
480                float length = getFloat();
481                LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
482                    text.text(), text.length(), count, x, y, paint, length);
483            }
484            break;
485            case ResetShader: {
486                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
487            }
488            break;
489            case SetupShader: {
490                SkiaShader* shader = getShader();
491                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
492            }
493            break;
494            case ResetColorFilter: {
495                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
496            }
497            break;
498            case SetupColorFilter: {
499                SkiaColorFilter *colorFilter = getColorFilter();
500                LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
501            }
502            break;
503            case ResetShadow: {
504                LOGD("%s%s", (char*) indent, OP_NAMES[op]);
505            }
506            break;
507            case SetupShadow: {
508                float radius = getFloat();
509                float dx = getFloat();
510                float dy = getFloat();
511                int color = getInt();
512                LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
513                    radius, dx, dy, color);
514            }
515            break;
516            default:
517                LOGD("Display List error: op not handled: %s%s",
518                    (char*) indent, OP_NAMES[op]);
519                break;
520        }
521    }
522
523    LOGD("%sDone", (char*) indent + 2);
524}
525
526/**
527 * Changes to replay(), specifically those involving opcode or parameter changes, should be mimicked
528 * in the output() function, since that function processes the same list of opcodes for the
529 * purposes of logging display list info for a given view.
530 */
531bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) {
532    bool needsInvalidate = false;
533    TextContainer text;
534    mReader.rewind();
535
536#if DEBUG_DISPLAY_LIST
537    uint32_t count = (level + 1) * 2;
538    char indent[count + 1];
539    for (uint32_t i = 0; i < count; i++) {
540        indent[i] = ' ';
541    }
542    indent[count] = '\0';
543    DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
544#endif
545
546    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
547    int saveCount = renderer.getSaveCount() - 1;
548    while (!mReader.eof()) {
549        int op = mReader.readInt();
550        logBuffer.writeCommand(level, op);
551
552        switch (op) {
553            case DrawGLFunction: {
554                Functor *functor = (Functor *) getInt();
555                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
556                needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
557            }
558            break;
559            case Save: {
560                int rendererNum = getInt();
561                DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
562                renderer.save(rendererNum);
563            }
564            break;
565            case Restore: {
566                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
567                renderer.restore();
568            }
569            break;
570            case RestoreToCount: {
571                int restoreCount = saveCount + getInt();
572                DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
573                renderer.restoreToCount(restoreCount);
574            }
575            break;
576            case SaveLayer: {
577                float f1 = getFloat();
578                float f2 = getFloat();
579                float f3 = getFloat();
580                float f4 = getFloat();
581                SkPaint* paint = getPaint();
582                int flags = getInt();
583                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
584                    OP_NAMES[op], f1, f2, f3, f4, paint, flags);
585                renderer.saveLayer(f1, f2, f3, f4, paint, flags);
586            }
587            break;
588            case SaveLayerAlpha: {
589                float f1 = getFloat();
590                float f2 = getFloat();
591                float f3 = getFloat();
592                float f4 = getFloat();
593                int alpha = getInt();
594                int flags = getInt();
595                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
596                    OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
597                renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags);
598            }
599            break;
600            case Translate: {
601                float f1 = getFloat();
602                float f2 = getFloat();
603                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
604                renderer.translate(f1, f2);
605            }
606            break;
607            case Rotate: {
608                float rotation = getFloat();
609                DISPLAY_LIST_LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
610                renderer.rotate(rotation);
611            }
612            break;
613            case Scale: {
614                float sx = getFloat();
615                float sy = getFloat();
616                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
617                renderer.scale(sx, sy);
618            }
619            break;
620            case Skew: {
621                float sx = getFloat();
622                float sy = getFloat();
623                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
624                renderer.skew(sx, sy);
625            }
626            break;
627            case SetMatrix: {
628                SkMatrix* matrix = getMatrix();
629                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
630                renderer.setMatrix(matrix);
631            }
632            break;
633            case ConcatMatrix: {
634                SkMatrix* matrix = getMatrix();
635                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
636                renderer.concatMatrix(matrix);
637            }
638            break;
639            case ClipRect: {
640                float f1 = getFloat();
641                float f2 = getFloat();
642                float f3 = getFloat();
643                float f4 = getFloat();
644                int regionOp = getInt();
645                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
646                    f1, f2, f3, f4, regionOp);
647                renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
648            }
649            break;
650            case DrawDisplayList: {
651                DisplayList* displayList = getDisplayList();
652                uint32_t width = getUInt();
653                uint32_t height = getUInt();
654                DISPLAY_LIST_LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
655                    displayList, width, height, level + 1);
656                needsInvalidate |= renderer.drawDisplayList(displayList, width, height,
657                        dirty, level + 1);
658            }
659            break;
660            case DrawLayer: {
661                Layer* layer = (Layer*) getInt();
662                float x = getFloat();
663                float y = getFloat();
664                SkPaint* paint = getPaint();
665                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
666                    layer, x, y, paint);
667                renderer.drawLayer(layer, x, y, paint);
668            }
669            break;
670            case DrawBitmap: {
671                SkBitmap* bitmap = getBitmap();
672                float x = getFloat();
673                float y = getFloat();
674                SkPaint* paint = getPaint();
675                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
676                    bitmap, x, y, paint);
677                renderer.drawBitmap(bitmap, x, y, paint);
678            }
679            break;
680            case DrawBitmapMatrix: {
681                SkBitmap* bitmap = getBitmap();
682                SkMatrix* matrix = getMatrix();
683                SkPaint* paint = getPaint();
684                DISPLAY_LIST_LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
685                    bitmap, matrix, paint);
686                renderer.drawBitmap(bitmap, matrix, paint);
687            }
688            break;
689            case DrawBitmapRect: {
690                SkBitmap* bitmap = getBitmap();
691                float f1 = getFloat();
692                float f2 = getFloat();
693                float f3 = getFloat();
694                float f4 = getFloat();
695                float f5 = getFloat();
696                float f6 = getFloat();
697                float f7 = getFloat();
698                float f8 = getFloat();
699                SkPaint* paint = getPaint();
700                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
701                    (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
702                renderer.drawBitmap(bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
703            }
704            break;
705            case DrawBitmapMesh: {
706                int verticesCount = 0;
707                uint32_t colorsCount = 0;
708
709                SkBitmap* bitmap = getBitmap();
710                uint32_t meshWidth = getInt();
711                uint32_t meshHeight = getInt();
712                float* vertices = getFloats(verticesCount);
713                bool hasColors = getInt();
714                int* colors = hasColors ? getInts(colorsCount) : NULL;
715                SkPaint* paint = getPaint();
716
717                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
718                renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint);
719            }
720            break;
721            case DrawPatch: {
722                int32_t* xDivs = NULL;
723                int32_t* yDivs = NULL;
724                uint32_t* colors = NULL;
725                uint32_t xDivsCount = 0;
726                uint32_t yDivsCount = 0;
727                int8_t numColors = 0;
728
729                SkBitmap* bitmap = getBitmap();
730
731                xDivs = getInts(xDivsCount);
732                yDivs = getInts(yDivsCount);
733                colors = getUInts(numColors);
734
735                float left = getFloat();
736                float top = getFloat();
737                float right = getFloat();
738                float bottom = getFloat();
739                SkPaint* paint = getPaint();
740
741                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
742                renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
743                        numColors, left, top, right, bottom, paint);
744            }
745            break;
746            case DrawColor: {
747                int color = getInt();
748                int xferMode = getInt();
749                DISPLAY_LIST_LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
750                renderer.drawColor(color, (SkXfermode::Mode) xferMode);
751            }
752            break;
753            case DrawRect: {
754                float f1 = getFloat();
755                float f2 = getFloat();
756                float f3 = getFloat();
757                float f4 = getFloat();
758                SkPaint* paint = getPaint();
759                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
760                    f1, f2, f3, f4, paint);
761                renderer.drawRect(f1, f2, f3, f4, paint);
762            }
763            break;
764            case DrawRoundRect: {
765                float f1 = getFloat();
766                float f2 = getFloat();
767                float f3 = getFloat();
768                float f4 = getFloat();
769                float f5 = getFloat();
770                float f6 = getFloat();
771                SkPaint* paint = getPaint();
772                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
773                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
774                renderer.drawRoundRect(f1, f2, f3, f4, f5, f6, paint);
775            }
776            break;
777            case DrawCircle: {
778                float f1 = getFloat();
779                float f2 = getFloat();
780                float f3 = getFloat();
781                SkPaint* paint = getPaint();
782                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %p",
783                    (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
784                renderer.drawCircle(f1, f2, f3, paint);
785            }
786            break;
787            case DrawOval: {
788                float f1 = getFloat();
789                float f2 = getFloat();
790                float f3 = getFloat();
791                float f4 = getFloat();
792                SkPaint* paint = getPaint();
793                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
794                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
795                renderer.drawOval(f1, f2, f3, f4, paint);
796            }
797            break;
798            case DrawArc: {
799                float f1 = getFloat();
800                float f2 = getFloat();
801                float f3 = getFloat();
802                float f4 = getFloat();
803                float f5 = getFloat();
804                float f6 = getFloat();
805                int i1 = getInt();
806                SkPaint* paint = getPaint();
807                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
808                    (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
809                renderer.drawArc(f1, f2, f3, f4, f5, f6, i1 == 1, paint);
810            }
811            break;
812            case DrawPath: {
813                SkPath* path = getPath();
814                SkPaint* paint = getPaint();
815                DISPLAY_LIST_LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
816                renderer.drawPath(path, paint);
817            }
818            break;
819            case DrawLines: {
820                int count = 0;
821                float* points = getFloats(count);
822                SkPaint* paint = getPaint();
823                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
824                renderer.drawLines(points, count, paint);
825            }
826            break;
827            case DrawPoints: {
828                int count = 0;
829                float* points = getFloats(count);
830                SkPaint* paint = getPaint();
831                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
832                renderer.drawPoints(points, count, paint);
833            }
834            break;
835            case DrawText: {
836                getText(&text);
837                int count = getInt();
838                float x = getFloat();
839                float y = getFloat();
840                SkPaint* paint = getPaint();
841                float length = getFloat();
842                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
843                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
844                renderer.drawText(text.text(), text.length(), count, x, y, paint, length);
845            }
846            break;
847            case ResetShader: {
848                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
849                renderer.resetShader();
850            }
851            break;
852            case SetupShader: {
853                SkiaShader* shader = getShader();
854                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
855                renderer.setupShader(shader);
856            }
857            break;
858            case ResetColorFilter: {
859                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
860                renderer.resetColorFilter();
861            }
862            break;
863            case SetupColorFilter: {
864                SkiaColorFilter *colorFilter = getColorFilter();
865                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
866                renderer.setupColorFilter(colorFilter);
867            }
868            break;
869            case ResetShadow: {
870                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
871                renderer.resetShadow();
872            }
873            break;
874            case SetupShadow: {
875                float radius = getFloat();
876                float dx = getFloat();
877                float dy = getFloat();
878                int color = getInt();
879                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
880                    radius, dx, dy, color);
881                renderer.setupShadow(radius, dx, dy, color);
882            }
883            break;
884            default:
885                DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
886                    (char*) indent, OP_NAMES[op]);
887                break;
888        }
889    }
890
891    DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate);
892    return needsInvalidate;
893}
894
895///////////////////////////////////////////////////////////////////////////////
896// Base structure
897///////////////////////////////////////////////////////////////////////////////
898
899DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE), mHasDrawOps(false) {
900}
901
902DisplayListRenderer::~DisplayListRenderer() {
903    reset();
904}
905
906void DisplayListRenderer::reset() {
907    mWriter.reset();
908
909    Caches& caches = Caches::getInstance();
910    for (size_t i = 0; i < mBitmapResources.size(); i++) {
911        caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
912    }
913    mBitmapResources.clear();
914
915    for (size_t i = 0; i < mFilterResources.size(); i++) {
916        caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
917    }
918    mFilterResources.clear();
919
920    for (size_t i = 0; i < mShaders.size(); i++) {
921        caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
922    }
923    mShaders.clear();
924    mShaderMap.clear();
925
926    mPaints.clear();
927    mPaintMap.clear();
928
929    mPaths.clear();
930    mPathMap.clear();
931
932    mMatrices.clear();
933
934    mHasDrawOps = false;
935}
936
937///////////////////////////////////////////////////////////////////////////////
938// Operations
939///////////////////////////////////////////////////////////////////////////////
940
941DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
942    if (!displayList) {
943        displayList = new DisplayList(*this);
944    } else {
945        displayList->initFromDisplayListRenderer(*this, true);
946    }
947    displayList->setRenderable(mHasDrawOps);
948    return displayList;
949}
950
951void DisplayListRenderer::setViewport(int width, int height) {
952    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
953
954    mWidth = width;
955    mHeight = height;
956}
957
958void DisplayListRenderer::prepareDirty(float left, float top,
959        float right, float bottom, bool opaque) {
960    mSnapshot = new Snapshot(mFirstSnapshot,
961            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
962    mSaveCount = 1;
963    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
964    mRestoreSaveCount = -1;
965}
966
967void DisplayListRenderer::finish() {
968    insertRestoreToCount();
969    OpenGLRenderer::finish();
970}
971
972void DisplayListRenderer::interrupt() {
973}
974
975void DisplayListRenderer::resume() {
976}
977
978bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
979    // Ignore dirty during recording, it matters only when we replay
980    addOp(DisplayList::DrawGLFunction);
981    addInt((int) functor);
982    return false; // No invalidate needed at record-time
983}
984
985int DisplayListRenderer::save(int flags) {
986    addOp(DisplayList::Save);
987    addInt(flags);
988    return OpenGLRenderer::save(flags);
989}
990
991void DisplayListRenderer::restore() {
992    if (mRestoreSaveCount < 0) {
993        addOp(DisplayList::Restore);
994    } else {
995        mRestoreSaveCount--;
996    }
997    OpenGLRenderer::restore();
998}
999
1000void DisplayListRenderer::restoreToCount(int saveCount) {
1001    mRestoreSaveCount = saveCount;
1002    OpenGLRenderer::restoreToCount(saveCount);
1003}
1004
1005int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
1006        SkPaint* p, int flags) {
1007    addOp(DisplayList::SaveLayer);
1008    addBounds(left, top, right, bottom);
1009    addPaint(p);
1010    addInt(flags);
1011    return OpenGLRenderer::save(flags);
1012}
1013
1014int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
1015        int alpha, int flags) {
1016    addOp(DisplayList::SaveLayerAlpha);
1017    addBounds(left, top, right, bottom);
1018    addInt(alpha);
1019    addInt(flags);
1020    return OpenGLRenderer::save(flags);
1021}
1022
1023void DisplayListRenderer::translate(float dx, float dy) {
1024    addOp(DisplayList::Translate);
1025    addPoint(dx, dy);
1026    OpenGLRenderer::translate(dx, dy);
1027}
1028
1029void DisplayListRenderer::rotate(float degrees) {
1030    addOp(DisplayList::Rotate);
1031    addFloat(degrees);
1032    OpenGLRenderer::rotate(degrees);
1033}
1034
1035void DisplayListRenderer::scale(float sx, float sy) {
1036    addOp(DisplayList::Scale);
1037    addPoint(sx, sy);
1038    OpenGLRenderer::scale(sx, sy);
1039}
1040
1041void DisplayListRenderer::skew(float sx, float sy) {
1042    addOp(DisplayList::Skew);
1043    addPoint(sx, sy);
1044    OpenGLRenderer::skew(sx, sy);
1045}
1046
1047void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
1048    addOp(DisplayList::SetMatrix);
1049    addMatrix(matrix);
1050    OpenGLRenderer::setMatrix(matrix);
1051}
1052
1053void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
1054    addOp(DisplayList::ConcatMatrix);
1055    addMatrix(matrix);
1056    OpenGLRenderer::concatMatrix(matrix);
1057}
1058
1059bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
1060        SkRegion::Op op) {
1061    addOp(DisplayList::ClipRect);
1062    addBounds(left, top, right, bottom);
1063    addInt(op);
1064    return OpenGLRenderer::clipRect(left, top, right, bottom, op);
1065}
1066
1067bool DisplayListRenderer::drawDisplayList(DisplayList* displayList,
1068        uint32_t width, uint32_t height, Rect& dirty, uint32_t level) {
1069    // dirty is an out parameter and should not be recorded,
1070    // it matters only when replaying the display list
1071    addOp(DisplayList::DrawDisplayList);
1072    addDisplayList(displayList);
1073    addSize(width, height);
1074    return false;
1075}
1076
1077void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
1078    addOp(DisplayList::DrawLayer);
1079    addInt((int) layer);
1080    addPoint(x, y);
1081    addPaint(paint);
1082}
1083
1084void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
1085        SkPaint* paint) {
1086    addOp(DisplayList::DrawBitmap);
1087    addBitmap(bitmap);
1088    addPoint(left, top);
1089    addPaint(paint);
1090}
1091
1092void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
1093        SkPaint* paint) {
1094    addOp(DisplayList::DrawBitmapMatrix);
1095    addBitmap(bitmap);
1096    addMatrix(matrix);
1097    addPaint(paint);
1098}
1099
1100void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
1101        float srcRight, float srcBottom, float dstLeft, float dstTop,
1102        float dstRight, float dstBottom, SkPaint* paint) {
1103    addOp(DisplayList::DrawBitmapRect);
1104    addBitmap(bitmap);
1105    addBounds(srcLeft, srcTop, srcRight, srcBottom);
1106    addBounds(dstLeft, dstTop, dstRight, dstBottom);
1107    addPaint(paint);
1108}
1109
1110void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
1111        float* vertices, int* colors, SkPaint* paint) {
1112    addOp(DisplayList::DrawBitmapMesh);
1113    addBitmap(bitmap);
1114    addInt(meshWidth);
1115    addInt(meshHeight);
1116    addFloats(vertices, (meshWidth + 1) * (meshHeight + 1) * 2);
1117    if (colors) {
1118        addInt(1);
1119        addInts(colors, (meshWidth + 1) * (meshHeight + 1));
1120    } else {
1121        addInt(0);
1122    }
1123    addPaint(paint);
1124}
1125
1126void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
1127        const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
1128        float left, float top, float right, float bottom, SkPaint* paint) {
1129    addOp(DisplayList::DrawPatch);
1130    addBitmap(bitmap);
1131    addInts(xDivs, width);
1132    addInts(yDivs, height);
1133    addUInts(colors, numColors);
1134    addBounds(left, top, right, bottom);
1135    addPaint(paint);
1136}
1137
1138void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
1139    addOp(DisplayList::DrawColor);
1140    addInt(color);
1141    addInt(mode);
1142}
1143
1144void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
1145        SkPaint* paint) {
1146    addOp(DisplayList::DrawRect);
1147    addBounds(left, top, right, bottom);
1148    addPaint(paint);
1149}
1150
1151void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
1152            float rx, float ry, SkPaint* paint) {
1153    addOp(DisplayList::DrawRoundRect);
1154    addBounds(left, top, right, bottom);
1155    addPoint(rx, ry);
1156    addPaint(paint);
1157}
1158
1159void DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
1160    addOp(DisplayList::DrawCircle);
1161    addPoint(x, y);
1162    addFloat(radius);
1163    addPaint(paint);
1164}
1165
1166void DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
1167        SkPaint* paint) {
1168    addOp(DisplayList::DrawOval);
1169    addBounds(left, top, right, bottom);
1170    addPaint(paint);
1171}
1172
1173void DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
1174        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
1175    addOp(DisplayList::DrawArc);
1176    addBounds(left, top, right, bottom);
1177    addPoint(startAngle, sweepAngle);
1178    addInt(useCenter ? 1 : 0);
1179    addPaint(paint);
1180}
1181
1182void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
1183    addOp(DisplayList::DrawPath);
1184    addPath(path);
1185    addPaint(paint);
1186}
1187
1188void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
1189    addOp(DisplayList::DrawLines);
1190    addFloats(points, count);
1191    addPaint(paint);
1192}
1193
1194void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
1195    addOp(DisplayList::DrawPoints);
1196    addFloats(points, count);
1197    addPaint(paint);
1198}
1199
1200void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
1201        float x, float y, SkPaint* paint, float length) {
1202    if (count <= 0) return;
1203    addOp(DisplayList::DrawText);
1204    addText(text, bytesCount);
1205    addInt(count);
1206    addPoint(x, y);
1207    // TODO: We should probably make a copy of the paint instead of modifying
1208    //       it; modifying the paint will change its generationID the first
1209    //       time, which might impact caches. More investigation needed to
1210    //       see if it matters.
1211    //       If we make a copy, then drawTextDecorations() should *not* make
1212    //       its own copy as it does right now.
1213    // Beware: this needs Glyph encoding (already done on the Paint constructor)
1214    paint->setAntiAlias(true);
1215    addPaint(paint);
1216    addFloat(length < 0.0f ? paint->measureText(text, bytesCount) : length);
1217}
1218
1219void DisplayListRenderer::resetShader() {
1220    addOp(DisplayList::ResetShader);
1221}
1222
1223void DisplayListRenderer::setupShader(SkiaShader* shader) {
1224    addOp(DisplayList::SetupShader);
1225    addShader(shader);
1226}
1227
1228void DisplayListRenderer::resetColorFilter() {
1229    addOp(DisplayList::ResetColorFilter);
1230}
1231
1232void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
1233    addOp(DisplayList::SetupColorFilter);
1234    addColorFilter(filter);
1235}
1236
1237void DisplayListRenderer::resetShadow() {
1238    addOp(DisplayList::ResetShadow);
1239}
1240
1241void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
1242    addOp(DisplayList::SetupShadow);
1243    addFloat(radius);
1244    addPoint(dx, dy);
1245    addInt(color);
1246}
1247
1248}; // namespace uirenderer
1249}; // namespace android
1250