DisplayListRenderer.cpp revision 735738c4ddf3229caa5f6e634bf591953ac29944
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "OpenGLRenderer"
18
19#include <SkCamera.h>
20
21#include <private/hwui/DrawGlInfo.h>
22
23#include "DisplayListLogBuffer.h"
24#include "DisplayListRenderer.h"
25#include "Caches.h"
26
27namespace android {
28namespace uirenderer {
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    "ClipPath",
48    "ClipRegion",
49    "DrawDisplayList",
50    "DrawLayer",
51    "DrawBitmap",
52    "DrawBitmapMatrix",
53    "DrawBitmapRect",
54    "DrawBitmapData",
55    "DrawBitmapMesh",
56    "DrawPatch",
57    "DrawColor",
58    "DrawRect",
59    "DrawRoundRect",
60    "DrawCircle",
61    "DrawOval",
62    "DrawArc",
63    "DrawPath",
64    "DrawLines",
65    "DrawPoints",
66    "DrawTextOnPath",
67    "DrawPosText",
68    "DrawText",
69    "DrawRects",
70    "ResetShader",
71    "SetupShader",
72    "ResetColorFilter",
73    "SetupColorFilter",
74    "ResetShadow",
75    "SetupShadow",
76    "ResetPaintFilter",
77    "SetupPaintFilter",
78    "DrawGLFunction"
79};
80
81void DisplayList::outputLogBuffer(int fd) {
82    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
83    if (logBuffer.isEmpty()) {
84        return;
85    }
86
87    FILE *file = fdopen(fd, "a");
88
89    fprintf(file, "\nRecent DisplayList operations\n");
90    logBuffer.outputCommands(file, OP_NAMES);
91
92    String8 cachesLog;
93    Caches::getInstance().dumpMemoryUsage(cachesLog);
94    fprintf(file, "\nCaches:\n%s", cachesLog.string());
95    fprintf(file, "\n");
96
97    fflush(file);
98}
99
100DisplayList::DisplayList(const DisplayListRenderer& recorder) :
101    mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
102    mStaticMatrix(NULL), mAnimationMatrix(NULL) {
103
104    initFromDisplayListRenderer(recorder);
105}
106
107DisplayList::~DisplayList() {
108    clearResources();
109}
110
111void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
112    if (displayList) {
113        DISPLAY_LIST_LOGD("Deferring display list destruction");
114        Caches::getInstance().deleteDisplayListDeferred(displayList);
115    }
116}
117
118void DisplayList::clearResources() {
119    sk_free((void*) mReader.base());
120    mReader.setMemory(NULL, 0);
121
122    delete mTransformMatrix;
123    delete mTransformCamera;
124    delete mTransformMatrix3D;
125    delete mStaticMatrix;
126    delete mAnimationMatrix;
127
128    mTransformMatrix = NULL;
129    mTransformCamera = NULL;
130    mTransformMatrix3D = NULL;
131    mStaticMatrix = NULL;
132    mAnimationMatrix = NULL;
133
134    Caches& caches = Caches::getInstance();
135    caches.unregisterFunctors(mFunctorCount);
136    caches.resourceCache.lock();
137
138    for (size_t i = 0; i < mBitmapResources.size(); i++) {
139        caches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
140    }
141
142    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
143        SkBitmap* bitmap = mOwnedBitmapResources.itemAt(i);
144        caches.resourceCache.decrementRefcountLocked(bitmap);
145        caches.resourceCache.destructorLocked(bitmap);
146    }
147
148    for (size_t i = 0; i < mFilterResources.size(); i++) {
149        caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
150    }
151
152    for (size_t i = 0; i < mShaders.size(); i++) {
153        caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
154        caches.resourceCache.destructorLocked(mShaders.itemAt(i));
155    }
156
157    for (size_t i = 0; i < mSourcePaths.size(); i++) {
158        caches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
159    }
160
161    for (size_t i = 0; i < mLayers.size(); i++) {
162        caches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
163    }
164
165    caches.resourceCache.unlock();
166
167    for (size_t i = 0; i < mPaints.size(); i++) {
168        delete mPaints.itemAt(i);
169    }
170
171    for (size_t i = 0; i < mRegions.size(); i++) {
172        delete mRegions.itemAt(i);
173    }
174
175    for (size_t i = 0; i < mPaths.size(); i++) {
176        SkPath* path = mPaths.itemAt(i);
177        caches.pathCache.remove(path);
178        delete path;
179    }
180
181    for (size_t i = 0; i < mMatrices.size(); i++) {
182        delete mMatrices.itemAt(i);
183    }
184
185    mBitmapResources.clear();
186    mOwnedBitmapResources.clear();
187    mFilterResources.clear();
188    mShaders.clear();
189    mSourcePaths.clear();
190    mPaints.clear();
191    mRegions.clear();
192    mPaths.clear();
193    mMatrices.clear();
194    mLayers.clear();
195}
196
197void DisplayList::reset() {
198    clearResources();
199    init();
200}
201
202void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
203
204    if (reusing) {
205        // re-using display list - clear out previous allocations
206        clearResources();
207    }
208
209    init();
210
211    const SkWriter32& writer = recorder.writeStream();
212    if (writer.size() == 0) {
213        return;
214    }
215
216    mSize = writer.size();
217    void* buffer = sk_malloc_throw(mSize);
218    writer.flatten(buffer);
219    mReader.setMemory(buffer, mSize);
220
221    mFunctorCount = recorder.getFunctorCount();
222
223    Caches& caches = Caches::getInstance();
224    caches.registerFunctors(mFunctorCount);
225    caches.resourceCache.lock();
226
227    const Vector<SkBitmap*>& bitmapResources = recorder.getBitmapResources();
228    for (size_t i = 0; i < bitmapResources.size(); i++) {
229        SkBitmap* resource = bitmapResources.itemAt(i);
230        mBitmapResources.add(resource);
231        caches.resourceCache.incrementRefcountLocked(resource);
232    }
233
234    const Vector<SkBitmap*> &ownedBitmapResources = recorder.getOwnedBitmapResources();
235    for (size_t i = 0; i < ownedBitmapResources.size(); i++) {
236        SkBitmap* resource = ownedBitmapResources.itemAt(i);
237        mOwnedBitmapResources.add(resource);
238        caches.resourceCache.incrementRefcountLocked(resource);
239    }
240
241    const Vector<SkiaColorFilter*>& filterResources = recorder.getFilterResources();
242    for (size_t i = 0; i < filterResources.size(); i++) {
243        SkiaColorFilter* resource = filterResources.itemAt(i);
244        mFilterResources.add(resource);
245        caches.resourceCache.incrementRefcountLocked(resource);
246    }
247
248    const Vector<SkiaShader*>& shaders = recorder.getShaders();
249    for (size_t i = 0; i < shaders.size(); i++) {
250        SkiaShader* resource = shaders.itemAt(i);
251        mShaders.add(resource);
252        caches.resourceCache.incrementRefcountLocked(resource);
253    }
254
255    const SortedVector<SkPath*>& sourcePaths = recorder.getSourcePaths();
256    for (size_t i = 0; i < sourcePaths.size(); i++) {
257        mSourcePaths.add(sourcePaths.itemAt(i));
258        caches.resourceCache.incrementRefcountLocked(sourcePaths.itemAt(i));
259    }
260
261    const Vector<Layer*>& layers = recorder.getLayers();
262    for (size_t i = 0; i < layers.size(); i++) {
263        mLayers.add(layers.itemAt(i));
264        caches.resourceCache.incrementRefcountLocked(layers.itemAt(i));
265    }
266
267    caches.resourceCache.unlock();
268
269    mPaints.appendVector(recorder.getPaints());
270    mRegions.appendVector(recorder.getRegions());
271    mPaths.appendVector(recorder.getPaths());
272    mMatrices.appendVector(recorder.getMatrices());
273}
274
275void DisplayList::init() {
276    mSize = 0;
277    mIsRenderable = true;
278    mFunctorCount = 0;
279    mLeft = 0;
280    mTop = 0;
281    mRight = 0;
282    mBottom = 0;
283    mClipChildren = true;
284    mAlpha = 1;
285    mMultipliedAlpha = 255;
286    mHasOverlappingRendering = true;
287    mTranslationX = 0;
288    mTranslationY = 0;
289    mRotation = 0;
290    mRotationX = 0;
291    mRotationY= 0;
292    mScaleX = 1;
293    mScaleY = 1;
294    mPivotX = 0;
295    mPivotY = 0;
296    mCameraDistance = 0;
297    mMatrixDirty = false;
298    mMatrixFlags = 0;
299    mPrevWidth = -1;
300    mPrevHeight = -1;
301    mWidth = 0;
302    mHeight = 0;
303    mPivotExplicitlySet = false;
304    mCaching = false;
305}
306
307size_t DisplayList::getSize() {
308    return mSize;
309}
310
311/**
312 * This function is a simplified version of replay(), where we simply retrieve and log the
313 * display list. This function should remain in sync with the replay() function.
314 */
315void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
316    TextContainer text;
317
318    uint32_t count = (level + 1) * 2;
319    char indent[count + 1];
320    for (uint32_t i = 0; i < count; i++) {
321        indent[i] = ' ';
322    }
323    indent[count] = '\0';
324    ALOGD("%sStart display list (%p, %s, render=%d)", (char*) indent + 2, this,
325            mName.string(), isRenderable());
326
327    ALOGD("%s%s %d", indent, "Save", SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
328    int saveCount = renderer.getSaveCount() - 1;
329
330    outputViewProperties(renderer, (char*) indent);
331    mReader.rewind();
332
333    while (!mReader.eof()) {
334        int op = mReader.readInt();
335        if (op & OP_MAY_BE_SKIPPED_MASK) {
336            int skip = mReader.readInt();
337            ALOGD("%sSkip %d", (char*) indent, skip);
338            op &= ~OP_MAY_BE_SKIPPED_MASK;
339        }
340
341        switch (op) {
342            case DrawGLFunction: {
343                Functor *functor = (Functor *) getInt();
344                ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
345            }
346            break;
347            case Save: {
348                int rendererNum = getInt();
349                ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
350            }
351            break;
352            case Restore: {
353                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
354            }
355            break;
356            case RestoreToCount: {
357                int restoreCount = saveCount + getInt();
358                ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
359            }
360            break;
361            case SaveLayer: {
362                float f1 = getFloat();
363                float f2 = getFloat();
364                float f3 = getFloat();
365                float f4 = getFloat();
366                SkPaint* paint = getPaint(renderer);
367                int flags = getInt();
368                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
369                        OP_NAMES[op], f1, f2, f3, f4, paint, flags);
370            }
371            break;
372            case SaveLayerAlpha: {
373                float f1 = getFloat();
374                float f2 = getFloat();
375                float f3 = getFloat();
376                float f4 = getFloat();
377                int alpha = getInt();
378                int flags = getInt();
379                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
380                        OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
381            }
382            break;
383            case Translate: {
384                float f1 = getFloat();
385                float f2 = getFloat();
386                ALOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
387            }
388            break;
389            case Rotate: {
390                float rotation = getFloat();
391                ALOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
392            }
393            break;
394            case Scale: {
395                float sx = getFloat();
396                float sy = getFloat();
397                ALOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
398            }
399            break;
400            case Skew: {
401                float sx = getFloat();
402                float sy = getFloat();
403                ALOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
404            }
405            break;
406            case SetMatrix: {
407                SkMatrix* matrix = getMatrix();
408                ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
409            }
410            break;
411            case ConcatMatrix: {
412                SkMatrix* matrix = getMatrix();
413                ALOGD("%s%s new concat %p: [%f, %f, %f]   [%f, %f, %f]   [%f, %f, %f]",
414                        (char*) indent, OP_NAMES[op], matrix, matrix->get(0), matrix->get(1),
415                        matrix->get(2), matrix->get(3), matrix->get(4), matrix->get(5),
416                        matrix->get(6), matrix->get(7), matrix->get(8));
417            }
418            break;
419            case ClipRect: {
420                float f1 = getFloat();
421                float f2 = getFloat();
422                float f3 = getFloat();
423                float f4 = getFloat();
424                int regionOp = getInt();
425                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
426                        f1, f2, f3, f4, regionOp);
427            }
428            break;
429            case ClipPath: {
430                SkPath* path = getPath();
431                int regionOp = getInt();
432                ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
433            }
434            break;
435            case ClipRegion: {
436                SkRegion* region = getRegion();
437                int regionOp = getInt();
438                ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
439            }
440            break;
441            case DrawDisplayList: {
442                DisplayList* displayList = getDisplayList();
443                int32_t flags = getInt();
444                ALOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op],
445                        displayList, mWidth, mHeight, flags, level + 1);
446                renderer.outputDisplayList(displayList, level + 1);
447            }
448            break;
449            case DrawLayer: {
450                Layer* layer = (Layer*) getInt();
451                float x = getFloat();
452                float y = getFloat();
453                SkPaint* paint = getPaint(renderer);
454                ALOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
455                        layer, x, y, paint);
456            }
457            break;
458            case DrawBitmap: {
459                SkBitmap* bitmap = getBitmap();
460                float x = getFloat();
461                float y = getFloat();
462                SkPaint* paint = getPaint(renderer);
463                ALOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
464                        bitmap, x, y, paint);
465            }
466            break;
467            case DrawBitmapMatrix: {
468                SkBitmap* bitmap = getBitmap();
469                SkMatrix* matrix = getMatrix();
470                SkPaint* paint = getPaint(renderer);
471                ALOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
472                        bitmap, matrix, paint);
473            }
474            break;
475            case DrawBitmapRect: {
476                SkBitmap* bitmap = getBitmap();
477                float f1 = getFloat();
478                float f2 = getFloat();
479                float f3 = getFloat();
480                float f4 = getFloat();
481                float f5 = getFloat();
482                float f6 = getFloat();
483                float f7 = getFloat();
484                float f8 = getFloat();
485                SkPaint* paint = getPaint(renderer);
486                ALOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
487                        (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
488            }
489            break;
490            case DrawBitmapData: {
491                SkBitmap* bitmap = getBitmapData();
492                float x = getFloat();
493                float y = getFloat();
494                SkPaint* paint = getPaint(renderer);
495                ALOGD("%s%s %.2f, %.2f, %p", (char*) indent, OP_NAMES[op], x, y, paint);
496            }
497            break;
498            case DrawBitmapMesh: {
499                int verticesCount = 0;
500                uint32_t colorsCount = 0;
501                SkBitmap* bitmap = getBitmap();
502                uint32_t meshWidth = getInt();
503                uint32_t meshHeight = getInt();
504                float* vertices = getFloats(verticesCount);
505                bool hasColors = getInt();
506                int* colors = hasColors ? getInts(colorsCount) : NULL;
507                SkPaint* paint = getPaint(renderer);
508                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
509            }
510            break;
511            case DrawPatch: {
512                int32_t* xDivs = NULL;
513                int32_t* yDivs = NULL;
514                uint32_t* colors = NULL;
515                uint32_t xDivsCount = 0;
516                uint32_t yDivsCount = 0;
517                int8_t numColors = 0;
518                SkBitmap* bitmap = getBitmap();
519                xDivs = getInts(xDivsCount);
520                yDivs = getInts(yDivsCount);
521                colors = getUInts(numColors);
522                float left = getFloat();
523                float top = getFloat();
524                float right = getFloat();
525                float bottom = getFloat();
526                int alpha = getInt();
527                SkXfermode::Mode mode = (SkXfermode::Mode) getInt();
528                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", (char*) indent, OP_NAMES[op],
529                        left, top, right, bottom);
530            }
531            break;
532            case DrawColor: {
533                int color = getInt();
534                int xferMode = getInt();
535                ALOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
536            }
537            break;
538            case DrawRect: {
539                float f1 = getFloat();
540                float f2 = getFloat();
541                float f3 = getFloat();
542                float f4 = getFloat();
543                SkPaint* paint = getPaint(renderer);
544                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
545                        f1, f2, f3, f4, paint);
546            }
547            break;
548            case DrawRoundRect: {
549                float f1 = getFloat();
550                float f2 = getFloat();
551                float f3 = getFloat();
552                float f4 = getFloat();
553                float f5 = getFloat();
554                float f6 = getFloat();
555                SkPaint* paint = getPaint(renderer);
556                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
557                        (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
558            }
559            break;
560            case DrawCircle: {
561                float f1 = getFloat();
562                float f2 = getFloat();
563                float f3 = getFloat();
564                SkPaint* paint = getPaint(renderer);
565                ALOGD("%s%s %.2f, %.2f, %.2f, %p",
566                        (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
567            }
568            break;
569            case DrawOval: {
570                float f1 = getFloat();
571                float f2 = getFloat();
572                float f3 = getFloat();
573                float f4 = getFloat();
574                SkPaint* paint = getPaint(renderer);
575                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
576                        (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
577            }
578            break;
579            case DrawArc: {
580                float f1 = getFloat();
581                float f2 = getFloat();
582                float f3 = getFloat();
583                float f4 = getFloat();
584                float f5 = getFloat();
585                float f6 = getFloat();
586                int i1 = getInt();
587                SkPaint* paint = getPaint(renderer);
588                ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
589                        (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
590            }
591            break;
592            case DrawPath: {
593                SkPath* path = getPath();
594                SkPaint* paint = getPaint(renderer);
595                ALOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
596            }
597            break;
598            case DrawLines: {
599                int count = 0;
600                float* points = getFloats(count);
601                SkPaint* paint = getPaint(renderer);
602                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
603            }
604            break;
605            case DrawPoints: {
606                int count = 0;
607                float* points = getFloats(count);
608                SkPaint* paint = getPaint(renderer);
609                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
610            }
611            break;
612            case DrawTextOnPath: {
613                getText(&text);
614                int32_t count = getInt();
615                SkPath* path = getPath();
616                float hOffset = getFloat();
617                float vOffset = getFloat();
618                SkPaint* paint = getPaint(renderer);
619                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
620                    text.text(), text.length(), count, paint);
621            }
622            break;
623            case DrawPosText: {
624                getText(&text);
625                int count = getInt();
626                int positionsCount = 0;
627                float* positions = getFloats(positionsCount);
628                SkPaint* paint = getPaint(renderer);
629                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
630                        text.text(), text.length(), count, paint);
631            }
632            break;
633            case DrawText: {
634                getText(&text);
635                int32_t count = getInt();
636                float x = getFloat();
637                float y = getFloat();
638                int32_t positionsCount = 0;
639                float* positions = getFloats(positionsCount);
640                SkPaint* paint = getPaint(renderer);
641                float length = getFloat();
642                ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
643                        text.text(), text.length(), count, paint);
644            }
645            break;
646            case DrawRects: {
647                int32_t count = 0;
648                float* rects = getFloats(count);
649                SkPaint* paint = getPaint(renderer);
650                ALOGD("%s%s %d, %p", (char*) indent, OP_NAMES[op], count / 4, paint);
651            }
652            break;
653            case ResetShader: {
654                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
655            }
656            break;
657            case SetupShader: {
658                SkiaShader* shader = getShader();
659                ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
660            }
661            break;
662            case ResetColorFilter: {
663                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
664            }
665            break;
666            case SetupColorFilter: {
667                SkiaColorFilter *colorFilter = getColorFilter();
668                ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
669            }
670            break;
671            case ResetShadow: {
672                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
673            }
674            break;
675            case SetupShadow: {
676                float radius = getFloat();
677                float dx = getFloat();
678                float dy = getFloat();
679                int color = getInt();
680                ALOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
681                        radius, dx, dy, color);
682            }
683            break;
684            case ResetPaintFilter: {
685                ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
686            }
687            break;
688            case SetupPaintFilter: {
689                int clearBits = getInt();
690                int setBits = getInt();
691                ALOGD("%s%s 0x%x, 0x%x", (char*) indent, OP_NAMES[op], clearBits, setBits);
692            }
693            break;
694            default:
695                ALOGD("Display List error: op not handled: %s%s",
696                        (char*) indent, OP_NAMES[op]);
697                break;
698        }
699    }
700    ALOGD("%sDone (%p, %s)", (char*) indent + 2, this, mName.string());
701}
702
703void DisplayList::updateMatrix() {
704    if (mMatrixDirty) {
705        if (!mTransformMatrix) {
706            mTransformMatrix = new SkMatrix();
707        }
708        if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
709            mTransformMatrix->reset();
710        } else {
711            if (!mPivotExplicitlySet) {
712                if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
713                    mPrevWidth = mWidth;
714                    mPrevHeight = mHeight;
715                    mPivotX = mPrevWidth / 2;
716                    mPivotY = mPrevHeight / 2;
717                }
718            }
719            if ((mMatrixFlags & ROTATION_3D) == 0) {
720                mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
721                mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
722                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
723            } else {
724                if (!mTransformCamera) {
725                    mTransformCamera = new Sk3DView();
726                    mTransformMatrix3D = new SkMatrix();
727                }
728                mTransformMatrix->reset();
729                mTransformCamera->save();
730                mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
731                mTransformCamera->rotateX(mRotationX);
732                mTransformCamera->rotateY(mRotationY);
733                mTransformCamera->rotateZ(-mRotation);
734                mTransformCamera->getMatrix(mTransformMatrix3D);
735                mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
736                mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
737                        mPivotY + mTranslationY);
738                mTransformMatrix->postConcat(*mTransformMatrix3D);
739                mTransformCamera->restore();
740            }
741        }
742        mMatrixDirty = false;
743    }
744}
745
746void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) {
747    updateMatrix();
748    if (mLeft != 0 || mTop != 0) {
749        ALOGD("%s%s %d, %d", indent, "Translate (left, top)", mLeft, mTop);
750    }
751    if (mStaticMatrix) {
752        ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
753                indent, "ConcatMatrix (static)", mStaticMatrix,
754                mStaticMatrix->get(0), mStaticMatrix->get(1),
755                mStaticMatrix->get(2), mStaticMatrix->get(3),
756                mStaticMatrix->get(4), mStaticMatrix->get(5),
757                mStaticMatrix->get(6), mStaticMatrix->get(7),
758                mStaticMatrix->get(8));
759    }
760    if (mAnimationMatrix) {
761        ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
762                indent, "ConcatMatrix (animation)", mAnimationMatrix,
763                mAnimationMatrix->get(0), mAnimationMatrix->get(1),
764                mAnimationMatrix->get(2), mAnimationMatrix->get(3),
765                mAnimationMatrix->get(4), mAnimationMatrix->get(5),
766                mAnimationMatrix->get(6), mAnimationMatrix->get(7),
767                mAnimationMatrix->get(8));
768    }
769    if (mMatrixFlags != 0) {
770        if (mMatrixFlags == TRANSLATION) {
771            ALOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY);
772        } else {
773            ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
774                    indent, "ConcatMatrix", mTransformMatrix,
775                    mTransformMatrix->get(0), mTransformMatrix->get(1),
776                    mTransformMatrix->get(2), mTransformMatrix->get(3),
777                    mTransformMatrix->get(4), mTransformMatrix->get(5),
778                    mTransformMatrix->get(6), mTransformMatrix->get(7),
779                    mTransformMatrix->get(8));
780        }
781    }
782    if (mAlpha < 1 && !mCaching) {
783        if (!mHasOverlappingRendering) {
784            ALOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
785        } else {
786            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
787            if (mClipChildren) {
788                flags |= SkCanvas::kClipToLayer_SaveFlag;
789            }
790            ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
791                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
792                    mMultipliedAlpha, flags);
793        }
794    }
795    if (mClipChildren) {
796        ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
797                (float) mRight - mLeft, (float) mBottom - mTop);
798    }
799}
800
801void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
802#if DEBUG_DISPLAY_LIST
803        uint32_t count = (level + 1) * 2;
804        char indent[count + 1];
805        for (uint32_t i = 0; i < count; i++) {
806            indent[i] = ' ';
807        }
808        indent[count] = '\0';
809#endif
810    updateMatrix();
811    if (mLeft != 0 || mTop != 0) {
812        DISPLAY_LIST_LOGD("%s%s %d, %d", indent, "Translate (left, top)", mLeft, mTop);
813        renderer.translate(mLeft, mTop);
814    }
815    if (mStaticMatrix) {
816        DISPLAY_LIST_LOGD(
817                "%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
818                indent, "ConcatMatrix (static)", mStaticMatrix,
819                mStaticMatrix->get(0), mStaticMatrix->get(1),
820                mStaticMatrix->get(2), mStaticMatrix->get(3),
821                mStaticMatrix->get(4), mStaticMatrix->get(5),
822                mStaticMatrix->get(6), mStaticMatrix->get(7),
823                mStaticMatrix->get(8));
824        renderer.concatMatrix(mStaticMatrix);
825    } else if (mAnimationMatrix) {
826        DISPLAY_LIST_LOGD(
827                "%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
828                indent, "ConcatMatrix (animation)", mAnimationMatrix,
829                mAnimationMatrix->get(0), mAnimationMatrix->get(1),
830                mAnimationMatrix->get(2), mAnimationMatrix->get(3),
831                mAnimationMatrix->get(4), mAnimationMatrix->get(5),
832                mAnimationMatrix->get(6), mAnimationMatrix->get(7),
833                mAnimationMatrix->get(8));
834        renderer.concatMatrix(mAnimationMatrix);
835    }
836    if (mMatrixFlags != 0) {
837        if (mMatrixFlags == TRANSLATION) {
838            DISPLAY_LIST_LOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY);
839            renderer.translate(mTranslationX, mTranslationY);
840        } else {
841            DISPLAY_LIST_LOGD(
842                    "%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
843                    indent, "ConcatMatrix", mTransformMatrix,
844                    mTransformMatrix->get(0), mTransformMatrix->get(1),
845                    mTransformMatrix->get(2), mTransformMatrix->get(3),
846                    mTransformMatrix->get(4), mTransformMatrix->get(5),
847                    mTransformMatrix->get(6), mTransformMatrix->get(7),
848                    mTransformMatrix->get(8));
849            renderer.concatMatrix(mTransformMatrix);
850        }
851    }
852    if (mAlpha < 1 && !mCaching) {
853        if (!mHasOverlappingRendering) {
854            DISPLAY_LIST_LOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
855            renderer.setAlpha(mAlpha);
856        } else {
857            // TODO: should be able to store the size of a DL at record time and not
858            // have to pass it into this call. In fact, this information might be in the
859            // location/size info that we store with the new native transform data.
860            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
861            if (mClipChildren) {
862                flags |= SkCanvas::kClipToLayer_SaveFlag;
863            }
864            DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
865                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
866                    mMultipliedAlpha, flags);
867            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
868                    mMultipliedAlpha, flags);
869        }
870    }
871    if (mClipChildren) {
872        DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
873                (float) mRight - mLeft, (float) mBottom - mTop);
874        renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
875                SkRegion::kIntersect_Op);
876    }
877}
878
879/**
880 * Changes to replay(), specifically those involving opcode or parameter changes, should be mimicked
881 * in the output() function, since that function processes the same list of opcodes for the
882 * purposes of logging display list info for a given view.
883 */
884status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
885    status_t drawGlStatus = DrawGlInfo::kStatusDone;
886    TextContainer text;
887    mReader.rewind();
888
889#if DEBUG_DISPLAY_LIST
890    uint32_t count = (level + 1) * 2;
891    char indent[count + 1];
892    for (uint32_t i = 0; i < count; i++) {
893        indent[i] = ' ';
894    }
895    indent[count] = '\0';
896    Rect* clipRect = renderer.getClipRect();
897    DISPLAY_LIST_LOGD("%sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
898            (char*) indent + 2, this, mName.string(), clipRect->left, clipRect->top,
899            clipRect->right, clipRect->bottom);
900#endif
901
902    renderer.startMark(mName.string());
903
904    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
905    DISPLAY_LIST_LOGD("%s%s %d %d", indent, "Save",
906            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
907    setViewProperties(renderer, level);
908
909    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
910        DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
911        renderer.restoreToCount(restoreTo);
912        renderer.endMark();
913        return drawGlStatus;
914    }
915
916    DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
917    int saveCount = renderer.getSaveCount() - 1;
918
919    while (!mReader.eof()) {
920        int op = mReader.readInt();
921        if (op & OP_MAY_BE_SKIPPED_MASK) {
922            int32_t skip = mReader.readInt();
923            if (CC_LIKELY(flags & kReplayFlag_ClipChildren)) {
924                mReader.skip(skip);
925                DISPLAY_LIST_LOGD("%s%s skipping %d bytes", (char*) indent,
926                        OP_NAMES[op & ~OP_MAY_BE_SKIPPED_MASK], skip);
927                continue;
928            } else {
929                op &= ~OP_MAY_BE_SKIPPED_MASK;
930            }
931        }
932        logBuffer.writeCommand(level, op);
933
934#if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
935        Caches::getInstance().eventMark(strlen(OP_NAMES[op]), OP_NAMES[op]);
936#endif
937
938        switch (op) {
939            case DrawGLFunction: {
940                Functor *functor = (Functor *) getInt();
941                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
942                renderer.startMark("GL functor");
943                drawGlStatus |= renderer.callDrawGLFunction(functor, dirty);
944                renderer.endMark();
945            }
946            break;
947            case Save: {
948                int32_t rendererNum = getInt();
949                DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
950                renderer.save(rendererNum);
951            }
952            break;
953            case Restore: {
954                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
955                renderer.restore();
956            }
957            break;
958            case RestoreToCount: {
959                int32_t restoreCount = saveCount + getInt();
960                DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
961                renderer.restoreToCount(restoreCount);
962            }
963            break;
964            case SaveLayer: {
965                float f1 = getFloat();
966                float f2 = getFloat();
967                float f3 = getFloat();
968                float f4 = getFloat();
969                SkPaint* paint = getPaint(renderer);
970                int32_t flags = getInt();
971                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
972                        OP_NAMES[op], f1, f2, f3, f4, paint, flags);
973                renderer.saveLayer(f1, f2, f3, f4, paint, flags);
974            }
975            break;
976            case SaveLayerAlpha: {
977                float f1 = getFloat();
978                float f2 = getFloat();
979                float f3 = getFloat();
980                float f4 = getFloat();
981                int32_t alpha = getInt();
982                int32_t flags = getInt();
983                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
984                        OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
985                renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags);
986            }
987            break;
988            case Translate: {
989                float f1 = getFloat();
990                float f2 = getFloat();
991                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
992                renderer.translate(f1, f2);
993            }
994            break;
995            case Rotate: {
996                float rotation = getFloat();
997                DISPLAY_LIST_LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
998                renderer.rotate(rotation);
999            }
1000            break;
1001            case Scale: {
1002                float sx = getFloat();
1003                float sy = getFloat();
1004                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
1005                renderer.scale(sx, sy);
1006            }
1007            break;
1008            case Skew: {
1009                float sx = getFloat();
1010                float sy = getFloat();
1011                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
1012                renderer.skew(sx, sy);
1013            }
1014            break;
1015            case SetMatrix: {
1016                SkMatrix* matrix = getMatrix();
1017                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
1018                renderer.setMatrix(matrix);
1019            }
1020            break;
1021            case ConcatMatrix: {
1022                SkMatrix* matrix = getMatrix();
1023                DISPLAY_LIST_LOGD(
1024                        "%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
1025                        (char*) indent, OP_NAMES[op], matrix,
1026                        matrix->get(0), matrix->get(1), matrix->get(2),
1027                        matrix->get(3), matrix->get(4), matrix->get(5),
1028                        matrix->get(6), matrix->get(7), matrix->get(8));
1029                renderer.concatMatrix(matrix);
1030            }
1031            break;
1032            case ClipRect: {
1033                float f1 = getFloat();
1034                float f2 = getFloat();
1035                float f3 = getFloat();
1036                float f4 = getFloat();
1037                int32_t regionOp = getInt();
1038                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
1039                        f1, f2, f3, f4, regionOp);
1040                renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
1041            }
1042            break;
1043            case ClipPath: {
1044                SkPath* path = getPath();
1045                int32_t regionOp = getInt();
1046                DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
1047                renderer.clipPath(path, (SkRegion::Op) regionOp);
1048            }
1049            break;
1050            case ClipRegion: {
1051                SkRegion* region = getRegion();
1052                int32_t regionOp = getInt();
1053                DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
1054                renderer.clipRegion(region, (SkRegion::Op) regionOp);
1055            }
1056            break;
1057            case DrawDisplayList: {
1058                DisplayList* displayList = getDisplayList();
1059                int32_t flags = getInt();
1060                DISPLAY_LIST_LOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op],
1061                        displayList, mWidth, mHeight, flags, level + 1);
1062                drawGlStatus |= renderer.drawDisplayList(displayList, dirty, flags, level + 1);
1063            }
1064            break;
1065            case DrawLayer: {
1066                int oldAlpha = -1;
1067                Layer* layer = (Layer*) getInt();
1068                float x = getFloat();
1069                float y = getFloat();
1070                SkPaint* paint = getPaint(renderer);
1071                if (mCaching && mMultipliedAlpha < 255) {
1072                    oldAlpha = layer->getAlpha();
1073                    layer->setAlpha(mMultipliedAlpha);
1074                }
1075                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
1076                        layer, x, y, paint);
1077                drawGlStatus |= renderer.drawLayer(layer, x, y, paint);
1078                if (oldAlpha >= 0) {
1079                    layer->setAlpha(oldAlpha);
1080                }
1081            }
1082            break;
1083            case DrawBitmap: {
1084                int oldAlpha = -1;
1085                SkBitmap* bitmap = getBitmap();
1086                float x = getFloat();
1087                float y = getFloat();
1088                SkPaint* paint = getPaint(renderer);
1089                if (mCaching && mMultipliedAlpha < 255) {
1090                    oldAlpha = paint->getAlpha();
1091                    paint->setAlpha(mMultipliedAlpha);
1092                }
1093                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
1094                        bitmap, x, y, paint);
1095                drawGlStatus |= renderer.drawBitmap(bitmap, x, y, paint);
1096                if (oldAlpha >= 0) {
1097                    paint->setAlpha(oldAlpha);
1098                }
1099            }
1100            break;
1101            case DrawBitmapMatrix: {
1102                SkBitmap* bitmap = getBitmap();
1103                SkMatrix* matrix = getMatrix();
1104                SkPaint* paint = getPaint(renderer);
1105                DISPLAY_LIST_LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
1106                        bitmap, matrix, paint);
1107                drawGlStatus |= renderer.drawBitmap(bitmap, matrix, paint);
1108            }
1109            break;
1110            case DrawBitmapRect: {
1111                SkBitmap* bitmap = getBitmap();
1112                float f1 = getFloat();
1113                float f2 = getFloat();
1114                float f3 = getFloat();
1115                float f4 = getFloat();
1116                float f5 = getFloat();
1117                float f6 = getFloat();
1118                float f7 = getFloat();
1119                float f8 = getFloat();
1120                SkPaint* paint = getPaint(renderer);
1121                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
1122                        (char*) indent, OP_NAMES[op], bitmap,
1123                        f1, f2, f3, f4, f5, f6, f7, f8,paint);
1124                drawGlStatus |= renderer.drawBitmap(bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
1125            }
1126            break;
1127            case DrawBitmapData: {
1128                SkBitmap* bitmap = getBitmapData();
1129                float x = getFloat();
1130                float y = getFloat();
1131                SkPaint* paint = getPaint(renderer);
1132                DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
1133                        bitmap, x, y, paint);
1134                drawGlStatus |= renderer.drawBitmap(bitmap, x, y, paint);
1135            }
1136            break;
1137            case DrawBitmapMesh: {
1138                int32_t verticesCount = 0;
1139                uint32_t colorsCount = 0;
1140
1141                SkBitmap* bitmap = getBitmap();
1142                uint32_t meshWidth = getInt();
1143                uint32_t meshHeight = getInt();
1144                float* vertices = getFloats(verticesCount);
1145                bool hasColors = getInt();
1146                int32_t* colors = hasColors ? getInts(colorsCount) : NULL;
1147                SkPaint* paint = getPaint(renderer);
1148
1149                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1150                drawGlStatus |= renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices,
1151                        colors, paint);
1152            }
1153            break;
1154            case DrawPatch: {
1155                int32_t* xDivs = NULL;
1156                int32_t* yDivs = NULL;
1157                uint32_t* colors = NULL;
1158                uint32_t xDivsCount = 0;
1159                uint32_t yDivsCount = 0;
1160                int8_t numColors = 0;
1161
1162                SkBitmap* bitmap = getBitmap();
1163
1164                xDivs = getInts(xDivsCount);
1165                yDivs = getInts(yDivsCount);
1166                colors = getUInts(numColors);
1167
1168                float left = getFloat();
1169                float top = getFloat();
1170                float right = getFloat();
1171                float bottom = getFloat();
1172
1173                int alpha = getInt();
1174                SkXfermode::Mode mode = (SkXfermode::Mode) getInt();
1175
1176                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1177                drawGlStatus |= renderer.drawPatch(bitmap, xDivs, yDivs, colors,
1178                        xDivsCount, yDivsCount, numColors, left, top, right, bottom,
1179                        alpha, mode);
1180            }
1181            break;
1182            case DrawColor: {
1183                int32_t color = getInt();
1184                int32_t xferMode = getInt();
1185                DISPLAY_LIST_LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
1186                drawGlStatus |= renderer.drawColor(color, (SkXfermode::Mode) xferMode);
1187            }
1188            break;
1189            case DrawRect: {
1190                float f1 = getFloat();
1191                float f2 = getFloat();
1192                float f3 = getFloat();
1193                float f4 = getFloat();
1194                SkPaint* paint = getPaint(renderer);
1195                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
1196                        f1, f2, f3, f4, paint);
1197                drawGlStatus |= renderer.drawRect(f1, f2, f3, f4, paint);
1198            }
1199            break;
1200            case DrawRoundRect: {
1201                float f1 = getFloat();
1202                float f2 = getFloat();
1203                float f3 = getFloat();
1204                float f4 = getFloat();
1205                float f5 = getFloat();
1206                float f6 = getFloat();
1207                SkPaint* paint = getPaint(renderer);
1208                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
1209                        (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
1210                drawGlStatus |= renderer.drawRoundRect(f1, f2, f3, f4, f5, f6, paint);
1211            }
1212            break;
1213            case DrawCircle: {
1214                float f1 = getFloat();
1215                float f2 = getFloat();
1216                float f3 = getFloat();
1217                SkPaint* paint = getPaint(renderer);
1218                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %p",
1219                        (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
1220                drawGlStatus |= renderer.drawCircle(f1, f2, f3, paint);
1221            }
1222            break;
1223            case DrawOval: {
1224                float f1 = getFloat();
1225                float f2 = getFloat();
1226                float f3 = getFloat();
1227                float f4 = getFloat();
1228                SkPaint* paint = getPaint(renderer);
1229                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
1230                        (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
1231                drawGlStatus |= renderer.drawOval(f1, f2, f3, f4, paint);
1232            }
1233            break;
1234            case DrawArc: {
1235                float f1 = getFloat();
1236                float f2 = getFloat();
1237                float f3 = getFloat();
1238                float f4 = getFloat();
1239                float f5 = getFloat();
1240                float f6 = getFloat();
1241                int32_t i1 = getInt();
1242                SkPaint* paint = getPaint(renderer);
1243                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
1244                        (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
1245                drawGlStatus |= renderer.drawArc(f1, f2, f3, f4, f5, f6, i1 == 1, paint);
1246            }
1247            break;
1248            case DrawPath: {
1249                SkPath* path = getPath();
1250                SkPaint* paint = getPaint(renderer);
1251                DISPLAY_LIST_LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
1252                drawGlStatus |= renderer.drawPath(path, paint);
1253            }
1254            break;
1255            case DrawLines: {
1256                int32_t count = 0;
1257                float* points = getFloats(count);
1258                SkPaint* paint = getPaint(renderer);
1259                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1260                drawGlStatus |= renderer.drawLines(points, count, paint);
1261            }
1262            break;
1263            case DrawPoints: {
1264                int32_t count = 0;
1265                float* points = getFloats(count);
1266                SkPaint* paint = getPaint(renderer);
1267                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1268                drawGlStatus |= renderer.drawPoints(points, count, paint);
1269            }
1270            break;
1271            case DrawTextOnPath: {
1272                getText(&text);
1273                int32_t count = getInt();
1274                SkPath* path = getPath();
1275                float hOffset = getFloat();
1276                float vOffset = getFloat();
1277                SkPaint* paint = getPaint(renderer);
1278                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
1279                    text.text(), text.length(), count, paint);
1280                drawGlStatus |= renderer.drawTextOnPath(text.text(), text.length(), count, path,
1281                        hOffset, vOffset, paint);
1282            }
1283            break;
1284            case DrawPosText: {
1285                getText(&text);
1286                int32_t count = getInt();
1287                int32_t positionsCount = 0;
1288                float* positions = getFloats(positionsCount);
1289                SkPaint* paint = getPaint(renderer);
1290                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %p", (char*) indent,
1291                        OP_NAMES[op], text.text(), text.length(), count, paint);
1292                drawGlStatus |= renderer.drawPosText(text.text(), text.length(), count,
1293                        positions, paint);
1294            }
1295            break;
1296            case DrawText: {
1297                getText(&text);
1298                int32_t count = getInt();
1299                float x = getFloat();
1300                float y = getFloat();
1301                int32_t positionsCount = 0;
1302                float* positions = getFloats(positionsCount);
1303                SkPaint* paint = getPaint(renderer);
1304                float length = getFloat();
1305                DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
1306                        OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
1307                drawGlStatus |= renderer.drawText(text.text(), text.length(), count,
1308                        x, y, positions, paint, length);
1309            }
1310            break;
1311            case DrawRects: {
1312                int32_t count = 0;
1313                float* rects = getFloats(count);
1314                SkPaint* paint = getPaint(renderer);
1315                DISPLAY_LIST_LOGD("%s%s %d, %p", (char*) indent, OP_NAMES[op], count, paint);
1316                drawGlStatus |= renderer.drawRects(rects, count / 4, paint);
1317            }
1318            break;
1319            case ResetShader: {
1320                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1321                renderer.resetShader();
1322            }
1323            break;
1324            case SetupShader: {
1325                SkiaShader* shader = getShader();
1326                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
1327                renderer.setupShader(shader);
1328            }
1329            break;
1330            case ResetColorFilter: {
1331                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1332                renderer.resetColorFilter();
1333            }
1334            break;
1335            case SetupColorFilter: {
1336                SkiaColorFilter *colorFilter = getColorFilter();
1337                DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
1338                renderer.setupColorFilter(colorFilter);
1339            }
1340            break;
1341            case ResetShadow: {
1342                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1343                renderer.resetShadow();
1344            }
1345            break;
1346            case SetupShadow: {
1347                float radius = getFloat();
1348                float dx = getFloat();
1349                float dy = getFloat();
1350                int32_t color = getInt();
1351                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
1352                        radius, dx, dy, color);
1353                renderer.setupShadow(radius, dx, dy, color);
1354            }
1355            break;
1356            case ResetPaintFilter: {
1357                DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
1358                renderer.resetPaintFilter();
1359            }
1360            break;
1361            case SetupPaintFilter: {
1362                int32_t clearBits = getInt();
1363                int32_t setBits = getInt();
1364                DISPLAY_LIST_LOGD("%s%s 0x%x, 0x%x", (char*) indent, OP_NAMES[op],
1365                        clearBits, setBits);
1366                renderer.setupPaintFilter(clearBits, setBits);
1367            }
1368            break;
1369            default:
1370                DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
1371                        (char*) indent, OP_NAMES[op]);
1372                break;
1373        }
1374    }
1375
1376    DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
1377    renderer.restoreToCount(restoreTo);
1378    renderer.endMark();
1379
1380    DISPLAY_LIST_LOGD("%sDone (%p, %s), returning %d", (char*) indent + 2, this, mName.string(),
1381            drawGlStatus);
1382    return drawGlStatus;
1383}
1384
1385///////////////////////////////////////////////////////////////////////////////
1386// Base structure
1387///////////////////////////////////////////////////////////////////////////////
1388
1389DisplayListRenderer::DisplayListRenderer():
1390        mCaches(Caches::getInstance()), mWriter(MIN_WRITER_SIZE),
1391        mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false),
1392        mHasDrawOps(false), mFunctorCount(0) {
1393}
1394
1395DisplayListRenderer::~DisplayListRenderer() {
1396    reset();
1397}
1398
1399void DisplayListRenderer::reset() {
1400    mWriter.reset();
1401
1402    mCaches.resourceCache.lock();
1403
1404    for (size_t i = 0; i < mBitmapResources.size(); i++) {
1405        mCaches.resourceCache.decrementRefcountLocked(mBitmapResources.itemAt(i));
1406    }
1407
1408    for (size_t i = 0; i < mOwnedBitmapResources.size(); i++) {
1409        mCaches.resourceCache.decrementRefcountLocked(mOwnedBitmapResources.itemAt(i));
1410    }
1411
1412    for (size_t i = 0; i < mFilterResources.size(); i++) {
1413        mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
1414    }
1415
1416    for (size_t i = 0; i < mShaders.size(); i++) {
1417        mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
1418    }
1419
1420    for (size_t i = 0; i < mSourcePaths.size(); i++) {
1421        mCaches.resourceCache.decrementRefcountLocked(mSourcePaths.itemAt(i));
1422    }
1423
1424    for (size_t i = 0; i < mLayers.size(); i++) {
1425        mCaches.resourceCache.decrementRefcountLocked(mLayers.itemAt(i));
1426    }
1427
1428    mCaches.resourceCache.unlock();
1429
1430    mBitmapResources.clear();
1431    mOwnedBitmapResources.clear();
1432    mFilterResources.clear();
1433    mSourcePaths.clear();
1434
1435    mShaders.clear();
1436    mShaderMap.clear();
1437
1438    mPaints.clear();
1439    mPaintMap.clear();
1440
1441    mRegions.clear();
1442    mRegionMap.clear();
1443
1444    mPaths.clear();
1445    mPathMap.clear();
1446
1447    mMatrices.clear();
1448
1449    mLayers.clear();
1450
1451    mHasDrawOps = false;
1452    mFunctorCount = 0;
1453}
1454
1455///////////////////////////////////////////////////////////////////////////////
1456// Operations
1457///////////////////////////////////////////////////////////////////////////////
1458
1459DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
1460    if (!displayList) {
1461        displayList = new DisplayList(*this);
1462    } else {
1463        displayList->initFromDisplayListRenderer(*this, true);
1464    }
1465    displayList->setRenderable(mHasDrawOps);
1466    return displayList;
1467}
1468
1469bool DisplayListRenderer::isDeferred() {
1470    return true;
1471}
1472
1473void DisplayListRenderer::setViewport(int width, int height) {
1474    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
1475
1476    mWidth = width;
1477    mHeight = height;
1478}
1479
1480status_t DisplayListRenderer::prepareDirty(float left, float top,
1481        float right, float bottom, bool opaque) {
1482    mSnapshot = new Snapshot(mFirstSnapshot,
1483            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
1484    mSaveCount = 1;
1485
1486    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
1487    mDirtyClip = opaque;
1488
1489    mRestoreSaveCount = -1;
1490
1491    return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
1492}
1493
1494void DisplayListRenderer::finish() {
1495    insertRestoreToCount();
1496    insertTranlate();
1497}
1498
1499void DisplayListRenderer::interrupt() {
1500}
1501
1502void DisplayListRenderer::resume() {
1503}
1504
1505status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
1506    // Ignore dirty during recording, it matters only when we replay
1507    addOp(DisplayList::DrawGLFunction);
1508    addInt((int) functor);
1509    mFunctorCount++;
1510    return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
1511}
1512
1513int DisplayListRenderer::save(int flags) {
1514    addOp(DisplayList::Save);
1515    addInt(flags);
1516    return OpenGLRenderer::save(flags);
1517}
1518
1519void DisplayListRenderer::restore() {
1520    if (mRestoreSaveCount < 0) {
1521        restoreToCount(getSaveCount() - 1);
1522        return;
1523    }
1524
1525    mRestoreSaveCount--;
1526    insertTranlate();
1527    OpenGLRenderer::restore();
1528}
1529
1530void DisplayListRenderer::restoreToCount(int saveCount) {
1531    mRestoreSaveCount = saveCount;
1532    insertTranlate();
1533    OpenGLRenderer::restoreToCount(saveCount);
1534}
1535
1536int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
1537        SkPaint* p, int flags) {
1538    addOp(DisplayList::SaveLayer);
1539    addBounds(left, top, right, bottom);
1540    addPaint(p);
1541    addInt(flags);
1542    return OpenGLRenderer::save(flags);
1543}
1544
1545int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
1546        int alpha, int flags) {
1547    addOp(DisplayList::SaveLayerAlpha);
1548    addBounds(left, top, right, bottom);
1549    addInt(alpha);
1550    addInt(flags);
1551    return OpenGLRenderer::save(flags);
1552}
1553
1554void DisplayListRenderer::translate(float dx, float dy) {
1555    mHasTranslate = true;
1556    mTranslateX += dx;
1557    mTranslateY += dy;
1558    insertRestoreToCount();
1559    OpenGLRenderer::translate(dx, dy);
1560}
1561
1562void DisplayListRenderer::rotate(float degrees) {
1563    addOp(DisplayList::Rotate);
1564    addFloat(degrees);
1565    OpenGLRenderer::rotate(degrees);
1566}
1567
1568void DisplayListRenderer::scale(float sx, float sy) {
1569    addOp(DisplayList::Scale);
1570    addPoint(sx, sy);
1571    OpenGLRenderer::scale(sx, sy);
1572}
1573
1574void DisplayListRenderer::skew(float sx, float sy) {
1575    addOp(DisplayList::Skew);
1576    addPoint(sx, sy);
1577    OpenGLRenderer::skew(sx, sy);
1578}
1579
1580void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
1581    addOp(DisplayList::SetMatrix);
1582    addMatrix(matrix);
1583    OpenGLRenderer::setMatrix(matrix);
1584}
1585
1586void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
1587    addOp(DisplayList::ConcatMatrix);
1588    addMatrix(matrix);
1589    OpenGLRenderer::concatMatrix(matrix);
1590}
1591
1592bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
1593        SkRegion::Op op) {
1594    addOp(DisplayList::ClipRect);
1595    addBounds(left, top, right, bottom);
1596    addInt(op);
1597    return OpenGLRenderer::clipRect(left, top, right, bottom, op);
1598}
1599
1600bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
1601    addOp(DisplayList::ClipPath);
1602    addPath(path);
1603    addInt(op);
1604    return OpenGLRenderer::clipPath(path, op);
1605}
1606
1607bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
1608    addOp(DisplayList::ClipRegion);
1609    addRegion(region);
1610    addInt(op);
1611    return OpenGLRenderer::clipRegion(region, op);
1612}
1613
1614status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
1615        Rect& dirty, int32_t flags, uint32_t level) {
1616    // dirty is an out parameter and should not be recorded,
1617    // it matters only when replaying the display list
1618
1619    addOp(DisplayList::DrawDisplayList);
1620    addDisplayList(displayList);
1621    addInt(flags);
1622    return DrawGlInfo::kStatusDone;
1623}
1624
1625status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
1626    addOp(DisplayList::DrawLayer);
1627    addLayer(layer);
1628    addPoint(x, y);
1629    addPaint(paint);
1630    return DrawGlInfo::kStatusDone;
1631}
1632
1633status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
1634    const bool reject = quickRejectNoScissor(left, top,
1635            left + bitmap->width(), top + bitmap->height());
1636    uint32_t* location = addOp(DisplayList::DrawBitmap, reject);
1637    addBitmap(bitmap);
1638    addPoint(left, top);
1639    addPaint(paint);
1640    addSkip(location);
1641    return DrawGlInfo::kStatusDone;
1642}
1643
1644status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
1645    Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height());
1646    const mat4 transform(*matrix);
1647    transform.mapRect(r);
1648
1649    const bool reject = quickRejectNoScissor(r.left, r.top, r.right, r.bottom);
1650    uint32_t* location = addOp(DisplayList::DrawBitmapMatrix, reject);
1651    addBitmap(bitmap);
1652    addMatrix(matrix);
1653    addPaint(paint);
1654    addSkip(location);
1655    return DrawGlInfo::kStatusDone;
1656}
1657
1658status_t DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
1659        float srcRight, float srcBottom, float dstLeft, float dstTop,
1660        float dstRight, float dstBottom, SkPaint* paint) {
1661    const bool reject = quickRejectNoScissor(dstLeft, dstTop, dstRight, dstBottom);
1662    uint32_t* location = addOp(DisplayList::DrawBitmapRect, reject);
1663    addBitmap(bitmap);
1664    addBounds(srcLeft, srcTop, srcRight, srcBottom);
1665    addBounds(dstLeft, dstTop, dstRight, dstBottom);
1666    addPaint(paint);
1667    addSkip(location);
1668    return DrawGlInfo::kStatusDone;
1669}
1670
1671status_t DisplayListRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
1672        SkPaint* paint) {
1673    const bool reject = quickRejectNoScissor(left, top,
1674            left + bitmap->width(), top + bitmap->height());
1675    uint32_t* location = addOp(DisplayList::DrawBitmapData, reject);
1676    addBitmapData(bitmap);
1677    addPoint(left, top);
1678    addPaint(paint);
1679    addSkip(location);
1680    return DrawGlInfo::kStatusDone;
1681}
1682
1683status_t DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
1684        float* vertices, int* colors, SkPaint* paint) {
1685    addOp(DisplayList::DrawBitmapMesh);
1686    addBitmap(bitmap);
1687    addInt(meshWidth);
1688    addInt(meshHeight);
1689    addFloats(vertices, (meshWidth + 1) * (meshHeight + 1) * 2);
1690    if (colors) {
1691        addInt(1);
1692        addInts(colors, (meshWidth + 1) * (meshHeight + 1));
1693    } else {
1694        addInt(0);
1695    }
1696    addPaint(paint);
1697    return DrawGlInfo::kStatusDone;
1698}
1699
1700status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs,
1701        const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
1702        int8_t numColors, float left, float top, float right, float bottom, SkPaint* paint) {
1703    int alpha;
1704    SkXfermode::Mode mode;
1705    OpenGLRenderer::getAlphaAndModeDirect(paint, &alpha, &mode);
1706
1707    const bool reject = quickRejectNoScissor(left, top, right, bottom);
1708    uint32_t* location = addOp(DisplayList::DrawPatch, reject);
1709    addBitmap(bitmap);
1710    addInts(xDivs, width);
1711    addInts(yDivs, height);
1712    addUInts(colors, numColors);
1713    addBounds(left, top, right, bottom);
1714    addInt(alpha);
1715    addInt(mode);
1716    addSkip(location);
1717    return DrawGlInfo::kStatusDone;
1718}
1719
1720status_t DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
1721    addOp(DisplayList::DrawColor);
1722    addInt(color);
1723    addInt(mode);
1724    return DrawGlInfo::kStatusDone;
1725}
1726
1727status_t DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
1728        SkPaint* paint) {
1729    const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
1730            quickRejectNoScissor(left, top, right, bottom);
1731    uint32_t* location = addOp(DisplayList::DrawRect, reject);
1732    addBounds(left, top, right, bottom);
1733    addPaint(paint);
1734    addSkip(location);
1735    return DrawGlInfo::kStatusDone;
1736}
1737
1738status_t DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
1739        float rx, float ry, SkPaint* paint) {
1740    const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
1741            quickRejectNoScissor(left, top, right, bottom);
1742    uint32_t* location = addOp(DisplayList::DrawRoundRect, reject);
1743    addBounds(left, top, right, bottom);
1744    addPoint(rx, ry);
1745    addPaint(paint);
1746    addSkip(location);
1747    return DrawGlInfo::kStatusDone;
1748}
1749
1750status_t DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
1751    addOp(DisplayList::DrawCircle);
1752    addPoint(x, y);
1753    addFloat(radius);
1754    addPaint(paint);
1755    return DrawGlInfo::kStatusDone;
1756}
1757
1758status_t DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
1759        SkPaint* paint) {
1760    addOp(DisplayList::DrawOval);
1761    addBounds(left, top, right, bottom);
1762    addPaint(paint);
1763    return DrawGlInfo::kStatusDone;
1764}
1765
1766status_t DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
1767        float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
1768    addOp(DisplayList::DrawArc);
1769    addBounds(left, top, right, bottom);
1770    addPoint(startAngle, sweepAngle);
1771    addInt(useCenter ? 1 : 0);
1772    addPaint(paint);
1773    return DrawGlInfo::kStatusDone;
1774}
1775
1776status_t DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
1777    float left, top, offset;
1778    uint32_t width, height;
1779    computePathBounds(path, paint, left, top, offset, width, height);
1780
1781    left -= offset;
1782    top -= offset;
1783
1784    const bool reject = quickRejectNoScissor(left, top, left + width, top + height);
1785    uint32_t* location = addOp(DisplayList::DrawPath, reject);
1786    addPath(path);
1787    addPaint(paint);
1788    addSkip(location);
1789    return DrawGlInfo::kStatusDone;
1790}
1791
1792status_t DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
1793    addOp(DisplayList::DrawLines);
1794    addFloats(points, count);
1795    addPaint(paint);
1796    return DrawGlInfo::kStatusDone;
1797}
1798
1799status_t DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
1800    addOp(DisplayList::DrawPoints);
1801    addFloats(points, count);
1802    addPaint(paint);
1803    return DrawGlInfo::kStatusDone;
1804}
1805
1806status_t DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
1807        SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
1808    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
1809    addOp(DisplayList::DrawTextOnPath);
1810    addText(text, bytesCount);
1811    addInt(count);
1812    addPath(path);
1813    addFloat(hOffset);
1814    addFloat(vOffset);
1815    paint->setAntiAlias(true);
1816    SkPaint* addedPaint = addPaint(paint);
1817    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
1818    fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform);
1819    return DrawGlInfo::kStatusDone;
1820}
1821
1822status_t DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
1823        const float* positions, SkPaint* paint) {
1824    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
1825    addOp(DisplayList::DrawPosText);
1826    addText(text, bytesCount);
1827    addInt(count);
1828    addFloats(positions, count * 2);
1829    paint->setAntiAlias(true);
1830    SkPaint* addedPaint = addPaint(paint);
1831    FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
1832    fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform);
1833    return DrawGlInfo::kStatusDone;
1834}
1835
1836status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
1837        float x, float y, const float* positions, SkPaint* paint, float length) {
1838    if (!text || count <= 0) return DrawGlInfo::kStatusDone;
1839
1840    // TODO: We should probably make a copy of the paint instead of modifying
1841    //       it; modifying the paint will change its generationID the first
1842    //       time, which might impact caches. More investigation needed to
1843    //       see if it matters.
1844    //       If we make a copy, then drawTextDecorations() should *not* make
1845    //       its own copy as it does right now.
1846    // Beware: this needs Glyph encoding (already done on the Paint constructor)
1847    paint->setAntiAlias(true);
1848    if (length < 0.0f) length = paint->measureText(text, bytesCount);
1849
1850    bool reject = false;
1851    if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
1852        SkPaint::FontMetrics metrics;
1853        paint->getFontMetrics(&metrics, 0.0f);
1854        reject = quickRejectNoScissor(x, y + metrics.fTop, x + length, y + metrics.fBottom);
1855    }
1856
1857    uint32_t* location = addOp(DisplayList::DrawText, reject);
1858    addText(text, bytesCount);
1859    addInt(count);
1860    addFloat(x);
1861    addFloat(y);
1862    addFloats(positions, count * 2);
1863    SkPaint* addedPaint = addPaint(paint);
1864    if (!reject) {
1865        FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
1866        fontRenderer.precache(addedPaint, text, count, *mSnapshot->transform);
1867    }
1868    addFloat(length);
1869    addSkip(location);
1870    return DrawGlInfo::kStatusDone;
1871}
1872
1873status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) {
1874    if (count <= 0) return DrawGlInfo::kStatusDone;
1875
1876    addOp(DisplayList::DrawRects);
1877    addFloats(rects, count * 4);
1878    addPaint(paint);
1879    return DrawGlInfo::kStatusDone;
1880}
1881
1882void DisplayListRenderer::resetShader() {
1883    addOp(DisplayList::ResetShader);
1884}
1885
1886void DisplayListRenderer::setupShader(SkiaShader* shader) {
1887    addOp(DisplayList::SetupShader);
1888    addShader(shader);
1889}
1890
1891void DisplayListRenderer::resetColorFilter() {
1892    addOp(DisplayList::ResetColorFilter);
1893}
1894
1895void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
1896    addOp(DisplayList::SetupColorFilter);
1897    addColorFilter(filter);
1898}
1899
1900void DisplayListRenderer::resetShadow() {
1901    addOp(DisplayList::ResetShadow);
1902}
1903
1904void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
1905    addOp(DisplayList::SetupShadow);
1906    addFloat(radius);
1907    addPoint(dx, dy);
1908    addInt(color);
1909}
1910
1911void DisplayListRenderer::resetPaintFilter() {
1912    addOp(DisplayList::ResetPaintFilter);
1913}
1914
1915void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
1916    addOp(DisplayList::SetupPaintFilter);
1917    addInt(clearBits);
1918    addInt(setBits);
1919}
1920
1921}; // namespace uirenderer
1922}; // namespace android
1923