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