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