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