DisplayListOp.h revision f40b8a939fef0a19b40188f007a3364311d6dabf
1/*
2 * Copyright (C) 2013 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#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
18#define ANDROID_HWUI_DISPLAY_OPERATION_H
19
20#ifndef LOG_TAG
21    #define LOG_TAG "OpenGLRenderer"
22#endif
23
24#include <SkXfermode.h>
25
26#include <private/hwui/DrawGlInfo.h>
27
28#include "OpenGLRenderer.h"
29#include "DeferredDisplayList.h"
30#include "DisplayListRenderer.h"
31#include "utils/LinearAllocator.h"
32
33#define CRASH() do { \
34    *(int *)(uintptr_t)0xbbadbeef = 0; \
35    ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
36} while(false)
37
38#define MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
39#define MATRIX_ARGS(m) \
40    m->get(0), m->get(1), m->get(2), \
41    m->get(3), m->get(4), m->get(5), \
42    m->get(6), m->get(7), m->get(8)
43#define RECT_STRING "%.2f %.2f %.2f %.2f"
44#define RECT_ARGS(r) \
45    r.left, r.top, r.right, r.bottom
46
47// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
48#define OP_LOGS(s) OP_LOG("%s", s)
49#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
50
51namespace android {
52namespace uirenderer {
53
54/**
55 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
56 * may be replayed to an OpenGLRenderer.
57 *
58 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
59 * LinearAllocator's managed memory buffers.  Each pointer held by a DisplayListOp is either a
60 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
61 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
62 * never called as LinearAllocators are simply discarded, so no memory management should be done in
63 * this class.
64 */
65class DisplayListOp {
66public:
67    // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
68    // standard new() intentionally not implemented, and delete/deconstructor should never be used.
69    virtual ~DisplayListOp() { CRASH(); }
70    static void operator delete(void* ptr) { CRASH(); }
71    /** static void* operator new(size_t size); PURPOSELY OMITTED **/
72    static void* operator new(size_t size, LinearAllocator& allocator) {
73        return allocator.alloc(size);
74    }
75
76    enum OpLogFlag {
77        kOpLogFlag_Recurse = 0x1,
78        kOpLogFlag_JSON = 0x2 // TODO: add?
79    };
80
81    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
82            int level, int multipliedAlpha) = 0;
83
84    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
85            int level, int multipliedAlpha) = 0;
86
87    virtual void output(int level, uint32_t logFlags = 0) = 0;
88
89    // NOTE: it would be nice to declare constants and overriding the implementation in each op to
90    // point at the constants, but that seems to require a .cpp file
91    virtual const char* name() = 0;
92
93    /**
94     * Stores the relevant canvas state of the object between deferral and replay (if the canvas
95     * state supports being stored) See OpenGLRenderer::simpleClipAndState()
96     *
97     * TODO: don't reserve space for StateOps that won't be deferred
98     */
99    DeferredDisplayState state;
100
101};
102
103class StateOp : public DisplayListOp {
104public:
105    StateOp() {};
106
107    virtual ~StateOp() {}
108
109    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
110            int level, int multipliedAlpha) {
111        // default behavior only affects immediate, deferrable state, issue directly to renderer
112        applyState(deferStruct.mRenderer, saveCount);
113    }
114
115    /**
116     * State operations are applied directly to the renderer, but can cause the deferred drawing op
117     * list to flush
118     */
119    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
120            int level, int multipliedAlpha) {
121        applyState(replayStruct.mRenderer, saveCount);
122    }
123
124    virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
125};
126
127class DrawOp : public DisplayListOp {
128public:
129    DrawOp(SkPaint* paint)
130            : mPaint(paint), mQuickRejected(false) {}
131
132    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
133            int level, int multipliedAlpha) {
134        if (mQuickRejected &&
135                CC_LIKELY(deferStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
136            return;
137        }
138
139        state.mMultipliedAlpha = multipliedAlpha;
140        if (!getLocalBounds(state.mBounds)) {
141            // empty bounds signify bounds can't be calculated
142            state.mBounds.setEmpty();
143        }
144
145        deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
146    }
147
148    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
149            int level, int multipliedAlpha) {
150        if (mQuickRejected &&
151                CC_LIKELY(replayStruct.mReplayFlags & DisplayList::kReplayFlag_ClipChildren)) {
152            return;
153        }
154
155        replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty,
156                level, multipliedAlpha);
157    }
158
159    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
160            int multipliedAlpha) = 0;
161
162    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
163    }
164
165    // returns true if bounds exist
166    virtual bool getLocalBounds(Rect& localBounds) { return false; }
167
168    // TODO: better refine localbounds usage
169    void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
170    bool getQuickRejected() { return mQuickRejected; }
171
172    /** Batching disabled by default, turned on for individual ops */
173    virtual DeferredDisplayList::OpBatchId getBatchId() {
174        return DeferredDisplayList::kOpBatch_None;
175    }
176
177    float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
178
179protected:
180    SkPaint* getPaint(OpenGLRenderer& renderer, bool alwaysCopy = false) {
181        return renderer.filterPaint(mPaint, alwaysCopy);
182    }
183
184    SkPaint* mPaint; // should be accessed via getPaint() when applying
185    bool mQuickRejected;
186};
187
188class DrawBoundedOp : public DrawOp {
189public:
190    DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
191            : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
192
193    // Calculates bounds as smallest rect encompassing all points
194    // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
195    // subclass' constructor)
196    DrawBoundedOp(const float* points, int count, SkPaint* paint)
197            : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
198        for (int i = 2; i < count; i += 2) {
199            mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
200            mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
201            mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
202            mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
203        }
204    }
205
206    // default empty constructor for bounds, to be overridden in child constructor body
207    DrawBoundedOp(SkPaint* paint)
208            : DrawOp(paint) {}
209
210    bool getLocalBounds(Rect& localBounds) {
211        localBounds.set(mLocalBounds);
212        return true;
213    }
214
215protected:
216    Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
217};
218
219///////////////////////////////////////////////////////////////////////////////
220// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
221//         not directly draw or alter output
222///////////////////////////////////////////////////////////////////////////////
223
224class SaveOp : public StateOp {
225    friend class DisplayList; // give DisplayList private constructor/reinit access
226public:
227    SaveOp(int flags)
228            : mFlags(flags) {}
229
230    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
231            int level, int multipliedAlpha) {
232        int newSaveCount = deferStruct.mRenderer.save(mFlags);
233        deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
234    }
235
236    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
237        renderer.save(mFlags);
238    }
239
240    virtual void output(int level, uint32_t logFlags) {
241        OP_LOG("Save flags %x", mFlags);
242    }
243
244    virtual const char* name() { return "Save"; }
245
246    int getFlags() const { return mFlags; }
247private:
248    SaveOp() {}
249    DisplayListOp* reinit(int flags) {
250        mFlags = flags;
251        return this;
252    }
253
254    int mFlags;
255};
256
257class RestoreToCountOp : public StateOp {
258    friend class DisplayList; // give DisplayList private constructor/reinit access
259public:
260    RestoreToCountOp(int count)
261            : mCount(count) {}
262
263    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
264            int level, int multipliedAlpha) {
265        deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer, saveCount + mCount);
266        deferStruct.mRenderer.restoreToCount(saveCount + mCount);
267    }
268
269    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
270        renderer.restoreToCount(saveCount + mCount);
271    }
272
273    virtual void output(int level, uint32_t logFlags) {
274        OP_LOG("Restore to count %d", mCount);
275    }
276
277    virtual const char* name() { return "RestoreToCount"; }
278
279private:
280    RestoreToCountOp() {}
281    DisplayListOp* reinit(int count) {
282        mCount = count;
283        return this;
284    }
285
286    int mCount;
287};
288
289class SaveLayerOp : public StateOp {
290    friend class DisplayList; // give DisplayList private constructor/reinit access
291public:
292    SaveLayerOp(float left, float top, float right, float bottom,
293            int alpha, SkXfermode::Mode mode, int flags)
294            : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
295
296    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
297            int level, int multipliedAlpha) {
298        // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
299        int newSaveCount = deferStruct.mRenderer.save(mFlags);
300        deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
301    }
302
303    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
304        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
305    }
306
307    virtual void output(int level, uint32_t logFlags) {
308        OP_LOG("SaveLayer%s of area " RECT_STRING,
309                (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
310    }
311
312    virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
313
314    int getFlags() { return mFlags; }
315
316private:
317    // Special case, reserved for direct DisplayList usage
318    SaveLayerOp() {}
319    DisplayListOp* reinit(float left, float top, float right, float bottom,
320            int alpha, SkXfermode::Mode mode, int flags) {
321        mArea.set(left, top, right, bottom);
322        mAlpha = alpha;
323        mMode = mode;
324        mFlags = flags;
325        return this;
326    }
327
328    bool isSaveLayerAlpha() { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
329    Rect mArea;
330    int mAlpha;
331    SkXfermode::Mode mMode;
332    int mFlags;
333};
334
335class TranslateOp : public StateOp {
336public:
337    TranslateOp(float dx, float dy)
338            : mDx(dx), mDy(dy) {}
339
340    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
341        renderer.translate(mDx, mDy);
342    }
343
344    virtual void output(int level, uint32_t logFlags) {
345        OP_LOG("Translate by %f %f", mDx, mDy);
346    }
347
348    virtual const char* name() { return "Translate"; }
349
350private:
351    float mDx;
352    float mDy;
353};
354
355class RotateOp : public StateOp {
356public:
357    RotateOp(float degrees)
358            : mDegrees(degrees) {}
359
360    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
361        renderer.rotate(mDegrees);
362    }
363
364    virtual void output(int level, uint32_t logFlags) {
365        OP_LOG("Rotate by %f degrees", mDegrees);
366    }
367
368    virtual const char* name() { return "Rotate"; }
369
370private:
371    float mDegrees;
372};
373
374class ScaleOp : public StateOp {
375public:
376    ScaleOp(float sx, float sy)
377            : mSx(sx), mSy(sy) {}
378
379    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
380        renderer.scale(mSx, mSy);
381    }
382
383    virtual void output(int level, uint32_t logFlags) {
384        OP_LOG("Scale by %f %f", mSx, mSy);
385    }
386
387    virtual const char* name() { return "Scale"; }
388
389private:
390    float mSx;
391    float mSy;
392};
393
394class SkewOp : public StateOp {
395public:
396    SkewOp(float sx, float sy)
397            : mSx(sx), mSy(sy) {}
398
399    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
400        renderer.skew(mSx, mSy);
401    }
402
403    virtual void output(int level, uint32_t logFlags) {
404        OP_LOG("Skew by %f %f", mSx, mSy);
405    }
406
407    virtual const char* name() { return "Skew"; }
408
409private:
410    float mSx;
411    float mSy;
412};
413
414class SetMatrixOp : public StateOp {
415public:
416    SetMatrixOp(SkMatrix* matrix)
417            : mMatrix(matrix) {}
418
419    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
420        renderer.setMatrix(mMatrix);
421    }
422
423    virtual void output(int level, uint32_t logFlags) {
424        OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
425    }
426
427    virtual const char* name() { return "SetMatrix"; }
428
429private:
430    SkMatrix* mMatrix;
431};
432
433class ConcatMatrixOp : public StateOp {
434public:
435    ConcatMatrixOp(SkMatrix* matrix)
436            : mMatrix(matrix) {}
437
438    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
439        renderer.concatMatrix(mMatrix);
440    }
441
442    virtual void output(int level, uint32_t logFlags) {
443        OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
444    }
445
446    virtual const char* name() { return "ConcatMatrix"; }
447
448private:
449    SkMatrix* mMatrix;
450};
451
452class ClipOp : public StateOp {
453public:
454    ClipOp(SkRegion::Op op) : mOp(op) {}
455
456    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
457            int level, int multipliedAlpha) {
458        // NOTE: must defer op BEFORE applying state, since it may read clip
459        deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
460
461        // TODO: Can we avoid applying complex clips at defer time?
462        applyState(deferStruct.mRenderer, saveCount);
463    }
464
465    bool canCauseComplexClip() {
466        return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
467    }
468
469protected:
470    ClipOp() {}
471    virtual bool isRect() { return false; }
472
473    SkRegion::Op mOp;
474};
475
476class ClipRectOp : public ClipOp {
477    friend class DisplayList; // give DisplayList private constructor/reinit access
478public:
479    ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
480            : ClipOp(op), mArea(left, top, right, bottom) {}
481
482    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
483        renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
484    }
485
486    virtual void output(int level, uint32_t logFlags) {
487        OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
488    }
489
490    virtual const char* name() { return "ClipRect"; }
491
492protected:
493    virtual bool isRect() { return true; }
494
495private:
496    ClipRectOp() {}
497    DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
498        mOp = op;
499        mArea.set(left, top, right, bottom);
500        return this;
501    }
502
503    Rect mArea;
504};
505
506class ClipPathOp : public ClipOp {
507public:
508    ClipPathOp(SkPath* path, SkRegion::Op op)
509            : ClipOp(op), mPath(path) {}
510
511    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
512        renderer.clipPath(mPath, mOp);
513    }
514
515    virtual void output(int level, uint32_t logFlags) {
516        SkRect bounds = mPath->getBounds();
517        OP_LOG("ClipPath bounds " RECT_STRING,
518                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
519    }
520
521    virtual const char* name() { return "ClipPath"; }
522
523private:
524    SkPath* mPath;
525};
526
527class ClipRegionOp : public ClipOp {
528public:
529    ClipRegionOp(SkRegion* region, SkRegion::Op op)
530            : ClipOp(op), mRegion(region) {}
531
532    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
533        renderer.clipRegion(mRegion, mOp);
534    }
535
536    virtual void output(int level, uint32_t logFlags) {
537        SkIRect bounds = mRegion->getBounds();
538        OP_LOG("ClipRegion bounds %d %d %d %d",
539                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
540    }
541
542    virtual const char* name() { return "ClipRegion"; }
543
544private:
545    SkRegion* mRegion;
546    SkRegion::Op mOp;
547};
548
549class ResetShaderOp : public StateOp {
550public:
551    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
552        renderer.resetShader();
553    }
554
555    virtual void output(int level, uint32_t logFlags) {
556        OP_LOGS("ResetShader");
557    }
558
559    virtual const char* name() { return "ResetShader"; }
560};
561
562class SetupShaderOp : public StateOp {
563public:
564    SetupShaderOp(SkiaShader* shader)
565            : mShader(shader) {}
566    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
567        renderer.setupShader(mShader);
568    }
569
570    virtual void output(int level, uint32_t logFlags) {
571        OP_LOG("SetupShader, shader %p", mShader);
572    }
573
574    virtual const char* name() { return "SetupShader"; }
575
576private:
577    SkiaShader* mShader;
578};
579
580class ResetColorFilterOp : public StateOp {
581public:
582    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
583        renderer.resetColorFilter();
584    }
585
586    virtual void output(int level, uint32_t logFlags) {
587        OP_LOGS("ResetColorFilter");
588    }
589
590    virtual const char* name() { return "ResetColorFilter"; }
591};
592
593class SetupColorFilterOp : public StateOp {
594public:
595    SetupColorFilterOp(SkiaColorFilter* colorFilter)
596            : mColorFilter(colorFilter) {}
597
598    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
599        renderer.setupColorFilter(mColorFilter);
600    }
601
602    virtual void output(int level, uint32_t logFlags) {
603        OP_LOG("SetupColorFilter, filter %p", mColorFilter);
604    }
605
606    virtual const char* name() { return "SetupColorFilter"; }
607
608private:
609    SkiaColorFilter* mColorFilter;
610};
611
612class ResetShadowOp : public StateOp {
613public:
614    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
615        renderer.resetShadow();
616    }
617
618    virtual void output(int level, uint32_t logFlags) {
619        OP_LOGS("ResetShadow");
620    }
621
622    virtual const char* name() { return "ResetShadow"; }
623};
624
625class SetupShadowOp : public StateOp {
626public:
627    SetupShadowOp(float radius, float dx, float dy, int color)
628            : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
629
630    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
631        renderer.setupShadow(mRadius, mDx, mDy, mColor);
632    }
633
634    virtual void output(int level, uint32_t logFlags) {
635        OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
636    }
637
638    virtual const char* name() { return "SetupShadow"; }
639
640private:
641    float mRadius;
642    float mDx;
643    float mDy;
644    int mColor;
645};
646
647class ResetPaintFilterOp : public StateOp {
648public:
649    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
650        renderer.resetPaintFilter();
651    }
652
653    virtual void output(int level, uint32_t logFlags) {
654        OP_LOGS("ResetPaintFilter");
655    }
656
657    virtual const char* name() { return "ResetPaintFilter"; }
658};
659
660class SetupPaintFilterOp : public StateOp {
661public:
662    SetupPaintFilterOp(int clearBits, int setBits)
663            : mClearBits(clearBits), mSetBits(setBits) {}
664
665    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
666        renderer.setupPaintFilter(mClearBits, mSetBits);
667    }
668
669    virtual void output(int level, uint32_t logFlags) {
670        OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
671    }
672
673    virtual const char* name() { return "SetupPaintFilter"; }
674
675private:
676    int mClearBits;
677    int mSetBits;
678};
679
680
681///////////////////////////////////////////////////////////////////////////////
682// DRAW OPERATIONS - these are operations that can draw to the canvas's device
683///////////////////////////////////////////////////////////////////////////////
684
685class DrawBitmapOp : public DrawBoundedOp {
686public:
687    DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
688            : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(),
689                    paint),
690            mBitmap(bitmap) {}
691
692    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
693            int multipliedAlpha) {
694        bool makeCopy = multipliedAlpha >= 0 && multipliedAlpha < 255;
695        SkPaint* paint = getPaint(renderer, makeCopy);
696        if (makeCopy) {
697            // The paint is safe to modify since we're working on a copy
698            paint->setAlpha(multipliedAlpha);
699        }
700        status_t ret = renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, paint);
701        return ret;
702    }
703
704    virtual void output(int level, uint32_t logFlags) {
705        OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
706    }
707
708    virtual const char* name() { return "DrawBitmap"; }
709    virtual DeferredDisplayList::OpBatchId getBatchId() {
710        return DeferredDisplayList::kOpBatch_Bitmap;
711    }
712
713protected:
714    SkBitmap* mBitmap;
715};
716
717class DrawBitmapMatrixOp : public DrawBoundedOp {
718public:
719    DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
720            : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
721        mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
722        const mat4 transform(*matrix);
723        transform.mapRect(mLocalBounds);
724    }
725
726    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
727            int multipliedAlpha) {
728        return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
729    }
730
731    virtual void output(int level, uint32_t logFlags) {
732        OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
733    }
734
735    virtual const char* name() { return "DrawBitmap"; }
736    virtual DeferredDisplayList::OpBatchId getBatchId() {
737        return DeferredDisplayList::kOpBatch_Bitmap;
738    }
739
740private:
741    SkBitmap* mBitmap;
742    SkMatrix* mMatrix;
743};
744
745class DrawBitmapRectOp : public DrawBoundedOp {
746public:
747    DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
748            float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
749            : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
750            mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
751
752    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
753            int multipliedAlpha) {
754        return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
755                mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
756                getPaint(renderer));
757    }
758
759    virtual void output(int level, uint32_t logFlags) {
760        OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
761                mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
762    }
763
764    virtual const char* name() { return "DrawBitmapRect"; }
765    virtual DeferredDisplayList::OpBatchId getBatchId() {
766        return DeferredDisplayList::kOpBatch_Bitmap;
767    }
768
769private:
770    SkBitmap* mBitmap;
771    Rect mSrc;
772};
773
774class DrawBitmapDataOp : public DrawBitmapOp {
775public:
776    DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
777            : DrawBitmapOp(bitmap, left, top, paint) {}
778
779    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
780            int multipliedAlpha) {
781        return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
782                mLocalBounds.top, getPaint(renderer));
783    }
784
785    virtual void output(int level, uint32_t logFlags) {
786        OP_LOG("Draw bitmap %p", mBitmap);
787    }
788
789    virtual const char* name() { return "DrawBitmapData"; }
790    virtual DeferredDisplayList::OpBatchId getBatchId() {
791        return DeferredDisplayList::kOpBatch_Bitmap;
792    }
793};
794
795class DrawBitmapMeshOp : public DrawBoundedOp {
796public:
797    DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
798            float* vertices, int* colors, SkPaint* paint)
799            : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
800            mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
801            mVertices(vertices), mColors(colors) {}
802
803    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
804            int multipliedAlpha) {
805        return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
806                mVertices, mColors, getPaint(renderer));
807    }
808
809    virtual void output(int level, uint32_t logFlags) {
810        OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
811    }
812
813    virtual const char* name() { return "DrawBitmapMesh"; }
814    virtual DeferredDisplayList::OpBatchId getBatchId() {
815        return DeferredDisplayList::kOpBatch_Bitmap;
816    }
817
818private:
819    SkBitmap* mBitmap;
820    int mMeshWidth;
821    int mMeshHeight;
822    float* mVertices;
823    int* mColors;
824};
825
826class DrawPatchOp : public DrawBoundedOp {
827public:
828    DrawPatchOp(SkBitmap* bitmap, const int32_t* xDivs,
829            const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
830            int8_t numColors, float left, float top, float right, float bottom,
831            int alpha, SkXfermode::Mode mode)
832            : DrawBoundedOp(left, top, right, bottom, 0),
833            mBitmap(bitmap), mxDivs(xDivs), myDivs(yDivs),
834            mColors(colors), mxDivsCount(width), myDivsCount(height),
835            mNumColors(numColors), mAlpha(alpha), mMode(mode) {};
836
837    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
838            int multipliedAlpha) {
839        // NOTE: not calling the virtual method, which takes a paint
840        return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors,
841                mxDivsCount, myDivsCount, mNumColors,
842                mLocalBounds.left, mLocalBounds.top,
843                mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
844    }
845
846    virtual void output(int level, uint32_t logFlags) {
847        OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
848    }
849
850    virtual const char* name() { return "DrawPatch"; }
851    virtual DeferredDisplayList::OpBatchId getBatchId() {
852        return DeferredDisplayList::kOpBatch_Patch;
853    }
854
855private:
856    SkBitmap* mBitmap;
857    const int32_t* mxDivs;
858    const int32_t* myDivs;
859    const uint32_t* mColors;
860    uint32_t mxDivsCount;
861    uint32_t myDivsCount;
862    int8_t mNumColors;
863    int mAlpha;
864    SkXfermode::Mode mMode;
865};
866
867class DrawColorOp : public DrawOp {
868public:
869    DrawColorOp(int color, SkXfermode::Mode mode)
870            : DrawOp(0), mColor(color), mMode(mode) {};
871
872    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
873            int multipliedAlpha) {
874        return renderer.drawColor(mColor, mMode);
875    }
876
877    virtual void output(int level, uint32_t logFlags) {
878        OP_LOG("Draw color %#x, mode %d", mColor, mMode);
879    }
880
881    virtual const char* name() { return "DrawColor"; }
882
883private:
884    int mColor;
885    SkXfermode::Mode mMode;
886};
887
888class DrawStrokableOp : public DrawBoundedOp {
889public:
890    DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
891            : DrawBoundedOp(left, top, right, bottom, paint) {};
892
893    bool getLocalBounds(Rect& localBounds) {
894        localBounds.set(mLocalBounds);
895        if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
896            localBounds.outset(strokeWidthOutset());
897        }
898        return true;
899    }
900
901    virtual DeferredDisplayList::OpBatchId getBatchId() {
902        if (mPaint->getPathEffect()) {
903            return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
904        }
905        return mPaint->isAntiAlias() ?
906                DeferredDisplayList::kOpBatch_AlphaVertices :
907                DeferredDisplayList::kOpBatch_Vertices;
908    }
909};
910
911class DrawRectOp : public DrawStrokableOp {
912public:
913    DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
914            : DrawStrokableOp(left, top, right, bottom, paint) {}
915
916    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
917            int multipliedAlpha) {
918        return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
919                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
920    }
921
922    virtual void output(int level, uint32_t logFlags) {
923        OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
924    }
925
926    virtual const char* name() { return "DrawRect"; }
927};
928
929class DrawRectsOp : public DrawBoundedOp {
930public:
931    DrawRectsOp(const float* rects, int count, SkPaint* paint)
932            : DrawBoundedOp(rects, count, paint),
933            mRects(rects), mCount(count) {}
934
935    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
936            int multipliedAlpha) {
937        return renderer.drawRects(mRects, mCount, getPaint(renderer));
938    }
939
940    virtual void output(int level, uint32_t logFlags) {
941        OP_LOG("Draw Rects count %d", mCount);
942    }
943
944    virtual const char* name() { return "DrawRects"; }
945
946    virtual DeferredDisplayList::OpBatchId getBatchId() {
947        return DeferredDisplayList::kOpBatch_Vertices;
948    }
949
950private:
951    const float* mRects;
952    int mCount;
953};
954
955class DrawRoundRectOp : public DrawStrokableOp {
956public:
957    DrawRoundRectOp(float left, float top, float right, float bottom,
958            float rx, float ry, SkPaint* paint)
959            : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
960
961    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
962            int multipliedAlpha) {
963        return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
964                mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
965    }
966
967    virtual void output(int level, uint32_t logFlags) {
968        OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
969    }
970
971    virtual const char* name() { return "DrawRoundRect"; }
972
973private:
974    float mRx;
975    float mRy;
976};
977
978class DrawCircleOp : public DrawStrokableOp {
979public:
980    DrawCircleOp(float x, float y, float radius, SkPaint* paint)
981            : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
982            mX(x), mY(y), mRadius(radius) {}
983
984    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
985            int multipliedAlpha) {
986        return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
987    }
988
989    virtual void output(int level, uint32_t logFlags) {
990        OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
991    }
992
993    virtual const char* name() { return "DrawCircle"; }
994
995private:
996    float mX;
997    float mY;
998    float mRadius;
999};
1000
1001class DrawOvalOp : public DrawStrokableOp {
1002public:
1003    DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
1004            : DrawStrokableOp(left, top, right, bottom, paint) {}
1005
1006    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1007            int multipliedAlpha) {
1008        return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1009                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1010    }
1011
1012    virtual void output(int level, uint32_t logFlags) {
1013        OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1014    }
1015
1016    virtual const char* name() { return "DrawOval"; }
1017};
1018
1019class DrawArcOp : public DrawStrokableOp {
1020public:
1021    DrawArcOp(float left, float top, float right, float bottom,
1022            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
1023            : DrawStrokableOp(left, top, right, bottom, paint),
1024            mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1025
1026    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1027            int multipliedAlpha) {
1028        return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1029                mLocalBounds.right, mLocalBounds.bottom,
1030                mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1031    }
1032
1033    virtual void output(int level, uint32_t logFlags) {
1034        OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1035                RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1036    }
1037
1038    virtual const char* name() { return "DrawArc"; }
1039
1040private:
1041    float mStartAngle;
1042    float mSweepAngle;
1043    bool mUseCenter;
1044};
1045
1046class DrawPathOp : public DrawBoundedOp {
1047public:
1048    DrawPathOp(SkPath* path, SkPaint* paint)
1049            : DrawBoundedOp(paint), mPath(path) {
1050        float left, top, offset;
1051        uint32_t width, height;
1052        PathCache::computePathBounds(path, paint, left, top, offset, width, height);
1053        left -= offset;
1054        top -= offset;
1055        mLocalBounds.set(left, top, left + width, top + height);
1056    }
1057
1058    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1059            int multipliedAlpha) {
1060        return renderer.drawPath(mPath, getPaint(renderer));
1061    }
1062
1063    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
1064        SkPaint* paint = getPaint(renderer);
1065        renderer.getCaches().pathCache.precache(mPath, paint);
1066    }
1067
1068    virtual void output(int level, uint32_t logFlags) {
1069        OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1070    }
1071
1072    virtual const char* name() { return "DrawPath"; }
1073
1074    virtual DeferredDisplayList::OpBatchId getBatchId() {
1075        return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1076    }
1077private:
1078    SkPath* mPath;
1079};
1080
1081class DrawLinesOp : public DrawBoundedOp {
1082public:
1083    DrawLinesOp(float* points, int count, SkPaint* paint)
1084            : DrawBoundedOp(points, count, paint),
1085            mPoints(points), mCount(count) {
1086        mLocalBounds.outset(strokeWidthOutset());
1087    }
1088
1089    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1090            int multipliedAlpha) {
1091        return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1092    }
1093
1094    virtual void output(int level, uint32_t logFlags) {
1095        OP_LOG("Draw Lines count %d", mCount);
1096    }
1097
1098    virtual const char* name() { return "DrawLines"; }
1099
1100    virtual DeferredDisplayList::OpBatchId getBatchId() {
1101        return mPaint->isAntiAlias() ?
1102                DeferredDisplayList::kOpBatch_AlphaVertices :
1103                DeferredDisplayList::kOpBatch_Vertices;
1104    }
1105
1106protected:
1107    float* mPoints;
1108    int mCount;
1109};
1110
1111class DrawPointsOp : public DrawLinesOp {
1112public:
1113    DrawPointsOp(float* points, int count, SkPaint* paint)
1114            : DrawLinesOp(points, count, paint) {}
1115
1116    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1117            int multipliedAlpha) {
1118        return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1119    }
1120
1121    virtual void output(int level, uint32_t logFlags) {
1122        OP_LOG("Draw Points count %d", mCount);
1123    }
1124
1125    virtual const char* name() { return "DrawPoints"; }
1126};
1127
1128class DrawSomeTextOp : public DrawOp {
1129public:
1130    DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
1131            : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1132
1133    virtual void output(int level, uint32_t logFlags) {
1134        OP_LOG("Draw some text, %d bytes", mBytesCount);
1135    }
1136
1137    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
1138        SkPaint* paint = getPaint(renderer);
1139        FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1140        fontRenderer.precache(paint, mText, mCount, mat4::identity());
1141    }
1142
1143    virtual DeferredDisplayList::OpBatchId getBatchId() {
1144        return mPaint->getColor() == 0xff000000 ?
1145                DeferredDisplayList::kOpBatch_Text :
1146                DeferredDisplayList::kOpBatch_ColorText;
1147    }
1148protected:
1149    const char* mText;
1150    int mBytesCount;
1151    int mCount;
1152};
1153
1154class DrawTextOnPathOp : public DrawSomeTextOp {
1155public:
1156    DrawTextOnPathOp(const char* text, int bytesCount, int count,
1157            SkPath* path, float hOffset, float vOffset, SkPaint* paint)
1158            : DrawSomeTextOp(text, bytesCount, count, paint),
1159            mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1160        /* TODO: inherit from DrawBounded and init mLocalBounds */
1161    }
1162
1163    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1164            int multipliedAlpha) {
1165        return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1166                mHOffset, mVOffset, getPaint(renderer));
1167    }
1168
1169    virtual const char* name() { return "DrawTextOnPath"; }
1170
1171private:
1172    SkPath* mPath;
1173    float mHOffset;
1174    float mVOffset;
1175};
1176
1177class DrawPosTextOp : public DrawSomeTextOp {
1178public:
1179    DrawPosTextOp(const char* text, int bytesCount, int count,
1180            const float* positions, SkPaint* paint)
1181            : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1182        /* TODO: inherit from DrawBounded and init mLocalBounds */
1183    }
1184
1185    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1186            int multipliedAlpha) {
1187        return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1188    }
1189
1190    virtual const char* name() { return "DrawPosText"; }
1191
1192private:
1193    const float* mPositions;
1194};
1195
1196class DrawTextOp : public DrawBoundedOp {
1197public:
1198    DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
1199            const float* positions, SkPaint* paint, float length)
1200            : DrawBoundedOp(paint), mText(text), mBytesCount(bytesCount), mCount(count),
1201            mX(x), mY(y), mPositions(positions), mLength(length) {
1202        // duplicates bounds calculation from OpenGLRenderer::drawText, but doesn't alter mX
1203        SkPaint::FontMetrics metrics;
1204        paint->getFontMetrics(&metrics, 0.0f);
1205        switch (paint->getTextAlign()) {
1206        case SkPaint::kCenter_Align:
1207            x -= length / 2.0f;
1208            break;
1209        case SkPaint::kRight_Align:
1210            x -= length;
1211            break;
1212        default:
1213            break;
1214        }
1215        mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom);
1216        memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
1217    }
1218
1219    /*
1220     * When this method is invoked the state field  is initialized to have the
1221     * final rendering state. We can thus use it to process data as it will be
1222     * used at draw time.
1223     */
1224    virtual void onDrawOpDeferred(OpenGLRenderer& renderer) {
1225        SkPaint* paint = getPaint(renderer);
1226        FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1227        const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1228        if (mPrecacheTransform != transform) {
1229            fontRenderer.precache(paint, mText, mCount, transform);
1230            mPrecacheTransform = transform;
1231        }
1232    }
1233
1234    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1235            int multipliedAlpha) {
1236        return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
1237                mPositions, getPaint(renderer), mLength);
1238    }
1239
1240    virtual void output(int level, uint32_t logFlags) {
1241        OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1242    }
1243
1244    virtual const char* name() { return "DrawText"; }
1245
1246    virtual DeferredDisplayList::OpBatchId getBatchId() {
1247        return mPaint->getColor() == 0xff000000 ?
1248                DeferredDisplayList::kOpBatch_Text :
1249                DeferredDisplayList::kOpBatch_ColorText;
1250    }
1251
1252private:
1253    const char* mText;
1254    int mBytesCount;
1255    int mCount;
1256    float mX;
1257    float mY;
1258    const float* mPositions;
1259    float mLength;
1260    mat4 mPrecacheTransform;
1261};
1262
1263///////////////////////////////////////////////////////////////////////////////
1264// SPECIAL DRAW OPERATIONS
1265///////////////////////////////////////////////////////////////////////////////
1266
1267class DrawFunctorOp : public DrawOp {
1268public:
1269    DrawFunctorOp(Functor* functor)
1270            : DrawOp(0), mFunctor(functor) {}
1271
1272    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1273            int multipliedAlpha) {
1274        renderer.startMark("GL functor");
1275        status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1276        renderer.endMark();
1277        return ret;
1278    }
1279
1280    virtual void output(int level, uint32_t logFlags) {
1281        OP_LOG("Draw Functor %p", mFunctor);
1282    }
1283
1284    virtual const char* name() { return "DrawFunctor"; }
1285
1286private:
1287    Functor* mFunctor;
1288};
1289
1290class DrawDisplayListOp : public DrawBoundedOp {
1291public:
1292    DrawDisplayListOp(DisplayList* displayList, int flags)
1293            : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
1294            mDisplayList(displayList), mFlags(flags) {}
1295
1296    virtual void defer(DeferStateStruct& deferStruct, int saveCount,
1297            int level, int multipliedAlpha) {
1298        if (mDisplayList && mDisplayList->isRenderable()) {
1299            mDisplayList->defer(deferStruct, level + 1);
1300        }
1301    }
1302
1303    virtual void replay(ReplayStateStruct& replayStruct, int saveCount,
1304            int level, int multipliedAlpha) {
1305        if (mDisplayList && mDisplayList->isRenderable()) {
1306            mDisplayList->replay(replayStruct, level + 1);
1307        }
1308    }
1309
1310    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1311            int multipliedAlpha) { return DrawGlInfo::kStatusDone; }
1312
1313    virtual void output(int level, uint32_t logFlags) {
1314        OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
1315        if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
1316            mDisplayList->output(level + 1);
1317        }
1318    }
1319
1320    virtual const char* name() { return "DrawDisplayList"; }
1321
1322private:
1323    DisplayList* mDisplayList;
1324    int mFlags;
1325};
1326
1327class DrawLayerOp : public DrawOp {
1328public:
1329    DrawLayerOp(Layer* layer, float x, float y, SkPaint* paint)
1330            : DrawOp(paint), mLayer(layer), mX(x), mY(y) {}
1331
1332    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, int level,
1333            int multipliedAlpha) {
1334        int oldAlpha = -1;
1335
1336        if (multipliedAlpha >= 0 && multipliedAlpha < 255) {
1337            oldAlpha = mLayer->getAlpha();
1338            mLayer->setAlpha(multipliedAlpha);
1339        }
1340        status_t ret = renderer.drawLayer(mLayer, mX, mY, getPaint(renderer));
1341        if (oldAlpha >= 0) {
1342            mLayer->setAlpha(oldAlpha);
1343        }
1344        return ret;
1345    }
1346
1347    virtual void output(int level, uint32_t logFlags) {
1348        OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1349    }
1350
1351    virtual const char* name() { return "DrawLayer"; }
1352
1353private:
1354    Layer* mLayer;
1355    float mX;
1356    float mY;
1357};
1358
1359}; // namespace uirenderer
1360}; // namespace android
1361
1362#endif // ANDROID_HWUI_DISPLAY_OPERATION_H
1363