GrRenderTargetContext.cpp revision 6a639040bc3ee5369d86c9cb5b9047208beb5206
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrBatchTest.h" 9#include "GrColor.h" 10#include "GrRenderTargetContext.h" 11#include "GrRenderTargetContextPriv.h" 12#include "GrDrawingManager.h" 13#include "GrFixedClip.h" 14#include "GrGpuResourcePriv.h" 15#include "GrOvalRenderer.h" 16#include "GrPathRenderer.h" 17#include "GrPipelineBuilder.h" 18#include "GrRenderTarget.h" 19#include "GrRenderTargetPriv.h" 20#include "GrResourceProvider.h" 21#include "SkSurfacePriv.h" 22 23#include "batches/GrClearBatch.h" 24#include "batches/GrDrawAtlasBatch.h" 25#include "batches/GrDrawVerticesBatch.h" 26#include "batches/GrNinePatch.h" // TODO Factory 27#include "batches/GrOp.h" 28#include "batches/GrRectOpFactory.h" 29#include "batches/GrRegionBatch.h" 30#include "batches/GrShadowRRectBatch.h" 31 32#include "effects/GrRRectEffect.h" 33 34#include "instanced/InstancedRendering.h" 35 36#include "text/GrAtlasTextContext.h" 37#include "text/GrStencilAndCoverTextContext.h" 38 39#include "../private/GrAuditTrail.h" 40 41#include "SkGr.h" 42#include "SkLatticeIter.h" 43#include "SkMatrixPriv.h" 44 45#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext()) 46#define ASSERT_SINGLE_OWNER \ 47 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);) 48#define ASSERT_SINGLE_OWNER_PRIV \ 49 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->fSingleOwner);) 50#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; } 51#define RETURN_IF_ABANDONED_PRIV if (fRenderTargetContext->fDrawingManager->wasAbandoned()) { return; } 52#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; } 53#define RETURN_FALSE_IF_ABANDONED_PRIV if (fRenderTargetContext->fDrawingManager->wasAbandoned()) { return false; } 54#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; } 55 56using gr_instanced::InstancedRendering; 57 58class AutoCheckFlush { 59public: 60 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) { 61 SkASSERT(fDrawingManager); 62 } 63 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); } 64 65private: 66 GrDrawingManager* fDrawingManager; 67}; 68 69bool GrRenderTargetContext::wasAbandoned() const { 70 return fDrawingManager->wasAbandoned(); 71} 72 73// In MDB mode the reffing of the 'getLastOpList' call's result allows in-progress 74// GrOpLists to be picked up and added to by renderTargetContexts lower in the call 75// stack. When this occurs with a closed GrOpList, a new one will be allocated 76// when the renderTargetContext attempts to use it (via getOpList). 77GrRenderTargetContext::GrRenderTargetContext(GrContext* context, 78 GrDrawingManager* drawingMgr, 79 sk_sp<GrRenderTargetProxy> rtp, 80 sk_sp<SkColorSpace> colorSpace, 81 const SkSurfaceProps* surfaceProps, 82 GrAuditTrail* auditTrail, 83 GrSingleOwner* singleOwner) 84 : GrSurfaceContext(context, auditTrail, singleOwner) 85 , fDrawingManager(drawingMgr) 86 , fRenderTargetProxy(std::move(rtp)) 87 , fOpList(SkSafeRef(fRenderTargetProxy->getLastRenderTargetOpList())) 88 , fInstancedPipelineInfo(fRenderTargetProxy.get()) 89 , fColorSpace(std::move(colorSpace)) 90 , fColorXformFromSRGB(nullptr) 91 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) 92{ 93 if (fColorSpace) { 94 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation 95 auto srgbColorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); 96 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get()); 97 } 98 SkDEBUGCODE(this->validate();) 99} 100 101#ifdef SK_DEBUG 102void GrRenderTargetContext::validate() const { 103 SkASSERT(fRenderTargetProxy); 104 fRenderTargetProxy->validate(fContext); 105 106 if (fOpList && !fOpList->isClosed()) { 107 SkASSERT(fRenderTargetProxy->getLastOpList() == fOpList); 108 } 109} 110#endif 111 112GrRenderTargetContext::~GrRenderTargetContext() { 113 ASSERT_SINGLE_OWNER 114 SkSafeUnref(fOpList); 115} 116 117GrRenderTarget* GrRenderTargetContext::instantiate() { 118 return fRenderTargetProxy->instantiate(fContext->textureProvider()); 119} 120 121GrTextureProxy* GrRenderTargetContext::asDeferredTexture() { 122 return fRenderTargetProxy->asTextureProxy(); 123} 124 125GrRenderTargetOpList* GrRenderTargetContext::getOpList() { 126 ASSERT_SINGLE_OWNER 127 SkDEBUGCODE(this->validate();) 128 129 if (!fOpList || fOpList->isClosed()) { 130 fOpList = fDrawingManager->newOpList(fRenderTargetProxy.get()); 131 } 132 133 return fOpList; 134} 135 136bool GrRenderTargetContext::copySurface(GrSurface* src, const SkIRect& srcRect, 137 const SkIPoint& dstPoint) { 138 ASSERT_SINGLE_OWNER 139 RETURN_FALSE_IF_ABANDONED 140 SkDEBUGCODE(this->validate();) 141 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copySurface"); 142 143 // TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget 144 sk_sp<GrRenderTarget> rt( 145 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); 146 if (!rt) { 147 return false; 148 } 149 150 return this->getOpList()->copySurface(rt.get(), src, srcRect, dstPoint); 151} 152 153void GrRenderTargetContext::drawText(const GrClip& clip, const GrPaint& grPaint, 154 const SkPaint& skPaint, 155 const SkMatrix& viewMatrix, 156 const char text[], size_t byteLength, 157 SkScalar x, SkScalar y, const SkIRect& clipBounds) { 158 ASSERT_SINGLE_OWNER 159 RETURN_IF_ABANDONED 160 SkDEBUGCODE(this->validate();) 161 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawText"); 162 163 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext(); 164 atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps, 165 text, byteLength, x, y, clipBounds); 166} 167 168void GrRenderTargetContext::drawPosText(const GrClip& clip, const GrPaint& grPaint, 169 const SkPaint& skPaint, 170 const SkMatrix& viewMatrix, 171 const char text[], size_t byteLength, 172 const SkScalar pos[], int scalarsPerPosition, 173 const SkPoint& offset, const SkIRect& clipBounds) { 174 ASSERT_SINGLE_OWNER 175 RETURN_IF_ABANDONED 176 SkDEBUGCODE(this->validate();) 177 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPosText"); 178 179 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext(); 180 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix, 181 fSurfaceProps, text, byteLength, pos, scalarsPerPosition, 182 offset, clipBounds); 183 184} 185 186void GrRenderTargetContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint, 187 const SkMatrix& viewMatrix, const SkTextBlob* blob, 188 SkScalar x, SkScalar y, 189 SkDrawFilter* filter, const SkIRect& clipBounds) { 190 ASSERT_SINGLE_OWNER 191 RETURN_IF_ABANDONED 192 SkDEBUGCODE(this->validate();) 193 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawTextBlob"); 194 195 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext(); 196 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob, 197 x, y, filter, clipBounds); 198} 199 200void GrRenderTargetContext::discard() { 201 ASSERT_SINGLE_OWNER 202 RETURN_IF_ABANDONED 203 SkDEBUGCODE(this->validate();) 204 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::discard"); 205 206 AutoCheckFlush acf(fDrawingManager); 207 208 // TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget 209 sk_sp<GrRenderTarget> rt( 210 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); 211 if (!rt) { 212 return; 213 } 214 215 this->getOpList()->discard(rt.get()); 216} 217 218void GrRenderTargetContext::clear(const SkIRect* rect, 219 const GrColor color, 220 bool canIgnoreRect) { 221 ASSERT_SINGLE_OWNER 222 RETURN_IF_ABANDONED 223 SkDEBUGCODE(this->validate();) 224 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::clear"); 225 226 AutoCheckFlush acf(fDrawingManager); 227 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect); 228} 229 230void GrRenderTargetContextPriv::absClear(const SkIRect* clearRect, const GrColor color) { 231 ASSERT_SINGLE_OWNER_PRIV 232 RETURN_IF_ABANDONED_PRIV 233 SkDEBUGCODE(fRenderTargetContext->validate();) 234 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 235 "GrRenderTargetContext::absClear"); 236 237 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); 238 239 SkIRect rtRect = SkIRect::MakeWH(fRenderTargetContext->fRenderTargetProxy->worstCaseWidth( 240 *fRenderTargetContext->caps()), 241 fRenderTargetContext->fRenderTargetProxy->worstCaseHeight( 242 *fRenderTargetContext->caps())); 243 244 if (clearRect) { 245 if (clearRect->contains(rtRect)) { 246 clearRect = nullptr; // full screen 247 } else { 248 if (!rtRect.intersect(*clearRect)) { 249 return; 250 } 251 } 252 } 253 254 // TODO: in a post-MDB world this should be handled at the OpList level. 255 // An op-list that is initially cleared and has no other ops should receive an 256 // extra draw. 257 if (fRenderTargetContext->fContext->caps()->useDrawInsteadOfClear()) { 258 // This works around a driver bug with clear by drawing a rect instead. 259 // The driver will ignore a clear if it is the only thing rendered to a 260 // target before the target is read. 261 GrPaint paint; 262 paint.setColor4f(GrColor4f::FromGrColor(color)); 263 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc)); 264 265 // We don't call drawRect() here to avoid the cropping to the, possibly smaller, 266 // RenderTargetProxy bounds 267 fRenderTargetContext->drawNonAAFilledRect(GrNoClip(), paint, SkMatrix::I(), 268 SkRect::Make(rtRect), 269 nullptr, nullptr, nullptr, GrAAType::kNone); 270 271 } else { 272 if (!fRenderTargetContext->accessRenderTarget()) { 273 return; 274 } 275 276 // This path doesn't handle coalescing of full screen clears b.c. it 277 // has to clear the entire render target - not just the content area. 278 // It could be done but will take more finagling. 279 sk_sp<GrOp> batch(GrClearBatch::Make(rtRect, color, 280 fRenderTargetContext->accessRenderTarget(), 281 !clearRect)); 282 if (!batch) { 283 return; 284 } 285 fRenderTargetContext->getOpList()->addOp(std::move(batch)); 286 } 287} 288 289void GrRenderTargetContextPriv::clear(const GrFixedClip& clip, 290 const GrColor color, 291 bool canIgnoreClip) { 292 ASSERT_SINGLE_OWNER_PRIV 293 RETURN_IF_ABANDONED_PRIV 294 SkDEBUGCODE(fRenderTargetContext->validate();) 295 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 296 "GrRenderTargetContextPriv::clear"); 297 298 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); 299 fRenderTargetContext->internalClear(clip, color, canIgnoreClip); 300} 301 302void GrRenderTargetContext::internalClear(const GrFixedClip& clip, 303 const GrColor color, 304 bool canIgnoreClip) { 305 bool isFull = false; 306 if (!clip.hasWindowRectangles()) { 307 isFull = !clip.scissorEnabled() || 308 (canIgnoreClip && fContext->caps()->fullClearIsFree()) || 309 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height())); 310 } 311 312 if (fContext->caps()->useDrawInsteadOfClear()) { 313 // This works around a driver bug with clear by drawing a rect instead. 314 // The driver will ignore a clear if it is the only thing rendered to a 315 // target before the target is read. 316 SkIRect clearRect = SkIRect::MakeWH(this->width(), this->height()); 317 if (isFull) { 318 this->discard(); 319 } else if (!clearRect.intersect(clip.scissorRect())) { 320 return; 321 } 322 323 GrPaint paint; 324 paint.setColor4f(GrColor4f::FromGrColor(color)); 325 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkBlendMode::kSrc)); 326 327 this->drawRect(clip, paint, GrAA::kNo, SkMatrix::I(), SkRect::Make(clearRect)); 328 } else if (isFull) { 329 if (this->accessRenderTarget()) { 330 this->getOpList()->fullClear(this->accessRenderTarget(), color); 331 } 332 } else { 333 if (!this->accessRenderTarget()) { 334 return; 335 } 336 sk_sp<GrOp> op(GrClearBatch::Make(clip, color, this->accessRenderTarget())); 337 if (!op) { 338 return; 339 } 340 this->getOpList()->addOp(std::move(op)); 341 } 342} 343 344void GrRenderTargetContext::drawPaint(const GrClip& clip, 345 const GrPaint& paint, 346 const SkMatrix& viewMatrix) { 347 ASSERT_SINGLE_OWNER 348 RETURN_IF_ABANDONED 349 SkDEBUGCODE(this->validate();) 350 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPaint"); 351 352 // set rect to be big enough to fill the space, but not super-huge, so we 353 // don't overflow fixed-point implementations 354 355 SkRect r = fRenderTargetProxy->getBoundsRect(); 356 357 SkRRect rrect; 358 GrAA aa; 359 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the 360 // transformation for non-rect rrects. Rects caused a performance regression on an Android 361 // test that needs investigation. We also skip cases where there are fragment processors 362 // because they may depend on having correct local coords and this path draws in device space 363 // without a local matrix. 364 if (!paint.numTotalFragmentProcessors() && clip.isRRect(r, &rrect, &aa) && !rrect.isRect()) { 365 this->drawRRect(GrNoClip(), paint, aa, SkMatrix::I(), rrect, GrStyle::SimpleFill()); 366 return; 367 } 368 369 370 bool isPerspective = viewMatrix.hasPerspective(); 371 372 // We attempt to map r by the inverse matrix and draw that. mapRect will 373 // map the four corners and bound them with a new rect. This will not 374 // produce a correct result for some perspective matrices. 375 if (!isPerspective) { 376 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) { 377 SkDebugf("Could not invert matrix\n"); 378 return; 379 } 380 this->drawRect(clip, paint, GrAA::kNo, viewMatrix, r); 381 } else { 382 SkMatrix localMatrix; 383 if (!viewMatrix.invert(&localMatrix)) { 384 SkDebugf("Could not invert matrix\n"); 385 return; 386 } 387 388 AutoCheckFlush acf(fDrawingManager); 389 390 this->drawNonAAFilledRect(clip, paint, SkMatrix::I(), r, nullptr, &localMatrix, 391 nullptr, GrAAType::kNone); 392 } 393} 394 395static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) { 396 return point.fX >= rect.fLeft && point.fX <= rect.fRight && 397 point.fY >= rect.fTop && point.fY <= rect.fBottom; 398} 399 400static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) { 401 return viewMatrix.preservesRightAngles(); 402} 403 404// Attempts to crop a rect and optional local rect to the clip boundaries. 405// Returns false if the draw can be skipped entirely. 406static bool crop_filled_rect(int width, int height, const GrClip& clip, 407 const SkMatrix& viewMatrix, SkRect* rect, 408 SkRect* localRect = nullptr) { 409 if (!viewMatrix.rectStaysRect()) { 410 return true; 411 } 412 413 SkIRect clipDevBounds; 414 SkRect clipBounds; 415 416 clip.getConservativeBounds(width, height, &clipDevBounds); 417 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) { 418 return false; 419 } 420 421 if (localRect) { 422 if (!rect->intersects(clipBounds)) { 423 return false; 424 } 425 const SkScalar dx = localRect->width() / rect->width(); 426 const SkScalar dy = localRect->height() / rect->height(); 427 if (clipBounds.fLeft > rect->fLeft) { 428 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx; 429 rect->fLeft = clipBounds.fLeft; 430 } 431 if (clipBounds.fTop > rect->fTop) { 432 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy; 433 rect->fTop = clipBounds.fTop; 434 } 435 if (clipBounds.fRight < rect->fRight) { 436 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx; 437 rect->fRight = clipBounds.fRight; 438 } 439 if (clipBounds.fBottom < rect->fBottom) { 440 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy; 441 rect->fBottom = clipBounds.fBottom; 442 } 443 return true; 444 } 445 446 return rect->intersect(clipBounds); 447} 448 449bool GrRenderTargetContext::drawFilledRect(const GrClip& clip, 450 const GrPaint& paint, 451 GrAA aa, 452 const SkMatrix& viewMatrix, 453 const SkRect& rect, 454 const GrUserStencilSettings* ss) { 455 SkRect croppedRect = rect; 456 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) { 457 return true; 458 } 459 460 sk_sp<GrDrawOp> op; 461 GrAAType aaType; 462 463 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) { 464 InstancedRendering* ir = this->getOpList()->instancedRendering(); 465 op.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(), aa, 466 fInstancedPipelineInfo, &aaType)); 467 if (op) { 468 GrPipelineBuilder pipelineBuilder(paint, aaType); 469 if (ss) { 470 pipelineBuilder.setUserStencil(ss); 471 } 472 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 473 return true; 474 } 475 } 476 aaType = this->decideAAType(aa); 477 if (GrAAType::kCoverage == aaType) { 478 // The fill path can handle rotation but not skew. 479 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { 480 SkRect devBoundRect; 481 viewMatrix.mapRect(&devBoundRect, croppedRect); 482 483 op = GrRectOpFactory::MakeAAFill(paint, viewMatrix, rect, croppedRect, devBoundRect); 484 if (op) { 485 GrPipelineBuilder pipelineBuilder(paint, aaType); 486 if (ss) { 487 pipelineBuilder.setUserStencil(ss); 488 } 489 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 490 return true; 491 } 492 } 493 } else { 494 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss, 495 aaType); 496 return true; 497 } 498 499 return false; 500} 501 502void GrRenderTargetContext::drawRect(const GrClip& clip, 503 const GrPaint& paint, 504 GrAA aa, 505 const SkMatrix& viewMatrix, 506 const SkRect& rect, 507 const GrStyle* style) { 508 if (!style) { 509 style = &GrStyle::SimpleFill(); 510 } 511 ASSERT_SINGLE_OWNER 512 RETURN_IF_ABANDONED 513 SkDEBUGCODE(this->validate();) 514 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRect"); 515 516 // Path effects should've been devolved to a path in SkGpuDevice 517 SkASSERT(!style->pathEffect()); 518 519 AutoCheckFlush acf(fDrawingManager); 520 521 const SkStrokeRec& stroke = style->strokeRec(); 522 if (stroke.getStyle() == SkStrokeRec::kFill_Style) { 523 524 if (!fContext->caps()->useDrawInsteadOfClear()) { 525 // Check if this is a full RT draw and can be replaced with a clear. We don't bother 526 // checking cases where the RT is fully inside a stroke. 527 SkRect rtRect = fRenderTargetProxy->getBoundsRect(); 528 // Does the clip contain the entire RT? 529 if (clip.quickContains(rtRect)) { 530 SkMatrix invM; 531 if (!viewMatrix.invert(&invM)) { 532 return; 533 } 534 // Does the rect bound the RT? 535 SkPoint srcSpaceRTQuad[4]; 536 invM.mapRectToQuad(srcSpaceRTQuad, rtRect); 537 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) && 538 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) && 539 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) && 540 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) { 541 // Will it blend? 542 GrColor clearColor; 543 if (paint.isConstantBlendedColor(&clearColor)) { 544 this->clear(nullptr, clearColor, true); 545 return; 546 } 547 } 548 } 549 } 550 551 if (this->drawFilledRect(clip, paint, aa, viewMatrix, rect, nullptr)) { 552 return; 553 } 554 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style || 555 stroke.getStyle() == SkStrokeRec::kHairline_Style) { 556 if ((!rect.width() || !rect.height()) && 557 SkStrokeRec::kHairline_Style != stroke.getStyle()) { 558 SkScalar r = stroke.getWidth() / 2; 559 // TODO: Move these stroke->fill fallbacks to GrShape? 560 switch (stroke.getJoin()) { 561 case SkPaint::kMiter_Join: 562 this->drawRect(clip, paint, aa, viewMatrix, 563 {rect.fLeft - r, rect.fTop - r, 564 rect.fRight + r, rect.fBottom + r}, 565 &GrStyle::SimpleFill()); 566 return; 567 case SkPaint::kRound_Join: 568 // Raster draws nothing when both dimensions are empty. 569 if (rect.width() || rect.height()){ 570 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r); 571 this->drawRRect(clip, paint, aa, viewMatrix, rrect, GrStyle::SimpleFill()); 572 return; 573 } 574 case SkPaint::kBevel_Join: 575 if (!rect.width()) { 576 this->drawRect(clip, paint, aa, viewMatrix, 577 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom}, 578 &GrStyle::SimpleFill()); 579 } else { 580 this->drawRect(clip, paint, aa, viewMatrix, 581 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r}, 582 &GrStyle::SimpleFill()); 583 } 584 return; 585 } 586 } 587 588 bool snapToPixelCenters = false; 589 sk_sp<GrDrawOp> op; 590 591 GrColor color = paint.getColor(); 592 GrAAType aaType = this->decideAAType(aa); 593 if (GrAAType::kCoverage == aaType) { 594 // The stroke path needs the rect to remain axis aligned (no rotation or skew). 595 if (viewMatrix.rectStaysRect()) { 596 op = GrRectOpFactory::MakeAAStroke(color, viewMatrix, rect, stroke); 597 } 598 } else { 599 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of 600 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not 601 // when MSAA is enabled because it can cause ugly artifacts. 602 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style && 603 !fRenderTargetProxy->isUnifiedMultisampled(); 604 op = GrRectOpFactory::MakeNonAAStroke(color, viewMatrix, rect, stroke, 605 snapToPixelCenters); 606 } 607 608 if (op) { 609 GrPipelineBuilder pipelineBuilder(paint, aaType); 610 611 if (snapToPixelCenters) { 612 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag, 613 snapToPixelCenters); 614 } 615 616 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 617 return; 618 } 619 } 620 621 SkPath path; 622 path.setIsVolatile(true); 623 path.addRect(rect); 624 this->internalDrawPath(clip, paint, aa, viewMatrix, path, *style); 625} 626 627int GrRenderTargetContextPriv::maxWindowRectangles() const { 628 return fRenderTargetContext->fRenderTargetProxy->maxWindowRectangles( 629 *fRenderTargetContext->fContext->caps()); 630} 631 632void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) { 633 ASSERT_SINGLE_OWNER_PRIV 634 RETURN_IF_ABANDONED_PRIV 635 SkDEBUGCODE(fRenderTargetContext->validate();) 636 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 637 "GrRenderTargetContextPriv::clearStencilClip"); 638 639 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); 640 if (!fRenderTargetContext->accessRenderTarget()) { 641 return; 642 } 643 fRenderTargetContext->getOpList()->clearStencilClip(clip, insideStencilMask, 644 fRenderTargetContext->accessRenderTarget()); 645} 646 647void GrRenderTargetContextPriv::stencilPath(const GrClip& clip, 648 GrAAType aaType, 649 const SkMatrix& viewMatrix, 650 const GrPath* path) { 651 SkASSERT(aaType != GrAAType::kCoverage); 652 fRenderTargetContext->getOpList()->stencilPath(fRenderTargetContext, clip, aaType, viewMatrix, 653 path); 654} 655 656void GrRenderTargetContextPriv::stencilRect(const GrClip& clip, 657 const GrUserStencilSettings* ss, 658 GrAAType aaType, 659 const SkMatrix& viewMatrix, 660 const SkRect& rect) { 661 ASSERT_SINGLE_OWNER_PRIV 662 RETURN_IF_ABANDONED_PRIV 663 SkDEBUGCODE(fRenderTargetContext->validate();) 664 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 665 "GrRenderTargetContext::stencilRect"); 666 SkASSERT(GrAAType::kCoverage != aaType); 667 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); 668 669 GrPaint paint; 670 paint.setXPFactory(GrDisableColorXPFactory::Make()); 671 672 fRenderTargetContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, 673 aaType); 674} 675 676bool GrRenderTargetContextPriv::drawAndStencilRect(const GrClip& clip, 677 const GrUserStencilSettings* ss, 678 SkRegion::Op op, 679 bool invert, 680 GrAA aa, 681 const SkMatrix& viewMatrix, 682 const SkRect& rect) { 683 ASSERT_SINGLE_OWNER_PRIV 684 RETURN_FALSE_IF_ABANDONED_PRIV 685 SkDEBUGCODE(fRenderTargetContext->validate();) 686 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 687 "GrRenderTargetContext::drawAndStencilRect"); 688 689 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); 690 691 GrPaint paint; 692 paint.setCoverageSetOpXPFactory(op, invert); 693 694 if (fRenderTargetContext->drawFilledRect(clip, paint, aa, viewMatrix, rect, ss)) { 695 return true; 696 } 697 SkPath path; 698 path.setIsVolatile(true); 699 path.addRect(rect); 700 return this->drawAndStencilPath(clip, ss, op, invert, aa, viewMatrix, path); 701} 702 703void GrRenderTargetContext::fillRectToRect(const GrClip& clip, 704 const GrPaint& paint, 705 GrAA aa, 706 const SkMatrix& viewMatrix, 707 const SkRect& rectToDraw, 708 const SkRect& localRect) { 709 ASSERT_SINGLE_OWNER 710 RETURN_IF_ABANDONED 711 SkDEBUGCODE(this->validate();) 712 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectToRect"); 713 714 SkRect croppedRect = rectToDraw; 715 SkRect croppedLocalRect = localRect; 716 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, 717 &croppedRect, &croppedLocalRect)) { 718 return; 719 } 720 721 AutoCheckFlush acf(fDrawingManager); 722 GrAAType aaType; 723 724 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) { 725 InstancedRendering* ir = this->getOpList()->instancedRendering(); 726 sk_sp<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(), 727 croppedLocalRect, aa, fInstancedPipelineInfo, &aaType)); 728 if (op) { 729 GrPipelineBuilder pipelineBuilder(paint, aaType); 730 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 731 return; 732 } 733 } 734 735 aaType = this->decideAAType(aa); 736 if (GrAAType::kCoverage != aaType) { 737 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect, nullptr, 738 nullptr, aaType); 739 return; 740 } 741 742 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { 743 sk_sp<GrDrawOp> op = GrAAFillRectOp::MakeWithLocalRect(paint.getColor(), viewMatrix, 744 croppedRect, croppedLocalRect); 745 GrPipelineBuilder pipelineBuilder(paint, aaType); 746 this->addDrawOp(pipelineBuilder, clip, std::move(op)); 747 return; 748 } 749 750 SkMatrix viewAndUnLocalMatrix; 751 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) { 752 SkDebugf("fillRectToRect called with empty local matrix.\n"); 753 return; 754 } 755 viewAndUnLocalMatrix.postConcat(viewMatrix); 756 757 SkPath path; 758 path.setIsVolatile(true); 759 path.addRect(localRect); 760 this->internalDrawPath(clip, paint, aa, viewAndUnLocalMatrix, path, GrStyle()); 761} 762 763void GrRenderTargetContext::fillRectWithLocalMatrix(const GrClip& clip, 764 const GrPaint& paint, 765 GrAA aa, 766 const SkMatrix& viewMatrix, 767 const SkRect& rectToDraw, 768 const SkMatrix& localMatrix) { 769 ASSERT_SINGLE_OWNER 770 RETURN_IF_ABANDONED 771 SkDEBUGCODE(this->validate();) 772 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::fillRectWithLocalMatrix"); 773 774 SkRect croppedRect = rectToDraw; 775 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) { 776 return; 777 } 778 779 AutoCheckFlush acf(fDrawingManager); 780 GrAAType aaType; 781 782 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) { 783 InstancedRendering* ir = this->getOpList()->instancedRendering(); 784 sk_sp<GrDrawOp> op(ir->recordRect(croppedRect, viewMatrix, paint.getColor(), localMatrix, 785 aa, fInstancedPipelineInfo, &aaType)); 786 if (op) { 787 GrPipelineBuilder pipelineBuilder(paint, aaType); 788 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 789 return; 790 } 791 } 792 793 aaType = this->decideAAType(aa); 794 if (GrAAType::kCoverage != aaType) { 795 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, &localMatrix, 796 nullptr, aaType); 797 return; 798 } 799 800 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) { 801 sk_sp<GrDrawOp> op = 802 GrAAFillRectOp::Make(paint.getColor(), viewMatrix, localMatrix, croppedRect); 803 GrPipelineBuilder pipelineBuilder(paint, aaType); 804 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 805 return; 806 } 807 808 SkMatrix viewAndUnLocalMatrix; 809 if (!localMatrix.invert(&viewAndUnLocalMatrix)) { 810 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n"); 811 return; 812 } 813 viewAndUnLocalMatrix.postConcat(viewMatrix); 814 815 SkPath path; 816 path.setIsVolatile(true); 817 path.addRect(rectToDraw); 818 path.transform(localMatrix); 819 this->internalDrawPath(clip, paint, aa, viewAndUnLocalMatrix, path, GrStyle()); 820} 821 822void GrRenderTargetContext::drawVertices(const GrClip& clip, 823 const GrPaint& paint, 824 const SkMatrix& viewMatrix, 825 GrPrimitiveType primitiveType, 826 int vertexCount, 827 const SkPoint positions[], 828 const SkPoint texCoords[], 829 const GrColor colors[], 830 const uint16_t indices[], 831 int indexCount) { 832 ASSERT_SINGLE_OWNER 833 RETURN_IF_ABANDONED 834 SkDEBUGCODE(this->validate();) 835 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawVertices"); 836 837 AutoCheckFlush acf(fDrawingManager); 838 839 // TODO clients should give us bounds 840 SkRect bounds; 841 if (!bounds.setBoundsCheck(positions, vertexCount)) { 842 SkDebugf("drawVertices call empty bounds\n"); 843 return; 844 } 845 846 viewMatrix.mapRect(&bounds); 847 848 sk_sp<GrDrawOp> op(new GrDrawVerticesBatch(paint.getColor(), primitiveType, viewMatrix, 849 positions, vertexCount, indices, indexCount, colors, 850 texCoords, bounds)); 851 852 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone); 853 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 854} 855 856/////////////////////////////////////////////////////////////////////////////// 857 858void GrRenderTargetContext::drawAtlas(const GrClip& clip, 859 const GrPaint& paint, 860 const SkMatrix& viewMatrix, 861 int spriteCount, 862 const SkRSXform xform[], 863 const SkRect texRect[], 864 const SkColor colors[]) { 865 ASSERT_SINGLE_OWNER 866 RETURN_IF_ABANDONED 867 SkDEBUGCODE(this->validate();) 868 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawAtlas"); 869 870 AutoCheckFlush acf(fDrawingManager); 871 872 sk_sp<GrDrawOp> op(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount, xform, 873 texRect, colors)); 874 875 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone); 876 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 877} 878 879/////////////////////////////////////////////////////////////////////////////// 880 881void GrRenderTargetContext::drawRRect(const GrClip& origClip, 882 const GrPaint& paint, 883 GrAA aa, 884 const SkMatrix& viewMatrix, 885 const SkRRect& rrect, 886 const GrStyle& style) { 887 ASSERT_SINGLE_OWNER 888 RETURN_IF_ABANDONED 889 SkDEBUGCODE(this->validate();) 890 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRRect"); 891 if (rrect.isEmpty()) { 892 return; 893 } 894 895 GrNoClip noclip; 896 const GrClip* clip = &origClip; 897#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK 898 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the 899 // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it 900 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test 901 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack 902 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls. 903 SkRRect devRRect; 904 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) { 905 clip = &noclip; 906 } 907#endif 908 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice 909 910 AutoCheckFlush acf(fDrawingManager); 911 const SkStrokeRec stroke = style.strokeRec(); 912 GrAAType aaType; 913 914 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() && 915 stroke.isFillStyle()) { 916 InstancedRendering* ir = this->getOpList()->instancedRendering(); 917 sk_sp<GrDrawOp> op(ir->recordRRect(rrect, viewMatrix, paint.getColor(), aa, 918 fInstancedPipelineInfo, &aaType)); 919 if (op) { 920 GrPipelineBuilder pipelineBuilder(paint, aaType); 921 this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op)); 922 return; 923 } 924 } 925 926 aaType = this->decideAAType(aa); 927 if (GrAAType::kCoverage == aaType) { 928 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); 929 sk_sp<GrDrawOp> op(GrOvalRenderer::CreateRRectBatch(paint.getColor(), 930 paint.usesDistanceVectorField(), 931 viewMatrix, 932 rrect, 933 stroke, 934 shaderCaps)); 935 if (op) { 936 GrPipelineBuilder pipelineBuilder(paint, aaType); 937 this->getOpList()->addDrawOp(pipelineBuilder, this, *clip, std::move(op)); 938 return; 939 } 940 } 941 942 SkPath path; 943 path.setIsVolatile(true); 944 path.addRRect(rrect); 945 this->internalDrawPath(*clip, paint, aa, viewMatrix, path, style); 946} 947 948/////////////////////////////////////////////////////////////////////////////// 949 950void GrRenderTargetContext::drawShadowRRect(const GrClip& clip, 951 const GrPaint& paint, 952 const SkMatrix& viewMatrix, 953 const SkRRect& rrect, 954 SkScalar blurRadius, 955 const GrStyle& style) { 956 ASSERT_SINGLE_OWNER 957 RETURN_IF_ABANDONED 958 SkDEBUGCODE(this->validate();) 959 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawShadowRRect"); 960 if (rrect.isEmpty()) { 961 return; 962 } 963 964 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice 965 966 AutoCheckFlush acf(fDrawingManager); 967 const SkStrokeRec stroke = style.strokeRec(); 968 // TODO: add instancing support? 969 970 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); 971 sk_sp<GrDrawOp> op(CreateShadowRRectBatch(paint.getColor(), 972 viewMatrix, 973 rrect, 974 blurRadius, 975 stroke, 976 shaderCaps)); 977 if (op) { 978 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone); 979 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 980 return; 981 } 982} 983 984/////////////////////////////////////////////////////////////////////////////// 985 986bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip, 987 const GrPaint& paintIn, 988 GrAA aa, 989 const SkMatrix& viewMatrix, 990 const SkRRect& origOuter, 991 const SkRRect& origInner) { 992 SkASSERT(!origInner.isEmpty()); 993 SkASSERT(!origOuter.isEmpty()); 994 GrAAType aaType; 995 996 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) { 997 InstancedRendering* ir = this->getOpList()->instancedRendering(); 998 sk_sp<GrDrawOp> op(ir->recordDRRect(origOuter, origInner, viewMatrix, paintIn.getColor(), 999 aa, fInstancedPipelineInfo, &aaType)); 1000 if (op) { 1001 GrPipelineBuilder pipelineBuilder(paintIn, aaType); 1002 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1003 return true; 1004 } 1005 } 1006 1007 aaType = this->decideAAType(aa); 1008 1009 GrPrimitiveEdgeType innerEdgeType, outerEdgeType; 1010 if (GrAAType::kCoverage == aaType) { 1011 innerEdgeType = kInverseFillAA_GrProcessorEdgeType; 1012 outerEdgeType = kFillAA_GrProcessorEdgeType; 1013 } else { 1014 innerEdgeType = kInverseFillBW_GrProcessorEdgeType; 1015 outerEdgeType = kFillBW_GrProcessorEdgeType; 1016 } 1017 1018 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter); 1019 SkMatrix inverseVM; 1020 if (!viewMatrix.isIdentity()) { 1021 if (!origInner.transform(viewMatrix, inner.writable())) { 1022 return false; 1023 } 1024 if (!origOuter.transform(viewMatrix, outer.writable())) { 1025 return false; 1026 } 1027 if (!viewMatrix.invert(&inverseVM)) { 1028 return false; 1029 } 1030 } else { 1031 inverseVM.reset(); 1032 } 1033 1034 GrPaint grPaint(paintIn); 1035 1036 // TODO these need to be a geometry processors 1037 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner)); 1038 if (!innerEffect) { 1039 return false; 1040 } 1041 1042 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer)); 1043 if (!outerEffect) { 1044 return false; 1045 } 1046 1047 grPaint.addCoverageFragmentProcessor(std::move(innerEffect)); 1048 grPaint.addCoverageFragmentProcessor(std::move(outerEffect)); 1049 1050 SkRect bounds = outer->getBounds(); 1051 if (GrAAType::kCoverage == aaType) { 1052 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 1053 } 1054 1055 this->fillRectWithLocalMatrix(clip, grPaint, GrAA::kNo, SkMatrix::I(), bounds, inverseVM); 1056 return true; 1057} 1058 1059void GrRenderTargetContext::drawDRRect(const GrClip& clip, 1060 const GrPaint& paint, 1061 GrAA aa, 1062 const SkMatrix& viewMatrix, 1063 const SkRRect& outer, 1064 const SkRRect& inner) { 1065 ASSERT_SINGLE_OWNER 1066 RETURN_IF_ABANDONED 1067 SkDEBUGCODE(this->validate();) 1068 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawDRRect"); 1069 1070 SkASSERT(!outer.isEmpty()); 1071 SkASSERT(!inner.isEmpty()); 1072 1073 AutoCheckFlush acf(fDrawingManager); 1074 1075 if (this->drawFilledDRRect(clip, paint, aa, viewMatrix, outer, inner)) { 1076 return; 1077 } 1078 1079 SkPath path; 1080 path.setIsVolatile(true); 1081 path.addRRect(inner); 1082 path.addRRect(outer); 1083 path.setFillType(SkPath::kEvenOdd_FillType); 1084 1085 this->internalDrawPath(clip, paint, aa, viewMatrix, path, GrStyle::SimpleFill()); 1086} 1087 1088/////////////////////////////////////////////////////////////////////////////// 1089 1090static inline bool is_int(float x) { 1091 return x == (float) sk_float_round2int(x); 1092} 1093 1094void GrRenderTargetContext::drawRegion(const GrClip& clip, 1095 const GrPaint& paint, 1096 GrAA aa, 1097 const SkMatrix& viewMatrix, 1098 const SkRegion& region, 1099 const GrStyle& style) { 1100 ASSERT_SINGLE_OWNER 1101 RETURN_IF_ABANDONED 1102 SkDEBUGCODE(this->validate();) 1103 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawRegion"); 1104 1105 if (GrAA::kYes == aa) { 1106 // GrRegionBatch performs no antialiasing but is much faster, so here we check the matrix 1107 // to see whether aa is really required. 1108 if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) && 1109 is_int(viewMatrix.getTranslateX()) && 1110 is_int(viewMatrix.getTranslateY())) { 1111 aa = GrAA::kNo; 1112 } 1113 } 1114 bool complexStyle = !style.isSimpleFill(); 1115 if (complexStyle || GrAA::kYes == aa) { 1116 SkPath path; 1117 region.getBoundaryPath(&path); 1118 return this->drawPath(clip, paint, aa, viewMatrix, path, style); 1119 } 1120 1121 sk_sp<GrDrawOp> op(GrRegionBatch::Create(paint.getColor(), viewMatrix, region)); 1122 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone); 1123 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1124} 1125 1126void GrRenderTargetContext::drawOval(const GrClip& clip, 1127 const GrPaint& paint, 1128 GrAA aa, 1129 const SkMatrix& viewMatrix, 1130 const SkRect& oval, 1131 const GrStyle& style) { 1132 ASSERT_SINGLE_OWNER 1133 RETURN_IF_ABANDONED 1134 SkDEBUGCODE(this->validate();) 1135 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawOval"); 1136 1137 if (oval.isEmpty()) { 1138 return; 1139 } 1140 1141 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice 1142 1143 AutoCheckFlush acf(fDrawingManager); 1144 const SkStrokeRec& stroke = style.strokeRec(); 1145 GrAAType aaType; 1146 1147 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() && 1148 stroke.isFillStyle()) { 1149 InstancedRendering* ir = this->getOpList()->instancedRendering(); 1150 sk_sp<GrDrawOp> op(ir->recordOval(oval, viewMatrix, paint.getColor(), aa, 1151 fInstancedPipelineInfo, &aaType)); 1152 if (op) { 1153 GrPipelineBuilder pipelineBuilder(paint, aaType); 1154 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1155 return; 1156 } 1157 } 1158 1159 aaType = this->decideAAType(aa); 1160 if (GrAAType::kCoverage == aaType) { 1161 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); 1162 sk_sp<GrDrawOp> op(GrOvalRenderer::CreateOvalBatch(paint.getColor(), 1163 viewMatrix, 1164 oval, 1165 stroke, 1166 shaderCaps)); 1167 if (op) { 1168 GrPipelineBuilder pipelineBuilder(paint, aaType); 1169 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1170 return; 1171 } 1172 } 1173 1174 SkPath path; 1175 path.setIsVolatile(true); 1176 path.addOval(oval); 1177 this->internalDrawPath(clip, paint, aa, viewMatrix, path, style); 1178} 1179 1180void GrRenderTargetContext::drawArc(const GrClip& clip, 1181 const GrPaint& paint, 1182 GrAA aa, 1183 const SkMatrix& viewMatrix, 1184 const SkRect& oval, 1185 SkScalar startAngle, 1186 SkScalar sweepAngle, 1187 bool useCenter, 1188 const GrStyle& style) { 1189 GrAAType aaType = this->decideAAType(aa); 1190 if (GrAAType::kCoverage == aaType) { 1191 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); 1192 sk_sp<GrDrawOp> op(GrOvalRenderer::CreateArcBatch(paint.getColor(), 1193 viewMatrix, 1194 oval, 1195 startAngle, 1196 sweepAngle, 1197 useCenter, 1198 style, 1199 shaderCaps)); 1200 if (op) { 1201 GrPipelineBuilder pipelineBuilder(paint, aaType); 1202 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1203 return; 1204 } 1205 } 1206 SkPath path; 1207 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter, 1208 style.isSimpleFill()); 1209 this->internalDrawPath(clip, paint, aa, viewMatrix, path, style); 1210} 1211 1212void GrRenderTargetContext::drawImageLattice(const GrClip& clip, 1213 const GrPaint& paint, 1214 const SkMatrix& viewMatrix, 1215 int imageWidth, 1216 int imageHeight, 1217 std::unique_ptr<SkLatticeIter> iter, 1218 const SkRect& dst) { 1219 ASSERT_SINGLE_OWNER 1220 RETURN_IF_ABANDONED 1221 SkDEBUGCODE(this->validate();) 1222 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawImageLattice"); 1223 1224 AutoCheckFlush acf(fDrawingManager); 1225 1226 sk_sp<GrDrawOp> op(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix, imageWidth, 1227 imageHeight, std::move(iter), dst)); 1228 1229 GrPipelineBuilder pipelineBuilder(paint, GrAAType::kNone); 1230 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1231} 1232 1233void GrRenderTargetContext::prepareForExternalIO() { 1234 ASSERT_SINGLE_OWNER 1235 RETURN_IF_ABANDONED 1236 SkDEBUGCODE(this->validate();) 1237 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::prepareForExternalIO"); 1238 1239 // Deferral of the VRAM resources must end in this instance anyway 1240 sk_sp<GrRenderTarget> rt( 1241 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); 1242 if (!rt) { 1243 return; 1244 } 1245 1246 ASSERT_OWNED_RESOURCE(rt); 1247 1248 fDrawingManager->prepareSurfaceForExternalIO(rt.get()); 1249} 1250 1251void GrRenderTargetContext::drawNonAAFilledRect(const GrClip& clip, 1252 const GrPaint& paint, 1253 const SkMatrix& viewMatrix, 1254 const SkRect& rect, 1255 const SkRect* localRect, 1256 const SkMatrix* localMatrix, 1257 const GrUserStencilSettings* ss, 1258 GrAAType hwOrNoneAAType) { 1259 SkASSERT(GrAAType::kCoverage != hwOrNoneAAType); 1260 SkASSERT(hwOrNoneAAType == GrAAType::kNone || this->isStencilBufferMultisampled()); 1261 sk_sp<GrDrawOp> op = GrRectOpFactory::MakeNonAAFill(paint.getColor(), viewMatrix, rect, 1262 localRect, localMatrix); 1263 GrPipelineBuilder pipelineBuilder(paint, hwOrNoneAAType); 1264 if (ss) { 1265 pipelineBuilder.setUserStencil(ss); 1266 } 1267 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1268} 1269 1270bool GrRenderTargetContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer, 1271 size_t dstRowBytes, int x, int y) { 1272 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels 1273 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps()); 1274 if (kUnknown_GrPixelConfig == config) { 1275 return false; 1276 } 1277 1278 uint32_t flags = 0; 1279 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) { 1280 flags = GrContext::kUnpremul_PixelOpsFlag; 1281 } 1282 1283 // Deferral of the VRAM resources must end in this instance anyway 1284 sk_sp<GrRenderTarget> rt( 1285 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); 1286 if (!rt) { 1287 return false; 1288 } 1289 1290 return rt->readPixels(x, y, dstInfo.width(), dstInfo.height(), 1291 config, dstBuffer, dstRowBytes, flags); 1292} 1293 1294bool GrRenderTargetContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer, 1295 size_t srcRowBytes, int x, int y) { 1296 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels 1297 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps()); 1298 if (kUnknown_GrPixelConfig == config) { 1299 return false; 1300 } 1301 uint32_t flags = 0; 1302 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) { 1303 flags = GrContext::kUnpremul_PixelOpsFlag; 1304 } 1305 1306 // Deferral of the VRAM resources must end in this instance anyway 1307 sk_sp<GrRenderTarget> rt( 1308 sk_ref_sp(fRenderTargetProxy->instantiate(fContext->textureProvider()))); 1309 if (!rt) { 1310 return false; 1311 } 1312 1313 return rt->writePixels(x, y, srcInfo.width(), srcInfo.height(), 1314 config, srcBuffer, srcRowBytes, flags); 1315} 1316 1317// Can 'path' be drawn as a pair of filled nested rectangles? 1318static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) { 1319 1320 if (path.isInverseFillType()) { 1321 return false; 1322 } 1323 1324 // TODO: this restriction could be lifted if we were willing to apply 1325 // the matrix to all the points individually rather than just to the rect 1326 if (!viewMatrix.rectStaysRect()) { 1327 return false; 1328 } 1329 1330 SkPath::Direction dirs[2]; 1331 if (!path.isNestedFillRects(rects, dirs)) { 1332 return false; 1333 } 1334 1335 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) { 1336 // The two rects need to be wound opposite to each other 1337 return false; 1338 } 1339 1340 // Right now, nested rects where the margin is not the same width 1341 // all around do not render correctly 1342 const SkScalar* outer = rects[0].asScalars(); 1343 const SkScalar* inner = rects[1].asScalars(); 1344 1345 bool allEq = true; 1346 1347 SkScalar margin = SkScalarAbs(outer[0] - inner[0]); 1348 bool allGoE1 = margin >= SK_Scalar1; 1349 1350 for (int i = 1; i < 4; ++i) { 1351 SkScalar temp = SkScalarAbs(outer[i] - inner[i]); 1352 if (temp < SK_Scalar1) { 1353 allGoE1 = false; 1354 } 1355 if (!SkScalarNearlyEqual(margin, temp)) { 1356 allEq = false; 1357 } 1358 } 1359 1360 return allEq || allGoE1; 1361} 1362 1363void GrRenderTargetContext::drawPath(const GrClip& clip, 1364 const GrPaint& paint, 1365 GrAA aa, 1366 const SkMatrix& viewMatrix, 1367 const SkPath& path, 1368 const GrStyle& style) { 1369 ASSERT_SINGLE_OWNER 1370 RETURN_IF_ABANDONED 1371 SkDEBUGCODE(this->validate();) 1372 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::drawPath"); 1373 1374 if (path.isEmpty()) { 1375 if (path.isInverseFillType()) { 1376 this->drawPaint(clip, paint, viewMatrix); 1377 } 1378 return; 1379 } 1380 1381 AutoCheckFlush acf(fDrawingManager); 1382 1383 GrAAType aaType = this->decideAAType(aa); 1384 if (GrAAType::kCoverage == aaType && !style.pathEffect()) { 1385 if (style.isSimpleFill() && !path.isConvex()) { 1386 // Concave AA paths are expensive - try to avoid them for special cases 1387 SkRect rects[2]; 1388 1389 if (fills_as_nested_rects(viewMatrix, path, rects)) { 1390 sk_sp<GrDrawOp> op = 1391 GrRectOpFactory::MakeAAFillNestedRects(paint.getColor(), viewMatrix, rects); 1392 if (op) { 1393 GrPipelineBuilder pipelineBuilder(paint, aaType); 1394 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1395 } 1396 return; 1397 } 1398 } 1399 SkRect ovalRect; 1400 bool isOval = path.isOval(&ovalRect); 1401 1402 if (isOval && !path.isInverseFillType()) { 1403 const GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps(); 1404 sk_sp<GrDrawOp> op(GrOvalRenderer::CreateOvalBatch(paint.getColor(), 1405 viewMatrix, 1406 ovalRect, 1407 style.strokeRec(), 1408 shaderCaps)); 1409 if (op) { 1410 GrPipelineBuilder pipelineBuilder(paint, aaType); 1411 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1412 return; 1413 } 1414 } 1415 } 1416 1417 // Note that internalDrawPath may sw-rasterize the path into a scratch texture. 1418 // Scratch textures can be recycled after they are returned to the texture 1419 // cache. This presents a potential hazard for buffered drawing. However, 1420 // the writePixels that uploads to the scratch will perform a flush so we're 1421 // OK. 1422 this->internalDrawPath(clip, paint, aa, viewMatrix, path, style); 1423} 1424 1425bool GrRenderTargetContextPriv::drawAndStencilPath(const GrClip& clip, 1426 const GrUserStencilSettings* ss, 1427 SkRegion::Op op, 1428 bool invert, 1429 GrAA aa, 1430 const SkMatrix& viewMatrix, 1431 const SkPath& path) { 1432 ASSERT_SINGLE_OWNER_PRIV 1433 RETURN_FALSE_IF_ABANDONED_PRIV 1434 SkDEBUGCODE(fRenderTargetContext->validate();) 1435 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail, 1436 "GrRenderTargetContextPriv::drawAndStencilPath"); 1437 1438 if (path.isEmpty() && path.isInverseFillType()) { 1439 this->drawAndStencilRect(clip, ss, op, invert, GrAA::kNo, SkMatrix::I(), 1440 SkRect::MakeIWH(fRenderTargetContext->width(), 1441 fRenderTargetContext->height())); 1442 return true; 1443 } 1444 1445 AutoCheckFlush acf(fRenderTargetContext->fDrawingManager); 1446 1447 // An Assumption here is that path renderer would use some form of tweaking 1448 // the src color (either the input alpha or in the frag shader) to implement 1449 // aa. If we have some future driver-mojo path AA that can do the right 1450 // thing WRT to the blend then we'll need some query on the PR. 1451 GrAAType aaType = fRenderTargetContext->decideAAType(aa); 1452 bool hasUserStencilSettings = !ss->isUnused(); 1453 1454 GrShape shape(path, GrStyle::SimpleFill()); 1455 GrPathRenderer::CanDrawPathArgs canDrawArgs; 1456 canDrawArgs.fShaderCaps = 1457 fRenderTargetContext->fDrawingManager->getContext()->caps()->shaderCaps(); 1458 canDrawArgs.fViewMatrix = &viewMatrix; 1459 canDrawArgs.fShape = &shape; 1460 canDrawArgs.fAAType = aaType; 1461 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; 1462 1463 // Don't allow the SW renderer 1464 GrPathRenderer* pr = fRenderTargetContext->fDrawingManager->getPathRenderer( 1465 canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor); 1466 if (!pr) { 1467 return false; 1468 } 1469 1470 GrPaint paint; 1471 paint.setCoverageSetOpXPFactory(op, invert); 1472 1473 GrPathRenderer::DrawPathArgs args; 1474 args.fResourceProvider = 1475 fRenderTargetContext->fDrawingManager->getContext()->resourceProvider(); 1476 args.fPaint = &paint; 1477 args.fUserStencilSettings = ss; 1478 args.fRenderTargetContext = fRenderTargetContext; 1479 args.fClip = &clip; 1480 args.fViewMatrix = &viewMatrix; 1481 args.fShape = &shape; 1482 args.fAAType = aaType; 1483 args.fGammaCorrect = fRenderTargetContext->isGammaCorrect(); 1484 pr->drawPath(args); 1485 return true; 1486} 1487 1488SkBudgeted GrRenderTargetContextPriv::isBudgeted() const { 1489 ASSERT_SINGLE_OWNER_PRIV 1490 1491 if (fRenderTargetContext->wasAbandoned()) { 1492 return SkBudgeted::kNo; 1493 } 1494 1495 SkDEBUGCODE(fRenderTargetContext->validate();) 1496 1497 return fRenderTargetContext->fRenderTargetProxy->isBudgeted(); 1498} 1499 1500void GrRenderTargetContext::internalDrawPath(const GrClip& clip, 1501 const GrPaint& paint, 1502 GrAA aa, 1503 const SkMatrix& viewMatrix, 1504 const SkPath& path, 1505 const GrStyle& style) { 1506 ASSERT_SINGLE_OWNER 1507 RETURN_IF_ABANDONED 1508 SkASSERT(!path.isEmpty()); 1509 GrShape shape; 1510 1511 GrAAType aaType = this->decideAAType(aa, /*allowMixedSamples*/ true); 1512 if (style.isSimpleHairline() && aaType == GrAAType::kMixedSamples) { 1513 // NVPR cannot handle hairlines, so this will would get picked up by a different stencil and 1514 // cover path renderer (i.e. default path renderer). The hairline renderer produces much 1515 // smoother hairlines than MSAA. 1516 aaType = GrAAType::kCoverage; 1517 } 1518 GrPathRenderer::CanDrawPathArgs canDrawArgs; 1519 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps(); 1520 canDrawArgs.fViewMatrix = &viewMatrix; 1521 canDrawArgs.fShape = &shape; 1522 canDrawArgs.fHasUserStencilSettings = false; 1523 1524 GrPathRenderer* pr; 1525 static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor; 1526 do { 1527 shape = GrShape(path, style); 1528 if (shape.isEmpty()) { 1529 return; 1530 } 1531 1532 canDrawArgs.fAAType = aaType; 1533 1534 // Try a 1st time without applying any of the style to the geometry (and barring sw) 1535 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, kType); 1536 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix); 1537 1538 if (!pr && shape.style().pathEffect()) { 1539 // It didn't work above, so try again with the path effect applied. 1540 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale); 1541 if (shape.isEmpty()) { 1542 return; 1543 } 1544 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, kType); 1545 } 1546 if (!pr) { 1547 if (shape.style().applies()) { 1548 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale); 1549 if (shape.isEmpty()) { 1550 return; 1551 } 1552 } 1553 // This time, allow SW renderer 1554 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, kType); 1555 } 1556 if (!pr && GrAATypeIsHW(aaType)) { 1557 // There are exceptional cases where we may wind up falling back to coverage based AA 1558 // when the target is MSAA (e.g. through disabling path renderers via GrContextOptions). 1559 aaType = GrAAType::kCoverage; 1560 } else { 1561 break; 1562 } 1563 } while(true); 1564 1565 if (!pr) { 1566#ifdef SK_DEBUG 1567 SkDebugf("Unable to find path renderer compatible with path.\n"); 1568#endif 1569 return; 1570 } 1571 1572 GrPathRenderer::DrawPathArgs args; 1573 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider(); 1574 args.fPaint = &paint; 1575 args.fUserStencilSettings = &GrUserStencilSettings::kUnused; 1576 args.fRenderTargetContext = this; 1577 args.fClip = &clip; 1578 args.fViewMatrix = &viewMatrix; 1579 args.fShape = &shape; 1580 args.fAAType = aaType; 1581 args.fGammaCorrect = this->isGammaCorrect(); 1582 pr->drawPath(args); 1583} 1584 1585void GrRenderTargetContext::addDrawOp(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip, 1586 sk_sp<GrDrawOp> op) { 1587 ASSERT_SINGLE_OWNER 1588 RETURN_IF_ABANDONED 1589 SkDEBUGCODE(this->validate();) 1590 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::addDrawOp"); 1591 1592 this->getOpList()->addDrawOp(pipelineBuilder, this, clip, std::move(op)); 1593} 1594