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