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