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