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