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