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