DisplayListOp.h revision 3f085429fd47ebd32ac2463b3eae2a5a6c17be25
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 DrawOvalOp : public DrawStrokableOp { 1202public: 1203 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint) 1204 : DrawStrokableOp(left, top, right, bottom, paint) {} 1205 1206 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1207 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top, 1208 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1209 } 1210 1211 virtual void output(int level, uint32_t logFlags) const { 1212 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds)); 1213 } 1214 1215 virtual const char* name() { return "DrawOval"; } 1216}; 1217 1218class DrawArcOp : public DrawStrokableOp { 1219public: 1220 DrawArcOp(float left, float top, float right, float bottom, 1221 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) 1222 : DrawStrokableOp(left, top, right, bottom, paint), 1223 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {} 1224 1225 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1226 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top, 1227 mLocalBounds.right, mLocalBounds.bottom, 1228 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer)); 1229 } 1230 1231 virtual void output(int level, uint32_t logFlags) const { 1232 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d", 1233 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter); 1234 } 1235 1236 virtual const char* name() { return "DrawArc"; } 1237 1238private: 1239 float mStartAngle; 1240 float mSweepAngle; 1241 bool mUseCenter; 1242}; 1243 1244class DrawPathOp : public DrawBoundedOp { 1245public: 1246 DrawPathOp(const SkPath* path, const SkPaint* paint) 1247 : DrawBoundedOp(paint), mPath(path) { 1248 float left, top, offset; 1249 uint32_t width, height; 1250 PathCache::computePathBounds(path, paint, left, top, offset, width, height); 1251 left -= offset; 1252 top -= offset; 1253 mLocalBounds.set(left, top, left + width, top + height); 1254 } 1255 1256 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1257 return renderer.drawPath(mPath, getPaint(renderer)); 1258 } 1259 1260 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1261 const DeferredDisplayState& state) { 1262 const SkPaint* paint = getPaint(renderer); 1263 renderer.getCaches().pathCache.precache(mPath, paint); 1264 1265 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 1266 } 1267 1268 virtual void output(int level, uint32_t logFlags) const { 1269 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds)); 1270 } 1271 1272 virtual const char* name() { return "DrawPath"; } 1273 1274private: 1275 const SkPath* mPath; 1276}; 1277 1278class DrawLinesOp : public DrawBoundedOp { 1279public: 1280 DrawLinesOp(const float* points, int count, const SkPaint* paint) 1281 : DrawBoundedOp(points, count, paint), 1282 mPoints(points), mCount(count) { 1283 mLocalBounds.outset(strokeWidthOutset()); 1284 } 1285 1286 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1287 return renderer.drawLines(mPoints, mCount, getPaint(renderer)); 1288 } 1289 1290 virtual void output(int level, uint32_t logFlags) const { 1291 OP_LOG("Draw Lines count %d", mCount); 1292 } 1293 1294 virtual const char* name() { return "DrawLines"; } 1295 1296 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1297 const DeferredDisplayState& state) { 1298 deferInfo.batchId = mPaint->isAntiAlias() ? 1299 DeferredDisplayList::kOpBatch_AlphaVertices : 1300 DeferredDisplayList::kOpBatch_Vertices; 1301 } 1302 1303protected: 1304 const float* mPoints; 1305 int mCount; 1306}; 1307 1308class DrawPointsOp : public DrawLinesOp { 1309public: 1310 DrawPointsOp(const float* points, int count, const SkPaint* paint) 1311 : DrawLinesOp(points, count, paint) {} 1312 1313 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1314 return renderer.drawPoints(mPoints, mCount, getPaint(renderer)); 1315 } 1316 1317 virtual void output(int level, uint32_t logFlags) const { 1318 OP_LOG("Draw Points count %d", mCount); 1319 } 1320 1321 virtual const char* name() { return "DrawPoints"; } 1322}; 1323 1324class DrawSomeTextOp : public DrawOp { 1325public: 1326 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint) 1327 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {}; 1328 1329 virtual void output(int level, uint32_t logFlags) const { 1330 OP_LOG("Draw some text, %d bytes", mBytesCount); 1331 } 1332 1333 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1334 const DeferredDisplayState& state) { 1335 const SkPaint* paint = getPaint(renderer); 1336 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1337 fontRenderer.precache(paint, mText, mCount, mat4::identity()); 1338 1339 deferInfo.batchId = mPaint->getColor() == 0xff000000 ? 1340 DeferredDisplayList::kOpBatch_Text : 1341 DeferredDisplayList::kOpBatch_ColorText; 1342 } 1343 1344protected: 1345 const char* mText; 1346 int mBytesCount; 1347 int mCount; 1348}; 1349 1350class DrawTextOnPathOp : public DrawSomeTextOp { 1351public: 1352 DrawTextOnPathOp(const char* text, int bytesCount, int count, 1353 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) 1354 : DrawSomeTextOp(text, bytesCount, count, paint), 1355 mPath(path), mHOffset(hOffset), mVOffset(vOffset) { 1356 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1357 } 1358 1359 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1360 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath, 1361 mHOffset, mVOffset, getPaint(renderer)); 1362 } 1363 1364 virtual const char* name() { return "DrawTextOnPath"; } 1365 1366private: 1367 const SkPath* mPath; 1368 float mHOffset; 1369 float mVOffset; 1370}; 1371 1372class DrawPosTextOp : public DrawSomeTextOp { 1373public: 1374 DrawPosTextOp(const char* text, int bytesCount, int count, 1375 const float* positions, const SkPaint* paint) 1376 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) { 1377 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1378 } 1379 1380 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1381 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer)); 1382 } 1383 1384 virtual const char* name() { return "DrawPosText"; } 1385 1386private: 1387 const float* mPositions; 1388}; 1389 1390class DrawTextOp : public DrawBoundedOp { 1391public: 1392 DrawTextOp(const char* text, int bytesCount, int count, float x, float y, 1393 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds) 1394 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count), 1395 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) { 1396 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float)); 1397 } 1398 1399 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1400 const DeferredDisplayState& state) { 1401 const SkPaint* paint = getPaint(renderer); 1402 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1403 const mat4& transform = renderer.findBestFontTransform(state.mMatrix); 1404 if (mPrecacheTransform != transform) { 1405 fontRenderer.precache(paint, mText, mCount, transform); 1406 mPrecacheTransform = transform; 1407 } 1408 deferInfo.batchId = mPaint->getColor() == 0xff000000 ? 1409 DeferredDisplayList::kOpBatch_Text : 1410 DeferredDisplayList::kOpBatch_ColorText; 1411 1412 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor()); 1413 1414 // don't merge decorated text - the decorations won't draw in order 1415 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag | 1416 SkPaint::kStrikeThruText_Flag)); 1417 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations && 1418 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; 1419 } 1420 1421 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1422 Rect bounds; 1423 getLocalBounds(renderer.getDrawModifiers(), bounds); 1424 return renderer.drawText(mText, mBytesCount, mCount, mX, mY, 1425 mPositions, getPaint(renderer), mTotalAdvance, bounds); 1426 } 1427 1428 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 1429 const Vector<OpStatePair>& ops, const Rect& bounds) { 1430 status_t status = DrawGlInfo::kStatusDone; 1431 for (unsigned int i = 0; i < ops.size(); i++) { 1432 const DeferredDisplayState& state = *(ops[i].state); 1433 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer; 1434 renderer.restoreDisplayState(state, true); // restore all but the clip 1435 1436 DrawTextOp& op = *((DrawTextOp*)ops[i].op); 1437 // quickReject() will not occure in drawText() so we can use mLocalBounds 1438 // directly, we do not need to account for shadow by calling getLocalBounds() 1439 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY, 1440 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds, 1441 drawOpMode); 1442 } 1443 return status; 1444 } 1445 1446 virtual void output(int level, uint32_t logFlags) const { 1447 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount); 1448 } 1449 1450 virtual const char* name() { return "DrawText"; } 1451 1452private: 1453 const char* mText; 1454 int mBytesCount; 1455 int mCount; 1456 float mX; 1457 float mY; 1458 const float* mPositions; 1459 float mTotalAdvance; 1460 mat4 mPrecacheTransform; 1461}; 1462 1463/////////////////////////////////////////////////////////////////////////////// 1464// SPECIAL DRAW OPERATIONS 1465/////////////////////////////////////////////////////////////////////////////// 1466 1467class DrawFunctorOp : public DrawOp { 1468public: 1469 DrawFunctorOp(Functor* functor) 1470 : DrawOp(NULL), mFunctor(functor) {} 1471 1472 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1473 renderer.startMark("GL functor"); 1474 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty); 1475 renderer.endMark(); 1476 return ret; 1477 } 1478 1479 virtual void output(int level, uint32_t logFlags) const { 1480 OP_LOG("Draw Functor %p", mFunctor); 1481 } 1482 1483 virtual const char* name() { return "DrawFunctor"; } 1484 1485private: 1486 Functor* mFunctor; 1487}; 1488 1489class DrawDisplayListOp : public DrawBoundedOp { 1490 friend class RenderNode; // grant DisplayList access to info of child 1491public: 1492 DrawDisplayListOp(RenderNode* displayList, int flags, const mat4& transformFromParent) 1493 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0), 1494 mDisplayList(displayList), mFlags(flags), mTransformFromParent(transformFromParent) {} 1495 1496 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 1497 bool useQuickReject) { 1498 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) { 1499 mDisplayList->deferNodeInParent(deferStruct, level + 1); 1500 } 1501 } 1502 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 1503 bool useQuickReject) { 1504 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) { 1505 mDisplayList->replayNodeInParent(replayStruct, level + 1); 1506 } 1507 } 1508 1509 // NOT USED since replay() is overridden 1510 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1511 return DrawGlInfo::kStatusDone; 1512 } 1513 1514 virtual void output(int level, uint32_t logFlags) const { 1515 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags); 1516 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) { 1517 mDisplayList->output(level + 1); 1518 } 1519 } 1520 1521 virtual const char* name() { return "DrawDisplayList"; } 1522 1523 RenderNode* renderNode() { return mDisplayList; } 1524 1525private: 1526 RenderNode* mDisplayList; 1527 const int mFlags; 1528 1529 /////////////////////////// 1530 // Properties below are used by DisplayList::computeOrderingImpl() and iterate() 1531 /////////////////////////// 1532 /** 1533 * Records transform vs parent, used for computing total transform without rerunning DL contents 1534 */ 1535 const mat4 mTransformFromParent; 1536 1537 /** 1538 * Holds the transformation between the projection surface ViewGroup and this DisplayList 1539 * drawing instance. Represents any translations / transformations done within the drawing of 1540 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this 1541 * DisplayList draw instance. 1542 * 1543 * Note: doesn't include any transformation recorded within the DisplayList and its properties. 1544 */ 1545 mat4 mTransformFromCompositingAncestor; 1546 bool mSkipInOrderDraw; 1547}; 1548 1549/** 1550 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate() 1551 */ 1552class DrawShadowOp : public DrawOp { 1553public: 1554 DrawShadowOp(const mat4& transformXY, const mat4& transformZ, 1555 float casterAlpha, bool casterUnclipped, 1556 float fallbackWidth, float fallbackHeight, 1557 const SkPath* outline, const SkPath* revealClip) 1558 : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), 1559 mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped), 1560 mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight), 1561 mOutline(outline), mRevealClip(revealClip) {} 1562 1563 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1564 SkPath casterPerimeter; 1565 if (!mOutline || mOutline->isEmpty()) { 1566 casterPerimeter.addRect(0, 0, mFallbackWidth, mFallbackHeight); 1567 } else { 1568 casterPerimeter = *mOutline; 1569 } 1570 1571 if (mRevealClip) { 1572 // intersect the outline with the convex reveal clip 1573 Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter); 1574 } 1575 1576 return renderer.drawShadow(mTransformXY, mTransformZ, 1577 mCasterAlpha, mCasterUnclipped, &casterPerimeter); 1578 } 1579 1580 virtual void output(int level, uint32_t logFlags) const { 1581 OP_LOG("DrawShadow of outline %p", mOutline); 1582 } 1583 1584 virtual const char* name() { return "DrawShadow"; } 1585 1586private: 1587 const mat4 mTransformXY; 1588 const mat4 mTransformZ; 1589 const float mCasterAlpha; 1590 const bool mCasterUnclipped; 1591 const float mFallbackWidth; 1592 const float mFallbackHeight; 1593 1594 // these point at convex SkPaths owned by RenderProperties, or null 1595 const SkPath* mOutline; 1596 const SkPath* mRevealClip; 1597}; 1598 1599class DrawLayerOp : public DrawOp { 1600public: 1601 DrawLayerOp(Layer* layer, float x, float y) 1602 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {} 1603 1604 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1605 return renderer.drawLayer(mLayer, mX, mY); 1606 } 1607 1608 virtual void output(int level, uint32_t logFlags) const { 1609 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY); 1610 } 1611 1612 virtual const char* name() { return "DrawLayer"; } 1613 1614private: 1615 Layer* mLayer; 1616 float mX; 1617 float mY; 1618}; 1619 1620}; // namespace uirenderer 1621}; // namespace android 1622 1623#endif // ANDROID_HWUI_DISPLAY_OPERATION_H 1624