DisplayListOp.h revision 4c2547fa9244e78115cde0a259291053108c3dc7
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 "AssetAtlas.h"
30#include "DeferredDisplayList.h"
31#include "DisplayListRenderer.h"
32#include "UvMapper.h"
33#include "utils/LinearAllocator.h"
34
35#define CRASH() do { \
36    *(int *)(uintptr_t)0xbbadbeef = 0; \
37    ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
38} while(false)
39
40#define MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]"
41#define MATRIX_ARGS(m) \
42    m->get(0), m->get(1), m->get(2), \
43    m->get(3), m->get(4), m->get(5), \
44    m->get(6), m->get(7), m->get(8)
45#define RECT_STRING "%.2f %.2f %.2f %.2f"
46#define RECT_ARGS(r) \
47    r.left, r.top, r.right, r.bottom
48
49// Use OP_LOG for logging with arglist, OP_LOGS if just printing char*
50#define OP_LOGS(s) OP_LOG("%s", s)
51#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
52
53namespace android {
54namespace uirenderer {
55
56/**
57 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they
58 * may be replayed to an OpenGLRenderer.
59 *
60 * To avoid individual memory allocations, DisplayListOps may only be allocated into a
61 * LinearAllocator's managed memory buffers.  Each pointer held by a DisplayListOp is either a
62 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or
63 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is
64 * never called as LinearAllocators are simply discarded, so no memory management should be done in
65 * this class.
66 */
67class DisplayListOp {
68public:
69    // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted.
70    // standard new() intentionally not implemented, and delete/deconstructor should never be used.
71    virtual ~DisplayListOp() { CRASH(); }
72    static void operator delete(void* ptr) { CRASH(); }
73    /** static void* operator new(size_t size); PURPOSELY OMITTED **/
74    static void* operator new(size_t size, LinearAllocator& allocator) {
75        return allocator.alloc(size);
76    }
77
78    enum OpLogFlag {
79        kOpLogFlag_Recurse = 0x1,
80        kOpLogFlag_JSON = 0x2 // TODO: add?
81    };
82
83    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
84            bool useQuickReject) = 0;
85
86    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
87            bool useQuickReject) = 0;
88
89    virtual void output(int level, uint32_t logFlags = 0) = 0;
90
91    // NOTE: it would be nice to declare constants and overriding the implementation in each op to
92    // point at the constants, but that seems to require a .cpp file
93    virtual const char* name() = 0;
94
95    /**
96     * Stores the relevant canvas state of the object between deferral and replay (if the canvas
97     * state supports being stored) See OpenGLRenderer::simpleClipAndState()
98     *
99     * TODO: don't reserve space for StateOps that won't be deferred
100     */
101    DeferredDisplayState state;
102
103};
104
105class StateOp : public DisplayListOp {
106public:
107    StateOp() {};
108
109    virtual ~StateOp() {}
110
111    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
112            bool useQuickReject) {
113        // default behavior only affects immediate, deferrable state, issue directly to renderer
114        applyState(deferStruct.mRenderer, saveCount);
115    }
116
117    /**
118     * State operations are applied directly to the renderer, but can cause the deferred drawing op
119     * list to flush
120     */
121    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
122            bool useQuickReject) {
123        applyState(replayStruct.mRenderer, saveCount);
124    }
125
126    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
127};
128
129class DrawOp : public DisplayListOp {
130friend class MergingDrawBatch;
131public:
132    DrawOp(SkPaint* paint)
133            : mPaint(paint), mQuickRejected(false) {}
134
135    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
136            bool useQuickReject) {
137        if (mQuickRejected && CC_LIKELY(useQuickReject)) {
138            return;
139        }
140
141        if (!getLocalBounds(state.mBounds)) {
142            // empty bounds signify bounds can't be calculated
143            state.mBounds.setEmpty();
144        }
145
146        deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
147    }
148
149    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
150            bool useQuickReject) {
151        if (mQuickRejected && CC_LIKELY(useQuickReject)) {
152            return;
153        }
154
155        replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
156    }
157
158    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
159
160    /**
161     * Draw multiple instances of an operation, must be overidden for operations that merge
162     *
163     * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
164     * and pure translation transformations. Other guarantees of similarity should be enforced by
165     * reducing which operations are tagged as mergeable.
166     */
167    virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
168            const Vector<DrawOp*>& ops, const Rect& bounds) {
169        status_t status = DrawGlInfo::kStatusDone;
170        for (unsigned int i = 0; i < ops.size(); i++) {
171            renderer.restoreDisplayState(ops[i]->state);
172            status |= ops[i]->applyDraw(renderer, dirty);
173        }
174        return status;
175    }
176
177    /*
178     * When this method is invoked the state field is initialized to have the
179     * final rendering state. We can thus use it to process data as it will be
180     * used at draw time.
181     *
182     * Additionally, this method allows subclasses to provide defer-time preferences for batching
183     * and merging.
184     *
185     * Return true if the op can merge with others of its kind (such subclasses should implement
186     * multiDraw)
187     */
188    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
189        return false;
190    }
191
192    // returns true if bounds exist
193    virtual bool getLocalBounds(Rect& localBounds) { return false; }
194
195    // TODO: better refine localbounds usage
196    void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
197    bool getQuickRejected() { return mQuickRejected; }
198
199    inline int getPaintAlpha() {
200        return OpenGLRenderer::getAlphaDirect(mPaint);
201    }
202
203    inline float strokeWidthOutset() {
204        float width = mPaint->getStrokeWidth();
205        if (width == 0) return 0.5f; // account for hairline
206        return width * 0.5f;
207    }
208
209protected:
210    SkPaint* getPaint(OpenGLRenderer& renderer) {
211        return renderer.filterPaint(mPaint);
212    }
213
214    SkPaint* mPaint; // should be accessed via getPaint() when applying
215    bool mQuickRejected;
216};
217
218class DrawBoundedOp : public DrawOp {
219public:
220    DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
221            : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
222
223    DrawBoundedOp(const Rect& localBounds, SkPaint* paint)
224            : DrawOp(paint), mLocalBounds(localBounds) {}
225
226    // Calculates bounds as smallest rect encompassing all points
227    // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
228    // subclass' constructor)
229    DrawBoundedOp(const float* points, int count, SkPaint* paint)
230            : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
231        for (int i = 2; i < count; i += 2) {
232            mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
233            mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
234            mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
235            mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
236        }
237    }
238
239    // default empty constructor for bounds, to be overridden in child constructor body
240    DrawBoundedOp(SkPaint* paint)
241            : DrawOp(paint) {}
242
243    bool getLocalBounds(Rect& localBounds) {
244        localBounds.set(mLocalBounds);
245        return true;
246    }
247
248    bool mergeAllowed() {
249        if (!state.mMatrix.isPureTranslate()) return false;
250
251        // checks that we're unclipped, and srcover
252        const Rect& opBounds = state.mBounds;
253        return fabs(opBounds.getWidth() - mLocalBounds.getWidth()) < 0.1 &&
254                fabs(opBounds.getHeight() - mLocalBounds.getHeight()) < 0.1 &&
255                (OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode);
256    }
257
258protected:
259    Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint
260};
261
262///////////////////////////////////////////////////////////////////////////////
263// STATE OPERATIONS - these may affect the state of the canvas/renderer, but do
264//         not directly draw or alter output
265///////////////////////////////////////////////////////////////////////////////
266
267class SaveOp : public StateOp {
268    friend class DisplayList; // give DisplayList private constructor/reinit access
269public:
270    SaveOp(int flags)
271            : mFlags(flags) {}
272
273    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
274            bool useQuickReject) {
275        int newSaveCount = deferStruct.mRenderer.save(mFlags);
276        deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount);
277    }
278
279    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
280        renderer.save(mFlags);
281    }
282
283    virtual void output(int level, uint32_t logFlags) {
284        OP_LOG("Save flags %x", mFlags);
285    }
286
287    virtual const char* name() { return "Save"; }
288
289    int getFlags() const { return mFlags; }
290private:
291    SaveOp() {}
292    DisplayListOp* reinit(int flags) {
293        mFlags = flags;
294        return this;
295    }
296
297    int mFlags;
298};
299
300class RestoreToCountOp : public StateOp {
301    friend class DisplayList; // give DisplayList private constructor/reinit access
302public:
303    RestoreToCountOp(int count)
304            : mCount(count) {}
305
306    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
307            bool useQuickReject) {
308        deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer,
309                this, saveCount + mCount);
310        deferStruct.mRenderer.restoreToCount(saveCount + mCount);
311    }
312
313    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
314        renderer.restoreToCount(saveCount + mCount);
315    }
316
317    virtual void output(int level, uint32_t logFlags) {
318        OP_LOG("Restore to count %d", mCount);
319    }
320
321    virtual const char* name() { return "RestoreToCount"; }
322
323private:
324    RestoreToCountOp() {}
325    DisplayListOp* reinit(int count) {
326        mCount = count;
327        return this;
328    }
329
330    int mCount;
331};
332
333class SaveLayerOp : public StateOp {
334    friend class DisplayList; // give DisplayList private constructor/reinit access
335public:
336    SaveLayerOp(float left, float top, float right, float bottom,
337            int alpha, SkXfermode::Mode mode, int flags)
338            : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {}
339
340    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
341            bool useQuickReject) {
342        // NOTE: don't bother with actual saveLayer, instead issuing it at flush time
343        int newSaveCount = deferStruct.mRenderer.getSaveCount();
344        deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount);
345
346        // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just
347        // setup the snapshot for deferral, and re-issue the op at flush time
348        deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom,
349                mAlpha, mMode, mFlags);
350    }
351
352    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
353        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags);
354    }
355
356    virtual void output(int level, uint32_t logFlags) {
357        OP_LOG("SaveLayer%s of area " RECT_STRING,
358                (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea));
359    }
360
361    virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; }
362
363    int getFlags() { return mFlags; }
364
365private:
366    // Special case, reserved for direct DisplayList usage
367    SaveLayerOp() {}
368    DisplayListOp* reinit(float left, float top, float right, float bottom,
369            int alpha, SkXfermode::Mode mode, int flags) {
370        mArea.set(left, top, right, bottom);
371        mAlpha = alpha;
372        mMode = mode;
373        mFlags = flags;
374        return this;
375    }
376
377    bool isSaveLayerAlpha() { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; }
378    Rect mArea;
379    int mAlpha;
380    SkXfermode::Mode mMode;
381    int mFlags;
382};
383
384class TranslateOp : public StateOp {
385public:
386    TranslateOp(float dx, float dy)
387            : mDx(dx), mDy(dy) {}
388
389    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
390        renderer.translate(mDx, mDy);
391    }
392
393    virtual void output(int level, uint32_t logFlags) {
394        OP_LOG("Translate by %f %f", mDx, mDy);
395    }
396
397    virtual const char* name() { return "Translate"; }
398
399private:
400    float mDx;
401    float mDy;
402};
403
404class RotateOp : public StateOp {
405public:
406    RotateOp(float degrees)
407            : mDegrees(degrees) {}
408
409    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
410        renderer.rotate(mDegrees);
411    }
412
413    virtual void output(int level, uint32_t logFlags) {
414        OP_LOG("Rotate by %f degrees", mDegrees);
415    }
416
417    virtual const char* name() { return "Rotate"; }
418
419private:
420    float mDegrees;
421};
422
423class ScaleOp : public StateOp {
424public:
425    ScaleOp(float sx, float sy)
426            : mSx(sx), mSy(sy) {}
427
428    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
429        renderer.scale(mSx, mSy);
430    }
431
432    virtual void output(int level, uint32_t logFlags) {
433        OP_LOG("Scale by %f %f", mSx, mSy);
434    }
435
436    virtual const char* name() { return "Scale"; }
437
438private:
439    float mSx;
440    float mSy;
441};
442
443class SkewOp : public StateOp {
444public:
445    SkewOp(float sx, float sy)
446            : mSx(sx), mSy(sy) {}
447
448    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
449        renderer.skew(mSx, mSy);
450    }
451
452    virtual void output(int level, uint32_t logFlags) {
453        OP_LOG("Skew by %f %f", mSx, mSy);
454    }
455
456    virtual const char* name() { return "Skew"; }
457
458private:
459    float mSx;
460    float mSy;
461};
462
463class SetMatrixOp : public StateOp {
464public:
465    SetMatrixOp(SkMatrix* matrix)
466            : mMatrix(matrix) {}
467
468    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
469        renderer.setMatrix(mMatrix);
470    }
471
472    virtual void output(int level, uint32_t logFlags) {
473        OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
474    }
475
476    virtual const char* name() { return "SetMatrix"; }
477
478private:
479    SkMatrix* mMatrix;
480};
481
482class ConcatMatrixOp : public StateOp {
483public:
484    ConcatMatrixOp(SkMatrix* matrix)
485            : mMatrix(matrix) {}
486
487    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
488        renderer.concatMatrix(mMatrix);
489    }
490
491    virtual void output(int level, uint32_t logFlags) {
492        OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix));
493    }
494
495    virtual const char* name() { return "ConcatMatrix"; }
496
497private:
498    SkMatrix* mMatrix;
499};
500
501class ClipOp : public StateOp {
502public:
503    ClipOp(SkRegion::Op op) : mOp(op) {}
504
505    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
506            bool useQuickReject) {
507        // NOTE: must defer op BEFORE applying state, since it may read clip
508        deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this);
509
510        // TODO: Can we avoid applying complex clips at defer time?
511        applyState(deferStruct.mRenderer, saveCount);
512    }
513
514    bool canCauseComplexClip() {
515        return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect();
516    }
517
518protected:
519    ClipOp() {}
520    virtual bool isRect() { return false; }
521
522    SkRegion::Op mOp;
523};
524
525class ClipRectOp : public ClipOp {
526    friend class DisplayList; // give DisplayList private constructor/reinit access
527public:
528    ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op)
529            : ClipOp(op), mArea(left, top, right, bottom) {}
530
531    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
532        renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp);
533    }
534
535    virtual void output(int level, uint32_t logFlags) {
536        OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea));
537    }
538
539    virtual const char* name() { return "ClipRect"; }
540
541protected:
542    virtual bool isRect() { return true; }
543
544private:
545    ClipRectOp() {}
546    DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
547        mOp = op;
548        mArea.set(left, top, right, bottom);
549        return this;
550    }
551
552    Rect mArea;
553};
554
555class ClipPathOp : public ClipOp {
556public:
557    ClipPathOp(SkPath* path, SkRegion::Op op)
558            : ClipOp(op), mPath(path) {}
559
560    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
561        renderer.clipPath(mPath, mOp);
562    }
563
564    virtual void output(int level, uint32_t logFlags) {
565        SkRect bounds = mPath->getBounds();
566        OP_LOG("ClipPath bounds " RECT_STRING,
567                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
568    }
569
570    virtual const char* name() { return "ClipPath"; }
571
572private:
573    SkPath* mPath;
574};
575
576class ClipRegionOp : public ClipOp {
577public:
578    ClipRegionOp(SkRegion* region, SkRegion::Op op)
579            : ClipOp(op), mRegion(region) {}
580
581    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
582        renderer.clipRegion(mRegion, mOp);
583    }
584
585    virtual void output(int level, uint32_t logFlags) {
586        SkIRect bounds = mRegion->getBounds();
587        OP_LOG("ClipRegion bounds %d %d %d %d",
588                bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
589    }
590
591    virtual const char* name() { return "ClipRegion"; }
592
593private:
594    SkRegion* mRegion;
595    SkRegion::Op mOp;
596};
597
598class ResetShaderOp : public StateOp {
599public:
600    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
601        renderer.resetShader();
602    }
603
604    virtual void output(int level, uint32_t logFlags) {
605        OP_LOGS("ResetShader");
606    }
607
608    virtual const char* name() { return "ResetShader"; }
609};
610
611class SetupShaderOp : public StateOp {
612public:
613    SetupShaderOp(SkiaShader* shader)
614            : mShader(shader) {}
615    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
616        renderer.setupShader(mShader);
617    }
618
619    virtual void output(int level, uint32_t logFlags) {
620        OP_LOG("SetupShader, shader %p", mShader);
621    }
622
623    virtual const char* name() { return "SetupShader"; }
624
625private:
626    SkiaShader* mShader;
627};
628
629class ResetColorFilterOp : public StateOp {
630public:
631    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
632        renderer.resetColorFilter();
633    }
634
635    virtual void output(int level, uint32_t logFlags) {
636        OP_LOGS("ResetColorFilter");
637    }
638
639    virtual const char* name() { return "ResetColorFilter"; }
640};
641
642class SetupColorFilterOp : public StateOp {
643public:
644    SetupColorFilterOp(SkiaColorFilter* colorFilter)
645            : mColorFilter(colorFilter) {}
646
647    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
648        renderer.setupColorFilter(mColorFilter);
649    }
650
651    virtual void output(int level, uint32_t logFlags) {
652        OP_LOG("SetupColorFilter, filter %p", mColorFilter);
653    }
654
655    virtual const char* name() { return "SetupColorFilter"; }
656
657private:
658    SkiaColorFilter* mColorFilter;
659};
660
661class ResetShadowOp : public StateOp {
662public:
663    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
664        renderer.resetShadow();
665    }
666
667    virtual void output(int level, uint32_t logFlags) {
668        OP_LOGS("ResetShadow");
669    }
670
671    virtual const char* name() { return "ResetShadow"; }
672};
673
674class SetupShadowOp : public StateOp {
675public:
676    SetupShadowOp(float radius, float dx, float dy, int color)
677            : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {}
678
679    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
680        renderer.setupShadow(mRadius, mDx, mDy, mColor);
681    }
682
683    virtual void output(int level, uint32_t logFlags) {
684        OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor);
685    }
686
687    virtual const char* name() { return "SetupShadow"; }
688
689private:
690    float mRadius;
691    float mDx;
692    float mDy;
693    int mColor;
694};
695
696class ResetPaintFilterOp : public StateOp {
697public:
698    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
699        renderer.resetPaintFilter();
700    }
701
702    virtual void output(int level, uint32_t logFlags) {
703        OP_LOGS("ResetPaintFilter");
704    }
705
706    virtual const char* name() { return "ResetPaintFilter"; }
707};
708
709class SetupPaintFilterOp : public StateOp {
710public:
711    SetupPaintFilterOp(int clearBits, int setBits)
712            : mClearBits(clearBits), mSetBits(setBits) {}
713
714    virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
715        renderer.setupPaintFilter(mClearBits, mSetBits);
716    }
717
718    virtual void output(int level, uint32_t logFlags) {
719        OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits);
720    }
721
722    virtual const char* name() { return "SetupPaintFilter"; }
723
724private:
725    int mClearBits;
726    int mSetBits;
727};
728
729///////////////////////////////////////////////////////////////////////////////
730// DRAW OPERATIONS - these are operations that can draw to the canvas's device
731///////////////////////////////////////////////////////////////////////////////
732
733class DrawBitmapOp : public DrawBoundedOp {
734public:
735    DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
736            : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
737            mBitmap(bitmap), mAtlasEntry(NULL) {
738    }
739
740    DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint,
741            const AssetAtlas::Entry* entry)
742            : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint),
743            mBitmap(bitmap), mAtlasEntry(entry) {
744        if (entry) mUvMapper = entry->uvMapper;
745    }
746
747    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
748        return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
749                getPaint(renderer));
750    }
751
752#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
753    TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
754            texCoordsRect.xDim, texCoordsRect.yDim)
755
756    virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
757            const Vector<DrawOp*>& ops, const Rect& bounds) {
758        renderer.restoreDisplayState(state, true); // restore all but the clip
759        renderer.setFullScreenClip(); // ensure merged ops aren't clipped
760        TextureVertex vertices[6 * ops.size()];
761        TextureVertex* vertex = &vertices[0];
762
763        bool transformed = false;
764
765        // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op,
766        // and allowing them to be merged in getBatchId()
767        for (unsigned int i = 0; i < ops.size(); i++) {
768            const Rect& opBounds = ops[i]->state.mBounds;
769            // When we reach multiDraw(), the matrix can be either
770            // pureTranslate or simple (translate and/or scale).
771            // If the matrix is not pureTranslate, then we have a scale
772            if (!ops[i]->state.mMatrix.isPureTranslate()) transformed = true;
773
774            Rect texCoords(0, 0, 1, 1);
775            ((DrawBitmapOp*) ops[i])->mUvMapper.map(texCoords);
776
777            SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
778            SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
779            SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
780
781            SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
782            SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
783            SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
784        }
785
786        return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0],
787                transformed, bounds, mPaint);
788    }
789
790    virtual void output(int level, uint32_t logFlags) {
791        OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
792    }
793
794    virtual const char* name() { return "DrawBitmap"; }
795
796    bool bitmapMergeAllowed() {
797        return state.mMatrix.isSimple() && !state.mClipped &&
798                OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode;
799    }
800
801    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
802        *batchId = DeferredDisplayList::kOpBatch_Bitmap;
803        *mergeId = mAtlasEntry ? (mergeid_t) &mAtlasEntry->atlas : (mergeid_t) mBitmap;
804
805        // don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
806        // MergingDrawBatch::canMergeWith
807        return bitmapMergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config);
808    }
809
810    const SkBitmap* bitmap() { return mBitmap; }
811protected:
812    SkBitmap* mBitmap;
813    const AssetAtlas::Entry* mAtlasEntry;
814    UvMapper mUvMapper;
815};
816
817class DrawBitmapMatrixOp : public DrawBoundedOp {
818public:
819    DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
820            : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
821        mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
822        const mat4 transform(*matrix);
823        transform.mapRect(mLocalBounds);
824    }
825
826    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
827        return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
828    }
829
830    virtual void output(int level, uint32_t logFlags) {
831        OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
832    }
833
834    virtual const char* name() { return "DrawBitmapMatrix"; }
835
836    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
837        *batchId = DeferredDisplayList::kOpBatch_Bitmap;
838        return false;
839    }
840
841private:
842    SkBitmap* mBitmap;
843    SkMatrix* mMatrix;
844};
845
846class DrawBitmapRectOp : public DrawBoundedOp {
847public:
848    DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
849            float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
850            : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
851            mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
852
853    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
854        return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
855                mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
856                getPaint(renderer));
857    }
858
859    virtual void output(int level, uint32_t logFlags) {
860        OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
861                mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
862    }
863
864    virtual const char* name() { return "DrawBitmapRect"; }
865
866    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
867        *batchId = DeferredDisplayList::kOpBatch_Bitmap;
868        return false;
869    }
870
871private:
872    SkBitmap* mBitmap;
873    Rect mSrc;
874};
875
876class DrawBitmapDataOp : public DrawBitmapOp {
877public:
878    DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
879            : DrawBitmapOp(bitmap, left, top, paint) {}
880
881    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
882        return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
883                mLocalBounds.top, getPaint(renderer));
884    }
885
886    virtual void output(int level, uint32_t logFlags) {
887        OP_LOG("Draw bitmap %p", mBitmap);
888    }
889
890    virtual const char* name() { return "DrawBitmapData"; }
891
892    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
893        *batchId = DeferredDisplayList::kOpBatch_Bitmap;
894        return false;
895    }
896};
897
898class DrawBitmapMeshOp : public DrawBoundedOp {
899public:
900    DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
901            float* vertices, int* colors, SkPaint* paint)
902            : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
903            mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
904            mVertices(vertices), mColors(colors) {}
905
906    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
907        return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
908                mVertices, mColors, getPaint(renderer));
909    }
910
911    virtual void output(int level, uint32_t logFlags) {
912        OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
913    }
914
915    virtual const char* name() { return "DrawBitmapMesh"; }
916
917    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
918        *batchId = DeferredDisplayList::kOpBatch_Bitmap;
919        return false;
920    }
921
922private:
923    SkBitmap* mBitmap;
924    int mMeshWidth;
925    int mMeshHeight;
926    float* mVertices;
927    int* mColors;
928};
929
930class DrawPatchOp : public DrawBoundedOp {
931public:
932    DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch,
933            float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode)
934            : DrawBoundedOp(left, top, right, bottom, 0),
935            mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode),
936            mGenerationId(0), mMesh(NULL) {
937        mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap);
938    };
939
940    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
941        if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) {
942            PatchCache& cache = renderer.getCaches().patchCache;
943            mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(),
944                    mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top,
945                    mPatch);
946            mGenerationId = cache.getGenerationId();
947        }
948        // We're not calling the public variant of drawPatch() here
949        // This method won't perform the quickReject() since we've already done it at this point
950        return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top,
951                mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
952    }
953
954    virtual void output(int level, uint32_t logFlags) {
955        OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
956    }
957
958    virtual const char* name() { return "DrawPatch"; }
959
960    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
961        *batchId = DeferredDisplayList::kOpBatch_Patch;
962        *mergeId = (mergeid_t) mBitmap;
963        return true;
964    }
965
966private:
967    SkBitmap* mBitmap;
968    Res_png_9patch* mPatch;
969
970    int mAlpha;
971    SkXfermode::Mode mMode;
972
973    uint32_t mGenerationId;
974    const Patch* mMesh;
975    AssetAtlas::Entry* mEntry;
976};
977
978class DrawColorOp : public DrawOp {
979public:
980    DrawColorOp(int color, SkXfermode::Mode mode)
981            : DrawOp(0), mColor(color), mMode(mode) {};
982
983    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
984        return renderer.drawColor(mColor, mMode);
985    }
986
987    virtual void output(int level, uint32_t logFlags) {
988        OP_LOG("Draw color %#x, mode %d", mColor, mMode);
989    }
990
991    virtual const char* name() { return "DrawColor"; }
992
993private:
994    int mColor;
995    SkXfermode::Mode mMode;
996};
997
998class DrawStrokableOp : public DrawBoundedOp {
999public:
1000    DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
1001            : DrawBoundedOp(left, top, right, bottom, paint) {};
1002
1003    bool getLocalBounds(Rect& localBounds) {
1004        localBounds.set(mLocalBounds);
1005        if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
1006            localBounds.outset(strokeWidthOutset());
1007        }
1008        return true;
1009    }
1010
1011    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
1012        if (mPaint->getPathEffect()) {
1013            *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1014        } else {
1015            *batchId = mPaint->isAntiAlias() ?
1016                    DeferredDisplayList::kOpBatch_AlphaVertices :
1017                    DeferredDisplayList::kOpBatch_Vertices;
1018        }
1019        return false;
1020    }
1021};
1022
1023class DrawRectOp : public DrawStrokableOp {
1024public:
1025    DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
1026            : DrawStrokableOp(left, top, right, bottom, paint) {}
1027
1028    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1029        return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
1030                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1031    }
1032
1033    virtual void output(int level, uint32_t logFlags) {
1034        OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
1035    }
1036
1037    virtual const char* name() { return "DrawRect"; }
1038};
1039
1040class DrawRectsOp : public DrawBoundedOp {
1041public:
1042    DrawRectsOp(const float* rects, int count, SkPaint* paint)
1043            : DrawBoundedOp(rects, count, paint),
1044            mRects(rects), mCount(count) {}
1045
1046    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1047        return renderer.drawRects(mRects, mCount, getPaint(renderer));
1048    }
1049
1050    virtual void output(int level, uint32_t logFlags) {
1051        OP_LOG("Draw Rects count %d", mCount);
1052    }
1053
1054    virtual const char* name() { return "DrawRects"; }
1055
1056    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
1057        *batchId = DeferredDisplayList::kOpBatch_Vertices;
1058        return false;
1059    }
1060
1061private:
1062    const float* mRects;
1063    int mCount;
1064};
1065
1066class DrawRoundRectOp : public DrawStrokableOp {
1067public:
1068    DrawRoundRectOp(float left, float top, float right, float bottom,
1069            float rx, float ry, SkPaint* paint)
1070            : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
1071
1072    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1073        return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
1074                mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
1075    }
1076
1077    virtual void output(int level, uint32_t logFlags) {
1078        OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
1079    }
1080
1081    virtual const char* name() { return "DrawRoundRect"; }
1082
1083private:
1084    float mRx;
1085    float mRy;
1086};
1087
1088class DrawCircleOp : public DrawStrokableOp {
1089public:
1090    DrawCircleOp(float x, float y, float radius, SkPaint* paint)
1091            : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
1092            mX(x), mY(y), mRadius(radius) {}
1093
1094    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1095        return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
1096    }
1097
1098    virtual void output(int level, uint32_t logFlags) {
1099        OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
1100    }
1101
1102    virtual const char* name() { return "DrawCircle"; }
1103
1104private:
1105    float mX;
1106    float mY;
1107    float mRadius;
1108};
1109
1110class DrawOvalOp : public DrawStrokableOp {
1111public:
1112    DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
1113            : DrawStrokableOp(left, top, right, bottom, paint) {}
1114
1115    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1116        return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
1117                mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
1118    }
1119
1120    virtual void output(int level, uint32_t logFlags) {
1121        OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
1122    }
1123
1124    virtual const char* name() { return "DrawOval"; }
1125};
1126
1127class DrawArcOp : public DrawStrokableOp {
1128public:
1129    DrawArcOp(float left, float top, float right, float bottom,
1130            float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
1131            : DrawStrokableOp(left, top, right, bottom, paint),
1132            mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
1133
1134    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1135        return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
1136                mLocalBounds.right, mLocalBounds.bottom,
1137                mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
1138    }
1139
1140    virtual void output(int level, uint32_t logFlags) {
1141        OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
1142                RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
1143    }
1144
1145    virtual const char* name() { return "DrawArc"; }
1146
1147private:
1148    float mStartAngle;
1149    float mSweepAngle;
1150    bool mUseCenter;
1151};
1152
1153class DrawPathOp : public DrawBoundedOp {
1154public:
1155    DrawPathOp(SkPath* path, SkPaint* paint)
1156            : DrawBoundedOp(paint), mPath(path) {
1157        float left, top, offset;
1158        uint32_t width, height;
1159        PathCache::computePathBounds(path, paint, left, top, offset, width, height);
1160        left -= offset;
1161        top -= offset;
1162        mLocalBounds.set(left, top, left + width, top + height);
1163    }
1164
1165    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1166        return renderer.drawPath(mPath, getPaint(renderer));
1167    }
1168
1169    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
1170        SkPaint* paint = getPaint(renderer);
1171        renderer.getCaches().pathCache.precache(mPath, paint);
1172
1173        *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
1174        return false;
1175    }
1176
1177    virtual void output(int level, uint32_t logFlags) {
1178        OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
1179    }
1180
1181    virtual const char* name() { return "DrawPath"; }
1182
1183private:
1184    SkPath* mPath;
1185};
1186
1187class DrawLinesOp : public DrawBoundedOp {
1188public:
1189    DrawLinesOp(float* points, int count, SkPaint* paint)
1190            : DrawBoundedOp(points, count, paint),
1191            mPoints(points), mCount(count) {
1192        mLocalBounds.outset(strokeWidthOutset());
1193    }
1194
1195    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1196        return renderer.drawLines(mPoints, mCount, getPaint(renderer));
1197    }
1198
1199    virtual void output(int level, uint32_t logFlags) {
1200        OP_LOG("Draw Lines count %d", mCount);
1201    }
1202
1203    virtual const char* name() { return "DrawLines"; }
1204
1205    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
1206        *batchId = mPaint->isAntiAlias() ?
1207                DeferredDisplayList::kOpBatch_AlphaVertices :
1208                DeferredDisplayList::kOpBatch_Vertices;
1209        return false;
1210    }
1211
1212protected:
1213    float* mPoints;
1214    int mCount;
1215};
1216
1217class DrawPointsOp : public DrawLinesOp {
1218public:
1219    DrawPointsOp(float* points, int count, SkPaint* paint)
1220            : DrawLinesOp(points, count, paint) {}
1221
1222    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1223        return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
1224    }
1225
1226    virtual void output(int level, uint32_t logFlags) {
1227        OP_LOG("Draw Points count %d", mCount);
1228    }
1229
1230    virtual const char* name() { return "DrawPoints"; }
1231};
1232
1233class DrawSomeTextOp : public DrawOp {
1234public:
1235    DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
1236            : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
1237
1238    virtual void output(int level, uint32_t logFlags) {
1239        OP_LOG("Draw some text, %d bytes", mBytesCount);
1240    }
1241
1242    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
1243        SkPaint* paint = getPaint(renderer);
1244        FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1245        fontRenderer.precache(paint, mText, mCount, mat4::identity());
1246
1247        *batchId = mPaint->getColor() == 0xff000000 ?
1248                DeferredDisplayList::kOpBatch_Text :
1249                DeferredDisplayList::kOpBatch_ColorText;
1250
1251        return false;
1252    }
1253
1254protected:
1255    const char* mText;
1256    int mBytesCount;
1257    int mCount;
1258};
1259
1260class DrawTextOnPathOp : public DrawSomeTextOp {
1261public:
1262    DrawTextOnPathOp(const char* text, int bytesCount, int count,
1263            SkPath* path, float hOffset, float vOffset, SkPaint* paint)
1264            : DrawSomeTextOp(text, bytesCount, count, paint),
1265            mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
1266        /* TODO: inherit from DrawBounded and init mLocalBounds */
1267    }
1268
1269    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1270        return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
1271                mHOffset, mVOffset, getPaint(renderer));
1272    }
1273
1274    virtual const char* name() { return "DrawTextOnPath"; }
1275
1276private:
1277    SkPath* mPath;
1278    float mHOffset;
1279    float mVOffset;
1280};
1281
1282class DrawPosTextOp : public DrawSomeTextOp {
1283public:
1284    DrawPosTextOp(const char* text, int bytesCount, int count,
1285            const float* positions, SkPaint* paint)
1286            : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
1287        /* TODO: inherit from DrawBounded and init mLocalBounds */
1288    }
1289
1290    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1291        return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
1292    }
1293
1294    virtual const char* name() { return "DrawPosText"; }
1295
1296private:
1297    const float* mPositions;
1298};
1299
1300class DrawTextOp : public DrawBoundedOp {
1301public:
1302    DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
1303            const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds)
1304            : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count),
1305            mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) {
1306        mLocalBounds.translate(x,y);
1307        memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
1308    }
1309
1310    virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
1311        SkPaint* paint = getPaint(renderer);
1312        FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
1313        const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
1314        if (mPrecacheTransform != transform) {
1315            fontRenderer.precache(paint, mText, mCount, transform);
1316            mPrecacheTransform = transform;
1317        }
1318        *batchId = mPaint->getColor() == 0xff000000 ?
1319                DeferredDisplayList::kOpBatch_Text :
1320                DeferredDisplayList::kOpBatch_ColorText;
1321
1322        *mergeId = (mergeid_t)mPaint->getColor();
1323
1324        // don't merge decorated text - the decorations won't draw in order
1325        bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
1326                        SkPaint::kStrikeThruText_Flag));
1327        return mergeAllowed() && noDecorations;
1328    }
1329
1330    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1331        return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
1332                mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds);
1333    }
1334
1335    virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
1336            const Vector<DrawOp*>& ops, const Rect& bounds) {
1337        status_t status = DrawGlInfo::kStatusDone;
1338        renderer.setFullScreenClip(); // ensure merged ops aren't clipped
1339        for (unsigned int i = 0; i < ops.size(); i++) {
1340            DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
1341            renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip
1342
1343            DrawTextOp& op = *((DrawTextOp*)ops[i]);
1344            status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
1345                    op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
1346                    drawOpMode);
1347        }
1348        return status;
1349    }
1350
1351    virtual void output(int level, uint32_t logFlags) {
1352        OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
1353    }
1354
1355    virtual const char* name() { return "DrawText"; }
1356
1357private:
1358    const char* mText;
1359    int mBytesCount;
1360    int mCount;
1361    float mX;
1362    float mY;
1363    const float* mPositions;
1364    float mTotalAdvance;
1365    mat4 mPrecacheTransform;
1366};
1367
1368///////////////////////////////////////////////////////////////////////////////
1369// SPECIAL DRAW OPERATIONS
1370///////////////////////////////////////////////////////////////////////////////
1371
1372class DrawFunctorOp : public DrawOp {
1373public:
1374    DrawFunctorOp(Functor* functor)
1375            : DrawOp(0), mFunctor(functor) {}
1376
1377    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1378        renderer.startMark("GL functor");
1379        status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
1380        renderer.endMark();
1381        return ret;
1382    }
1383
1384    virtual void output(int level, uint32_t logFlags) {
1385        OP_LOG("Draw Functor %p", mFunctor);
1386    }
1387
1388    virtual const char* name() { return "DrawFunctor"; }
1389
1390private:
1391    Functor* mFunctor;
1392};
1393
1394class DrawDisplayListOp : public DrawBoundedOp {
1395public:
1396    DrawDisplayListOp(DisplayList* displayList, int flags)
1397            : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
1398            mDisplayList(displayList), mFlags(flags) {}
1399
1400    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
1401            bool useQuickReject) {
1402        if (mDisplayList && mDisplayList->isRenderable()) {
1403            mDisplayList->defer(deferStruct, level + 1);
1404        }
1405    }
1406    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
1407            bool useQuickReject) {
1408        if (mDisplayList && mDisplayList->isRenderable()) {
1409            mDisplayList->replay(replayStruct, level + 1);
1410        }
1411    }
1412
1413    // NOT USED since replay() is overridden
1414    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1415        return DrawGlInfo::kStatusDone;
1416    }
1417
1418    virtual void output(int level, uint32_t logFlags) {
1419        OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
1420        if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
1421            mDisplayList->output(level + 1);
1422        }
1423    }
1424
1425    virtual const char* name() { return "DrawDisplayList"; }
1426
1427private:
1428    DisplayList* mDisplayList;
1429    int mFlags;
1430};
1431
1432class DrawLayerOp : public DrawOp {
1433public:
1434    DrawLayerOp(Layer* layer, float x, float y)
1435            : DrawOp(0), mLayer(layer), mX(x), mY(y) {}
1436
1437    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
1438        return renderer.drawLayer(mLayer, mX, mY);
1439    }
1440
1441    virtual void output(int level, uint32_t logFlags) {
1442        OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
1443    }
1444
1445    virtual const char* name() { return "DrawLayer"; }
1446
1447private:
1448    Layer* mLayer;
1449    float mX;
1450    float mY;
1451};
1452
1453}; // namespace uirenderer
1454}; // namespace android
1455
1456#endif // ANDROID_HWUI_DISPLAY_OPERATION_H
1457