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