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