DisplayListOp.h revision 5d11676414b3606792e23c269cf75b44faa1a2af
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()) {
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() { 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() { 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() { 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
437private:
438    Rect mArea;
439    SkRegion::Op mOp;
440};
441
442class ClipPathOp : public StateOp {
443public:
444    ClipPathOp(SkPath* path, SkRegion::Op op)
445            : mPath(path), mOp(op) {}
446
447    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
448        renderer.clipPath(mPath, mOp);
449    }
450
451    virtual void output(int level, uint32_t flags = 0) {
452        SkRect bounds = mPath->getBounds();
453        OP_LOG("ClipPath bounds " RECT_STRING,
454                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
455    }
456
457    virtual const char* name() { return "ClipPath"; }
458    virtual bool requiresDrawOpFlush() { return true; }
459
460private:
461    SkPath* mPath;
462    SkRegion::Op mOp;
463};
464
465class ClipRegionOp : public StateOp {
466public:
467    ClipRegionOp(SkRegion* region, SkRegion::Op op)
468            : mRegion(region), mOp(op) {}
469
470    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
471        renderer.clipRegion(mRegion, mOp);
472    }
473
474    virtual void output(int level, uint32_t flags = 0) {
475        SkIRect bounds = mRegion->getBounds();
476        OP_LOG("ClipRegion bounds %d %d %d %d",
477                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
478    }
479
480    virtual const char* name() { return "ClipRegion"; }
481    virtual bool requiresDrawOpFlush() { return true; }
482
483private:
484    SkRegion* mRegion;
485    SkRegion::Op mOp;
486};
487
488class ResetShaderOp : public StateOp {
489public:
490    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
491        renderer.resetShader();
492    }
493
494    virtual void output(int level, uint32_t flags = 0) {
495        OP_LOGS("ResetShader");
496    }
497
498    virtual const char* name() { return "ResetShader"; }
499};
500
501class SetupShaderOp : public StateOp {
502public:
503    SetupShaderOp(SkiaShader* shader)
504            : mShader(shader) {}
505    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
506        renderer.setupShader(mShader);
507    }
508
509    virtual void output(int level, uint32_t flags = 0) {
510        OP_LOG("SetupShader, shader %p", mShader);
511    }
512
513    virtual const char* name() { return "SetupShader"; }
514
515private:
516    SkiaShader* mShader;
517};
518
519class ResetColorFilterOp : public StateOp {
520public:
521    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
522        renderer.resetColorFilter();
523    }
524
525    virtual void output(int level, uint32_t flags = 0) {
526        OP_LOGS("ResetColorFilter");
527    }
528
529    virtual const char* name() { return "ResetColorFilter"; }
530};
531
532class SetupColorFilterOp : public StateOp {
533public:
534    SetupColorFilterOp(SkiaColorFilter* colorFilter)
535            : mColorFilter(colorFilter) {}
536
537    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
538        renderer.setupColorFilter(mColorFilter);
539    }
540
541    virtual void output(int level, uint32_t flags = 0) {
542        OP_LOG("SetupColorFilter, filter %p", mColorFilter);
543    }
544
545    virtual const char* name() { return "SetupColorFilter"; }
546
547private:
548    SkiaColorFilter* mColorFilter;
549};
550
551class ResetShadowOp : public StateOp {
552public:
553    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
554        renderer.resetShadow();
555    }
556
557    virtual void output(int level, uint32_t flags = 0) {
558        OP_LOGS("ResetShadow");
559    }
560
561    virtual const char* name() { return "ResetShadow"; }
562};
563
564class SetupShadowOp : public StateOp {
565public:
566    SetupShadowOp(float radius, float dx, float dy, int color)
567            : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
568
569    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
570        renderer.setupShadow(mRadius, mDx, mDy, mColor);
571    }
572
573    virtual void output(int level, uint32_t flags = 0) {
574        OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
575    }
576
577    virtual const char* name() { return "SetupShadow"; }
578
579private:
580    float mRadius;
581    float mDx;
582    float mDy;
583    int mColor;
584};
585
586class ResetPaintFilterOp : public StateOp {
587public:
588    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
589        renderer.resetPaintFilter();
590    }
591
592    virtual void output(int level, uint32_t flags = 0) {
593        OP_LOGS("ResetPaintFilter");
594    }
595
596    virtual const char* name() { return "ResetPaintFilter"; }
597};
598
599class SetupPaintFilterOp : public StateOp {
600public:
601    SetupPaintFilterOp(int clearBits, int setBits)
602            : mClearBits(clearBits), mSetBits(setBits) {}
603
604    virtual void applyState(OpenGLRenderer& renderer, int saveCount) {
605        renderer.setupPaintFilter(mClearBits, mSetBits);
606    }
607
608    virtual void output(int level, uint32_t flags = 0) {
609        OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
610    }
611
612    virtual const char* name() { return "SetupPaintFilter"; }
613
614private:
615    int mClearBits;
616    int mSetBits;
617};
618
619
620///////////////////////////////////////////////////////////////////////////////
621// DRAW OPERATIONS - these are operations that can draw to the canvas's device
622///////////////////////////////////////////////////////////////////////////////
623
624class DrawBitmapOp : public DrawBoundedOp {
625public:
626    DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
627            : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(),
628                    paint),
629            mBitmap(bitmap) {}
630
631    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
632            bool caching, int multipliedAlpha) {
633        SkPaint* paint = getPaint(renderer);
634        int oldAlpha = -1;
635        if (caching && multipliedAlpha < 255) {
636            oldAlpha = paint->getAlpha();
637            paint->setAlpha(multipliedAlpha);
638        }
639        status_t ret = renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, paint);
640        if (oldAlpha >= 0) {
641            paint->setAlpha(oldAlpha);
642        }
643        return ret;
644    }
645
646    virtual void output(int level, uint32_t flags) {
647        OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
648    }
649
650    virtual const char* name() { return "DrawBitmap"; }
651    virtual DeferredDisplayList::OpBatchId getBatchId() {
652        return DeferredDisplayList::kOpBatch_Bitmap;
653    }
654
655protected:
656    SkBitmap* mBitmap;
657};
658
659class DrawBitmapMatrixOp : public DrawBoundedOp {
660public:
661    DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
662            : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
663        mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
664        const mat4 transform(*matrix);
665        transform.mapRect(mLocalBounds);
666    }
667
668    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
669            bool caching, int multipliedAlpha) {
670        return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
671    }
672
673    virtual void output(int level, uint32_t flags) {
674        OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
675    }
676
677    virtual const char* name() { return "DrawBitmap"; }
678    virtual DeferredDisplayList::OpBatchId getBatchId() {
679        return DeferredDisplayList::kOpBatch_Bitmap;
680    }
681
682private:
683    SkBitmap* mBitmap;
684    SkMatrix* mMatrix;
685};
686
687class DrawBitmapRectOp : public DrawBoundedOp {
688public:
689    DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
690            float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
691            : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
692            mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
693
694    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
695            bool caching, int multipliedAlpha) {
696        return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
697                mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
698                getPaint(renderer));
699    }
700
701    virtual void output(int level, uint32_t flags) {
702        OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
703                mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
704    }
705
706    virtual const char* name() { return "DrawBitmapRect"; }
707    virtual DeferredDisplayList::OpBatchId getBatchId() {
708        return DeferredDisplayList::kOpBatch_Bitmap;
709    }
710
711private:
712    SkBitmap* mBitmap;
713    Rect mSrc;
714};
715
716class DrawBitmapDataOp : public DrawBitmapOp {
717public:
718    DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
719            : DrawBitmapOp(bitmap, left, top, paint) {}
720
721    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
722            bool caching, int multipliedAlpha) {
723        return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
724                mLocalBounds.top, getPaint(renderer));
725    }
726
727    virtual void output(int level, uint32_t flags) {
728        OP_LOG("Draw bitmap %p", mBitmap);
729    }
730
731    virtual const char* name() { return "DrawBitmapData"; }
732    virtual DeferredDisplayList::OpBatchId getBatchId() {
733        return DeferredDisplayList::kOpBatch_Bitmap;
734    }
735};
736
737class DrawBitmapMeshOp : public DrawBoundedOp {
738public:
739    DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
740            float* vertices, int* colors, SkPaint* paint)
741            : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
742            mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
743            mVertices(vertices), mColors(colors) {}
744
745    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
746            bool caching, int multipliedAlpha) {
747        return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
748                mVertices, mColors, getPaint(renderer));
749    }
750
751    virtual void output(int level, uint32_t flags) {
752        OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
753    }
754
755    virtual const char* name() { return "DrawBitmapMesh"; }
756    virtual DeferredDisplayList::OpBatchId getBatchId() {
757        return DeferredDisplayList::kOpBatch_Bitmap;
758    }
759
760private:
761    SkBitmap* mBitmap;
762    int mMeshWidth;
763    int mMeshHeight;
764    float* mVertices;
765    int* mColors;
766};
767
768class DrawPatchOp : public DrawBoundedOp {
769public:
770    DrawPatchOp(SkBitmap* bitmap, const int32_t* xDivs,
771            const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
772            int8_t numColors, float left, float top, float right, float bottom,
773            int alpha, SkXfermode::Mode mode)
774            : DrawBoundedOp(left, top, right, bottom, 0),
775            mBitmap(bitmap), mxDivs(xDivs), myDivs(yDivs),
776            mColors(colors), mxDivsCount(width), myDivsCount(height),
777            mNumColors(numColors), mAlpha(alpha), mMode(mode) {};
778
779    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
780            bool caching, int multipliedAlpha) {
781        // NOTE: not calling the virtual method, which takes a paint
782        return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors,
783                mxDivsCount, myDivsCount, mNumColors,
784                mLocalBounds.left, mLocalBounds.top,
785                mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
786    }
787
788    virtual void output(int level, uint32_t flags) {
789        OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
790    }
791
792    virtual const char* name() { return "DrawPatch"; }
793    virtual DeferredDisplayList::OpBatchId getBatchId() {
794        return DeferredDisplayList::kOpBatch_Patch;
795    }
796
797private:
798    SkBitmap* mBitmap;
799    const int32_t* mxDivs;
800    const int32_t* myDivs;
801    const uint32_t* mColors;
802    uint32_t mxDivsCount;
803    uint32_t myDivsCount;
804    int8_t mNumColors;
805    int mAlpha;
806    SkXfermode::Mode mMode;
807};
808
809class DrawColorOp : public DrawOp {
810public:
811    DrawColorOp(int color, SkXfermode::Mode mode)
812            : DrawOp(0), mColor(color), mMode(mode) {};
813
814    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
815            bool caching, int multipliedAlpha) {
816        return renderer.drawColor(mColor, mMode);
817    }
818
819    virtual void output(int level, uint32_t flags) {
820        OP_LOG("Draw color %#x, mode %d", mColor, mMode);
821    }
822
823    virtual const char* name() { return "DrawColor"; }
824
825private:
826    int mColor;
827    SkXfermode::Mode mMode;
828};
829
830class DrawStrokableOp : public DrawBoundedOp {
831public:
832    DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
833            : DrawBoundedOp(left, top, right, bottom, paint) {};
834
835    bool getLocalBounds(Rect& localBounds) {
836        localBounds.set(mLocalBounds);
837        if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
838            localBounds.outset(strokeWidthOutset());
839        }
840        return true;
841    }
842
843    virtual DeferredDisplayList::OpBatchId getBatchId() {
844        if (mPaint->getPathEffect()) {
845            return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
846        }
847        return mPaint->isAntiAlias() ?
848                DeferredDisplayList::kOpBatch_AlphaVertices :
849                DeferredDisplayList::kOpBatch_Vertices;
850    }
851};
852
853class DrawRectOp : public DrawStrokableOp {
854public:
855    DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
856            : DrawStrokableOp(left, top, right, bottom, paint) {}
857
858    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
859            bool caching, int multipliedAlpha) {
860        return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
861                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
862    }
863
864    virtual void output(int level, uint32_t flags) {
865        OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
866    }
867
868    virtual const char* name() { return "DrawRect"; }
869};
870
871class DrawRectsOp : public DrawBoundedOp {
872public:
873    DrawRectsOp(const float* rects, int count, SkPaint* paint)
874            : DrawBoundedOp(rects, count, paint),
875            mRects(rects), mCount(count) {}
876
877    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
878            bool caching, int multipliedAlpha) {
879        return renderer.drawRects(mRects, mCount, getPaint(renderer));
880    }
881
882    virtual void output(int level, uint32_t flags) {
883        OP_LOG("Draw Rects count %d", mCount);
884    }
885
886    virtual const char* name() { return "DrawRects"; }
887
888    virtual DeferredDisplayList::OpBatchId getBatchId() {
889        return DeferredDisplayList::kOpBatch_Vertices;
890    }
891
892private:
893    const float* mRects;
894    int mCount;
895};
896
897class DrawRoundRectOp : public DrawStrokableOp {
898public:
899    DrawRoundRectOp(float left, float top, float right, float bottom,
900            float rx, float ry, SkPaint* paint)
901            : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
902
903    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
904            bool caching, int multipliedAlpha) {
905        return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
906                mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
907    }
908
909    virtual void output(int level, uint32_t flags) {
910        OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
911    }
912
913    virtual const char* name() { return "DrawRoundRect"; }
914
915private:
916    float mRx;
917    float mRy;
918};
919
920class DrawCircleOp : public DrawStrokableOp {
921public:
922    DrawCircleOp(float x, float y, float radius, SkPaint* paint)
923            : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
924            mX(x), mY(y), mRadius(radius) {}
925
926    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
927            bool caching, int multipliedAlpha) {
928        return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
929    }
930
931    virtual void output(int level, uint32_t flags) {
932        OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
933    }
934
935    virtual const char* name() { return "DrawCircle"; }
936
937private:
938    float mX;
939    float mY;
940    float mRadius;
941};
942
943class DrawOvalOp : public DrawStrokableOp {
944public:
945    DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
946            : DrawStrokableOp(left, top, right, bottom, paint) {}
947
948    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
949            bool caching, int multipliedAlpha) {
950        return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
951                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
952    }
953
954    virtual void output(int level, uint32_t flags) {
955        OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
956    }
957
958    virtual const char* name() { return "DrawOval"; }
959};
960
961class DrawArcOp : public DrawStrokableOp {
962public:
963    DrawArcOp(float left, float top, float right, float bottom,
964            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
965            : DrawStrokableOp(left, top, right, bottom, paint),
966            mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
967
968    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
969            bool caching, int multipliedAlpha) {
970        return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
971                mLocalBounds.right, mLocalBounds.bottom,
972                mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
973    }
974
975    virtual void output(int level, uint32_t flags) {
976        OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
977                RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
978    }
979
980    virtual const char* name() { return "DrawArc"; }
981
982private:
983    float mStartAngle;
984    float mSweepAngle;
985    bool mUseCenter;
986};
987
988class DrawPathOp : public DrawBoundedOp {
989public:
990    DrawPathOp(SkPath* path, SkPaint* paint)
991            : DrawBoundedOp(paint), mPath(path) {
992        float left, top, offset;
993        uint32_t width, height;
994        computePathBounds(path, paint, left, top, offset, width, height);
995        left -= offset;
996        top -= offset;
997        mLocalBounds.set(left, top, left + width, top + height);
998    }
999
1000    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1001            bool caching, int multipliedAlpha) {
1002        return renderer.drawPath(mPath, getPaint(renderer));
1003    }
1004
1005    virtual void output(int level, uint32_t flags) {
1006        OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1007    }
1008
1009    virtual const char* name() { return "DrawPath"; }
1010
1011    virtual DeferredDisplayList::OpBatchId getBatchId() {
1012        return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1013    }
1014private:
1015    SkPath* mPath;
1016};
1017
1018class DrawLinesOp : public DrawBoundedOp {
1019public:
1020    DrawLinesOp(float* points, int count, SkPaint* paint)
1021            : DrawBoundedOp(points, count, paint),
1022            mPoints(points), mCount(count) {
1023        mLocalBounds.outset(strokeWidthOutset());
1024    }
1025
1026    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1027            bool caching, int multipliedAlpha) {
1028        return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1029    }
1030
1031    virtual void output(int level, uint32_t flags) {
1032        OP_LOG("Draw Lines count %d", mCount);
1033    }
1034
1035    virtual const char* name() { return "DrawLines"; }
1036
1037    virtual DeferredDisplayList::OpBatchId getBatchId() {
1038        return mPaint->isAntiAlias() ?
1039                DeferredDisplayList::kOpBatch_AlphaVertices :
1040                DeferredDisplayList::kOpBatch_Vertices;
1041    }
1042
1043protected:
1044    float* mPoints;
1045    int mCount;
1046};
1047
1048class DrawPointsOp : public DrawLinesOp {
1049public:
1050    DrawPointsOp(float* points, int count, SkPaint* paint)
1051            : DrawLinesOp(points, count, paint) {}
1052
1053    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1054            bool caching, int multipliedAlpha) {
1055        return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1056    }
1057
1058    virtual void output(int level, uint32_t flags) {
1059        OP_LOG("Draw Points count %d", mCount);
1060    }
1061
1062    virtual const char* name() { return "DrawPoints"; }
1063};
1064
1065class DrawSomeTextOp : public DrawOp {
1066public:
1067    DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
1068            : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1069
1070    virtual void output(int level, uint32_t flags) {
1071        OP_LOG("Draw some text, %d bytes", mBytesCount);
1072    }
1073
1074    virtual DeferredDisplayList::OpBatchId getBatchId() {
1075        return mPaint->getColor() == 0xff000000 ?
1076                DeferredDisplayList::kOpBatch_Text :
1077                DeferredDisplayList::kOpBatch_ColorText;
1078    }
1079protected:
1080    const char* mText;
1081    int mBytesCount;
1082    int mCount;
1083};
1084
1085class DrawTextOnPathOp : public DrawSomeTextOp {
1086public:
1087    DrawTextOnPathOp(const char* text, int bytesCount, int count,
1088            SkPath* path, float hOffset, float vOffset, SkPaint* paint)
1089            : DrawSomeTextOp(text, bytesCount, count, paint),
1090            mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1091        /* TODO: inherit from DrawBounded and init mLocalBounds */
1092    }
1093
1094    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1095            bool caching, int multipliedAlpha) {
1096        return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1097                mHOffset, mVOffset, getPaint(renderer));
1098    }
1099
1100    virtual const char* name() { return "DrawTextOnPath"; }
1101
1102private:
1103    SkPath* mPath;
1104    float mHOffset;
1105    float mVOffset;
1106};
1107
1108class DrawPosTextOp : public DrawSomeTextOp {
1109public:
1110    DrawPosTextOp(const char* text, int bytesCount, int count,
1111            const float* positions, SkPaint* paint)
1112            : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1113        /* TODO: inherit from DrawBounded and init mLocalBounds */
1114    }
1115
1116    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1117            bool caching, int multipliedAlpha) {
1118        return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1119    }
1120
1121    virtual const char* name() { return "DrawPosText"; }
1122
1123private:
1124    const float* mPositions;
1125};
1126
1127class DrawTextOp : public DrawBoundedOp {
1128public:
1129    DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
1130            const float* positions, SkPaint* paint, float length)
1131            : DrawBoundedOp(paint), mText(text), mBytesCount(bytesCount), mCount(count),
1132            mX(x), mY(y), mPositions(positions), mLength(length) {
1133        SkPaint::FontMetrics metrics;
1134        paint->getFontMetrics(&metrics, 0.0f);
1135        mLocalBounds.set(mX, mY + metrics.fTop, mX + length, mY + metrics.fBottom);
1136    }
1137
1138    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1139            bool caching, int multipliedAlpha) {
1140        return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
1141                mPositions, getPaint(renderer), mLength);
1142    }
1143
1144    virtual void output(int level, uint32_t flags) {
1145        OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1146    }
1147
1148    virtual const char* name() { return "DrawText"; }
1149
1150    virtual DeferredDisplayList::OpBatchId getBatchId() {
1151        return mPaint->getColor() == 0xff000000 ?
1152                DeferredDisplayList::kOpBatch_Text :
1153                DeferredDisplayList::kOpBatch_ColorText;
1154    }
1155
1156private:
1157    const char* mText;
1158    int mBytesCount;
1159    int mCount;
1160    float mX;
1161    float mY;
1162    const float* mPositions;
1163    float mLength;
1164};
1165
1166///////////////////////////////////////////////////////////////////////////////
1167// SPECIAL DRAW OPERATIONS
1168///////////////////////////////////////////////////////////////////////////////
1169
1170class DrawFunctorOp : public DrawOp {
1171public:
1172    DrawFunctorOp(Functor* functor)
1173            : DrawOp(0), mFunctor(functor) {}
1174
1175    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1176            bool caching, int multipliedAlpha) {
1177        renderer.startMark("GL functor");
1178        status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1179        renderer.endMark();
1180        return ret;
1181    }
1182
1183    virtual void output(int level, uint32_t flags) {
1184        OP_LOG("Draw Functor %p", mFunctor);
1185    }
1186
1187    virtual const char* name() { return "DrawFunctor"; }
1188
1189private:
1190    Functor* mFunctor;
1191};
1192
1193class DrawDisplayListOp : public DrawBoundedOp {
1194public:
1195    DrawDisplayListOp(DisplayList* displayList, int flags)
1196            : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
1197            mDisplayList(displayList), mFlags(flags) {}
1198
1199    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
1200            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
1201        if (mDisplayList && mDisplayList->isRenderable()) {
1202            return mDisplayList->replay(renderer, dirty, mFlags, level + 1, deferredList);
1203        }
1204        return DrawGlInfo::kStatusDone;
1205    }
1206
1207    // NOT USED, since replay is overridden
1208    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1209            bool caching, int multipliedAlpha) { return DrawGlInfo::kStatusDone; }
1210
1211    virtual void output(int level, uint32_t flags) {
1212        OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
1213        if (mDisplayList && (flags & kOpLogFlag_Recurse)) {
1214            mDisplayList->output(level + 1);
1215        }
1216    }
1217
1218    virtual const char* name() { return "DrawDisplayList"; }
1219
1220private:
1221    DisplayList* mDisplayList;
1222    int mFlags;
1223};
1224
1225class DrawLayerOp : public DrawOp {
1226public:
1227    DrawLayerOp(Layer* layer, float x, float y, SkPaint* paint)
1228            : DrawOp(paint), mLayer(layer), mX(x), mY(y) {}
1229
1230    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
1231            bool caching, int multipliedAlpha) {
1232        int oldAlpha = -1;
1233
1234        if (caching && multipliedAlpha < 255) {
1235            oldAlpha = mLayer->getAlpha();
1236            mLayer->setAlpha(multipliedAlpha);
1237        }
1238        status_t ret = renderer.drawLayer(mLayer, mX, mY, getPaint(renderer));
1239        if (oldAlpha >= 0) {
1240            mLayer->setAlpha(oldAlpha);
1241        }
1242        return ret;
1243    }
1244
1245    virtual void output(int level, uint32_t flags) {
1246        OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1247    }
1248
1249    virtual const char* name() { return "DrawLayer"; }
1250
1251private:
1252    Layer* mLayer;
1253    float mX;
1254    float mY;
1255};
1256
1257}; // namespace uirenderer
1258}; // namespace android
1259
1260#endif // ANDROID_HWUI_DISPLAY_OPERATION_H
1261