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