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 <SkXfermode.h> 25 26 #include <private/hwui/DrawGlInfo.h> 27 28 #include "OpenGLRenderer.h" 29 #include "DeferredDisplayList.h" 30 #include "DisplayListRenderer.h" 31 #include "utils/LinearAllocator.h" 32 33 #define CRASH() do { \ 34 *(int *)(uintptr_t)0xbbadbeef = 0; \ 35 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ 36 } while(false) 37 38 #define MATRIX_STRING "[%.2f %.2f %.2f] [%.2f %.2f %.2f] [%.2f %.2f %.2f]" 39 #define MATRIX_ARGS(m) \ 40 m->get(0), m->get(1), m->get(2), \ 41 m->get(3), m->get(4), m->get(5), \ 42 m->get(6), m->get(7), m->get(8) 43 #define RECT_STRING "%.2f %.2f %.2f %.2f" 44 #define RECT_ARGS(r) \ 45 r.left, r.top, r.right, r.bottom 46 47 // Use OP_LOG for logging with arglist, OP_LOGS if just printing char* 48 #define OP_LOGS(s) OP_LOG("%s", s) 49 #define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ ) 50 51 namespace android { 52 namespace uirenderer { 53 54 /** 55 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they 56 * may be replayed to an OpenGLRenderer. 57 * 58 * To avoid individual memory allocations, DisplayListOps may only be allocated into a 59 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a 60 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or 61 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is 62 * never called as LinearAllocators are simply discarded, so no memory management should be done in 63 * this class. 64 */ 65 class DisplayListOp { 66 public: 67 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted. 68 // standard new() intentionally not implemented, and delete/deconstructor should never be used. 69 virtual ~DisplayListOp() { CRASH(); } 70 static void operator delete(void* ptr) { CRASH(); } 71 /** static void* operator new(size_t size); PURPOSELY OMITTED **/ 72 static void* operator new(size_t size, LinearAllocator& allocator) { 73 return allocator.alloc(size); 74 } 75 76 enum OpLogFlag { 77 kOpLogFlag_Recurse = 0x1, 78 kOpLogFlag_JSON = 0x2 // TODO: add? 79 }; 80 81 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 82 bool useQuickReject) = 0; 83 84 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 85 bool useQuickReject) = 0; 86 87 virtual void output(int level, uint32_t logFlags = 0) = 0; 88 89 // NOTE: it would be nice to declare constants and overriding the implementation in each op to 90 // point at the constants, but that seems to require a .cpp file 91 virtual const char* name() = 0; 92 93 /** 94 * Stores the relevant canvas state of the object between deferral and replay (if the canvas 95 * state supports being stored) See OpenGLRenderer::simpleClipAndState() 96 * 97 * TODO: don't reserve space for StateOps that won't be deferred 98 */ 99 DeferredDisplayState state; 100 101 }; 102 103 class StateOp : public DisplayListOp { 104 public: 105 StateOp() {}; 106 107 virtual ~StateOp() {} 108 109 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 110 bool useQuickReject) { 111 // default behavior only affects immediate, deferrable state, issue directly to renderer 112 applyState(deferStruct.mRenderer, saveCount); 113 } 114 115 /** 116 * State operations are applied directly to the renderer, but can cause the deferred drawing op 117 * list to flush 118 */ 119 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 120 bool useQuickReject) { 121 applyState(replayStruct.mRenderer, saveCount); 122 } 123 124 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0; 125 }; 126 127 class DrawOp : public DisplayListOp { 128 friend class MergingDrawBatch; 129 public: 130 DrawOp(SkPaint* paint) 131 : mPaint(paint), mQuickRejected(false) {} 132 133 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 134 bool useQuickReject) { 135 if (mQuickRejected && CC_LIKELY(useQuickReject)) { 136 return; 137 } 138 139 if (!getLocalBounds(state.mBounds)) { 140 // empty bounds signify bounds can't be calculated 141 state.mBounds.setEmpty(); 142 } 143 144 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this); 145 } 146 147 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 148 bool useQuickReject) { 149 if (mQuickRejected && CC_LIKELY(useQuickReject)) { 150 return; 151 } 152 153 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty); 154 } 155 156 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0; 157 158 /** 159 * Draw multiple instances of an operation, must be overidden for operations that merge 160 * 161 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith), 162 * and pure translation transformations. Other guarantees of similarity should be enforced by 163 * reducing which operations are tagged as mergeable. 164 */ 165 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 166 const Vector<DrawOp*>& ops, const Rect& bounds) { 167 status_t status = DrawGlInfo::kStatusDone; 168 for (unsigned int i = 0; i < ops.size(); i++) { 169 renderer.restoreDisplayState(ops[i]->state); 170 status |= ops[i]->applyDraw(renderer, dirty); 171 } 172 return status; 173 } 174 175 /* 176 * When this method is invoked the state field is initialized to have the 177 * final rendering state. We can thus use it to process data as it will be 178 * used at draw time. 179 * 180 * Additionally, this method allows subclasses to provide defer-time preferences for batching 181 * and merging. 182 * 183 * Return true if the op can merge with others of its kind (such subclasses should implement 184 * multiDraw) 185 */ 186 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 187 return false; 188 } 189 190 // returns true if bounds exist 191 virtual bool getLocalBounds(Rect& localBounds) { return false; } 192 193 // TODO: better refine localbounds usage 194 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; } 195 bool getQuickRejected() { return mQuickRejected; } 196 197 inline int getPaintAlpha() { 198 return OpenGLRenderer::getAlphaDirect(mPaint); 199 } 200 201 inline float strokeWidthOutset() { 202 float width = mPaint->getStrokeWidth(); 203 if (width == 0) return 0.5f; // account for hairline 204 return width * 0.5f; 205 } 206 207 protected: 208 SkPaint* getPaint(OpenGLRenderer& renderer) { 209 return renderer.filterPaint(mPaint); 210 } 211 212 SkPaint* mPaint; // should be accessed via getPaint() when applying 213 bool mQuickRejected; 214 }; 215 216 class DrawBoundedOp : public DrawOp { 217 public: 218 DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint) 219 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {} 220 221 // Calculates bounds as smallest rect encompassing all points 222 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in 223 // subclass' constructor) 224 DrawBoundedOp(const float* points, int count, SkPaint* paint) 225 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) { 226 for (int i = 2; i < count; i += 2) { 227 mLocalBounds.left = fminf(mLocalBounds.left, points[i]); 228 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]); 229 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]); 230 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]); 231 } 232 } 233 234 // default empty constructor for bounds, to be overridden in child constructor body 235 DrawBoundedOp(SkPaint* paint) 236 : DrawOp(paint) {} 237 238 bool getLocalBounds(Rect& localBounds) { 239 localBounds.set(mLocalBounds); 240 return true; 241 } 242 243 bool mergeAllowed() { 244 if (!state.mMatrix.isPureTranslate()) return false; 245 246 // checks that we're unclipped, and srcover 247 const Rect& opBounds = state.mBounds; 248 return fabs(opBounds.getWidth() - mLocalBounds.getWidth()) < 0.1 && 249 fabs(opBounds.getHeight() - mLocalBounds.getHeight()) < 0.1 && 250 (OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode); 251 } 252 253 protected: 254 Rect mLocalBounds; // displayed area in LOCAL coord. doesn't incorporate stroke, so check paint 255 }; 256 257 /////////////////////////////////////////////////////////////////////////////// 258 // STATE OPERATIONS - these may affect the state of the canvas/renderer, but do 259 // not directly draw or alter output 260 /////////////////////////////////////////////////////////////////////////////// 261 262 class SaveOp : public StateOp { 263 friend class DisplayList; // give DisplayList private constructor/reinit access 264 public: 265 SaveOp(int flags) 266 : mFlags(flags) {} 267 268 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 269 bool useQuickReject) { 270 int newSaveCount = deferStruct.mRenderer.save(mFlags); 271 deferStruct.mDeferredList.addSave(deferStruct.mRenderer, this, newSaveCount); 272 } 273 274 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 275 renderer.save(mFlags); 276 } 277 278 virtual void output(int level, uint32_t logFlags) { 279 OP_LOG("Save flags %x", mFlags); 280 } 281 282 virtual const char* name() { return "Save"; } 283 284 int getFlags() const { return mFlags; } 285 private: 286 SaveOp() {} 287 DisplayListOp* reinit(int flags) { 288 mFlags = flags; 289 return this; 290 } 291 292 int mFlags; 293 }; 294 295 class RestoreToCountOp : public StateOp { 296 friend class DisplayList; // give DisplayList private constructor/reinit access 297 public: 298 RestoreToCountOp(int count) 299 : mCount(count) {} 300 301 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 302 bool useQuickReject) { 303 deferStruct.mDeferredList.addRestoreToCount(deferStruct.mRenderer, 304 this, saveCount + mCount); 305 deferStruct.mRenderer.restoreToCount(saveCount + mCount); 306 } 307 308 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 309 renderer.restoreToCount(saveCount + mCount); 310 } 311 312 virtual void output(int level, uint32_t logFlags) { 313 OP_LOG("Restore to count %d", mCount); 314 } 315 316 virtual const char* name() { return "RestoreToCount"; } 317 318 private: 319 RestoreToCountOp() {} 320 DisplayListOp* reinit(int count) { 321 mCount = count; 322 return this; 323 } 324 325 int mCount; 326 }; 327 328 class SaveLayerOp : public StateOp { 329 friend class DisplayList; // give DisplayList private constructor/reinit access 330 public: 331 SaveLayerOp(float left, float top, float right, float bottom, 332 int alpha, SkXfermode::Mode mode, int flags) 333 : mArea(left, top, right, bottom), mAlpha(alpha), mMode(mode), mFlags(flags) {} 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 mAlpha, mMode, mFlags); 345 } 346 347 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 348 renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mAlpha, mMode, mFlags); 349 } 350 351 virtual void output(int level, uint32_t logFlags) { 352 OP_LOG("SaveLayer%s of area " RECT_STRING, 353 (isSaveLayerAlpha() ? "Alpha" : ""),RECT_ARGS(mArea)); 354 } 355 356 virtual const char* name() { return isSaveLayerAlpha() ? "SaveLayerAlpha" : "SaveLayer"; } 357 358 int getFlags() { return mFlags; } 359 360 private: 361 // Special case, reserved for direct DisplayList usage 362 SaveLayerOp() {} 363 DisplayListOp* reinit(float left, float top, float right, float bottom, 364 int alpha, SkXfermode::Mode mode, int flags) { 365 mArea.set(left, top, right, bottom); 366 mAlpha = alpha; 367 mMode = mode; 368 mFlags = flags; 369 return this; 370 } 371 372 bool isSaveLayerAlpha() { return mAlpha < 255 && mMode == SkXfermode::kSrcOver_Mode; } 373 Rect mArea; 374 int mAlpha; 375 SkXfermode::Mode mMode; 376 int mFlags; 377 }; 378 379 class TranslateOp : public StateOp { 380 public: 381 TranslateOp(float dx, float dy) 382 : mDx(dx), mDy(dy) {} 383 384 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 385 renderer.translate(mDx, mDy); 386 } 387 388 virtual void output(int level, uint32_t logFlags) { 389 OP_LOG("Translate by %f %f", mDx, mDy); 390 } 391 392 virtual const char* name() { return "Translate"; } 393 394 private: 395 float mDx; 396 float mDy; 397 }; 398 399 class RotateOp : public StateOp { 400 public: 401 RotateOp(float degrees) 402 : mDegrees(degrees) {} 403 404 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 405 renderer.rotate(mDegrees); 406 } 407 408 virtual void output(int level, uint32_t logFlags) { 409 OP_LOG("Rotate by %f degrees", mDegrees); 410 } 411 412 virtual const char* name() { return "Rotate"; } 413 414 private: 415 float mDegrees; 416 }; 417 418 class ScaleOp : public StateOp { 419 public: 420 ScaleOp(float sx, float sy) 421 : mSx(sx), mSy(sy) {} 422 423 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 424 renderer.scale(mSx, mSy); 425 } 426 427 virtual void output(int level, uint32_t logFlags) { 428 OP_LOG("Scale by %f %f", mSx, mSy); 429 } 430 431 virtual const char* name() { return "Scale"; } 432 433 private: 434 float mSx; 435 float mSy; 436 }; 437 438 class SkewOp : public StateOp { 439 public: 440 SkewOp(float sx, float sy) 441 : mSx(sx), mSy(sy) {} 442 443 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 444 renderer.skew(mSx, mSy); 445 } 446 447 virtual void output(int level, uint32_t logFlags) { 448 OP_LOG("Skew by %f %f", mSx, mSy); 449 } 450 451 virtual const char* name() { return "Skew"; } 452 453 private: 454 float mSx; 455 float mSy; 456 }; 457 458 class SetMatrixOp : public StateOp { 459 public: 460 SetMatrixOp(SkMatrix* matrix) 461 : mMatrix(matrix) {} 462 463 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 464 renderer.setMatrix(mMatrix); 465 } 466 467 virtual void output(int level, uint32_t logFlags) { 468 OP_LOG("SetMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix)); 469 } 470 471 virtual const char* name() { return "SetMatrix"; } 472 473 private: 474 SkMatrix* mMatrix; 475 }; 476 477 class ConcatMatrixOp : public StateOp { 478 public: 479 ConcatMatrixOp(SkMatrix* matrix) 480 : mMatrix(matrix) {} 481 482 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 483 renderer.concatMatrix(mMatrix); 484 } 485 486 virtual void output(int level, uint32_t logFlags) { 487 OP_LOG("ConcatMatrix " MATRIX_STRING, MATRIX_ARGS(mMatrix)); 488 } 489 490 virtual const char* name() { return "ConcatMatrix"; } 491 492 private: 493 SkMatrix* mMatrix; 494 }; 495 496 class ClipOp : public StateOp { 497 public: 498 ClipOp(SkRegion::Op op) : mOp(op) {} 499 500 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 501 bool useQuickReject) { 502 // NOTE: must defer op BEFORE applying state, since it may read clip 503 deferStruct.mDeferredList.addClip(deferStruct.mRenderer, this); 504 505 // TODO: Can we avoid applying complex clips at defer time? 506 applyState(deferStruct.mRenderer, saveCount); 507 } 508 509 bool canCauseComplexClip() { 510 return ((mOp != SkRegion::kIntersect_Op) && (mOp != SkRegion::kReplace_Op)) || !isRect(); 511 } 512 513 protected: 514 ClipOp() {} 515 virtual bool isRect() { return false; } 516 517 SkRegion::Op mOp; 518 }; 519 520 class ClipRectOp : public ClipOp { 521 friend class DisplayList; // give DisplayList private constructor/reinit access 522 public: 523 ClipRectOp(float left, float top, float right, float bottom, SkRegion::Op op) 524 : ClipOp(op), mArea(left, top, right, bottom) {} 525 526 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 527 renderer.clipRect(mArea.left, mArea.top, mArea.right, mArea.bottom, mOp); 528 } 529 530 virtual void output(int level, uint32_t logFlags) { 531 OP_LOG("ClipRect " RECT_STRING, RECT_ARGS(mArea)); 532 } 533 534 virtual const char* name() { return "ClipRect"; } 535 536 protected: 537 virtual bool isRect() { return true; } 538 539 private: 540 ClipRectOp() {} 541 DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) { 542 mOp = op; 543 mArea.set(left, top, right, bottom); 544 return this; 545 } 546 547 Rect mArea; 548 }; 549 550 class ClipPathOp : public ClipOp { 551 public: 552 ClipPathOp(SkPath* path, SkRegion::Op op) 553 : ClipOp(op), mPath(path) {} 554 555 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 556 renderer.clipPath(mPath, mOp); 557 } 558 559 virtual void output(int level, uint32_t logFlags) { 560 SkRect bounds = mPath->getBounds(); 561 OP_LOG("ClipPath bounds " RECT_STRING, 562 bounds.left(), bounds.top(), bounds.right(), bounds.bottom()); 563 } 564 565 virtual const char* name() { return "ClipPath"; } 566 567 private: 568 SkPath* mPath; 569 }; 570 571 class ClipRegionOp : public ClipOp { 572 public: 573 ClipRegionOp(SkRegion* region, SkRegion::Op op) 574 : ClipOp(op), mRegion(region) {} 575 576 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 577 renderer.clipRegion(mRegion, mOp); 578 } 579 580 virtual void output(int level, uint32_t logFlags) { 581 SkIRect bounds = mRegion->getBounds(); 582 OP_LOG("ClipRegion bounds %d %d %d %d", 583 bounds.left(), bounds.top(), bounds.right(), bounds.bottom()); 584 } 585 586 virtual const char* name() { return "ClipRegion"; } 587 588 private: 589 SkRegion* mRegion; 590 SkRegion::Op mOp; 591 }; 592 593 class ResetShaderOp : public StateOp { 594 public: 595 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 596 renderer.resetShader(); 597 } 598 599 virtual void output(int level, uint32_t logFlags) { 600 OP_LOGS("ResetShader"); 601 } 602 603 virtual const char* name() { return "ResetShader"; } 604 }; 605 606 class SetupShaderOp : public StateOp { 607 public: 608 SetupShaderOp(SkiaShader* shader) 609 : mShader(shader) {} 610 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 611 renderer.setupShader(mShader); 612 } 613 614 virtual void output(int level, uint32_t logFlags) { 615 OP_LOG("SetupShader, shader %p", mShader); 616 } 617 618 virtual const char* name() { return "SetupShader"; } 619 620 private: 621 SkiaShader* mShader; 622 }; 623 624 class ResetColorFilterOp : public StateOp { 625 public: 626 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 627 renderer.resetColorFilter(); 628 } 629 630 virtual void output(int level, uint32_t logFlags) { 631 OP_LOGS("ResetColorFilter"); 632 } 633 634 virtual const char* name() { return "ResetColorFilter"; } 635 }; 636 637 class SetupColorFilterOp : public StateOp { 638 public: 639 SetupColorFilterOp(SkiaColorFilter* colorFilter) 640 : mColorFilter(colorFilter) {} 641 642 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 643 renderer.setupColorFilter(mColorFilter); 644 } 645 646 virtual void output(int level, uint32_t logFlags) { 647 OP_LOG("SetupColorFilter, filter %p", mColorFilter); 648 } 649 650 virtual const char* name() { return "SetupColorFilter"; } 651 652 private: 653 SkiaColorFilter* mColorFilter; 654 }; 655 656 class ResetShadowOp : public StateOp { 657 public: 658 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 659 renderer.resetShadow(); 660 } 661 662 virtual void output(int level, uint32_t logFlags) { 663 OP_LOGS("ResetShadow"); 664 } 665 666 virtual const char* name() { return "ResetShadow"; } 667 }; 668 669 class SetupShadowOp : public StateOp { 670 public: 671 SetupShadowOp(float radius, float dx, float dy, int color) 672 : mRadius(radius), mDx(dx), mDy(dy), mColor(color) {} 673 674 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 675 renderer.setupShadow(mRadius, mDx, mDy, mColor); 676 } 677 678 virtual void output(int level, uint32_t logFlags) { 679 OP_LOG("SetupShadow, radius %f, %f, %f, color %#x", mRadius, mDx, mDy, mColor); 680 } 681 682 virtual const char* name() { return "SetupShadow"; } 683 684 private: 685 float mRadius; 686 float mDx; 687 float mDy; 688 int mColor; 689 }; 690 691 class ResetPaintFilterOp : public StateOp { 692 public: 693 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 694 renderer.resetPaintFilter(); 695 } 696 697 virtual void output(int level, uint32_t logFlags) { 698 OP_LOGS("ResetPaintFilter"); 699 } 700 701 virtual const char* name() { return "ResetPaintFilter"; } 702 }; 703 704 class SetupPaintFilterOp : public StateOp { 705 public: 706 SetupPaintFilterOp(int clearBits, int setBits) 707 : mClearBits(clearBits), mSetBits(setBits) {} 708 709 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const { 710 renderer.setupPaintFilter(mClearBits, mSetBits); 711 } 712 713 virtual void output(int level, uint32_t logFlags) { 714 OP_LOG("SetupPaintFilter, clear %#x, set %#x", mClearBits, mSetBits); 715 } 716 717 virtual const char* name() { return "SetupPaintFilter"; } 718 719 private: 720 int mClearBits; 721 int mSetBits; 722 }; 723 724 725 /////////////////////////////////////////////////////////////////////////////// 726 // DRAW OPERATIONS - these are operations that can draw to the canvas's device 727 /////////////////////////////////////////////////////////////////////////////// 728 729 class DrawBitmapOp : public DrawBoundedOp { 730 public: 731 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint) 732 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), 733 paint), 734 mBitmap(bitmap) {} 735 736 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 737 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, 738 getPaint(renderer)); 739 } 740 741 #define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \ 742 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \ 743 texCoordsRect.xDim, texCoordsRect.yDim) 744 745 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 746 const Vector<DrawOp*>& ops, const Rect& bounds) { 747 renderer.restoreDisplayState(state, true); // restore all but the clip 748 renderer.setFullScreenClip(); // ensure merged ops aren't clipped 749 TextureVertex vertices[6 * ops.size()]; 750 TextureVertex* vertex = &vertices[0]; 751 752 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, and allowing 753 // them to be merged in getBatchId() 754 const Rect texCoords(0, 0, 1, 1); 755 756 const float width = mBitmap->width(); 757 const float height = mBitmap->height(); 758 for (unsigned int i = 0; i < ops.size(); i++) { 759 const Rect& opBounds = ops[i]->state.mBounds; 760 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top); 761 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); 762 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); 763 764 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); 765 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); 766 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom); 767 } 768 769 return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], bounds, mPaint); 770 } 771 772 virtual void output(int level, uint32_t logFlags) { 773 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top); 774 } 775 776 virtual const char* name() { return "DrawBitmap"; } 777 778 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 779 *batchId = DeferredDisplayList::kOpBatch_Bitmap; 780 *mergeId = (mergeid_t)mBitmap; 781 782 // don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in 783 // MergingDrawBatch::canMergeWith 784 return mergeAllowed() && (mBitmap->getConfig() != SkBitmap::kA8_Config); 785 } 786 787 const SkBitmap* bitmap() { return mBitmap; } 788 protected: 789 SkBitmap* mBitmap; 790 }; 791 792 class DrawBitmapMatrixOp : public DrawBoundedOp { 793 public: 794 DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) 795 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) { 796 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height()); 797 const mat4 transform(*matrix); 798 transform.mapRect(mLocalBounds); 799 } 800 801 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 802 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer)); 803 } 804 805 virtual void output(int level, uint32_t logFlags) { 806 OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix)); 807 } 808 809 virtual const char* name() { return "DrawBitmapMatrix"; } 810 811 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 812 *batchId = DeferredDisplayList::kOpBatch_Bitmap; 813 return false; 814 } 815 816 private: 817 SkBitmap* mBitmap; 818 SkMatrix* mMatrix; 819 }; 820 821 class DrawBitmapRectOp : public DrawBoundedOp { 822 public: 823 DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, 824 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) 825 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint), 826 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {} 827 828 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 829 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom, 830 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, 831 getPaint(renderer)); 832 } 833 834 virtual void output(int level, uint32_t logFlags) { 835 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING, 836 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds)); 837 } 838 839 virtual const char* name() { return "DrawBitmapRect"; } 840 841 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 842 *batchId = DeferredDisplayList::kOpBatch_Bitmap; 843 return false; 844 } 845 846 private: 847 SkBitmap* mBitmap; 848 Rect mSrc; 849 }; 850 851 class DrawBitmapDataOp : public DrawBitmapOp { 852 public: 853 DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint) 854 : DrawBitmapOp(bitmap, left, top, paint) {} 855 856 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 857 return renderer.drawBitmapData(mBitmap, mLocalBounds.left, 858 mLocalBounds.top, getPaint(renderer)); 859 } 860 861 virtual void output(int level, uint32_t logFlags) { 862 OP_LOG("Draw bitmap %p", mBitmap); 863 } 864 865 virtual const char* name() { return "DrawBitmapData"; } 866 867 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 868 *batchId = DeferredDisplayList::kOpBatch_Bitmap; 869 return false; 870 } 871 }; 872 873 class DrawBitmapMeshOp : public DrawBoundedOp { 874 public: 875 DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight, 876 float* vertices, int* colors, SkPaint* paint) 877 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint), 878 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight), 879 mVertices(vertices), mColors(colors) {} 880 881 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 882 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight, 883 mVertices, mColors, getPaint(renderer)); 884 } 885 886 virtual void output(int level, uint32_t logFlags) { 887 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight); 888 } 889 890 virtual const char* name() { return "DrawBitmapMesh"; } 891 892 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 893 *batchId = DeferredDisplayList::kOpBatch_Bitmap; 894 return false; 895 } 896 897 private: 898 SkBitmap* mBitmap; 899 int mMeshWidth; 900 int mMeshHeight; 901 float* mVertices; 902 int* mColors; 903 }; 904 905 class DrawPatchOp : public DrawBoundedOp { 906 public: 907 DrawPatchOp(SkBitmap* bitmap, const int32_t* xDivs, 908 const int32_t* yDivs, const uint32_t* colors, uint32_t width, uint32_t height, 909 int8_t numColors, float left, float top, float right, float bottom, 910 int alpha, SkXfermode::Mode mode) 911 : DrawBoundedOp(left, top, right, bottom, 0), 912 mBitmap(bitmap), mxDivs(xDivs), myDivs(yDivs), 913 mColors(colors), mxDivsCount(width), myDivsCount(height), 914 mNumColors(numColors), mAlpha(alpha), mMode(mode) {}; 915 916 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 917 // NOTE: not calling the virtual method, which takes a paint 918 return renderer.drawPatch(mBitmap, mxDivs, myDivs, mColors, 919 mxDivsCount, myDivsCount, mNumColors, 920 mLocalBounds.left, mLocalBounds.top, 921 mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode); 922 } 923 924 virtual void output(int level, uint32_t logFlags) { 925 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds)); 926 } 927 928 virtual const char* name() { return "DrawPatch"; } 929 930 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 931 *batchId = DeferredDisplayList::kOpBatch_Patch; 932 *mergeId = (mergeid_t)mBitmap; 933 return true; 934 } 935 936 private: 937 SkBitmap* mBitmap; 938 const int32_t* mxDivs; 939 const int32_t* myDivs; 940 const uint32_t* mColors; 941 uint32_t mxDivsCount; 942 uint32_t myDivsCount; 943 int8_t mNumColors; 944 int mAlpha; 945 SkXfermode::Mode mMode; 946 }; 947 948 class DrawColorOp : public DrawOp { 949 public: 950 DrawColorOp(int color, SkXfermode::Mode mode) 951 : DrawOp(0), mColor(color), mMode(mode) {}; 952 953 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 954 return renderer.drawColor(mColor, mMode); 955 } 956 957 virtual void output(int level, uint32_t logFlags) { 958 OP_LOG("Draw color %#x, mode %d", mColor, mMode); 959 } 960 961 virtual const char* name() { return "DrawColor"; } 962 963 private: 964 int mColor; 965 SkXfermode::Mode mMode; 966 }; 967 968 class DrawStrokableOp : public DrawBoundedOp { 969 public: 970 DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint) 971 : DrawBoundedOp(left, top, right, bottom, paint) {}; 972 973 bool getLocalBounds(Rect& localBounds) { 974 localBounds.set(mLocalBounds); 975 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) { 976 localBounds.outset(strokeWidthOutset()); 977 } 978 return true; 979 } 980 981 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 982 if (mPaint->getPathEffect()) { 983 *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 984 } else { 985 *batchId = mPaint->isAntiAlias() ? 986 DeferredDisplayList::kOpBatch_AlphaVertices : 987 DeferredDisplayList::kOpBatch_Vertices; 988 } 989 return false; 990 } 991 }; 992 993 class DrawRectOp : public DrawStrokableOp { 994 public: 995 DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint) 996 : DrawStrokableOp(left, top, right, bottom, paint) {} 997 998 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 999 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top, 1000 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1001 } 1002 1003 virtual void output(int level, uint32_t logFlags) { 1004 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds)); 1005 } 1006 1007 virtual const char* name() { return "DrawRect"; } 1008 }; 1009 1010 class DrawRectsOp : public DrawBoundedOp { 1011 public: 1012 DrawRectsOp(const float* rects, int count, SkPaint* paint) 1013 : DrawBoundedOp(rects, count, paint), 1014 mRects(rects), mCount(count) {} 1015 1016 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1017 return renderer.drawRects(mRects, mCount, getPaint(renderer)); 1018 } 1019 1020 virtual void output(int level, uint32_t logFlags) { 1021 OP_LOG("Draw Rects count %d", mCount); 1022 } 1023 1024 virtual const char* name() { return "DrawRects"; } 1025 1026 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 1027 *batchId = DeferredDisplayList::kOpBatch_Vertices; 1028 return false; 1029 } 1030 1031 private: 1032 const float* mRects; 1033 int mCount; 1034 }; 1035 1036 class DrawRoundRectOp : public DrawStrokableOp { 1037 public: 1038 DrawRoundRectOp(float left, float top, float right, float bottom, 1039 float rx, float ry, SkPaint* paint) 1040 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {} 1041 1042 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1043 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top, 1044 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer)); 1045 } 1046 1047 virtual void output(int level, uint32_t logFlags) { 1048 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy); 1049 } 1050 1051 virtual const char* name() { return "DrawRoundRect"; } 1052 1053 private: 1054 float mRx; 1055 float mRy; 1056 }; 1057 1058 class DrawCircleOp : public DrawStrokableOp { 1059 public: 1060 DrawCircleOp(float x, float y, float radius, SkPaint* paint) 1061 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint), 1062 mX(x), mY(y), mRadius(radius) {} 1063 1064 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1065 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer)); 1066 } 1067 1068 virtual void output(int level, uint32_t logFlags) { 1069 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius); 1070 } 1071 1072 virtual const char* name() { return "DrawCircle"; } 1073 1074 private: 1075 float mX; 1076 float mY; 1077 float mRadius; 1078 }; 1079 1080 class DrawOvalOp : public DrawStrokableOp { 1081 public: 1082 DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint) 1083 : DrawStrokableOp(left, top, right, bottom, paint) {} 1084 1085 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1086 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top, 1087 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1088 } 1089 1090 virtual void output(int level, uint32_t logFlags) { 1091 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds)); 1092 } 1093 1094 virtual const char* name() { return "DrawOval"; } 1095 }; 1096 1097 class DrawArcOp : public DrawStrokableOp { 1098 public: 1099 DrawArcOp(float left, float top, float right, float bottom, 1100 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) 1101 : DrawStrokableOp(left, top, right, bottom, paint), 1102 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {} 1103 1104 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1105 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top, 1106 mLocalBounds.right, mLocalBounds.bottom, 1107 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer)); 1108 } 1109 1110 virtual void output(int level, uint32_t logFlags) { 1111 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d", 1112 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter); 1113 } 1114 1115 virtual const char* name() { return "DrawArc"; } 1116 1117 private: 1118 float mStartAngle; 1119 float mSweepAngle; 1120 bool mUseCenter; 1121 }; 1122 1123 class DrawPathOp : public DrawBoundedOp { 1124 public: 1125 DrawPathOp(SkPath* path, SkPaint* paint) 1126 : DrawBoundedOp(paint), mPath(path) { 1127 float left, top, offset; 1128 uint32_t width, height; 1129 PathCache::computePathBounds(path, paint, left, top, offset, width, height); 1130 left -= offset; 1131 top -= offset; 1132 mLocalBounds.set(left, top, left + width, top + height); 1133 } 1134 1135 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1136 return renderer.drawPath(mPath, getPaint(renderer)); 1137 } 1138 1139 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 1140 SkPaint* paint = getPaint(renderer); 1141 renderer.getCaches().pathCache.precache(mPath, paint); 1142 1143 *batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 1144 return false; 1145 } 1146 1147 virtual void output(int level, uint32_t logFlags) { 1148 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds)); 1149 } 1150 1151 virtual const char* name() { return "DrawPath"; } 1152 1153 private: 1154 SkPath* mPath; 1155 }; 1156 1157 class DrawLinesOp : public DrawBoundedOp { 1158 public: 1159 DrawLinesOp(float* points, int count, SkPaint* paint) 1160 : DrawBoundedOp(points, count, paint), 1161 mPoints(points), mCount(count) { 1162 mLocalBounds.outset(strokeWidthOutset()); 1163 } 1164 1165 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1166 return renderer.drawLines(mPoints, mCount, getPaint(renderer)); 1167 } 1168 1169 virtual void output(int level, uint32_t logFlags) { 1170 OP_LOG("Draw Lines count %d", mCount); 1171 } 1172 1173 virtual const char* name() { return "DrawLines"; } 1174 1175 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 1176 *batchId = mPaint->isAntiAlias() ? 1177 DeferredDisplayList::kOpBatch_AlphaVertices : 1178 DeferredDisplayList::kOpBatch_Vertices; 1179 return false; 1180 } 1181 1182 protected: 1183 float* mPoints; 1184 int mCount; 1185 }; 1186 1187 class DrawPointsOp : public DrawLinesOp { 1188 public: 1189 DrawPointsOp(float* points, int count, SkPaint* paint) 1190 : DrawLinesOp(points, count, paint) {} 1191 1192 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1193 return renderer.drawPoints(mPoints, mCount, getPaint(renderer)); 1194 } 1195 1196 virtual void output(int level, uint32_t logFlags) { 1197 OP_LOG("Draw Points count %d", mCount); 1198 } 1199 1200 virtual const char* name() { return "DrawPoints"; } 1201 }; 1202 1203 class DrawSomeTextOp : public DrawOp { 1204 public: 1205 DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint) 1206 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {}; 1207 1208 virtual void output(int level, uint32_t logFlags) { 1209 OP_LOG("Draw some text, %d bytes", mBytesCount); 1210 } 1211 1212 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 1213 SkPaint* paint = getPaint(renderer); 1214 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1215 fontRenderer.precache(paint, mText, mCount, mat4::identity()); 1216 1217 *batchId = mPaint->getColor() == 0xff000000 ? 1218 DeferredDisplayList::kOpBatch_Text : 1219 DeferredDisplayList::kOpBatch_ColorText; 1220 1221 return false; 1222 } 1223 1224 protected: 1225 const char* mText; 1226 int mBytesCount; 1227 int mCount; 1228 }; 1229 1230 class DrawTextOnPathOp : public DrawSomeTextOp { 1231 public: 1232 DrawTextOnPathOp(const char* text, int bytesCount, int count, 1233 SkPath* path, float hOffset, float vOffset, SkPaint* paint) 1234 : DrawSomeTextOp(text, bytesCount, count, paint), 1235 mPath(path), mHOffset(hOffset), mVOffset(vOffset) { 1236 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1237 } 1238 1239 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1240 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath, 1241 mHOffset, mVOffset, getPaint(renderer)); 1242 } 1243 1244 virtual const char* name() { return "DrawTextOnPath"; } 1245 1246 private: 1247 SkPath* mPath; 1248 float mHOffset; 1249 float mVOffset; 1250 }; 1251 1252 class DrawPosTextOp : public DrawSomeTextOp { 1253 public: 1254 DrawPosTextOp(const char* text, int bytesCount, int count, 1255 const float* positions, SkPaint* paint) 1256 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) { 1257 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1258 } 1259 1260 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1261 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer)); 1262 } 1263 1264 virtual const char* name() { return "DrawPosText"; } 1265 1266 private: 1267 const float* mPositions; 1268 }; 1269 1270 class DrawTextOp : public DrawBoundedOp { 1271 public: 1272 DrawTextOp(const char* text, int bytesCount, int count, float x, float y, 1273 const float* positions, SkPaint* paint, float length) 1274 : DrawBoundedOp(paint), mText(text), mBytesCount(bytesCount), mCount(count), 1275 mX(x), mY(y), mPositions(positions), mLength(length) { 1276 // duplicates bounds calculation from OpenGLRenderer::drawText, but doesn't alter mX 1277 SkPaint::FontMetrics metrics; 1278 paint->getFontMetrics(&metrics, 0.0f); 1279 switch (paint->getTextAlign()) { 1280 case SkPaint::kCenter_Align: 1281 x -= length / 2.0f; 1282 break; 1283 case SkPaint::kRight_Align: 1284 x -= length; 1285 break; 1286 default: 1287 break; 1288 } 1289 mLocalBounds.set(x, mY + metrics.fTop, x + length, mY + metrics.fBottom); 1290 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float)); 1291 } 1292 1293 virtual bool onDefer(OpenGLRenderer& renderer, int* batchId, mergeid_t* mergeId) { 1294 SkPaint* paint = getPaint(renderer); 1295 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1296 const mat4& transform = renderer.findBestFontTransform(state.mMatrix); 1297 if (mPrecacheTransform != transform) { 1298 fontRenderer.precache(paint, mText, mCount, transform); 1299 mPrecacheTransform = transform; 1300 } 1301 *batchId = mPaint->getColor() == 0xff000000 ? 1302 DeferredDisplayList::kOpBatch_Text : 1303 DeferredDisplayList::kOpBatch_ColorText; 1304 1305 *mergeId = (mergeid_t)mPaint->getColor(); 1306 1307 // don't merge decorated text - the decorations won't draw in order 1308 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag | 1309 SkPaint::kStrikeThruText_Flag)); 1310 return mergeAllowed() && noDecorations; 1311 } 1312 1313 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1314 return renderer.drawText(mText, mBytesCount, mCount, mX, mY, 1315 mPositions, getPaint(renderer), mLength); 1316 } 1317 1318 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 1319 const Vector<DrawOp*>& ops, const Rect& bounds) { 1320 status_t status = DrawGlInfo::kStatusDone; 1321 renderer.setFullScreenClip(); // ensure merged ops aren't clipped 1322 for (unsigned int i = 0; i < ops.size(); i++) { 1323 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer; 1324 renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip 1325 1326 DrawTextOp& op = *((DrawTextOp*)ops[i]); 1327 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY, 1328 op.mPositions, op.getPaint(renderer), op.mLength, drawOpMode); 1329 } 1330 return status; 1331 } 1332 1333 virtual void output(int level, uint32_t logFlags) { 1334 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount); 1335 } 1336 1337 virtual const char* name() { return "DrawText"; } 1338 1339 private: 1340 const char* mText; 1341 int mBytesCount; 1342 int mCount; 1343 float mX; 1344 float mY; 1345 const float* mPositions; 1346 float mLength; 1347 mat4 mPrecacheTransform; 1348 }; 1349 1350 /////////////////////////////////////////////////////////////////////////////// 1351 // SPECIAL DRAW OPERATIONS 1352 /////////////////////////////////////////////////////////////////////////////// 1353 1354 class DrawFunctorOp : public DrawOp { 1355 public: 1356 DrawFunctorOp(Functor* functor) 1357 : DrawOp(0), mFunctor(functor) {} 1358 1359 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1360 renderer.startMark("GL functor"); 1361 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty); 1362 renderer.endMark(); 1363 return ret; 1364 } 1365 1366 virtual void output(int level, uint32_t logFlags) { 1367 OP_LOG("Draw Functor %p", mFunctor); 1368 } 1369 1370 virtual const char* name() { return "DrawFunctor"; } 1371 1372 private: 1373 Functor* mFunctor; 1374 }; 1375 1376 class DrawDisplayListOp : public DrawBoundedOp { 1377 public: 1378 DrawDisplayListOp(DisplayList* displayList, int flags) 1379 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0), 1380 mDisplayList(displayList), mFlags(flags) {} 1381 1382 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 1383 bool useQuickReject) { 1384 if (mDisplayList && mDisplayList->isRenderable()) { 1385 mDisplayList->defer(deferStruct, level + 1); 1386 } 1387 } 1388 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 1389 bool useQuickReject) { 1390 if (mDisplayList && mDisplayList->isRenderable()) { 1391 mDisplayList->replay(replayStruct, level + 1); 1392 } 1393 } 1394 1395 // NOT USED since replay() is overridden 1396 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1397 return DrawGlInfo::kStatusDone; 1398 } 1399 1400 virtual void output(int level, uint32_t logFlags) { 1401 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags); 1402 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) { 1403 mDisplayList->output(level + 1); 1404 } 1405 } 1406 1407 virtual const char* name() { return "DrawDisplayList"; } 1408 1409 private: 1410 DisplayList* mDisplayList; 1411 int mFlags; 1412 }; 1413 1414 class DrawLayerOp : public DrawOp { 1415 public: 1416 DrawLayerOp(Layer* layer, float x, float y) 1417 : DrawOp(0), mLayer(layer), mX(x), mY(y) {} 1418 1419 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1420 return renderer.drawLayer(mLayer, mX, mY); 1421 } 1422 1423 virtual void output(int level, uint32_t logFlags) { 1424 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY); 1425 } 1426 1427 virtual const char* name() { return "DrawLayer"; } 1428 1429 private: 1430 Layer* mLayer; 1431 float mX; 1432 float mY; 1433 }; 1434 1435 }; // namespace uirenderer 1436 }; // namespace android 1437 1438 #endif // ANDROID_HWUI_DISPLAY_OPERATION_H 1439