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