DisplayListOp.h revision 7031ff68bb998dbbd7caf3b2fd75eef747a86725
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_HWUI_DISPLAY_OPERATION_H
18#define ANDROID_HWUI_DISPLAY_OPERATION_H
19
20#ifndef LOG_TAG
21    #define LOG_TAG "OpenGLRenderer"
22#endif
23
24#include <SkXfermode.h>
25
26#include <private/hwui/DrawGlInfo.h>
27
28#include "OpenGLRenderer.h"
29#include "DeferredDisplayList.h"
30#include "DisplayListRenderer.h"
31#include "utils/LinearAllocator.h"
32
33#define CRASH() do { \
34    *(int *)(uintptr_t)0xbbadbeef = 0; \
35    ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
36} while(false)
37
38#define MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
39#define MATRIX_ARGS(m) \
40    m->get(0), m->get(1), m->get(2), \
41    m->get(3), m->get(4), m->get(5), \
42    m->get(6), m->get(7), m->get(8)
43#define RECT_STRING "%.2f %.2f %.2f %.2f"
44#define RECT_ARGS(r) \
45    r.left, r.top, r.right, r.bottom
46
47// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
48#define OP_LOGS(s) OP_LOG("%s", s)
49#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
50
51namespace android {
52namespace uirenderer {
53
54/**
55 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
56 * may be replayed to an OpenGLRenderer.
57 *
58 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
59 * LinearAllocator's managed memory buffers.  Each pointer held by a DisplayListOp is either a
60 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
61 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
62 * never called as LinearAllocators are simply discarded, so no memory management should be done in
63 * this class.
64 */
65class DisplayListOp {
66public:
67    // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
68    // standard new() intentionally not implemented, and delete/deconstructor should never be used.
69    virtual ~DisplayListOp() { CRASH(); }
70    static void operator delete(void* ptr) { CRASH(); }
71    /** static void* operator new(size_t size); PURPOSELY OMITTED **/
72    static void* operator new(size_t size, LinearAllocator& allocator) {
73        return allocator.alloc(size);
74    }
75
76    enum OpLogFlag {
77        kOpLogFlag_Recurse = 0x1,
78        kOpLogFlag_JSON = 0x2 // TODO: add?
79    };
80
81    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
82            uint32_t level, bool caching, int multipliedAlpha) = 0;
83
84    // same as replay above, but draw operations will defer into the deferredList if possible
85    // NOTE: colorfilters, paintfilters, shaders, shadow, and complex clips prevent deferral
86    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
87            uint32_t level, bool caching, int multipliedAlpha,
88            DeferredDisplayList& deferredList) = 0;
89
90    virtual void output(int level, uint32_t flags = 0) = 0;
91
92    // NOTE: it would be nice to declare constants and overriding the implementation in each op to
93    // point at the constants, but that seems to require a .cpp file
94    virtual const char* name() = 0;
95};
96
97class StateOp : public DisplayListOp {
98public:
99    StateOp() {};
100
101    virtual ~StateOp() {}
102
103    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
104            uint32_t level, bool caching, int multipliedAlpha) {
105        applyState(renderer, saveCount);
106        return DrawGlInfo::kStatusDone;
107    }
108
109    /**
110     * State operations are applied directly to the renderer, but can cause the deferred drawing op
111     * list to flush
112     */
113    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
114            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
115        status_t status = DrawGlInfo::kStatusDone;
116        if (requiresDrawOpFlush()) {
117            // will be setting renderer state that affects ops in deferredList, so flush list first
118            status |= deferredList.flush(renderer, dirty, flags, level);
119        }
120        applyState(renderer, saveCount);
121        return status;
122    }
123
124    virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
125
126    /**
127     * Returns true if it affects renderer drawing state in such a way to break deferral
128     * see OpenGLRenderer::disallowDeferral()
129     */
130    virtual bool requiresDrawOpFlush() { return false; }
131};
132
133class DrawOp : public DisplayListOp {
134public:
135    DrawOp(SkPaint* paint)
136            : mPaint(paint), mQuickRejected(false) {}
137
138    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
139            uint32_t level, bool caching, int multipliedAlpha) {
140        if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
141            return DrawGlInfo::kStatusDone;
142        }
143
144        return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
145    }
146
147    /** Draw operations are stored in the deferredList with information necessary for playback */
148    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
149            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
150        if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
151            return DrawGlInfo::kStatusDone;
152        }
153
154        if (renderer.disallowDeferral()) {
155            // dispatch draw immediately, since the renderer's state is too complex for deferral
156            return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
157        }
158
159        if (!caching) multipliedAlpha = -1;
160        state.mMultipliedAlpha = multipliedAlpha;
161        if (!getLocalBounds(state.mBounds)) {
162            // empty bounds signify bounds can't be calculated
163            state.mBounds.setEmpty();
164        }
165
166        if (!renderer.storeDisplayState(state)) {
167            // op wasn't quick-rejected, so defer
168            deferredList.add(this, renderer.disallowReorder());
169        }
170
171        return DrawGlInfo::kStatusDone;
172    }
173
174    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
175            bool caching, int multipliedAlpha) = 0;
176
177    // returns true if bounds exist
178    virtual bool getLocalBounds(Rect& localBounds) { return false; }
179
180    // TODO: better refine localbounds usage
181    void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
182    bool getQuickRejected() { return mQuickRejected; }
183
184    /** Batching disabled by default, turned on for individual ops */
185    virtual DeferredDisplayList::OpBatchId getBatchId() {
186        return DeferredDisplayList::kOpBatch_None;
187    }
188
189    float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
190
191public:
192    /**
193     * Stores the relevant canvas state of the object between deferral and replay (if the canvas
194     * state supports being stored) See OpenGLRenderer::simpleClipAndState()
195     */
196    DeferredDisplayState state;
197protected:
198    SkPaint* getPaint(OpenGLRenderer& renderer) {
199        return renderer.filterPaint(mPaint);
200    }
201
202    SkPaint* mPaint; // should be accessed via getPaint() when applying
203    bool mQuickRejected;
204};
205
206class DrawBoundedOp : public DrawOp {
207public:
208    DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
209            : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
210
211    // default constructor for area, to be overridden in child constructor body
212    DrawBoundedOp(SkPaint* paint)
213            : DrawOp(paint) {}
214
215    bool getLocalBounds(Rect& localBounds) {
216        localBounds.set(mLocalBounds);
217        return true;
218    }
219
220protected:
221    Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
222};
223
224///////////////////////////////////////////////////////////////////////////////
225// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
226//         not directly draw or alter output
227///////////////////////////////////////////////////////////////////////////////
228
229class SaveOp : public StateOp {
230public:
231    SaveOp(int flags)
232            : mFlags(flags) {}
233
234    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
235        renderer.save(mFlags);
236    }
237
238    virtual void output(int level, uint32_t flags = 0) {
239        OP_LOG("Save flags %x", mFlags);
240    }
241
242    virtual const char* name() { return "Save"; }
243
244private:
245    int mFlags;
246};
247
248class RestoreToCountOp : public StateOp {
249public:
250    RestoreToCountOp(int count)
251            : mCount(count) {}
252
253    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
254        renderer.restoreToCount(saveCount + mCount);
255
256    }
257
258    virtual void output(int level, uint32_t flags = 0) {
259        OP_LOG("Restore to count %d", mCount);
260    }
261
262    virtual const char* name() { return "RestoreToCount"; }
263    // Note: don't have to return true for requiresDrawOpFlush - even though restore can create a
264    // complex clip, the clip and matrix are overridden by DeferredDisplayList::flush()
265
266private:
267    int mCount;
268};
269
270class SaveLayerOp : public StateOp {
271public:
272    SaveLayerOp(float left, float top, float right, float bottom, SkPaint* paint, int flags)
273            : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
274
275    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
276        SkPaint* paint = renderer.filterPaint(mPaint);
277        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, paint, mFlags);
278    }
279
280    virtual void output(int level, uint32_t flags = 0) {
281        OP_LOG("SaveLayer of area " RECT_STRING, RECT_ARGS(mArea));
282    }
283
284    virtual const char* name() { return "SaveLayer"; }
285    virtual bool requiresDrawOpFlush() { return true; }
286
287private:
288    Rect mArea;
289    SkPaint* mPaint;
290    int mFlags;
291};
292
293class SaveLayerAlphaOp : public StateOp {
294public:
295    SaveLayerAlphaOp(float left, float top, float right, float bottom, int alpha, int flags)
296            : mArea(left, top, right, bottom), mAlpha(alpha), mFlags(flags) {}
297
298    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
299        renderer.saveLayerAlpha(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mFlags);
300    }
301
302    virtual void output(int level, uint32_t flags = 0) {
303        OP_LOG("SaveLayerAlpha of area " RECT_STRING, RECT_ARGS(mArea));
304    }
305
306    virtual const char* name() { return "SaveLayerAlpha"; }
307    virtual bool requiresDrawOpFlush() { return true; }
308
309private:
310    Rect mArea;
311    int mAlpha;
312    int mFlags;
313};
314
315class TranslateOp : public StateOp {
316public:
317    TranslateOp(float dx, float dy)
318            : mDx(dx), mDy(dy) {}
319
320    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
321        renderer.translate(mDx, mDy);
322    }
323
324    virtual void output(int level, uint32_t flags = 0) {
325        OP_LOG("Translate by %f %f", mDx, mDy);
326    }
327
328    virtual const char* name() { return "Translate"; }
329
330private:
331    float mDx;
332    float mDy;
333};
334
335class RotateOp : public StateOp {
336public:
337    RotateOp(float degrees)
338            : mDegrees(degrees) {}
339
340    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
341        renderer.rotate(mDegrees);
342    }
343
344    virtual void output(int level, uint32_t flags = 0) {
345        OP_LOG("Rotate by %f degrees", mDegrees);
346    }
347
348    virtual const char* name() { return "Rotate"; }
349
350private:
351    float mDegrees;
352};
353
354class ScaleOp : public StateOp {
355public:
356    ScaleOp(float sx, float sy)
357            : mSx(sx), mSy(sy) {}
358
359    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
360        renderer.scale(mSx, mSy);
361    }
362
363    virtual void output(int level, uint32_t flags = 0) {
364        OP_LOG("Scale by %f %f", mSx, mSy);
365    }
366
367    virtual const char* name() { return "Scale"; }
368
369private:
370    float mSx;
371    float mSy;
372};
373
374class SkewOp : public StateOp {
375public:
376    SkewOp(float sx, float sy)
377            : mSx(sx), mSy(sy) {}
378
379    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
380        renderer.skew(mSx, mSy);
381    }
382
383    virtual void output(int level, uint32_t flags = 0) {
384        OP_LOG("Skew by %f %f", mSx, mSy);
385    }
386
387    virtual const char* name() { return "Skew"; }
388
389private:
390    float mSx;
391    float mSy;
392};
393
394class SetMatrixOp : public StateOp {
395public:
396    SetMatrixOp(SkMatrix* matrix)
397            : mMatrix(matrix) {}
398
399    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
400        renderer.setMatrix(mMatrix);
401    }
402
403    virtual void output(int level, uint32_t flags = 0) {
404        OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
405    }
406
407    virtual const char* name() { return "SetMatrix"; }
408
409private:
410    SkMatrix* mMatrix;
411};
412
413class ConcatMatrixOp : public StateOp {
414public:
415    ConcatMatrixOp(SkMatrix* matrix)
416            : mMatrix(matrix) {}
417
418    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
419        renderer.concatMatrix(mMatrix);
420    }
421
422    virtual void output(int level, uint32_t flags = 0) {
423        OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
424    }
425
426    virtual const char* name() { return "ConcatMatrix"; }
427
428private:
429    SkMatrix* mMatrix;
430};
431
432class ClipRectOp : public StateOp {
433public:
434    ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
435            : mArea(left, top, right, bottom), mOp(op) {}
436
437    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
438        renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
439    }
440
441    virtual void output(int level, uint32_t flags = 0) {
442        OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
443    }
444
445    virtual const char* name() { return "ClipRect"; }
446
447private:
448    Rect mArea;
449    SkRegion::Op mOp;
450};
451
452class ClipPathOp : public StateOp {
453public:
454    ClipPathOp(SkPath* path, SkRegion::Op op)
455            : mPath(path), mOp(op) {}
456
457    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
458        renderer.clipPath(mPath, mOp);
459    }
460
461    virtual void output(int level, uint32_t flags = 0) {
462        SkRect bounds = mPath->getBounds();
463        OP_LOG("ClipPath bounds " RECT_STRING,
464                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
465    }
466
467    virtual const char* name() { return "ClipPath"; }
468    virtual bool requiresDrawOpFlush() { return true; }
469
470private:
471    SkPath* mPath;
472    SkRegion::Op mOp;
473};
474
475class ClipRegionOp : public StateOp {
476public:
477    ClipRegionOp(SkRegion* region, SkRegion::Op op)
478            : mRegion(region), mOp(op) {}
479
480    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
481        renderer.clipRegion(mRegion, mOp);
482    }
483
484    virtual void output(int level, uint32_t flags = 0) {
485        SkIRect bounds = mRegion->getBounds();
486        OP_LOG("ClipRegion bounds %d %d %d %d",
487                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
488    }
489
490    virtual const char* name() { return "ClipRegion"; }
491    virtual bool requiresDrawOpFlush() { return true; }
492
493private:
494    SkRegion* mRegion;
495    SkRegion::Op mOp;
496};
497
498class ResetShaderOp : public StateOp {
499public:
500    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
501        renderer.resetShader();
502    }
503
504    virtual void output(int level, uint32_t flags = 0) {
505        OP_LOGS("ResetShader");
506    }
507
508    virtual const char* name() { return "ResetShader"; }
509};
510
511class SetupShaderOp : public StateOp {
512public:
513    SetupShaderOp(SkiaShader* shader)
514            : mShader(shader) {}
515    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
516        renderer.setupShader(mShader);
517    }
518
519    virtual void output(int level, uint32_t flags = 0) {
520        OP_LOG("SetupShader, shader %p", mShader);
521    }
522
523    virtual const char* name() { return "SetupShader"; }
524
525private:
526    SkiaShader* mShader;
527};
528
529class ResetColorFilterOp : public StateOp {
530public:
531    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
532        renderer.resetColorFilter();
533    }
534
535    virtual void output(int level, uint32_t flags = 0) {
536        OP_LOGS("ResetColorFilter");
537    }
538
539    virtual const char* name() { return "ResetColorFilter"; }
540};
541
542class SetupColorFilterOp : public StateOp {
543public:
544    SetupColorFilterOp(SkiaColorFilter* colorFilter)
545            : mColorFilter(colorFilter) {}
546
547    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
548        renderer.setupColorFilter(mColorFilter);
549    }
550
551    virtual void output(int level, uint32_t flags = 0) {
552        OP_LOG("SetupColorFilter, filter %p", mColorFilter);
553    }
554
555    virtual const char* name() { return "SetupColorFilter"; }
556
557private:
558    SkiaColorFilter* mColorFilter;
559};
560
561class ResetShadowOp : public StateOp {
562public:
563    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
564        renderer.resetShadow();
565    }
566
567    virtual void output(int level, uint32_t flags = 0) {
568        OP_LOGS("ResetShadow");
569    }
570
571    virtual const char* name() { return "ResetShadow"; }
572};
573
574class SetupShadowOp : public StateOp {
575public:
576    SetupShadowOp(float radius, float dx, float dy, int color)
577            : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
578
579    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
580        renderer.setupShadow(mRadius, mDx, mDy, mColor);
581    }
582
583    virtual void output(int level, uint32_t flags = 0) {
584        OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
585    }
586
587    virtual const char* name() { return "SetupShadow"; }
588
589private:
590    float mRadius;
591    float mDx;
592    float mDy;
593    int mColor;
594};
595
596class ResetPaintFilterOp : public StateOp {
597public:
598    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
599        renderer.resetPaintFilter();
600    }
601
602    virtual void output(int level, uint32_t flags = 0) {
603        OP_LOGS("ResetPaintFilter");
604    }
605
606    virtual const char* name() { return "ResetPaintFilter"; }
607};
608
609class SetupPaintFilterOp : public StateOp {
610public:
611    SetupPaintFilterOp(int clearBits, int setBits)
612            : mClearBits(clearBits), mSetBits(setBits) {}
613
614    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
615        renderer.setupPaintFilter(mClearBits, mSetBits);
616    }
617
618    virtual void output(int level, uint32_t flags = 0) {
619        OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
620    }
621
622    virtual const char* name() { return "SetupPaintFilter"; }
623
624private:
625    int mClearBits;
626    int mSetBits;
627};
628
629
630///////////////////////////////////////////////////////////////////////////////
631// DRAW OPERATIONS - these are operations that can draw to the canvas's device
632///////////////////////////////////////////////////////////////////////////////
633
634class DrawBitmapOp : public DrawBoundedOp {
635public:
636    DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
637            : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(),
638                    paint),
639            mBitmap(bitmap) {}
640
641    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
642            bool caching, int multipliedAlpha) {
643        SkPaint* paint = getPaint(renderer);
644        int oldAlpha = -1;
645        if (caching && multipliedAlpha < 255) {
646            oldAlpha = paint->getAlpha();
647            paint->setAlpha(multipliedAlpha);
648        }
649        status_t ret = renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, paint);
650        if (oldAlpha >= 0) {
651            paint->setAlpha(oldAlpha);
652        }
653        return ret;
654    }
655
656    virtual void output(int level, uint32_t flags) {
657        OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
658    }
659
660    virtual const char* name() { return "DrawBitmap"; }
661    virtual DeferredDisplayList::OpBatchId getBatchId() {
662        return DeferredDisplayList::kOpBatch_Bitmap;
663    }
664
665protected:
666    SkBitmap* mBitmap;
667};
668
669class DrawBitmapMatrixOp : public DrawBoundedOp {
670public:
671    DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
672            : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
673        mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
674        const mat4 transform(*matrix);
675        transform.mapRect(mLocalBounds);
676    }
677
678    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
679            bool caching, int multipliedAlpha) {
680        return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
681    }
682
683    virtual void output(int level, uint32_t flags) {
684        OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
685    }
686
687    virtual const char* name() { return "DrawBitmap"; }
688    virtual DeferredDisplayList::OpBatchId getBatchId() {
689        return DeferredDisplayList::kOpBatch_Bitmap;
690    }
691
692private:
693    SkBitmap* mBitmap;
694    SkMatrix* mMatrix;
695};
696
697class DrawBitmapRectOp : public DrawBoundedOp {
698public:
699    DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
700            float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
701            : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
702            mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
703
704    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
705            bool caching, int multipliedAlpha) {
706        return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
707                mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
708                getPaint(renderer));
709    }
710
711    virtual void output(int level, uint32_t flags) {
712        OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
713                mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
714    }
715
716    virtual const char* name() { return "DrawBitmapRect"; }
717    virtual DeferredDisplayList::OpBatchId getBatchId() {
718        return DeferredDisplayList::kOpBatch_Bitmap;
719    }
720
721private:
722    SkBitmap* mBitmap;
723    Rect mSrc;
724};
725
726class DrawBitmapDataOp : public DrawBitmapOp {
727public:
728    DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
729            : DrawBitmapOp(bitmap, left, top, paint) {}
730
731    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
732            bool caching, int multipliedAlpha) {
733        return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
734                mLocalBounds.top, getPaint(renderer));
735    }
736
737    virtual void output(int level, uint32_t flags) {
738        OP_LOG("Draw bitmap %p", mBitmap);
739    }
740
741    virtual const char* name() { return "DrawBitmapData"; }
742    virtual DeferredDisplayList::OpBatchId getBatchId() {
743        return DeferredDisplayList::kOpBatch_Bitmap;
744    }
745};
746
747class DrawBitmapMeshOp : public DrawOp {
748public:
749    DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
750            float* vertices, int* colors, SkPaint* paint)
751            : DrawOp(paint), 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 DrawOp {
881public:
882    DrawRectsOp(const float* rects, int count, SkPaint* paint)
883            : DrawOp(paint), mRects(rects), mCount(count) {}
884
885    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
886            bool caching, int multipliedAlpha) {
887        return renderer.drawRects(mRects, mCount, getPaint(renderer));
888    }
889
890    virtual void output(int level, uint32_t flags) {
891        OP_LOG("Draw Rects count %d", mCount);
892    }
893
894    virtual const char* name() { return "DrawRects"; }
895
896    virtual DeferredDisplayList::OpBatchId getBatchId() {
897        return DeferredDisplayList::kOpBatch_Vertices;
898    }
899
900private:
901    const float* mRects;
902    int mCount;
903};
904
905class DrawRoundRectOp : public DrawStrokableOp {
906public:
907    DrawRoundRectOp(float left, float top, float right, float bottom,
908            float rx, float ry, SkPaint* paint)
909            : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
910
911    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
912            bool caching, int multipliedAlpha) {
913        return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
914                mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
915    }
916
917    virtual void output(int level, uint32_t flags) {
918        OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
919    }
920
921    virtual const char* name() { return "DrawRoundRect"; }
922
923private:
924    float mRx;
925    float mRy;
926};
927
928class DrawCircleOp : public DrawStrokableOp {
929public:
930    DrawCircleOp(float x, float y, float radius, SkPaint* paint)
931            : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
932            mX(x), mY(y), mRadius(radius) {}
933
934    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
935            bool caching, int multipliedAlpha) {
936        return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
937    }
938
939    virtual void output(int level, uint32_t flags) {
940        OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
941    }
942
943    virtual const char* name() { return "DrawCircle"; }
944
945private:
946    float mX;
947    float mY;
948    float mRadius;
949};
950
951class DrawOvalOp : public DrawStrokableOp {
952public:
953    DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
954            : DrawStrokableOp(left, top, right, bottom, paint) {}
955
956    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
957            bool caching, int multipliedAlpha) {
958        return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
959                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
960    }
961
962    virtual void output(int level, uint32_t flags) {
963        OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
964    }
965
966    virtual const char* name() { return "DrawOval"; }
967};
968
969class DrawArcOp : public DrawStrokableOp {
970public:
971    DrawArcOp(float left, float top, float right, float bottom,
972            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
973            : DrawStrokableOp(left, top, right, bottom, paint),
974            mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
975
976    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
977            bool caching, int multipliedAlpha) {
978        return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
979                mLocalBounds.right, mLocalBounds.bottom,
980                mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
981    }
982
983    virtual void output(int level, uint32_t flags) {
984        OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
985                RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
986    }
987
988    virtual const char* name() { return "DrawArc"; }
989
990private:
991    float mStartAngle;
992    float mSweepAngle;
993    bool mUseCenter;
994};
995
996class DrawPathOp : public DrawBoundedOp {
997public:
998    DrawPathOp(SkPath* path, SkPaint* paint)
999            : DrawBoundedOp(paint), mPath(path) {
1000        float left, top, offset;
1001        uint32_t width, height;
1002        computePathBounds(path, paint, left, top, offset, width, height);
1003        left -= offset;
1004        top -= offset;
1005        mLocalBounds.set(left, top, left + width, top + height);
1006    }
1007
1008    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1009            bool caching, int multipliedAlpha) {
1010        return renderer.drawPath(mPath, getPaint(renderer));
1011    }
1012
1013    virtual void output(int level, uint32_t flags) {
1014        OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1015    }
1016
1017    virtual const char* name() { return "DrawPath"; }
1018
1019    virtual DeferredDisplayList::OpBatchId getBatchId() {
1020        return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1021    }
1022private:
1023    SkPath* mPath;
1024};
1025
1026class DrawLinesOp : public DrawBoundedOp {
1027public:
1028    DrawLinesOp(float* points, int count, SkPaint* paint)
1029            : DrawBoundedOp(paint), mPoints(points), mCount(count) {
1030        for (int i = 0; i < count; i += 2) {
1031            mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
1032            mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
1033            mLocalBounds.top = fminf(mLocalBounds.top, points[i+1]);
1034            mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i+1]);
1035        }
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 DrawOp {
1207public:
1208    DrawDisplayListOp(DisplayList* displayList, int flags)
1209            : DrawOp(0), mDisplayList(displayList), mFlags(flags) {}
1210
1211    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
1212            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
1213        if (mDisplayList && mDisplayList->isRenderable()) {
1214            return mDisplayList->replay(renderer, dirty, mFlags, level + 1, &deferredList);
1215        }
1216        return DrawGlInfo::kStatusDone;
1217    }
1218
1219    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1220            bool caching, int multipliedAlpha) {
1221        if (mDisplayList && mDisplayList->isRenderable()) {
1222            return mDisplayList->replay(renderer, dirty, mFlags, level + 1);
1223        }
1224        return DrawGlInfo::kStatusDone;
1225    }
1226
1227    virtual void output(int level, uint32_t flags) {
1228        OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
1229        if (mDisplayList && (flags & kOpLogFlag_Recurse)) {
1230            mDisplayList->output(level + 1);
1231        }
1232    }
1233
1234    virtual const char* name() { return "DrawDisplayList"; }
1235
1236private:
1237    DisplayList* mDisplayList;
1238    int mFlags;
1239};
1240
1241class DrawLayerOp : public DrawOp {
1242public:
1243    DrawLayerOp(Layer* layer, float x, float y, SkPaint* paint)
1244            : DrawOp(paint), mLayer(layer), mX(x), mY(y) {}
1245
1246    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1247            bool caching, int multipliedAlpha) {
1248        int oldAlpha = -1;
1249
1250        if (caching && multipliedAlpha < 255) {
1251            oldAlpha = mLayer->getAlpha();
1252            mLayer->setAlpha(multipliedAlpha);
1253        }
1254        status_t ret = renderer.drawLayer(mLayer, mX, mY, getPaint(renderer));
1255        if (oldAlpha >= 0) {
1256            mLayer->setAlpha(oldAlpha);
1257        }
1258        return ret;
1259    }
1260
1261    virtual void output(int level, uint32_t flags) {
1262        OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1263    }
1264
1265    virtual const char* name() { return "DrawLayer"; }
1266
1267private:
1268    Layer* mLayer;
1269    float mX;
1270    float mY;
1271};
1272
1273}; // namespace uirenderer
1274}; // namespace android
1275
1276#endif // ANDROID_HWUI_DISPLAY_OPERATION_H
1277