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