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