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