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