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