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