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