DisplayListOp.h revision 5216c3b05fc6c7bacd74be67b932fe3aba89cc8e
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 "AssetAtlas.h" 30#include "DeferredDisplayList.h" 31#include "DisplayListRenderer.h" 32#include "UvMapper.h" 33#include "utils/LinearAllocator.h" 34 35#define CRASH() do { \ 36 *(int *)(uintptr_t) 0xbbadbeef = 0; \ 37 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ 38} while(false) 39 40// Use OP_LOG for logging with arglist, OP_LOGS if just printing char* 41#define OP_LOGS(s) OP_LOG("%s", (s)) 42#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ ) 43 44namespace android { 45namespace uirenderer { 46 47/** 48 * Structure for storing canvas operations when they are recorded into a DisplayList, so that they 49 * may be replayed to an OpenGLRenderer. 50 * 51 * To avoid individual memory allocations, DisplayListOps may only be allocated into a 52 * LinearAllocator's managed memory buffers. Each pointer held by a DisplayListOp is either a 53 * pointer into memory also allocated in the LinearAllocator (mostly for text and float buffers) or 54 * references a externally refcounted object (Sk... and Skia... objects). ~DisplayListOp() is 55 * never called as LinearAllocators are simply discarded, so no memory management should be done in 56 * this class. 57 */ 58class DisplayListOp { 59public: 60 // These objects should always be allocated with a LinearAllocator, and never destroyed/deleted. 61 // standard new() intentionally not implemented, and delete/deconstructor should never be used. 62 virtual ~DisplayListOp() { CRASH(); } 63 static void operator delete(void* ptr) { CRASH(); } 64 /** static void* operator new(size_t size); PURPOSELY OMITTED **/ 65 static void* operator new(size_t size, LinearAllocator& allocator) { 66 return allocator.alloc(size); 67 } 68 69 enum OpLogFlag { 70 kOpLogFlag_Recurse = 0x1, 71 kOpLogFlag_JSON = 0x2 // TODO: add? 72 }; 73 74 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 75 bool useQuickReject) = 0; 76 77 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 78 bool useQuickReject) = 0; 79 80 virtual void output(int level, uint32_t logFlags = 0) = 0; 81 82 // NOTE: it would be nice to declare constants and overriding the implementation in each op to 83 // point at the constants, but that seems to require a .cpp file 84 virtual const char* name() = 0; 85 86 /** 87 * Stores the relevant canvas state of the object between deferral and replay (if the canvas 88 * state supports being stored) See OpenGLRenderer::simpleClipAndState() 89 * 90 * TODO: don't reserve space for StateOps that won't be deferred 91 */ 92 DeferredDisplayState state; 93 94}; 95 96class StateOp : public DisplayListOp { 97public: 98 StateOp() {}; 99 100 virtual ~StateOp() {} 101 102 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 103 bool useQuickReject) { 104 // default behavior only affects immediate, deferrable state, issue directly to renderer 105 applyState(deferStruct.mRenderer, saveCount); 106 } 107 108 /** 109 * State operations are applied directly to the renderer, but can cause the deferred drawing op 110 * list to flush 111 */ 112 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 113 bool useQuickReject) { 114 applyState(replayStruct.mRenderer, saveCount); 115 } 116 117 virtual void applyState(OpenGLRenderer& renderer, int saveCount) const = 0; 118}; 119 120class DrawOp : public DisplayListOp { 121friend class MergingDrawBatch; 122public: 123 DrawOp(SkPaint* paint) 124 : mPaint(paint), mQuickRejected(false) {} 125 126 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 127 bool useQuickReject) { 128 if (mQuickRejected && CC_LIKELY(useQuickReject)) { 129 return; 130 } 131 132 if (!getLocalBounds(state.mBounds)) { 133 // empty bounds signify bounds can't be calculated 134 state.mBounds.setEmpty(); 135 } 136 137 deferStruct.mDeferredList.addDrawOp(deferStruct.mRenderer, this); 138 } 139 140 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 141 bool useQuickReject) { 142 if (mQuickRejected && CC_LIKELY(useQuickReject)) { 143 return; 144 } 145 146 replayStruct.mDrawGlStatus |= applyDraw(replayStruct.mRenderer, replayStruct.mDirty); 147 } 148 149 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) = 0; 150 151 /** 152 * Draw multiple instances of an operation, must be overidden for operations that merge 153 * 154 * Currently guarantees certain similarities between ops (see MergingDrawBatch::canMergeWith), 155 * and pure translation transformations. Other guarantees of similarity should be enforced by 156 * reducing which operations are tagged as mergeable. 157 */ 158 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 159 const Vector<DrawOp*>& ops, const Rect& bounds) { 160 status_t status = DrawGlInfo::kStatusDone; 161 for (unsigned int i = 0; i < ops.size(); i++) { 162 renderer.restoreDisplayState(ops[i]->state, true); 163 status |= ops[i]->applyDraw(renderer, dirty); 164 } 165 return status; 166 } 167 168 /** 169 * When this method is invoked the state field is initialized to have the 170 * final rendering state. We can thus use it to process data as it will be 171 * used at draw time. 172 * 173 * Additionally, this method allows subclasses to provide defer-time preferences for batching 174 * and merging. 175 * 176 * if a subclass can set deferInfo.mergeable to true, it should implement multiDraw() 177 */ 178 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {} 179 180 // returns true if bounds exist 181 virtual bool getLocalBounds(Rect& localBounds) { return false; } 182 183 // TODO: better refine localbounds usage 184 void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; } 185 bool getQuickRejected() { return mQuickRejected; } 186 187 inline int getPaintAlpha() { 188 return OpenGLRenderer::getAlphaDirect(mPaint); 189 } 190 191 inline float strokeWidthOutset() { 192 float width = mPaint->getStrokeWidth(); 193 if (width == 0) return 0.5f; // account for hairline 194 return width * 0.5f; 195 } 196 197protected: 198 SkPaint* getPaint(OpenGLRenderer& renderer) { 199 return renderer.filterPaint(mPaint); 200 } 201 202 // Helper method for determining op opaqueness. Assumes op fills its bounds in local 203 // coordinates, and that paint's alpha is used 204 inline bool isOpaqueOverBounds() { 205 // ensure that local bounds cover mapped bounds 206 if (!state.mMatrix.isSimple()) return false; 207 208 // check state/paint for transparency 209 if (state.mDrawModifiers.mShader || 210 state.mAlpha != 1.0f || 211 (mPaint && mPaint->getAlpha() != 0xFF)) return false; 212 213 SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint); 214 return (mode == SkXfermode::kSrcOver_Mode || 215 mode == SkXfermode::kSrc_Mode); 216 217 } 218 219 SkPaint* mPaint; // should be accessed via getPaint() when applying 220 bool mQuickRejected; 221}; 222 223class DrawBoundedOp : public DrawOp { 224public: 225 DrawBoundedOp(float left, float top, float right, float bottom, SkPaint* paint) 226 : DrawOp(paint), mLocalBounds(left, top, right, bottom) {} 227 228 DrawBoundedOp(const Rect& localBounds, SkPaint* paint) 229 : DrawOp(paint), mLocalBounds(localBounds) {} 230 231 // Calculates bounds as smallest rect encompassing all points 232 // NOTE: requires at least 1 vertex, and doesn't account for stroke size (should be handled in 233 // subclass' constructor) 234 DrawBoundedOp(const float* points, int count, SkPaint* paint) 235 : DrawOp(paint), mLocalBounds(points[0], points[1], points[0], points[1]) { 236 for (int i = 2; i < count; i += 2) { 237 mLocalBounds.left = fminf(mLocalBounds.left, points[i]); 238 mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]); 239 mLocalBounds.top = fminf(mLocalBounds.top, points[i + 1]); 240 mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i + 1]); 241 } 242 } 243 244 // default empty constructor for bounds, to be overridden in child constructor body 245 DrawBoundedOp(SkPaint* paint) 246 : DrawOp(paint) {} 247 248 bool getLocalBounds(Rect& localBounds) { 249 localBounds.set(mLocalBounds); 250 return true; 251 } 252 253protected: 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 262class SaveOp : public StateOp { 263 friend class DisplayList; // give DisplayList private constructor/reinit access 264public: 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; } 285private: 286 SaveOp() {} 287 DisplayListOp* reinit(int flags) { 288 mFlags = flags; 289 return this; 290 } 291 292 int mFlags; 293}; 294 295class RestoreToCountOp : public StateOp { 296 friend class DisplayList; // give DisplayList private constructor/reinit access 297public: 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 318private: 319 RestoreToCountOp() {} 320 DisplayListOp* reinit(int count) { 321 mCount = count; 322 return this; 323 } 324 325 int mCount; 326}; 327 328class SaveLayerOp : public StateOp { 329 friend class DisplayList; // give DisplayList private constructor/reinit access 330public: 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 360private: 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 379class TranslateOp : public StateOp { 380public: 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 394private: 395 float mDx; 396 float mDy; 397}; 398 399class RotateOp : public StateOp { 400public: 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 414private: 415 float mDegrees; 416}; 417 418class ScaleOp : public StateOp { 419public: 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 433private: 434 float mSx; 435 float mSy; 436}; 437 438class SkewOp : public StateOp { 439public: 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 453private: 454 float mSx; 455 float mSy; 456}; 457 458class SetMatrixOp : public StateOp { 459public: 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 473private: 474 SkMatrix* mMatrix; 475}; 476 477class ConcatMatrixOp : public StateOp { 478public: 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 492private: 493 SkMatrix* mMatrix; 494}; 495 496class ClipOp : public StateOp { 497public: 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 513protected: 514 ClipOp() {} 515 virtual bool isRect() { return false; } 516 517 SkRegion::Op mOp; 518}; 519 520class ClipRectOp : public ClipOp { 521 friend class DisplayList; // give DisplayList private constructor/reinit access 522public: 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 536protected: 537 virtual bool isRect() { return true; } 538 539private: 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 550class ClipPathOp : public ClipOp { 551public: 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 567private: 568 SkPath* mPath; 569}; 570 571class ClipRegionOp : public ClipOp { 572public: 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 588private: 589 SkRegion* mRegion; 590 SkRegion::Op mOp; 591}; 592 593class ResetShaderOp : public StateOp { 594public: 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 606class SetupShaderOp : public StateOp { 607public: 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 620private: 621 SkiaShader* mShader; 622}; 623 624class ResetColorFilterOp : public StateOp { 625public: 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 637class SetupColorFilterOp : public StateOp { 638public: 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 652private: 653 SkiaColorFilter* mColorFilter; 654}; 655 656class ResetShadowOp : public StateOp { 657public: 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 669class SetupShadowOp : public StateOp { 670public: 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 684private: 685 float mRadius; 686 float mDx; 687 float mDy; 688 int mColor; 689}; 690 691class ResetPaintFilterOp : public StateOp { 692public: 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 704class SetupPaintFilterOp : public StateOp { 705public: 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 719private: 720 int mClearBits; 721 int mSetBits; 722}; 723 724/////////////////////////////////////////////////////////////////////////////// 725// DRAW OPERATIONS - these are operations that can draw to the canvas's device 726/////////////////////////////////////////////////////////////////////////////// 727 728class DrawBitmapOp : public DrawBoundedOp { 729public: 730 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint) 731 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint), 732 mBitmap(bitmap), mAtlasEntry(NULL) { 733 } 734 735 DrawBitmapOp(SkBitmap* bitmap, float left, float top, SkPaint* paint, 736 const AssetAtlas::Entry* entry) 737 : DrawBoundedOp(left, top, left + bitmap->width(), top + bitmap->height(), paint), 738 mBitmap(bitmap), mAtlasEntry(entry) { 739 if (entry) mUvMapper = entry->uvMapper; 740 } 741 742 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 743 return renderer.drawBitmap(mBitmap, mLocalBounds.left, mLocalBounds.top, 744 getPaint(renderer)); 745 } 746 747#define SET_TEXTURE(ptr, posRect, offsetRect, texCoordsRect, xDim, yDim) \ 748 TextureVertex::set(ptr++, posRect.xDim - offsetRect.left, posRect.yDim - offsetRect.top, \ 749 texCoordsRect.xDim, texCoordsRect.yDim) 750 751 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 752 const Vector<DrawOp*>& ops, const Rect& bounds) { 753 renderer.restoreDisplayState(state, true); // restore all but the clip 754 TextureVertex vertices[6 * ops.size()]; 755 TextureVertex* vertex = &vertices[0]; 756 757 bool transformed = false; 758 759 // TODO: manually handle rect clip for bitmaps by adjusting texCoords per op, 760 // and allowing them to be merged in getBatchId() 761 for (unsigned int i = 0; i < ops.size(); i++) { 762 const Rect& opBounds = ops[i]->state.mBounds; 763 // When we reach multiDraw(), the matrix can be either 764 // pureTranslate or simple (translate and/or scale). 765 // If the matrix is not pureTranslate, then we have a scale 766 if (!ops[i]->state.mMatrix.isPureTranslate()) transformed = true; 767 768 Rect texCoords(0, 0, 1, 1); 769 ((DrawBitmapOp*) ops[i])->mUvMapper.map(texCoords); 770 771 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, top); 772 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); 773 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); 774 775 SET_TEXTURE(vertex, opBounds, bounds, texCoords, left, bottom); 776 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, top); 777 SET_TEXTURE(vertex, opBounds, bounds, texCoords, right, bottom); 778 } 779 780 return renderer.drawBitmaps(mBitmap, ops.size(), &vertices[0], 781 transformed, bounds, mPaint); 782 } 783 784 virtual void output(int level, uint32_t logFlags) { 785 OP_LOG("Draw bitmap %p at %f %f", mBitmap, mLocalBounds.left, mLocalBounds.top); 786 } 787 788 virtual const char* name() { return "DrawBitmap"; } 789 790 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 791 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 792 deferInfo.mergeId = mAtlasEntry ? (mergeid_t) &mAtlasEntry->atlas : (mergeid_t) mBitmap; 793 794 // Don't merge A8 bitmaps - the paint's color isn't compared by mergeId, or in 795 // MergingDrawBatch::canMergeWith() 796 // TODO: support clipped bitmaps by handling them in SET_TEXTURE 797 deferInfo.mergeable = state.mMatrix.isSimple() && !state.mClipSideFlags && 798 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode && 799 (mBitmap->getConfig() != SkBitmap::kA8_Config); 800 } 801 802 const SkBitmap* bitmap() { return mBitmap; } 803protected: 804 SkBitmap* mBitmap; 805 const AssetAtlas::Entry* mAtlasEntry; 806 UvMapper mUvMapper; 807}; 808 809class DrawBitmapMatrixOp : public DrawBoundedOp { 810public: 811 DrawBitmapMatrixOp(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) 812 : DrawBoundedOp(paint), mBitmap(bitmap), mMatrix(matrix) { 813 mLocalBounds.set(0, 0, bitmap->width(), bitmap->height()); 814 const mat4 transform(*matrix); 815 transform.mapRect(mLocalBounds); 816 } 817 818 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 819 return renderer.drawBitmap(mBitmap, mMatrix, getPaint(renderer)); 820 } 821 822 virtual void output(int level, uint32_t logFlags) { 823 OP_LOG("Draw bitmap %p matrix " MATRIX_STRING, mBitmap, MATRIX_ARGS(mMatrix)); 824 } 825 826 virtual const char* name() { return "DrawBitmapMatrix"; } 827 828 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 829 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 830 } 831 832private: 833 SkBitmap* mBitmap; 834 SkMatrix* mMatrix; 835}; 836 837class DrawBitmapRectOp : public DrawBoundedOp { 838public: 839 DrawBitmapRectOp(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, 840 float dstLeft, float dstTop, float dstRight, float dstBottom, SkPaint* paint) 841 : DrawBoundedOp(dstLeft, dstTop, dstRight, dstBottom, paint), 842 mBitmap(bitmap), mSrc(srcLeft, srcTop, srcRight, srcBottom) {} 843 844 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 845 return renderer.drawBitmap(mBitmap, mSrc.left, mSrc.top, mSrc.right, mSrc.bottom, 846 mLocalBounds.left, mLocalBounds.top, mLocalBounds.right, mLocalBounds.bottom, 847 getPaint(renderer)); 848 } 849 850 virtual void output(int level, uint32_t logFlags) { 851 OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING, 852 mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds)); 853 } 854 855 virtual const char* name() { return "DrawBitmapRect"; } 856 857 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 858 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 859 } 860 861private: 862 SkBitmap* mBitmap; 863 Rect mSrc; 864}; 865 866class DrawBitmapDataOp : public DrawBitmapOp { 867public: 868 DrawBitmapDataOp(SkBitmap* bitmap, float left, float top, SkPaint* paint) 869 : DrawBitmapOp(bitmap, left, top, paint) {} 870 871 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 872 return renderer.drawBitmapData(mBitmap, mLocalBounds.left, 873 mLocalBounds.top, getPaint(renderer)); 874 } 875 876 virtual void output(int level, uint32_t logFlags) { 877 OP_LOG("Draw bitmap %p", mBitmap); 878 } 879 880 virtual const char* name() { return "DrawBitmapData"; } 881 882 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 883 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 884 } 885}; 886 887class DrawBitmapMeshOp : public DrawBoundedOp { 888public: 889 DrawBitmapMeshOp(SkBitmap* bitmap, int meshWidth, int meshHeight, 890 float* vertices, int* colors, SkPaint* paint) 891 : DrawBoundedOp(vertices, 2 * (meshWidth + 1) * (meshHeight + 1), paint), 892 mBitmap(bitmap), mMeshWidth(meshWidth), mMeshHeight(meshHeight), 893 mVertices(vertices), mColors(colors) {} 894 895 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 896 return renderer.drawBitmapMesh(mBitmap, mMeshWidth, mMeshHeight, 897 mVertices, mColors, getPaint(renderer)); 898 } 899 900 virtual void output(int level, uint32_t logFlags) { 901 OP_LOG("Draw bitmap %p mesh %d x %d", mBitmap, mMeshWidth, mMeshHeight); 902 } 903 904 virtual const char* name() { return "DrawBitmapMesh"; } 905 906 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 907 deferInfo.batchId = DeferredDisplayList::kOpBatch_Bitmap; 908 } 909 910private: 911 SkBitmap* mBitmap; 912 int mMeshWidth; 913 int mMeshHeight; 914 float* mVertices; 915 int* mColors; 916}; 917 918class DrawPatchOp : public DrawBoundedOp { 919public: 920 DrawPatchOp(SkBitmap* bitmap, Res_png_9patch* patch, 921 float left, float top, float right, float bottom, int alpha, SkXfermode::Mode mode) 922 : DrawBoundedOp(left, top, right, bottom, 0), 923 mBitmap(bitmap), mPatch(patch), mAlpha(alpha), mMode(mode), 924 mGenerationId(0), mMesh(NULL) { 925 mEntry = Caches::getInstance().assetAtlas.getEntry(bitmap); 926 }; 927 928 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 929 if (!mMesh || renderer.getCaches().patchCache.getGenerationId() != mGenerationId) { 930 PatchCache& cache = renderer.getCaches().patchCache; 931 mMesh = cache.get(mEntry, mBitmap->width(), mBitmap->height(), 932 mLocalBounds.right - mLocalBounds.left, mLocalBounds.bottom - mLocalBounds.top, 933 mPatch); 934 mGenerationId = cache.getGenerationId(); 935 } 936 // We're not calling the public variant of drawPatch() here 937 // This method won't perform the quickReject() since we've already done it at this point 938 return renderer.drawPatch(mBitmap, mMesh, mEntry, mLocalBounds.left, mLocalBounds.top, 939 mLocalBounds.right, mLocalBounds.bottom, mAlpha, mMode); 940 } 941 942 virtual void output(int level, uint32_t logFlags) { 943 OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds)); 944 } 945 946 virtual const char* name() { return "DrawPatch"; } 947 948 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 949 deferInfo.batchId = DeferredDisplayList::kOpBatch_Patch; 950 deferInfo.mergeId = mEntry ? (mergeid_t) &mEntry->atlas : (mergeid_t) mBitmap; 951 deferInfo.mergeable = true; 952 deferInfo.opaqueOverBounds = isOpaqueOverBounds() && mBitmap->isOpaque(); 953 } 954 955private: 956 SkBitmap* mBitmap; 957 Res_png_9patch* mPatch; 958 959 int mAlpha; 960 SkXfermode::Mode mMode; 961 962 uint32_t mGenerationId; 963 const Patch* mMesh; 964 AssetAtlas::Entry* mEntry; 965}; 966 967class DrawColorOp : public DrawOp { 968public: 969 DrawColorOp(int color, SkXfermode::Mode mode) 970 : DrawOp(0), mColor(color), mMode(mode) {}; 971 972 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 973 return renderer.drawColor(mColor, mMode); 974 } 975 976 virtual void output(int level, uint32_t logFlags) { 977 OP_LOG("Draw color %#x, mode %d", mColor, mMode); 978 } 979 980 virtual const char* name() { return "DrawColor"; } 981 982private: 983 int mColor; 984 SkXfermode::Mode mMode; 985}; 986 987class DrawStrokableOp : public DrawBoundedOp { 988public: 989 DrawStrokableOp(float left, float top, float right, float bottom, SkPaint* paint) 990 : DrawBoundedOp(left, top, right, bottom, paint) {}; 991 992 bool getLocalBounds(Rect& localBounds) { 993 localBounds.set(mLocalBounds); 994 if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) { 995 localBounds.outset(strokeWidthOutset()); 996 } 997 return true; 998 } 999 1000 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1001 if (mPaint->getPathEffect()) { 1002 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 1003 } else { 1004 deferInfo.batchId = mPaint->isAntiAlias() ? 1005 DeferredDisplayList::kOpBatch_AlphaVertices : 1006 DeferredDisplayList::kOpBatch_Vertices; 1007 } 1008 } 1009}; 1010 1011class DrawRectOp : public DrawStrokableOp { 1012public: 1013 DrawRectOp(float left, float top, float right, float bottom, SkPaint* paint) 1014 : DrawStrokableOp(left, top, right, bottom, paint) {} 1015 1016 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1017 return renderer.drawRect(mLocalBounds.left, mLocalBounds.top, 1018 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1019 } 1020 1021 virtual void output(int level, uint32_t logFlags) { 1022 OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds)); 1023 } 1024 1025 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1026 DrawStrokableOp::onDefer(renderer, deferInfo); 1027 deferInfo.opaqueOverBounds = isOpaqueOverBounds() && 1028 mPaint->getStyle() == SkPaint::kFill_Style; 1029 } 1030 1031 virtual const char* name() { return "DrawRect"; } 1032}; 1033 1034class DrawRectsOp : public DrawBoundedOp { 1035public: 1036 DrawRectsOp(const float* rects, int count, SkPaint* paint) 1037 : DrawBoundedOp(rects, count, paint), 1038 mRects(rects), mCount(count) {} 1039 1040 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1041 return renderer.drawRects(mRects, mCount, getPaint(renderer)); 1042 } 1043 1044 virtual void output(int level, uint32_t logFlags) { 1045 OP_LOG("Draw Rects count %d", mCount); 1046 } 1047 1048 virtual const char* name() { return "DrawRects"; } 1049 1050 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1051 deferInfo.batchId = DeferredDisplayList::kOpBatch_Vertices; 1052 } 1053 1054private: 1055 const float* mRects; 1056 int mCount; 1057}; 1058 1059class DrawRoundRectOp : public DrawStrokableOp { 1060public: 1061 DrawRoundRectOp(float left, float top, float right, float bottom, 1062 float rx, float ry, SkPaint* paint) 1063 : DrawStrokableOp(left, top, right, bottom, paint), mRx(rx), mRy(ry) {} 1064 1065 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1066 return renderer.drawRoundRect(mLocalBounds.left, mLocalBounds.top, 1067 mLocalBounds.right, mLocalBounds.bottom, mRx, mRy, getPaint(renderer)); 1068 } 1069 1070 virtual void output(int level, uint32_t logFlags) { 1071 OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy); 1072 } 1073 1074 virtual const char* name() { return "DrawRoundRect"; } 1075 1076private: 1077 float mRx; 1078 float mRy; 1079}; 1080 1081class DrawCircleOp : public DrawStrokableOp { 1082public: 1083 DrawCircleOp(float x, float y, float radius, SkPaint* paint) 1084 : DrawStrokableOp(x - radius, y - radius, x + radius, y + radius, paint), 1085 mX(x), mY(y), mRadius(radius) {} 1086 1087 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1088 return renderer.drawCircle(mX, mY, mRadius, getPaint(renderer)); 1089 } 1090 1091 virtual void output(int level, uint32_t logFlags) { 1092 OP_LOG("Draw Circle x %f, y %f, r %f", mX, mY, mRadius); 1093 } 1094 1095 virtual const char* name() { return "DrawCircle"; } 1096 1097private: 1098 float mX; 1099 float mY; 1100 float mRadius; 1101}; 1102 1103class DrawOvalOp : public DrawStrokableOp { 1104public: 1105 DrawOvalOp(float left, float top, float right, float bottom, SkPaint* paint) 1106 : DrawStrokableOp(left, top, right, bottom, paint) {} 1107 1108 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1109 return renderer.drawOval(mLocalBounds.left, mLocalBounds.top, 1110 mLocalBounds.right, mLocalBounds.bottom, getPaint(renderer)); 1111 } 1112 1113 virtual void output(int level, uint32_t logFlags) { 1114 OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds)); 1115 } 1116 1117 virtual const char* name() { return "DrawOval"; } 1118}; 1119 1120class DrawArcOp : public DrawStrokableOp { 1121public: 1122 DrawArcOp(float left, float top, float right, float bottom, 1123 float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) 1124 : DrawStrokableOp(left, top, right, bottom, paint), 1125 mStartAngle(startAngle), mSweepAngle(sweepAngle), mUseCenter(useCenter) {} 1126 1127 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1128 return renderer.drawArc(mLocalBounds.left, mLocalBounds.top, 1129 mLocalBounds.right, mLocalBounds.bottom, 1130 mStartAngle, mSweepAngle, mUseCenter, getPaint(renderer)); 1131 } 1132 1133 virtual void output(int level, uint32_t logFlags) { 1134 OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d", 1135 RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter); 1136 } 1137 1138 virtual const char* name() { return "DrawArc"; } 1139 1140private: 1141 float mStartAngle; 1142 float mSweepAngle; 1143 bool mUseCenter; 1144}; 1145 1146class DrawPathOp : public DrawBoundedOp { 1147public: 1148 DrawPathOp(SkPath* path, SkPaint* paint) 1149 : DrawBoundedOp(paint), mPath(path) { 1150 float left, top, offset; 1151 uint32_t width, height; 1152 PathCache::computePathBounds(path, paint, left, top, offset, width, height); 1153 left -= offset; 1154 top -= offset; 1155 mLocalBounds.set(left, top, left + width, top + height); 1156 } 1157 1158 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1159 return renderer.drawPath(mPath, getPaint(renderer)); 1160 } 1161 1162 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1163 SkPaint* paint = getPaint(renderer); 1164 renderer.getCaches().pathCache.precache(mPath, paint); 1165 1166 deferInfo.batchId = DeferredDisplayList::kOpBatch_AlphaMaskTexture; 1167 } 1168 1169 virtual void output(int level, uint32_t logFlags) { 1170 OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds)); 1171 } 1172 1173 virtual const char* name() { return "DrawPath"; } 1174 1175private: 1176 SkPath* mPath; 1177}; 1178 1179class DrawLinesOp : public DrawBoundedOp { 1180public: 1181 DrawLinesOp(float* points, int count, SkPaint* paint) 1182 : DrawBoundedOp(points, count, paint), 1183 mPoints(points), mCount(count) { 1184 mLocalBounds.outset(strokeWidthOutset()); 1185 } 1186 1187 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1188 return renderer.drawLines(mPoints, mCount, getPaint(renderer)); 1189 } 1190 1191 virtual void output(int level, uint32_t logFlags) { 1192 OP_LOG("Draw Lines count %d", mCount); 1193 } 1194 1195 virtual const char* name() { return "DrawLines"; } 1196 1197 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1198 deferInfo.batchId = mPaint->isAntiAlias() ? 1199 DeferredDisplayList::kOpBatch_AlphaVertices : 1200 DeferredDisplayList::kOpBatch_Vertices; 1201 } 1202 1203protected: 1204 float* mPoints; 1205 int mCount; 1206}; 1207 1208class DrawPointsOp : public DrawLinesOp { 1209public: 1210 DrawPointsOp(float* points, int count, SkPaint* paint) 1211 : DrawLinesOp(points, count, paint) {} 1212 1213 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1214 return renderer.drawPoints(mPoints, mCount, getPaint(renderer)); 1215 } 1216 1217 virtual void output(int level, uint32_t logFlags) { 1218 OP_LOG("Draw Points count %d", mCount); 1219 } 1220 1221 virtual const char* name() { return "DrawPoints"; } 1222}; 1223 1224class DrawSomeTextOp : public DrawOp { 1225public: 1226 DrawSomeTextOp(const char* text, int bytesCount, int count, SkPaint* paint) 1227 : DrawOp(paint), mText(text), mBytesCount(bytesCount), mCount(count) {}; 1228 1229 virtual void output(int level, uint32_t logFlags) { 1230 OP_LOG("Draw some text, %d bytes", mBytesCount); 1231 } 1232 1233 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1234 SkPaint* paint = getPaint(renderer); 1235 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1236 fontRenderer.precache(paint, mText, mCount, mat4::identity()); 1237 1238 deferInfo.batchId = mPaint->getColor() == 0xff000000 ? 1239 DeferredDisplayList::kOpBatch_Text : 1240 DeferredDisplayList::kOpBatch_ColorText; 1241 } 1242 1243protected: 1244 const char* mText; 1245 int mBytesCount; 1246 int mCount; 1247}; 1248 1249class DrawTextOnPathOp : public DrawSomeTextOp { 1250public: 1251 DrawTextOnPathOp(const char* text, int bytesCount, int count, 1252 SkPath* path, float hOffset, float vOffset, SkPaint* paint) 1253 : DrawSomeTextOp(text, bytesCount, count, paint), 1254 mPath(path), mHOffset(hOffset), mVOffset(vOffset) { 1255 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1256 } 1257 1258 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1259 return renderer.drawTextOnPath(mText, mBytesCount, mCount, mPath, 1260 mHOffset, mVOffset, getPaint(renderer)); 1261 } 1262 1263 virtual const char* name() { return "DrawTextOnPath"; } 1264 1265private: 1266 SkPath* mPath; 1267 float mHOffset; 1268 float mVOffset; 1269}; 1270 1271class DrawPosTextOp : public DrawSomeTextOp { 1272public: 1273 DrawPosTextOp(const char* text, int bytesCount, int count, 1274 const float* positions, SkPaint* paint) 1275 : DrawSomeTextOp(text, bytesCount, count, paint), mPositions(positions) { 1276 /* TODO: inherit from DrawBounded and init mLocalBounds */ 1277 } 1278 1279 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1280 return renderer.drawPosText(mText, mBytesCount, mCount, mPositions, getPaint(renderer)); 1281 } 1282 1283 virtual const char* name() { return "DrawPosText"; } 1284 1285private: 1286 const float* mPositions; 1287}; 1288 1289class DrawTextOp : public DrawBoundedOp { 1290public: 1291 DrawTextOp(const char* text, int bytesCount, int count, float x, float y, 1292 const float* positions, SkPaint* paint, float totalAdvance, const Rect& bounds) 1293 : DrawBoundedOp(bounds, paint), mText(text), mBytesCount(bytesCount), mCount(count), 1294 mX(x), mY(y), mPositions(positions), mTotalAdvance(totalAdvance) { 1295 mLocalBounds.translate(x,y); 1296 memset(&mPrecacheTransform.data[0], 0xff, 16 * sizeof(float)); 1297 } 1298 1299 virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) { 1300 SkPaint* paint = getPaint(renderer); 1301 FontRenderer& fontRenderer = renderer.getCaches().fontRenderer->getFontRenderer(paint); 1302 const mat4& transform = renderer.findBestFontTransform(state.mMatrix); 1303 if (mPrecacheTransform != transform) { 1304 fontRenderer.precache(paint, mText, mCount, transform); 1305 mPrecacheTransform = transform; 1306 } 1307 deferInfo.batchId = mPaint->getColor() == 0xff000000 ? 1308 DeferredDisplayList::kOpBatch_Text : 1309 DeferredDisplayList::kOpBatch_ColorText; 1310 1311 deferInfo.mergeId = (mergeid_t)mPaint->getColor(); 1312 1313 // don't merge decorated text - the decorations won't draw in order 1314 bool noDecorations = !(mPaint->getFlags() & (SkPaint::kUnderlineText_Flag | 1315 SkPaint::kStrikeThruText_Flag)); 1316 deferInfo.mergeable = state.mMatrix.isPureTranslate() && noDecorations && 1317 OpenGLRenderer::getXfermodeDirect(mPaint) == SkXfermode::kSrcOver_Mode; 1318 } 1319 1320 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1321 return renderer.drawText(mText, mBytesCount, mCount, mX, mY, 1322 mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds); 1323 } 1324 1325 virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty, 1326 const Vector<DrawOp*>& ops, const Rect& bounds) { 1327 status_t status = DrawGlInfo::kStatusDone; 1328 for (unsigned int i = 0; i < ops.size(); i++) { 1329 DrawOpMode drawOpMode = (i == ops.size() - 1) ? kDrawOpMode_Flush : kDrawOpMode_Defer; 1330 renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip 1331 1332 DrawTextOp& op = *((DrawTextOp*)ops[i]); 1333 status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY, 1334 op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds, 1335 drawOpMode); 1336 } 1337 return status; 1338 } 1339 1340 virtual void output(int level, uint32_t logFlags) { 1341 OP_LOG("Draw Text of count %d, bytes %d", mCount, mBytesCount); 1342 } 1343 1344 virtual const char* name() { return "DrawText"; } 1345 1346private: 1347 const char* mText; 1348 int mBytesCount; 1349 int mCount; 1350 float mX; 1351 float mY; 1352 const float* mPositions; 1353 float mTotalAdvance; 1354 mat4 mPrecacheTransform; 1355}; 1356 1357/////////////////////////////////////////////////////////////////////////////// 1358// SPECIAL DRAW OPERATIONS 1359/////////////////////////////////////////////////////////////////////////////// 1360 1361class DrawFunctorOp : public DrawOp { 1362public: 1363 DrawFunctorOp(Functor* functor) 1364 : DrawOp(0), mFunctor(functor) {} 1365 1366 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1367 renderer.startMark("GL functor"); 1368 status_t ret = renderer.callDrawGLFunction(mFunctor, dirty); 1369 renderer.endMark(); 1370 return ret; 1371 } 1372 1373 virtual void output(int level, uint32_t logFlags) { 1374 OP_LOG("Draw Functor %p", mFunctor); 1375 } 1376 1377 virtual const char* name() { return "DrawFunctor"; } 1378 1379private: 1380 Functor* mFunctor; 1381}; 1382 1383class DrawDisplayListOp : public DrawBoundedOp { 1384public: 1385 DrawDisplayListOp(DisplayList* displayList, int flags) 1386 : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0), 1387 mDisplayList(displayList), mFlags(flags) {} 1388 1389 virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level, 1390 bool useQuickReject) { 1391 if (mDisplayList && mDisplayList->isRenderable()) { 1392 mDisplayList->defer(deferStruct, level + 1); 1393 } 1394 } 1395 virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level, 1396 bool useQuickReject) { 1397 if (mDisplayList && mDisplayList->isRenderable()) { 1398 mDisplayList->replay(replayStruct, level + 1); 1399 } 1400 } 1401 1402 // NOT USED since replay() is overridden 1403 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1404 return DrawGlInfo::kStatusDone; 1405 } 1406 1407 virtual void output(int level, uint32_t logFlags) { 1408 OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags); 1409 if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) { 1410 mDisplayList->output(level + 1); 1411 } 1412 } 1413 1414 virtual const char* name() { return "DrawDisplayList"; } 1415 1416private: 1417 DisplayList* mDisplayList; 1418 int mFlags; 1419}; 1420 1421class DrawLayerOp : public DrawOp { 1422public: 1423 DrawLayerOp(Layer* layer, float x, float y) 1424 : DrawOp(0), mLayer(layer), mX(x), mY(y) {} 1425 1426 virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { 1427 return renderer.drawLayer(mLayer, mX, mY); 1428 } 1429 1430 virtual void output(int level, uint32_t logFlags) { 1431 OP_LOG("Draw Layer %p at %f %f", mLayer, mX, mY); 1432 } 1433 1434 virtual const char* name() { return "DrawLayer"; } 1435 1436private: 1437 Layer* mLayer; 1438 float mX; 1439 float mY; 1440}; 1441 1442}; // namespace uirenderer 1443}; // namespace android 1444 1445#endif // ANDROID_HWUI_DISPLAY_OPERATION_H 1446