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