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