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