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