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