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