DisplayListOp.h revision 860d155f866cc15a725e7ce03763280987f24901
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), mPaint(&mCachedPaint), mFlags(flags) { 322 mCachedPaint.setAlpha(alpha); 323 } 324 325 SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags) 326 : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {} 327 328 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 329 bool useQuickReject) { 330 // NOTE: don't bother with actual saveLayer, instead issuing it at flush time 331 int newSaveCount = deferStruct.mRenderer.getSaveCount(); 332 deferStruct.mDeferredList.addSaveLayer(deferStruct.mRenderer, this, newSaveCount); 333 334 // NOTE: don't issue full saveLayer, since that has side effects/is costly. instead just 335 // setup the snapshot for deferral, and re-issue the op at flush time 336 deferStruct.mRenderer.saveLayerDeferred(mArea.left, mArea.top, mArea.right, mArea.bottom, 337 mPaint, mFlags); 338 } 339 340 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 341 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mPaint, mFlags); 342 } 343 344 virtual void output(int level, uint32_t logFlags) const { 345 OP_LOG("SaveLayer%s of area " RECT_STRING, 346 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea)); 347 } 348 349 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; } 350 351 int getFlags() { return mFlags; } 352 353private: 354 bool isSaveLayerAlpha() const { 355 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint); 356 int alpha = OpenGLRenderer::getAlphaDirect(mPaint); 357 return alpha < 255 && mode == SkXfermode::kSrcOver_Mode; 358 } 359 360 Rect mArea; 361 const SkPaint* mPaint; 362 SkPaint mCachedPaint; 363 int mFlags; 364}; 365 366class TranslateOp : public StateOp { 367public: 368 TranslateOp(float dx, float dy) 369 : mDx(dx), mDy(dy) {} 370 371 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 372 renderer.translate(mDx, mDy); 373 } 374 375 virtual void output(int level, uint32_t logFlags) const { 376 OP_LOG("Translate by %f %f", mDx, mDy); 377 } 378 379 virtual const char* name() { return "Translate"; } 380 381private: 382 float mDx; 383 float mDy; 384}; 385 386class RotateOp : public StateOp { 387public: 388 RotateOp(float degrees) 389 : mDegrees(degrees) {} 390 391 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 392 renderer.rotate(mDegrees); 393 } 394 395 virtual void output(int level, uint32_t logFlags) const { 396 OP_LOG("Rotate by %f degrees", mDegrees); 397 } 398 399 virtual const char* name() { return "Rotate"; } 400 401private: 402 float mDegrees; 403}; 404 405class ScaleOp : public StateOp { 406public: 407 ScaleOp(float sx, float sy) 408 : mSx(sx), mSy(sy) {} 409 410 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 411 renderer.scale(mSx, mSy); 412 } 413 414 virtual void output(int level, uint32_t logFlags) const { 415 OP_LOG("Scale by %f %f", mSx, mSy); 416 } 417 418 virtual const char* name() { return "Scale"; } 419 420private: 421 float mSx; 422 float mSy; 423}; 424 425class SkewOp : public StateOp { 426public: 427 SkewOp(float sx, float sy) 428 : mSx(sx), mSy(sy) {} 429 430 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 431 renderer.skew(mSx, mSy); 432 } 433 434 virtual void output(int level, uint32_t logFlags) const { 435 OP_LOG("Skew by %f %f", mSx, mSy); 436 } 437 438 virtual const char* name() { return "Skew"; } 439 440private: 441 float mSx; 442 float mSy; 443}; 444 445class SetMatrixOp : public StateOp { 446public: 447 SetMatrixOp(const SkMatrix* matrix) 448 : mMatrix(matrix) {} 449 450 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 451 renderer.setMatrix(mMatrix); 452 } 453 454 virtual void output(int level, uint32_t logFlags) const { 455 if (mMatrix) { 456 OP_LOG("SetMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix)); 457 } else { 458 OP_LOGS("SetMatrix (reset)"); 459 } 460 } 461 462 virtual const char* name() { return "SetMatrix"; } 463 464private: 465 const SkMatrix* mMatrix; 466}; 467 468class ConcatMatrixOp : public StateOp { 469public: 470 ConcatMatrixOp(const SkMatrix* matrix) 471 : mMatrix(matrix) {} 472 473 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 474 renderer.concatMatrix(mMatrix); 475 } 476 477 virtual void output(int level, uint32_t logFlags) const { 478 OP_LOG("ConcatMatrix " SK_MATRIX_STRING, SK_MATRIX_ARGS(mMatrix)); 479 } 480 481 virtual const char* name() { return "ConcatMatrix"; } 482 483private: 484 const SkMatrix* mMatrix; 485}; 486 487class ClipOp : public StateOp { 488public: 489 ClipOp(SkRegion::Op op) : mOp(op) {} 490 491 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 492 bool useQuickReject) { 493 // NOTE: must defer op BEFORE applying state, since it may read clip 494 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this); 495 496 // TODO: Can we avoid applying complex clips at defer time? 497 applyState(deferStruct.mRenderer, saveCount); 498 } 499 500 bool canCauseComplexClip() { 501 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect(); 502 } 503 504protected: 505 virtual bool isRect() { return false; } 506 507 SkRegion::Op mOp; 508}; 509 510class ClipRectOp : public ClipOp { 511public: 512 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op) 513 : ClipOp(op), mArea(left, top, right, bottom) {} 514 515 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 516 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp); 517 } 518 519 virtual void output(int level, uint32_t logFlags) const { 520 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea)); 521 } 522 523 virtual const char* name() { return "ClipRect"; } 524 525protected: 526 virtual bool isRect() { return true; } 527 528private: 529 Rect mArea; 530}; 531 532class ClipPathOp : public ClipOp { 533public: 534 ClipPathOp(const SkPath* path, SkRegion::Op op) 535 : ClipOp(op), mPath(path) {} 536 537 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 538 renderer.clipPath(mPath, mOp); 539 } 540 541 virtual void output(int level, uint32_t logFlags) const { 542 SkRect bounds = mPath->getBounds(); 543 OP_LOG("ClipPath bounds " RECT_STRING, 544 bounds.left(), bounds.top(), bounds.right(), bounds.bottom()); 545 } 546 547 virtual const char* name() { return "ClipPath"; } 548 549private: 550 const SkPath* mPath; 551}; 552 553class ClipRegionOp : public ClipOp { 554public: 555 ClipRegionOp(const SkRegion* region, SkRegion::Op op) 556 : ClipOp(op), mRegion(region) {} 557 558 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 559 renderer.clipRegion(mRegion, mOp); 560 } 561 562 virtual void output(int level, uint32_t logFlags) const { 563 SkIRect bounds = mRegion->getBounds(); 564 OP_LOG("ClipRegion bounds %d %d %d %d", 565 bounds.left(), bounds.top(), bounds.right(), bounds.bottom()); 566 } 567 568 virtual const char* name() { return "ClipRegion"; } 569 570private: 571 const SkRegion* mRegion; 572}; 573 574class ResetShaderOp : public StateOp { 575public: 576 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 577 renderer.resetShader(); 578 } 579 580 virtual void output(int level, uint32_t logFlags) const { 581 OP_LOGS("ResetShader"); 582 } 583 584 virtual const char* name() { return "ResetShader"; } 585}; 586 587class SetupShaderOp : public StateOp { 588public: 589 SetupShaderOp(SkiaShader* shader) 590 : mShader(shader) {} 591 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 592 renderer.setupShader(mShader); 593 } 594 595 virtual void output(int level, uint32_t logFlags) const { 596 OP_LOG("SetupShader, shader %p", mShader); 597 } 598 599 virtual const char* name() { return "SetupShader"; } 600 601private: 602 SkiaShader* mShader; 603}; 604 605class ResetShadowOp : public StateOp { 606public: 607 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 608 renderer.resetShadow(); 609 } 610 611 virtual void output(int level, uint32_t logFlags) const { 612 OP_LOGS("ResetShadow"); 613 } 614 615 virtual const char* name() { return "ResetShadow"; } 616}; 617 618class SetupShadowOp : public StateOp { 619public: 620 SetupShadowOp(float radius, float dx, float dy, int color) 621 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {} 622 623 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 624 renderer.setupShadow(mRadius, mDx, mDy, mColor); 625 } 626 627 virtual void output(int level, uint32_t logFlags) const { 628 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor); 629 } 630 631 virtual const char* name() { return "SetupShadow"; } 632 633private: 634 float mRadius; 635 float mDx; 636 float mDy; 637 int mColor; 638}; 639 640class ResetPaintFilterOp : public StateOp { 641public: 642 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 643 renderer.resetPaintFilter(); 644 } 645 646 virtual void output(int level, uint32_t logFlags) const { 647 OP_LOGS("ResetPaintFilter"); 648 } 649 650 virtual const char* name() { return "ResetPaintFilter"; } 651}; 652 653class SetupPaintFilterOp : public StateOp { 654public: 655 SetupPaintFilterOp(int clearBits, int setBits) 656 : mClearBits(clearBits), mSetBits(setBits) {} 657 658 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 659 renderer.setupPaintFilter(mClearBits, mSetBits); 660 } 661 662 virtual void output(int level, uint32_t logFlags) const { 663 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits); 664 } 665 666 virtual const char* name() { return "SetupPaintFilter"; } 667 668private: 669 int mClearBits; 670 int mSetBits; 671}; 672 673/////////////////////////////////////////////////////////////////////////////// 674// DRAW OPERATIONS - these are operations that can draw to the canvas's device 675/////////////////////////////////////////////////////////////////////////////// 676 677class DrawBitmapOp : public DrawBoundedOp { 678public: 679 DrawBitmapOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint) 680 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint), 681 mBitmap(bitmap), mAtlas(Caches::getInstance().assetAtlas) { 682 mEntry = mAtlas.getEntry(bitmap); 683 if (mEntry) { 684 mEntryGenerationId = mAtlas.getGenerationId(); 685 mUvMapper = mEntry->uvMapper; 686 } 687 } 688 689 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 690 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, 691 getPaint(renderer)); 692 } 693 694 AssetAtlas::Entry* getAtlasEntry() { 695 // The atlas entry is stale, let's get a new one 696 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) { 697 mEntryGenerationId = mAtlas.getGenerationId(); 698 mEntry = mAtlas.getEntry(mBitmap); 699 mUvMapper = mEntry->uvMapper; 700 } 701 return mEntry; 702 } 703 704#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \ 705 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \ 706 texCoordsRect.xDim, texCoordsRect.yDim) 707 708 /** 709 * This multi-draw operation builds a mesh on the stack by generating a quad 710 * for each bitmap in the batch. This method is also responsible for dirtying 711 * the current layer, if any. 712 */ 713 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 714 const Vector<OpStatePair>& ops, const Rect& bounds) { 715 const DeferredDisplayState& firstState = *(ops[0].state); 716 renderer.restoreDisplayState(firstState, true); // restore all but the clip 717 718 TextureVertex vertices[6 * ops.size()]; 719 TextureVertex* vertex = &vertices[0]; 720 721 const bool hasLayer = renderer.hasLayer(); 722 bool pureTranslate = true; 723 724 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, 725 // and allowing them to be merged in getBatchId() 726 for (unsigned int i = 0; i < ops.size(); i++) { 727 const DeferredDisplayState& state = *(ops[i].state); 728 const Rect& opBounds = state.mBounds; 729 // When we reach multiDraw(), the matrix can be either 730 // pureTranslate or simple (translate and/or scale). 731 // If the matrix is not pureTranslate, then we have a scale 732 pureTranslate &= state.mMatrix.isPureTranslate(); 733 734 Rect texCoords(0, 0, 1, 1); 735 ((DrawBitmapOp*) ops[i].op)->mUvMapper.map(texCoords); 736 737 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top); 738 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); 739 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); 740 741 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); 742 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); 743 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom); 744 745 if (hasLayer) { 746 renderer.dirtyLayer(opBounds.left, opBounds.top, opBounds.right, opBounds.bottom); 747 } 748 } 749 750 return renderer.drawBitmaps(mBitmap, mEntry, ops.size(), &vertices[0], 751 pureTranslate, bounds, mPaint); 752 } 753 754 virtual void output(int level, uint32_t logFlags) const { 755 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top); 756 } 757 758 virtual const char* name() { return "DrawBitmap"; } 759 760 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 761 const DeferredDisplayState& state) { 762 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 763 deferInfo.mergeId = getAtlasEntry() ? 764 (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap; 765 766 // Don't merge non-simply transformed or neg scale ops, SET_TEXTURE doesn't handle rotation 767 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in 768 // MergingDrawBatch::canMergeWith() 769 // TODO: support clipped bitmaps by handling them in SET_TEXTURE 770 deferInfo.mergeable = state.mMatrix.isSimple() && state.mMatrix.positiveScale() && 771 !state.mClipSideFlags && 772 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode && 773 (mBitmap->config() != SkBitmap::kA8_Config); 774 } 775 776 const SkBitmap* bitmap() { return mBitmap; } 777protected: 778 const SkBitmap* mBitmap; 779 const AssetAtlas& mAtlas; 780 uint32_t mEntryGenerationId; 781 AssetAtlas::Entry* mEntry; 782 UvMapper mUvMapper; 783}; 784 785class DrawBitmapMatrixOp : public DrawBoundedOp { 786public: 787 DrawBitmapMatrixOp(const SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) 788 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) { 789 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height()); 790 const mat4 transform(*matrix); 791 transform.mapRect(mLocalBounds); 792 } 793 794 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 795 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer)); 796 } 797 798 virtual void output(int level, uint32_t logFlags) const { 799 OP_LOG("Draw bitmap %p matrix " SK_MATRIX_STRING, mBitmap, SK_MATRIX_ARGS(mMatrix)); 800 } 801 802 virtual const char* name() { return "DrawBitmapMatrix"; } 803 804 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 805 const DeferredDisplayState& state) { 806 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 807 } 808 809private: 810 const SkBitmap* mBitmap; 811 const SkMatrix* mMatrix; 812}; 813 814class DrawBitmapRectOp : public DrawBoundedOp { 815public: 816 DrawBitmapRectOp(const SkBitmap* bitmap, 817 float srcLeft, float srcTop, float srcRight, float srcBottom, 818 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) 819 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint), 820 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {} 821 822 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 823 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom, 824 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, 825 getPaint(renderer)); 826 } 827 828 virtual void output(int level, uint32_t logFlags) const { 829 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING, 830 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds)); 831 } 832 833 virtual const char* name() { return "DrawBitmapRect"; } 834 835 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 836 const DeferredDisplayState& state) { 837 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 838 } 839 840private: 841 const SkBitmap* mBitmap; 842 Rect mSrc; 843}; 844 845class DrawBitmapDataOp : public DrawBitmapOp { 846public: 847 DrawBitmapDataOp(const SkBitmap* bitmap, float left, float top, const SkPaint* paint) 848 : DrawBitmapOp(bitmap, left, top, paint) {} 849 850 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 851 return renderer.drawBitmapData(mBitmap, mLocalBounds.left, 852 mLocalBounds.top, getPaint(renderer)); 853 } 854 855 virtual void output(int level, uint32_t logFlags) const { 856 OP_LOG("Draw bitmap %p", mBitmap); 857 } 858 859 virtual const char* name() { return "DrawBitmapData"; } 860 861 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 862 const DeferredDisplayState& state) { 863 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 864 } 865}; 866 867class DrawBitmapMeshOp : public DrawBoundedOp { 868public: 869 DrawBitmapMeshOp(const SkBitmap* bitmap, int meshWidth, int meshHeight, 870 const float* vertices, const int* colors, const SkPaint* paint) 871 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint), 872 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight), 873 mVertices(vertices), mColors(colors) {} 874 875 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 876 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight, 877 mVertices, mColors, getPaint(renderer)); 878 } 879 880 virtual void output(int level, uint32_t logFlags) const { 881 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight); 882 } 883 884 virtual const char* name() { return "DrawBitmapMesh"; } 885 886 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 887 const DeferredDisplayState& state) { 888 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 889 } 890 891private: 892 const SkBitmap* mBitmap; 893 int mMeshWidth; 894 int mMeshHeight; 895 const float* mVertices; 896 const int* mColors; 897}; 898 899class DrawPatchOp : public DrawBoundedOp { 900public: 901 DrawPatchOp(const SkBitmap* bitmap, const Res_png_9patch* patch, 902 float left, float top, float right, float bottom, const SkPaint* paint) 903 : DrawBoundedOp(left, top, right, bottom, paint), 904 mBitmap(bitmap), mPatch(patch), mGenerationId(0), mMesh(NULL), 905 mAtlas(Caches::getInstance().assetAtlas) { 906 mEntry = mAtlas.getEntry(bitmap); 907 if (mEntry) { 908 mEntryGenerationId = mAtlas.getGenerationId(); 909 } 910 }; 911 912 AssetAtlas::Entry* getAtlasEntry() { 913 // The atlas entry is stale, let's get a new one 914 if (mEntry && mEntryGenerationId != mAtlas.getGenerationId()) { 915 mEntryGenerationId = mAtlas.getGenerationId(); 916 mEntry = mAtlas.getEntry(mBitmap); 917 } 918 return mEntry; 919 } 920 921 const Patch* getMesh(OpenGLRenderer& renderer) { 922 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) { 923 PatchCache& cache = renderer.getCaches().patchCache; 924 mMesh = cache.get(getAtlasEntry(), mBitmap->width(), mBitmap->height(), 925 mLocalBounds.getWidth(), mLocalBounds.getHeight(), mPatch); 926 mGenerationId = cache.getGenerationId(); 927 } 928 return mMesh; 929 } 930 931 /** 932 * This multi-draw operation builds an indexed mesh on the stack by copying 933 * and transforming the vertices of each 9-patch in the batch. This method 934 * is also responsible for dirtying the current layer, if any. 935 */ 936 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 937 const Vector<OpStatePair>& ops, const Rect& bounds) { 938 const DeferredDisplayState& firstState = *(ops[0].state); 939 renderer.restoreDisplayState(firstState, true); // restore all but the clip 940 941 // Batches will usually contain a small number of items so it's 942 // worth performing a first iteration to count the exact number 943 // of vertices we need in the new mesh 944 uint32_t totalVertices = 0; 945 for (unsigned int i = 0; i < ops.size(); i++) { 946 totalVertices += ((DrawPatchOp*) ops[i].op)->getMesh(renderer)->verticesCount; 947 } 948 949 const bool hasLayer = renderer.hasLayer(); 950 951 uint32_t indexCount = 0; 952 953 TextureVertex vertices[totalVertices]; 954 TextureVertex* vertex = &vertices[0]; 955 956 // Create a mesh that contains the transformed vertices for all the 957 // 9-patch objects that are part of the batch. Note that onDefer() 958 // enforces ops drawn by this function to have a pure translate or 959 // identity matrix 960 for (unsigned int i = 0; i < ops.size(); i++) { 961 DrawPatchOp* patchOp = (DrawPatchOp*) ops[i].op; 962 const DeferredDisplayState* state = ops[i].state; 963 const Patch* opMesh = patchOp->getMesh(renderer); 964 uint32_t vertexCount = opMesh->verticesCount; 965 if (vertexCount == 0) continue; 966 967 // We use the bounds to know where to translate our vertices 968 // Using patchOp->state.mBounds wouldn't work because these 969 // bounds are clipped 970 const float tx = (int) floorf(state->mMatrix.getTranslateX() + 971 patchOp->mLocalBounds.left + 0.5f); 972 const float ty = (int) floorf(state->mMatrix.getTranslateY() + 973 patchOp->mLocalBounds.top + 0.5f); 974 975 // Copy & transform all the vertices for the current operation 976 TextureVertex* opVertices = opMesh->vertices; 977 for (uint32_t j = 0; j < vertexCount; j++, opVertices++) { 978 TextureVertex::set(vertex++, 979 opVertices->x + tx, opVertices->y + ty, 980 opVertices->u, opVertices->v); 981 } 982 983 // Dirty the current layer if possible. When the 9-patch does not 984 // contain empty quads we can take a shortcut and simply set the 985 // dirty rect to the object's bounds. 986 if (hasLayer) { 987 if (!opMesh->hasEmptyQuads) { 988 renderer.dirtyLayer(tx, ty, 989 tx + patchOp->mLocalBounds.getWidth(), 990 ty + patchOp->mLocalBounds.getHeight()); 991 } else { 992 const size_t count = opMesh->quads.size(); 993 for (size_t i = 0; i < count; i++) { 994 const Rect& quadBounds = opMesh->quads[i]; 995 const float x = tx + quadBounds.left; 996 const float y = ty + quadBounds.top; 997 renderer.dirtyLayer(x, y, 998 x + quadBounds.getWidth(), y + quadBounds.getHeight()); 999 } 1000 } 1001 } 1002 1003 indexCount += opMesh->indexCount; 1004 } 1005 1006 return renderer.drawPatches(mBitmap, getAtlasEntry(), 1007 &vertices[0], indexCount, getPaint(renderer)); 1008 } 1009 1010 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1011 // We're not calling the public variant of drawPatch() here 1012 // This method won't perform the quickReject() since we've already done it at this point 1013 return renderer.drawPatch(mBitmap, getMesh(renderer), getAtlasEntry(), 1014 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, 1015 getPaint(renderer)); 1016 } 1017 1018 virtual void output(int level, uint32_t logFlags) const { 1019 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds)); 1020 } 1021 1022 virtual const char* name() { return "DrawPatch"; } 1023 1024 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1025 const DeferredDisplayState& state) { 1026 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch; 1027 deferInfo.mergeId = getAtlasEntry() ? (mergeid_t) mEntry->getMergeId() : (mergeid_t) mBitmap; 1028 deferInfo.mergeable = state.mMatrix.isPureTranslate() && 1029 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; 1030 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && mBitmap->isOpaque(); 1031 } 1032 1033private: 1034 const SkBitmap* mBitmap; 1035 const Res_png_9patch* mPatch; 1036 1037 uint32_t mGenerationId; 1038 const Patch* mMesh; 1039 1040 const AssetAtlas& mAtlas; 1041 uint32_t mEntryGenerationId; 1042 AssetAtlas::Entry* mEntry; 1043}; 1044 1045class DrawColorOp : public DrawOp { 1046public: 1047 DrawColorOp(int color, SkXfermode::Mode mode) 1048 : DrawOp(NULL), mColor(color), mMode(mode) {}; 1049 1050 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1051 return renderer.drawColor(mColor, mMode); 1052 } 1053 1054 virtual void output(int level, uint32_t logFlags) const { 1055 OP_LOG("Draw color %#x, mode %d", mColor, mMode); 1056 } 1057 1058 virtual const char* name() { return "DrawColor"; } 1059 1060private: 1061 int mColor; 1062 SkXfermode::Mode mMode; 1063}; 1064 1065class DrawStrokableOp : public DrawBoundedOp { 1066public: 1067 DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint) 1068 : DrawBoundedOp(left, top, right, bottom, paint) {}; 1069 1070 bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) { 1071 localBounds.set(mLocalBounds); 1072 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) { 1073 localBounds.outset(strokeWidthOutset()); 1074 } 1075 return true; 1076 } 1077 1078 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1079 const DeferredDisplayState& state) { 1080 if (mPaint->getPathEffect()) { 1081 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 1082 } else { 1083 deferInfo.batchId = mPaint->isAntiAlias() ? 1084 DeferredDisplayList::kOpBatch_AlphaVertices : 1085 DeferredDisplayList::kOpBatch_Vertices; 1086 } 1087 } 1088}; 1089 1090class DrawRectOp : public DrawStrokableOp { 1091public: 1092 DrawRectOp(float left, float top, float right, float bottom, const SkPaint* paint) 1093 : DrawStrokableOp(left, top, right, bottom, paint) {} 1094 1095 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1096 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top, 1097 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1098 } 1099 1100 virtual void output(int level, uint32_t logFlags) const { 1101 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds)); 1102 } 1103 1104 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1105 const DeferredDisplayState& state) { 1106 DrawStrokableOp::onDefer(renderer, deferInfo, state); 1107 deferInfo.opaqueOverBounds = isOpaqueOverBounds(state) && 1108 mPaint->getStyle() == SkPaint::kFill_Style; 1109 } 1110 1111 virtual const char* name() { return "DrawRect"; } 1112}; 1113 1114class DrawRectsOp : public DrawBoundedOp { 1115public: 1116 DrawRectsOp(const float* rects, int count, const SkPaint* paint) 1117 : DrawBoundedOp(rects, count, paint), 1118 mRects(rects), mCount(count) {} 1119 1120 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1121 return renderer.drawRects(mRects, mCount, getPaint(renderer)); 1122 } 1123 1124 virtual void output(int level, uint32_t logFlags) const { 1125 OP_LOG("Draw Rects count %d", mCount); 1126 } 1127 1128 virtual const char* name() { return "DrawRects"; } 1129 1130 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1131 const DeferredDisplayState& state) { 1132 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices; 1133 } 1134 1135private: 1136 const float* mRects; 1137 int mCount; 1138}; 1139 1140class DrawRoundRectOp : public DrawStrokableOp { 1141public: 1142 DrawRoundRectOp(float left, float top, float right, float bottom, 1143 float rx, float ry, const SkPaint* paint) 1144 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {} 1145 1146 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1147 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top, 1148 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer)); 1149 } 1150 1151 virtual void output(int level, uint32_t logFlags) const { 1152 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy); 1153 } 1154 1155 virtual const char* name() { return "DrawRoundRect"; } 1156 1157private: 1158 float mRx; 1159 float mRy; 1160}; 1161 1162class DrawCircleOp : public DrawStrokableOp { 1163public: 1164 DrawCircleOp(float x, float y, float radius, const SkPaint* paint) 1165 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint), 1166 mX(x), mY(y), mRadius(radius) {} 1167 1168 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1169 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer)); 1170 } 1171 1172 virtual void output(int level, uint32_t logFlags) const { 1173 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius); 1174 } 1175 1176 virtual const char* name() { return "DrawCircle"; } 1177 1178private: 1179 float mX; 1180 float mY; 1181 float mRadius; 1182}; 1183 1184class DrawOvalOp : public DrawStrokableOp { 1185public: 1186 DrawOvalOp(float left, float top, float right, float bottom, const SkPaint* paint) 1187 : DrawStrokableOp(left, top, right, bottom, paint) {} 1188 1189 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1190 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top, 1191 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1192 } 1193 1194 virtual void output(int level, uint32_t logFlags) const { 1195 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds)); 1196 } 1197 1198 virtual const char* name() { return "DrawOval"; } 1199}; 1200 1201class DrawArcOp : public DrawStrokableOp { 1202public: 1203 DrawArcOp(float left, float top, float right, float bottom, 1204 float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) 1205 : DrawStrokableOp(left, top, right, bottom, paint), 1206 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {} 1207 1208 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1209 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top, 1210 mLocalBounds.right, mLocalBounds.bottom, 1211 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer)); 1212 } 1213 1214 virtual void output(int level, uint32_t logFlags) const { 1215 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d", 1216 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter); 1217 } 1218 1219 virtual const char* name() { return "DrawArc"; } 1220 1221private: 1222 float mStartAngle; 1223 float mSweepAngle; 1224 bool mUseCenter; 1225}; 1226 1227class DrawPathOp : public DrawBoundedOp { 1228public: 1229 DrawPathOp(const SkPath* path, const SkPaint* paint) 1230 : DrawBoundedOp(paint), mPath(path) { 1231 float left, top, offset; 1232 uint32_t width, height; 1233 PathCache::computePathBounds(path, paint, left, top, offset, width, height); 1234 left -= offset; 1235 top -= offset; 1236 mLocalBounds.set(left, top, left + width, top + height); 1237 } 1238 1239 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1240 return renderer.drawPath(mPath, getPaint(renderer)); 1241 } 1242 1243 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1244 const DeferredDisplayState& state) { 1245 const SkPaint* paint = getPaint(renderer); 1246 renderer.getCaches().pathCache.precache(mPath, paint); 1247 1248 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 1249 } 1250 1251 virtual void output(int level, uint32_t logFlags) const { 1252 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds)); 1253 } 1254 1255 virtual const char* name() { return "DrawPath"; } 1256 1257private: 1258 const SkPath* mPath; 1259}; 1260 1261class DrawLinesOp : public DrawBoundedOp { 1262public: 1263 DrawLinesOp(const float* points, int count, const SkPaint* paint) 1264 : DrawBoundedOp(points, count, paint), 1265 mPoints(points), mCount(count) { 1266 mLocalBounds.outset(strokeWidthOutset()); 1267 } 1268 1269 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1270 return renderer.drawLines(mPoints, mCount, getPaint(renderer)); 1271 } 1272 1273 virtual void output(int level, uint32_t logFlags) const { 1274 OP_LOG("Draw Lines count %d", mCount); 1275 } 1276 1277 virtual const char* name() { return "DrawLines"; } 1278 1279 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1280 const DeferredDisplayState& state) { 1281 deferInfo.batchId = mPaint->isAntiAlias() ? 1282 DeferredDisplayList::kOpBatch_AlphaVertices : 1283 DeferredDisplayList::kOpBatch_Vertices; 1284 } 1285 1286protected: 1287 const float* mPoints; 1288 int mCount; 1289}; 1290 1291class DrawPointsOp : public DrawLinesOp { 1292public: 1293 DrawPointsOp(const float* points, int count, const SkPaint* paint) 1294 : DrawLinesOp(points, count, paint) {} 1295 1296 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1297 return renderer.drawPoints(mPoints, mCount, getPaint(renderer)); 1298 } 1299 1300 virtual void output(int level, uint32_t logFlags) const { 1301 OP_LOG("Draw Points count %d", mCount); 1302 } 1303 1304 virtual const char* name() { return "DrawPoints"; } 1305}; 1306 1307class DrawSomeTextOp : public DrawOp { 1308public: 1309 DrawSomeTextOp(const char* text, int bytesCount, int count, const SkPaint* paint) 1310 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {}; 1311 1312 virtual void output(int level, uint32_t logFlags) const { 1313 OP_LOG("Draw some text, %d bytes", mBytesCount); 1314 } 1315 1316 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1317 const DeferredDisplayState& state) { 1318 const SkPaint* paint = getPaint(renderer); 1319 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1320 fontRenderer.precache(paint, mText, mCount, mat4::identity()); 1321 1322 deferInfo.batchId = mPaint->getColor() == 0xff000000 ? 1323 DeferredDisplayList::kOpBatch_Text : 1324 DeferredDisplayList::kOpBatch_ColorText; 1325 } 1326 1327protected: 1328 const char* mText; 1329 int mBytesCount; 1330 int mCount; 1331}; 1332 1333class DrawTextOnPathOp : public DrawSomeTextOp { 1334public: 1335 DrawTextOnPathOp(const char* text, int bytesCount, int count, 1336 const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) 1337 : DrawSomeTextOp(text, bytesCount, count, paint), 1338 mPath(path), mHOffset(hOffset), mVOffset(vOffset) { 1339 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1340 } 1341 1342 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1343 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath, 1344 mHOffset, mVOffset, getPaint(renderer)); 1345 } 1346 1347 virtual const char* name() { return "DrawTextOnPath"; } 1348 1349private: 1350 const SkPath* mPath; 1351 float mHOffset; 1352 float mVOffset; 1353}; 1354 1355class DrawPosTextOp : public DrawSomeTextOp { 1356public: 1357 DrawPosTextOp(const char* text, int bytesCount, int count, 1358 const float* positions, const SkPaint* paint) 1359 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) { 1360 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1361 } 1362 1363 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1364 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer)); 1365 } 1366 1367 virtual const char* name() { return "DrawPosText"; } 1368 1369private: 1370 const float* mPositions; 1371}; 1372 1373class DrawTextOp : public DrawBoundedOp { 1374public: 1375 DrawTextOp(const char* text, int bytesCount, int count, float x, float y, 1376 const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds) 1377 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count), 1378 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) { 1379 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float)); 1380 } 1381 1382 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo, 1383 const DeferredDisplayState& state) { 1384 const SkPaint* paint = getPaint(renderer); 1385 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1386 const mat4& transform = renderer.findBestFontTransform(state.mMatrix); 1387 if (mPrecacheTransform != transform) { 1388 fontRenderer.precache(paint, mText, mCount, transform); 1389 mPrecacheTransform = transform; 1390 } 1391 deferInfo.batchId = mPaint->getColor() == 0xff000000 ? 1392 DeferredDisplayList::kOpBatch_Text : 1393 DeferredDisplayList::kOpBatch_ColorText; 1394 1395 deferInfo.mergeId = reinterpret_cast<mergeid_t>(mPaint->getColor()); 1396 1397 // don't merge decorated text - the decorations won't draw in order 1398 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag | 1399 SkPaint::kStrikeThruText_Flag)); 1400 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations && 1401 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; 1402 } 1403 1404 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1405 Rect bounds; 1406 getLocalBounds(renderer.getDrawModifiers(), bounds); 1407 return renderer.drawText(mText, mBytesCount, mCount, mX, mY, 1408 mPositions, getPaint(renderer), mTotalAdvance, bounds); 1409 } 1410 1411 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 1412 const Vector<OpStatePair>& ops, const Rect& bounds) { 1413 status_t status = DrawGlInfo::kStatusDone; 1414 for (unsigned int i = 0; i < ops.size(); i++) { 1415 const DeferredDisplayState& state = *(ops[i].state); 1416 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer; 1417 renderer.restoreDisplayState(state, true); // restore all but the clip 1418 1419 DrawTextOp& op = *((DrawTextOp*)ops[i].op); 1420 // quickReject() will not occure in drawText() so we can use mLocalBounds 1421 // directly, we do not need to account for shadow by calling getLocalBounds() 1422 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY, 1423 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds, 1424 drawOpMode); 1425 } 1426 return status; 1427 } 1428 1429 virtual void output(int level, uint32_t logFlags) const { 1430 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount); 1431 } 1432 1433 virtual const char* name() { return "DrawText"; } 1434 1435private: 1436 const char* mText; 1437 int mBytesCount; 1438 int mCount; 1439 float mX; 1440 float mY; 1441 const float* mPositions; 1442 float mTotalAdvance; 1443 mat4 mPrecacheTransform; 1444}; 1445 1446/////////////////////////////////////////////////////////////////////////////// 1447// SPECIAL DRAW OPERATIONS 1448/////////////////////////////////////////////////////////////////////////////// 1449 1450class DrawFunctorOp : public DrawOp { 1451public: 1452 DrawFunctorOp(Functor* functor) 1453 : DrawOp(NULL), mFunctor(functor) {} 1454 1455 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1456 renderer.startMark("GL functor"); 1457 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty); 1458 renderer.endMark(); 1459 return ret; 1460 } 1461 1462 virtual void output(int level, uint32_t logFlags) const { 1463 OP_LOG("Draw Functor %p", mFunctor); 1464 } 1465 1466 virtual const char* name() { return "DrawFunctor"; } 1467 1468private: 1469 Functor* mFunctor; 1470}; 1471 1472class DrawDisplayListOp : public DrawBoundedOp { 1473 friend class RenderNode; // grant DisplayList access to info of child 1474public: 1475 DrawDisplayListOp(RenderNode* displayList, int flags, const mat4& transformFromParent) 1476 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0), 1477 mDisplayList(displayList), mFlags(flags), mTransformFromParent(transformFromParent) {} 1478 1479 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 1480 bool useQuickReject) { 1481 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) { 1482 mDisplayList->deferNodeInParent(deferStruct, level + 1); 1483 } 1484 } 1485 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 1486 bool useQuickReject) { 1487 if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) { 1488 mDisplayList->replayNodeInParent(replayStruct, level + 1); 1489 } 1490 } 1491 1492 // NOT USED since replay() is overridden 1493 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1494 return DrawGlInfo::kStatusDone; 1495 } 1496 1497 virtual void output(int level, uint32_t logFlags) const { 1498 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags); 1499 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) { 1500 mDisplayList->output(level + 1); 1501 } 1502 } 1503 1504 virtual const char* name() { return "DrawDisplayList"; } 1505 1506 RenderNode* renderNode() { return mDisplayList; } 1507 1508private: 1509 RenderNode* mDisplayList; 1510 const int mFlags; 1511 1512 /////////////////////////// 1513 // Properties below are used by DisplayList::computeOrderingImpl() and iterate() 1514 /////////////////////////// 1515 /** 1516 * Records transform vs parent, used for computing total transform without rerunning DL contents 1517 */ 1518 const mat4 mTransformFromParent; 1519 1520 /** 1521 * Holds the transformation between the projection surface ViewGroup and this DisplayList 1522 * drawing instance. Represents any translations / transformations done within the drawing of 1523 * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this 1524 * DisplayList draw instance. 1525 * 1526 * Note: doesn't include any transformation recorded within the DisplayList and its properties. 1527 */ 1528 mat4 mTransformFromCompositingAncestor; 1529 bool mSkipInOrderDraw; 1530}; 1531 1532/** 1533 * Not a canvas operation, used only by 3d / z ordering logic in RenderNode::iterate() 1534 */ 1535class DrawShadowOp : public DrawOp { 1536public: 1537 DrawShadowOp(const mat4& transformXY, const mat4& transformZ, 1538 float casterAlpha, bool casterUnclipped, 1539 float fallbackWidth, float fallbackHeight, 1540 const SkPath* outline, const SkPath* revealClip) 1541 : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), 1542 mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped), 1543 mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight), 1544 mOutline(outline), mRevealClip(revealClip) {} 1545 1546 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1547 SkPath casterPerimeter; 1548 if (!mOutline || mOutline->isEmpty()) { 1549 casterPerimeter.addRect(0, 0, mFallbackWidth, mFallbackHeight); 1550 } else { 1551 casterPerimeter = *mOutline; 1552 } 1553 1554 if (mRevealClip) { 1555 // intersect the outline with the convex reveal clip 1556 Op(casterPerimeter, *mRevealClip, kIntersect_PathOp, &casterPerimeter); 1557 } 1558 1559 return renderer.drawShadow(mTransformXY, mTransformZ, 1560 mCasterAlpha, mCasterUnclipped, &casterPerimeter); 1561 } 1562 1563 virtual void output(int level, uint32_t logFlags) const { 1564 OP_LOG("DrawShadow of outline %p", mOutline); 1565 } 1566 1567 virtual const char* name() { return "DrawShadow"; } 1568 1569private: 1570 const mat4 mTransformXY; 1571 const mat4 mTransformZ; 1572 const float mCasterAlpha; 1573 const bool mCasterUnclipped; 1574 const float mFallbackWidth; 1575 const float mFallbackHeight; 1576 1577 // these point at convex SkPaths owned by RenderProperties, or null 1578 const SkPath* mOutline; 1579 const SkPath* mRevealClip; 1580}; 1581 1582class DrawLayerOp : public DrawOp { 1583public: 1584 DrawLayerOp(Layer* layer, float x, float y) 1585 : DrawOp(NULL), mLayer(layer), mX(x), mY(y) {} 1586 1587 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1588 return renderer.drawLayer(mLayer, mX, mY); 1589 } 1590 1591 virtual void output(int level, uint32_t logFlags) const { 1592 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY); 1593 } 1594 1595 virtual const char* name() { return "DrawLayer"; } 1596 1597private: 1598 Layer* mLayer; 1599 float mX; 1600 float mY; 1601}; 1602 1603}; // namespace uirenderer 1604}; // namespace android 1605 1606#endif // ANDROID_HWUI_DISPLAY_OPERATION_H 1607