Home | History | Annotate | Download | only in hwui
      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 
     51 namespace android {
     52 namespace 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  */
     65 class DisplayListOp {
     66 public:
     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,
     82             bool useQuickReject) = 0;
     83 
     84     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
     85             bool useQuickReject) = 0;
     86 
     87     virtual void output(int level, uint32_t logFlags = 0) = 0;
     88 
     89     // NOTE: it would be nice to declare constants and overriding the implementation in each op to
     90     // point at the constants, but that seems to require a .cpp file
     91     virtual const char* name() = 0;
     92 
     93     /**
     94      * Stores the relevant canvas state of the object between deferral and replay (if the canvas
     95      * state supports being stored) See OpenGLRenderer::simpleClipAndState()
     96      *
     97      * TODO: don't reserve space for StateOps that won't be deferred
     98      */
     99     DeferredDisplayState state;
    100 
    101 };
    102 
    103 class StateOp : public DisplayListOp {
    104 public:
    105     StateOp() {};
    106 
    107     virtual ~StateOp() {}
    108 
    109     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
    110             bool useQuickReject) {
    111         // default behavior only affects immediate, deferrable state, issue directly to renderer
    112         applyState(deferStruct.mRenderer, saveCount);
    113     }
    114 
    115     /**
    116      * State operations are applied directly to the renderer, but can cause the deferred drawing op
    117      * list to flush
    118      */
    119     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
    120             bool useQuickReject) {
    121         applyState(replayStruct.mRenderer, saveCount);
    122     }
    123 
    124     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0;
    125 };
    126 
    127 class DrawOp : public DisplayListOp {
    128 friend class MergingDrawBatch;
    129 public:
    130     DrawOp(SkPaint* paint)
    131             : mPaint(paint), mQuickRejected(false) {}
    132 
    133     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
    134             bool useQuickReject) {
    135         if (mQuickRejected && CC_LIKELY(useQuickReject)) {
    136             return;
    137         }
    138 
    139         if (!getLocalBounds(state.mBounds)) {
    140             // empty bounds signify bounds can't be calculated
    141             state.mBounds.setEmpty();
    142         }
    143 
    144         deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this);
    145     }
    146 
    147     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
    148             bool useQuickReject) {
    149         if (mQuickRejected && CC_LIKELY(useQuickReject)) {
    150             return;
    151         }
    152 
    153         replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty);
    154     }
    155 
    156     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0;
    157 
    158     /**
    159      * Draw multiple instances of an operation, must be overidden for operations that merge
    160      *
    161      * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith),
    162      * and pure translation transformations. Other guarantees of similarity should be enforced by
    163      * reducing which operations are tagged as mergeable.
    164      */
    165     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
    166             const Vector<DrawOp*>& ops, const Rect& bounds) {
    167         status_t status = DrawGlInfo::kStatusDone;
    168         for (unsigned int i = 0; i < ops.size(); i++) {
    169             renderer.restoreDisplayState(ops[i]->state);
    170             status |= ops[i]->applyDraw(renderer, dirty);
    171         }
    172         return status;
    173     }
    174 
    175     /*
    176      * When this method is invoked the state field is initialized to have the
    177      * final rendering state. We can thus use it to process data as it will be
    178      * used at draw time.
    179      *
    180      * Additionally, this method allows subclasses to provide defer-time preferences for batching
    181      * and merging.
    182      *
    183      * Return true if the op can merge with others of its kind (such subclasses should implement
    184      * multiDraw)
    185      */
    186     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    187         return false;
    188     }
    189 
    190     // returns true if bounds exist
    191     virtual bool getLocalBounds(Rect& localBounds) { return false; }
    192 
    193     // TODO: better refine localbounds usage
    194     void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
    195     bool getQuickRejected() { return mQuickRejected; }
    196 
    197     inline int getPaintAlpha() {
    198         return OpenGLRenderer::getAlphaDirect(mPaint);
    199     }
    200 
    201     inline float strokeWidthOutset() {
    202         float width = mPaint->getStrokeWidth();
    203         if (width == 0) return 0.5f; // account for hairline
    204         return width * 0.5f;
    205     }
    206 
    207 protected:
    208     SkPaint* getPaint(OpenGLRenderer& renderer) {
    209         return renderer.filterPaint(mPaint);
    210     }
    211 
    212     SkPaint* mPaint; // should be accessed via getPaint() when applying
    213     bool mQuickRejected;
    214 };
    215 
    216 class DrawBoundedOp : public DrawOp {
    217 public:
    218     DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint)
    219             : DrawOp(paint), mLocalBounds(left, top, right, bottom) {}
    220 
    221     // Calculates bounds as smallest rect encompassing all points
    222     // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in
    223     // subclass' constructor)
    224     DrawBoundedOp(const float* points, int count, SkPaint* paint)
    225             : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) {
    226         for (int i = 2; i < count; i += 2) {
    227             mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
    228             mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
    229             mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]);
    230             mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]);
    231         }
    232     }
    233 
    234     // default empty constructor for bounds, to be overridden in child constructor body
    235     DrawBoundedOp(SkPaint* paint)
    236             : DrawOp(paint) {}
    237 
    238     bool getLocalBounds(Rect& localBounds) {
    239         localBounds.set(mLocalBounds);
    240         return true;
    241     }
    242 
    243     bool mergeAllowed() {
    244         if (!state.mMatrix.isPureTranslate()) return false;
    245 
    246         // checks that we're unclipped, and srcover
    247         const Rect& opBounds = state.mBounds;
    248         return fabs(opBounds.getWidth() - mLocalBounds.getWidth()) < 0.1 &&
    249                 fabs(opBounds.getHeight() - mLocalBounds.getHeight()) < 0.1 &&
    250                 (OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode);
    251     }
    252 
    253 protected:
    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 
    262 class SaveOp : public StateOp {
    263     friend class DisplayList; // give DisplayList private constructor/reinit access
    264 public:
    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; }
    285 private:
    286     SaveOp() {}
    287     DisplayListOp* reinit(int flags) {
    288         mFlags = flags;
    289         return this;
    290     }
    291 
    292     int mFlags;
    293 };
    294 
    295 class RestoreToCountOp : public StateOp {
    296     friend class DisplayList; // give DisplayList private constructor/reinit access
    297 public:
    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 
    318 private:
    319     RestoreToCountOp() {}
    320     DisplayListOp* reinit(int count) {
    321         mCount = count;
    322         return this;
    323     }
    324 
    325     int mCount;
    326 };
    327 
    328 class SaveLayerOp : public StateOp {
    329     friend class DisplayList; // give DisplayList private constructor/reinit access
    330 public:
    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 
    360 private:
    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 
    379 class TranslateOp : public StateOp {
    380 public:
    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 
    394 private:
    395     float mDx;
    396     float mDy;
    397 };
    398 
    399 class RotateOp : public StateOp {
    400 public:
    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 
    414 private:
    415     float mDegrees;
    416 };
    417 
    418 class ScaleOp : public StateOp {
    419 public:
    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 
    433 private:
    434     float mSx;
    435     float mSy;
    436 };
    437 
    438 class SkewOp : public StateOp {
    439 public:
    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 
    453 private:
    454     float mSx;
    455     float mSy;
    456 };
    457 
    458 class SetMatrixOp : public StateOp {
    459 public:
    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 
    473 private:
    474     SkMatrix* mMatrix;
    475 };
    476 
    477 class ConcatMatrixOp : public StateOp {
    478 public:
    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 
    492 private:
    493     SkMatrix* mMatrix;
    494 };
    495 
    496 class ClipOp : public StateOp {
    497 public:
    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 
    513 protected:
    514     ClipOp() {}
    515     virtual bool isRect() { return false; }
    516 
    517     SkRegion::Op mOp;
    518 };
    519 
    520 class ClipRectOp : public ClipOp {
    521     friend class DisplayList; // give DisplayList private constructor/reinit access
    522 public:
    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 
    536 protected:
    537     virtual bool isRect() { return true; }
    538 
    539 private:
    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 
    550 class ClipPathOp : public ClipOp {
    551 public:
    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 
    567 private:
    568     SkPath* mPath;
    569 };
    570 
    571 class ClipRegionOp : public ClipOp {
    572 public:
    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 
    588 private:
    589     SkRegion* mRegion;
    590     SkRegion::Op mOp;
    591 };
    592 
    593 class ResetShaderOp : public StateOp {
    594 public:
    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 
    606 class SetupShaderOp : public StateOp {
    607 public:
    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 
    620 private:
    621     SkiaShader* mShader;
    622 };
    623 
    624 class ResetColorFilterOp : public StateOp {
    625 public:
    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 
    637 class SetupColorFilterOp : public StateOp {
    638 public:
    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 
    652 private:
    653     SkiaColorFilter* mColorFilter;
    654 };
    655 
    656 class ResetShadowOp : public StateOp {
    657 public:
    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 
    669 class SetupShadowOp : public StateOp {
    670 public:
    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 
    684 private:
    685     float mRadius;
    686     float mDx;
    687     float mDy;
    688     int mColor;
    689 };
    690 
    691 class ResetPaintFilterOp : public StateOp {
    692 public:
    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 
    704 class SetupPaintFilterOp : public StateOp {
    705 public:
    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 
    719 private:
    720     int mClearBits;
    721     int mSetBits;
    722 };
    723 
    724 
    725 ///////////////////////////////////////////////////////////////////////////////
    726 // DRAW OPERATIONS - these are operations that can draw to the canvas's device
    727 ///////////////////////////////////////////////////////////////////////////////
    728 
    729 class DrawBitmapOp : public DrawBoundedOp {
    730 public:
    731     DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
    732             : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(),
    733                     paint),
    734             mBitmap(bitmap) {}
    735 
    736     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    737         return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top,
    738                 getPaint(renderer));
    739     }
    740 
    741 #define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \
    742     TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \
    743             texCoordsRect.xDim, texCoordsRect.yDim)
    744 
    745     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
    746             const Vector<DrawOp*>& ops, const Rect& bounds) {
    747         renderer.restoreDisplayState(state, true); // restore all but the clip
    748         renderer.setFullScreenClip(); // ensure merged ops aren't clipped
    749         TextureVertex vertices[6 * ops.size()];
    750         TextureVertex* vertex = &vertices[0];
    751 
    752         // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, and allowing
    753         // them to be merged in getBatchId()
    754         const Rect texCoords(0, 0, 1, 1);
    755 
    756         const float width = mBitmap->width();
    757         const float height = mBitmap->height();
    758         for (unsigned int i = 0; i < ops.size(); i++) {
    759             const Rect& opBounds = ops[i]->state.mBounds;
    760             SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top);
    761             SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
    762             SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
    763 
    764             SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom);
    765             SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top);
    766             SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom);
    767         }
    768 
    769         return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], bounds, mPaint);
    770     }
    771 
    772     virtual void output(int level, uint32_t logFlags) {
    773         OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top);
    774     }
    775 
    776     virtual const char* name() { return "DrawBitmap"; }
    777 
    778     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    779         *batchId = DeferredDisplayList::kOpBatch_Bitmap;
    780         *mergeId = (mergeid_t)mBitmap;
    781 
    782         // don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in
    783         // MergingDrawBatch::canMergeWith
    784         return mergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config);
    785     }
    786 
    787     const SkBitmap* bitmap() { return mBitmap; }
    788 protected:
    789     SkBitmap* mBitmap;
    790 };
    791 
    792 class DrawBitmapMatrixOp : public DrawBoundedOp {
    793 public:
    794     DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint)
    795             : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) {
    796         mLocalBounds.set(0, 0, bitmap->width(), bitmap->height());
    797         const mat4 transform(*matrix);
    798         transform.mapRect(mLocalBounds);
    799     }
    800 
    801     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    802         return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer));
    803     }
    804 
    805     virtual void output(int level, uint32_t logFlags) {
    806         OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix));
    807     }
    808 
    809     virtual const char* name() { return "DrawBitmapMatrix"; }
    810 
    811     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    812         *batchId = DeferredDisplayList::kOpBatch_Bitmap;
    813         return false;
    814     }
    815 
    816 private:
    817     SkBitmap* mBitmap;
    818     SkMatrix* mMatrix;
    819 };
    820 
    821 class DrawBitmapRectOp : public DrawBoundedOp {
    822 public:
    823     DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
    824             float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint)
    825             : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint),
    826             mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {}
    827 
    828     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    829         return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom,
    830                 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom,
    831                 getPaint(renderer));
    832     }
    833 
    834     virtual void output(int level, uint32_t logFlags) {
    835         OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
    836                 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
    837     }
    838 
    839     virtual const char* name() { return "DrawBitmapRect"; }
    840 
    841     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    842         *batchId = DeferredDisplayList::kOpBatch_Bitmap;
    843         return false;
    844     }
    845 
    846 private:
    847     SkBitmap* mBitmap;
    848     Rect mSrc;
    849 };
    850 
    851 class DrawBitmapDataOp : public DrawBitmapOp {
    852 public:
    853     DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint)
    854             : DrawBitmapOp(bitmap, left, top, paint) {}
    855 
    856     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    857         return renderer.drawBitmapData(mBitmap, mLocalBounds.left,
    858                 mLocalBounds.top, getPaint(renderer));
    859     }
    860 
    861     virtual void output(int level, uint32_t logFlags) {
    862         OP_LOG("Draw bitmap %p", mBitmap);
    863     }
    864 
    865     virtual const char* name() { return "DrawBitmapData"; }
    866 
    867     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    868         *batchId = DeferredDisplayList::kOpBatch_Bitmap;
    869         return false;
    870     }
    871 };
    872 
    873 class DrawBitmapMeshOp : public DrawBoundedOp {
    874 public:
    875     DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight,
    876             float* vertices, int* colors, SkPaint* paint)
    877             : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint),
    878             mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight),
    879             mVertices(vertices), mColors(colors) {}
    880 
    881     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    882         return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight,
    883                 mVertices, mColors, getPaint(renderer));
    884     }
    885 
    886     virtual void output(int level, uint32_t logFlags) {
    887         OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight);
    888     }
    889 
    890     virtual const char* name() { return "DrawBitmapMesh"; }
    891 
    892     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    893         *batchId = DeferredDisplayList::kOpBatch_Bitmap;
    894         return false;
    895     }
    896 
    897 private:
    898     SkBitmap* mBitmap;
    899     int mMeshWidth;
    900     int mMeshHeight;
    901     float* mVertices;
    902     int* mColors;
    903 };
    904 
    905 class DrawPatchOp : public DrawBoundedOp {
    906 public:
    907     DrawPatchOp(SkBitmap* bitmap, const int32_t* xDivs,
    908             const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height,
    909             int8_t numColors, float left, float top, float right, float bottom,
    910             int alpha, SkXfermode::Mode mode)
    911             : DrawBoundedOp(left, top, right, bottom, 0),
    912             mBitmap(bitmap), mxDivs(xDivs), myDivs(yDivs),
    913             mColors(colors), mxDivsCount(width), myDivsCount(height),
    914             mNumColors(numColors), mAlpha(alpha), mMode(mode) {};
    915 
    916     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    917         // NOTE: not calling the virtual method, which takes a paint
    918         return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors,
    919                 mxDivsCount, myDivsCount, mNumColors,
    920                 mLocalBounds.left, mLocalBounds.top,
    921                 mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode);
    922     }
    923 
    924     virtual void output(int level, uint32_t logFlags) {
    925         OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
    926     }
    927 
    928     virtual const char* name() { return "DrawPatch"; }
    929 
    930     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    931         *batchId = DeferredDisplayList::kOpBatch_Patch;
    932         *mergeId = (mergeid_t)mBitmap;
    933         return true;
    934     }
    935 
    936 private:
    937     SkBitmap* mBitmap;
    938     const int32_t* mxDivs;
    939     const int32_t* myDivs;
    940     const uint32_t* mColors;
    941     uint32_t mxDivsCount;
    942     uint32_t myDivsCount;
    943     int8_t mNumColors;
    944     int mAlpha;
    945     SkXfermode::Mode mMode;
    946 };
    947 
    948 class DrawColorOp : public DrawOp {
    949 public:
    950     DrawColorOp(int color, SkXfermode::Mode mode)
    951             : DrawOp(0), mColor(color), mMode(mode) {};
    952 
    953     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    954         return renderer.drawColor(mColor, mMode);
    955     }
    956 
    957     virtual void output(int level, uint32_t logFlags) {
    958         OP_LOG("Draw color %#x, mode %d", mColor, mMode);
    959     }
    960 
    961     virtual const char* name() { return "DrawColor"; }
    962 
    963 private:
    964     int mColor;
    965     SkXfermode::Mode mMode;
    966 };
    967 
    968 class DrawStrokableOp : public DrawBoundedOp {
    969 public:
    970     DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint)
    971             : DrawBoundedOp(left, top, right, bottom, paint) {};
    972 
    973     bool getLocalBounds(Rect& localBounds) {
    974         localBounds.set(mLocalBounds);
    975         if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
    976             localBounds.outset(strokeWidthOutset());
    977         }
    978         return true;
    979     }
    980 
    981     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
    982         if (mPaint->getPathEffect()) {
    983             *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
    984         } else {
    985             *batchId = mPaint->isAntiAlias() ?
    986                     DeferredDisplayList::kOpBatch_AlphaVertices :
    987                     DeferredDisplayList::kOpBatch_Vertices;
    988         }
    989         return false;
    990     }
    991 };
    992 
    993 class DrawRectOp : public DrawStrokableOp {
    994 public:
    995     DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint)
    996             : DrawStrokableOp(left, top, right, bottom, paint) {}
    997 
    998     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
    999         return renderer.drawRect(mLocalBounds.left, mLocalBounds.top,
   1000                 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
   1001     }
   1002 
   1003     virtual void output(int level, uint32_t logFlags) {
   1004         OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
   1005     }
   1006 
   1007     virtual const char* name() { return "DrawRect"; }
   1008 };
   1009 
   1010 class DrawRectsOp : public DrawBoundedOp {
   1011 public:
   1012     DrawRectsOp(const float* rects, int count, SkPaint* paint)
   1013             : DrawBoundedOp(rects, count, paint),
   1014             mRects(rects), mCount(count) {}
   1015 
   1016     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1017         return renderer.drawRects(mRects, mCount, getPaint(renderer));
   1018     }
   1019 
   1020     virtual void output(int level, uint32_t logFlags) {
   1021         OP_LOG("Draw Rects count %d", mCount);
   1022     }
   1023 
   1024     virtual const char* name() { return "DrawRects"; }
   1025 
   1026     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
   1027         *batchId = DeferredDisplayList::kOpBatch_Vertices;
   1028         return false;
   1029     }
   1030 
   1031 private:
   1032     const float* mRects;
   1033     int mCount;
   1034 };
   1035 
   1036 class DrawRoundRectOp : public DrawStrokableOp {
   1037 public:
   1038     DrawRoundRectOp(float left, float top, float right, float bottom,
   1039             float rx, float ry, SkPaint* paint)
   1040             : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {}
   1041 
   1042     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1043         return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top,
   1044                 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer));
   1045     }
   1046 
   1047     virtual void output(int level, uint32_t logFlags) {
   1048         OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
   1049     }
   1050 
   1051     virtual const char* name() { return "DrawRoundRect"; }
   1052 
   1053 private:
   1054     float mRx;
   1055     float mRy;
   1056 };
   1057 
   1058 class DrawCircleOp : public DrawStrokableOp {
   1059 public:
   1060     DrawCircleOp(float x, float y, float radius, SkPaint* paint)
   1061             : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint),
   1062             mX(x), mY(y), mRadius(radius) {}
   1063 
   1064     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1065         return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer));
   1066     }
   1067 
   1068     virtual void output(int level, uint32_t logFlags) {
   1069         OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius);
   1070     }
   1071 
   1072     virtual const char* name() { return "DrawCircle"; }
   1073 
   1074 private:
   1075     float mX;
   1076     float mY;
   1077     float mRadius;
   1078 };
   1079 
   1080 class DrawOvalOp : public DrawStrokableOp {
   1081 public:
   1082     DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint)
   1083             : DrawStrokableOp(left, top, right, bottom, paint) {}
   1084 
   1085     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1086         return renderer.drawOval(mLocalBounds.left, mLocalBounds.top,
   1087                 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer));
   1088     }
   1089 
   1090     virtual void output(int level, uint32_t logFlags) {
   1091         OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
   1092     }
   1093 
   1094     virtual const char* name() { return "DrawOval"; }
   1095 };
   1096 
   1097 class DrawArcOp : public DrawStrokableOp {
   1098 public:
   1099     DrawArcOp(float left, float top, float right, float bottom,
   1100             float startAngle, float sweepAngle, bool useCenter, SkPaint* paint)
   1101             : DrawStrokableOp(left, top, right, bottom, paint),
   1102             mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {}
   1103 
   1104     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1105         return renderer.drawArc(mLocalBounds.left, mLocalBounds.top,
   1106                 mLocalBounds.right, mLocalBounds.bottom,
   1107                 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer));
   1108     }
   1109 
   1110     virtual void output(int level, uint32_t logFlags) {
   1111         OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
   1112                 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
   1113     }
   1114 
   1115     virtual const char* name() { return "DrawArc"; }
   1116 
   1117 private:
   1118     float mStartAngle;
   1119     float mSweepAngle;
   1120     bool mUseCenter;
   1121 };
   1122 
   1123 class DrawPathOp : public DrawBoundedOp {
   1124 public:
   1125     DrawPathOp(SkPath* path, SkPaint* paint)
   1126             : DrawBoundedOp(paint), mPath(path) {
   1127         float left, top, offset;
   1128         uint32_t width, height;
   1129         PathCache::computePathBounds(path, paint, left, top, offset, width, height);
   1130         left -= offset;
   1131         top -= offset;
   1132         mLocalBounds.set(left, top, left + width, top + height);
   1133     }
   1134 
   1135     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1136         return renderer.drawPath(mPath, getPaint(renderer));
   1137     }
   1138 
   1139     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
   1140         SkPaint* paint = getPaint(renderer);
   1141         renderer.getCaches().pathCache.precache(mPath, paint);
   1142 
   1143         *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture;
   1144         return false;
   1145     }
   1146 
   1147     virtual void output(int level, uint32_t logFlags) {
   1148         OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
   1149     }
   1150 
   1151     virtual const char* name() { return "DrawPath"; }
   1152 
   1153 private:
   1154     SkPath* mPath;
   1155 };
   1156 
   1157 class DrawLinesOp : public DrawBoundedOp {
   1158 public:
   1159     DrawLinesOp(float* points, int count, SkPaint* paint)
   1160             : DrawBoundedOp(points, count, paint),
   1161             mPoints(points), mCount(count) {
   1162         mLocalBounds.outset(strokeWidthOutset());
   1163     }
   1164 
   1165     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1166         return renderer.drawLines(mPoints, mCount, getPaint(renderer));
   1167     }
   1168 
   1169     virtual void output(int level, uint32_t logFlags) {
   1170         OP_LOG("Draw Lines count %d", mCount);
   1171     }
   1172 
   1173     virtual const char* name() { return "DrawLines"; }
   1174 
   1175     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
   1176         *batchId = mPaint->isAntiAlias() ?
   1177                 DeferredDisplayList::kOpBatch_AlphaVertices :
   1178                 DeferredDisplayList::kOpBatch_Vertices;
   1179         return false;
   1180     }
   1181 
   1182 protected:
   1183     float* mPoints;
   1184     int mCount;
   1185 };
   1186 
   1187 class DrawPointsOp : public DrawLinesOp {
   1188 public:
   1189     DrawPointsOp(float* points, int count, SkPaint* paint)
   1190             : DrawLinesOp(points, count, paint) {}
   1191 
   1192     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1193         return renderer.drawPoints(mPoints, mCount, getPaint(renderer));
   1194     }
   1195 
   1196     virtual void output(int level, uint32_t logFlags) {
   1197         OP_LOG("Draw Points count %d", mCount);
   1198     }
   1199 
   1200     virtual const char* name() { return "DrawPoints"; }
   1201 };
   1202 
   1203 class DrawSomeTextOp : public DrawOp {
   1204 public:
   1205     DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint)
   1206             : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {};
   1207 
   1208     virtual void output(int level, uint32_t logFlags) {
   1209         OP_LOG("Draw some text, %d bytes", mBytesCount);
   1210     }
   1211 
   1212     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
   1213         SkPaint* paint = getPaint(renderer);
   1214         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
   1215         fontRenderer.precache(paint, mText, mCount, mat4::identity());
   1216 
   1217         *batchId = mPaint->getColor() == 0xff000000 ?
   1218                 DeferredDisplayList::kOpBatch_Text :
   1219                 DeferredDisplayList::kOpBatch_ColorText;
   1220 
   1221         return false;
   1222     }
   1223 
   1224 protected:
   1225     const char* mText;
   1226     int mBytesCount;
   1227     int mCount;
   1228 };
   1229 
   1230 class DrawTextOnPathOp : public DrawSomeTextOp {
   1231 public:
   1232     DrawTextOnPathOp(const char* text, int bytesCount, int count,
   1233             SkPath* path, float hOffset, float vOffset, SkPaint* paint)
   1234             : DrawSomeTextOp(text, bytesCount, count, paint),
   1235             mPath(path), mHOffset(hOffset), mVOffset(vOffset) {
   1236         /* TODO: inherit from DrawBounded and init mLocalBounds */
   1237     }
   1238 
   1239     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1240         return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath,
   1241                 mHOffset, mVOffset, getPaint(renderer));
   1242     }
   1243 
   1244     virtual const char* name() { return "DrawTextOnPath"; }
   1245 
   1246 private:
   1247     SkPath* mPath;
   1248     float mHOffset;
   1249     float mVOffset;
   1250 };
   1251 
   1252 class DrawPosTextOp : public DrawSomeTextOp {
   1253 public:
   1254     DrawPosTextOp(const char* text, int bytesCount, int count,
   1255             const float* positions, SkPaint* paint)
   1256             : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) {
   1257         /* TODO: inherit from DrawBounded and init mLocalBounds */
   1258     }
   1259 
   1260     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1261         return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer));
   1262     }
   1263 
   1264     virtual const char* name() { return "DrawPosText"; }
   1265 
   1266 private:
   1267     const float* mPositions;
   1268 };
   1269 
   1270 class DrawTextOp : public DrawBoundedOp {
   1271 public:
   1272     DrawTextOp(const char* text, int bytesCount, int count, float x, float y,
   1273             const float* positions, SkPaint* paint, float length)
   1274             : DrawBoundedOp(paint), mText(text), mBytesCount(bytesCount), mCount(count),
   1275             mX(x), mY(y), mPositions(positions), mLength(length) {
   1276         // duplicates bounds calculation from OpenGLRenderer::drawText, but doesn't alter mX
   1277         SkPaint::FontMetrics metrics;
   1278         paint->getFontMetrics(&metrics, 0.0f);
   1279         switch (paint->getTextAlign()) {
   1280         case SkPaint::kCenter_Align:
   1281             x -= length / 2.0f;
   1282             break;
   1283         case SkPaint::kRight_Align:
   1284             x -= length;
   1285             break;
   1286         default:
   1287             break;
   1288         }
   1289         mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom);
   1290         memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float));
   1291     }
   1292 
   1293     virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) {
   1294         SkPaint* paint = getPaint(renderer);
   1295         FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint);
   1296         const mat4& transform = renderer.findBestFontTransform(state.mMatrix);
   1297         if (mPrecacheTransform != transform) {
   1298             fontRenderer.precache(paint, mText, mCount, transform);
   1299             mPrecacheTransform = transform;
   1300         }
   1301         *batchId = mPaint->getColor() == 0xff000000 ?
   1302                 DeferredDisplayList::kOpBatch_Text :
   1303                 DeferredDisplayList::kOpBatch_ColorText;
   1304 
   1305         *mergeId = (mergeid_t)mPaint->getColor();
   1306 
   1307         // don't merge decorated text - the decorations won't draw in order
   1308         bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag |
   1309                         SkPaint::kStrikeThruText_Flag));
   1310         return mergeAllowed() && noDecorations;
   1311     }
   1312 
   1313     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1314         return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
   1315                 mPositions, getPaint(renderer), mLength);
   1316     }
   1317 
   1318     virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
   1319             const Vector<DrawOp*>& ops, const Rect& bounds) {
   1320         status_t status = DrawGlInfo::kStatusDone;
   1321         renderer.setFullScreenClip(); // ensure merged ops aren't clipped
   1322         for (unsigned int i = 0; i < ops.size(); i++) {
   1323             DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer;
   1324             renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip
   1325 
   1326             DrawTextOp& op = *((DrawTextOp*)ops[i]);
   1327             status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
   1328                     op.mPositions, op.getPaint(renderer), op.mLength, drawOpMode);
   1329         }
   1330         return status;
   1331     }
   1332 
   1333     virtual void output(int level, uint32_t logFlags) {
   1334         OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount);
   1335     }
   1336 
   1337     virtual const char* name() { return "DrawText"; }
   1338 
   1339 private:
   1340     const char* mText;
   1341     int mBytesCount;
   1342     int mCount;
   1343     float mX;
   1344     float mY;
   1345     const float* mPositions;
   1346     float mLength;
   1347     mat4 mPrecacheTransform;
   1348 };
   1349 
   1350 ///////////////////////////////////////////////////////////////////////////////
   1351 // SPECIAL DRAW OPERATIONS
   1352 ///////////////////////////////////////////////////////////////////////////////
   1353 
   1354 class DrawFunctorOp : public DrawOp {
   1355 public:
   1356     DrawFunctorOp(Functor* functor)
   1357             : DrawOp(0), mFunctor(functor) {}
   1358 
   1359     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1360         renderer.startMark("GL functor");
   1361         status_t ret = renderer.callDrawGLFunction(mFunctor, dirty);
   1362         renderer.endMark();
   1363         return ret;
   1364     }
   1365 
   1366     virtual void output(int level, uint32_t logFlags) {
   1367         OP_LOG("Draw Functor %p", mFunctor);
   1368     }
   1369 
   1370     virtual const char* name() { return "DrawFunctor"; }
   1371 
   1372 private:
   1373     Functor* mFunctor;
   1374 };
   1375 
   1376 class DrawDisplayListOp : public DrawBoundedOp {
   1377 public:
   1378     DrawDisplayListOp(DisplayList* displayList, int flags)
   1379             : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
   1380             mDisplayList(displayList), mFlags(flags) {}
   1381 
   1382     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
   1383             bool useQuickReject) {
   1384         if (mDisplayList && mDisplayList->isRenderable()) {
   1385             mDisplayList->defer(deferStruct, level + 1);
   1386         }
   1387     }
   1388     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
   1389             bool useQuickReject) {
   1390         if (mDisplayList && mDisplayList->isRenderable()) {
   1391             mDisplayList->replay(replayStruct, level + 1);
   1392         }
   1393     }
   1394 
   1395     // NOT USED since replay() is overridden
   1396     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1397         return DrawGlInfo::kStatusDone;
   1398     }
   1399 
   1400     virtual void output(int level, uint32_t logFlags) {
   1401         OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
   1402         if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
   1403             mDisplayList->output(level + 1);
   1404         }
   1405     }
   1406 
   1407     virtual const char* name() { return "DrawDisplayList"; }
   1408 
   1409 private:
   1410     DisplayList* mDisplayList;
   1411     int mFlags;
   1412 };
   1413 
   1414 class DrawLayerOp : public DrawOp {
   1415 public:
   1416     DrawLayerOp(Layer* layer, float x, float y)
   1417             : DrawOp(0), mLayer(layer), mX(x), mY(y) {}
   1418 
   1419     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
   1420         return renderer.drawLayer(mLayer, mX, mY);
   1421     }
   1422 
   1423     virtual void output(int level, uint32_t logFlags) {
   1424         OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY);
   1425     }
   1426 
   1427     virtual const char* name() { return "DrawLayer"; }
   1428 
   1429 private:
   1430     Layer* mLayer;
   1431     float mX;
   1432     float mY;
   1433 };
   1434 
   1435 }; // namespace uirenderer
   1436 }; // namespace android
   1437 
   1438 #endif // ANDROID_HWUI_DISPLAY_OPERATION_H
   1439