2 * Copyright 2015 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrBatchTest.h"
10 #include "GrDrawContext.h"
11 #include "GrDrawContextPriv.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"
23 #include "batches/GrBatch.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"
31 #include "effects/GrRRectEffect.h"
33 #include "instanced/InstancedRendering.h"
35 #include "text/GrAtlasTextContext.h"
36 #include "text/GrStencilAndCoverTextContext.h"
38 #include "../private/GrAuditTrail.h"
41 #include "SkLatticeIter.h"
42 #include "SkMatrixPriv.h"
44 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
45 #define ASSERT_SINGLE_OWNER \
46 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
47 #define ASSERT_SINGLE_OWNER_PRIV \
48 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fDrawContext->fSingleOwner);)
49 #define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
50 #define RETURN_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return; }
51 #define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
52 #define RETURN_FALSE_IF_ABANDONED_PRIV if (fDrawContext->fDrawingManager->wasAbandoned()) { return false; }
53 #define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
55 using gr_instanced::InstancedRendering;
57 class AutoCheckFlush {
59 AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
60 SkASSERT(fDrawingManager);
62 ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
65 GrDrawingManager* fDrawingManager;
68 bool GrDrawContext::wasAbandoned() const {
69 return fDrawingManager->wasAbandoned();
72 // In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
73 // drawTargets to be picked up and added to by drawContexts lower in the call
74 // stack. When this occurs with a closed drawTarget, a new one will be allocated
75 // when the drawContext attempts to use it (via getDrawTarget).
76 GrDrawContext::GrDrawContext(GrContext* context,
77 GrDrawingManager* drawingMgr,
78 sk_sp<GrRenderTarget> rt,
79 sk_sp<SkColorSpace> colorSpace,
80 const SkSurfaceProps* surfaceProps,
81 GrAuditTrail* auditTrail,
82 GrSingleOwner* singleOwner)
83 : fDrawingManager(drawingMgr)
84 , fRenderTarget(std::move(rt))
85 , fDrawTarget(SkSafeRef(fRenderTarget->getLastDrawTarget()))
87 , fInstancedPipelineInfo(fRenderTarget.get())
88 , fColorSpace(std::move(colorSpace))
89 , fColorXformFromSRGB(nullptr)
90 , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
91 , fAuditTrail(auditTrail)
93 , fSingleOwner(singleOwner)
97 // sRGB sources are very common (SkColor, etc...), so we cache that gamut transformation
98 auto srgbColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
99 fColorXformFromSRGB = GrColorSpaceXform::Make(srgbColorSpace.get(), fColorSpace.get());
101 SkDEBUGCODE(this->validate();)
105 void GrDrawContext::validate() const {
106 SkASSERT(fRenderTarget);
107 ASSERT_OWNED_RESOURCE(fRenderTarget);
109 if (fDrawTarget && !fDrawTarget->isClosed()) {
110 SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
115 GrDrawContext::~GrDrawContext() {
117 SkSafeUnref(fDrawTarget);
120 GrDrawTarget* GrDrawContext::getDrawTarget() {
122 SkDEBUGCODE(this->validate();)
124 if (!fDrawTarget || fDrawTarget->isClosed()) {
125 fDrawTarget = fDrawingManager->newDrawTarget(fRenderTarget.get());
131 bool GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
133 RETURN_FALSE_IF_ABANDONED
134 SkDEBUGCODE(this->validate();)
135 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::copySurface");
137 return this->getDrawTarget()->copySurface(fRenderTarget.get(), src, srcRect, dstPoint);
140 void GrDrawContext::drawText(const GrClip& clip, const GrPaint& grPaint,
141 const SkPaint& skPaint,
142 const SkMatrix& viewMatrix,
143 const char text[], size_t byteLength,
144 SkScalar x, SkScalar y, const SkIRect& clipBounds) {
147 SkDEBUGCODE(this->validate();)
148 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawText");
150 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
151 atlasTextContext->drawText(fContext, this, clip, grPaint, skPaint, viewMatrix, fSurfaceProps,
152 text, byteLength, x, y, clipBounds);
155 void GrDrawContext::drawPosText(const GrClip& clip, const GrPaint& grPaint,
156 const SkPaint& skPaint,
157 const SkMatrix& viewMatrix,
158 const char text[], size_t byteLength,
159 const SkScalar pos[], int scalarsPerPosition,
160 const SkPoint& offset, const SkIRect& clipBounds) {
163 SkDEBUGCODE(this->validate();)
164 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPosText");
166 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
167 atlasTextContext->drawPosText(fContext, this, clip, grPaint, skPaint, viewMatrix,
168 fSurfaceProps, text, byteLength, pos, scalarsPerPosition,
173 void GrDrawContext::drawTextBlob(const GrClip& clip, const SkPaint& skPaint,
174 const SkMatrix& viewMatrix, const SkTextBlob* blob,
175 SkScalar x, SkScalar y,
176 SkDrawFilter* filter, const SkIRect& clipBounds) {
179 SkDEBUGCODE(this->validate();)
180 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawTextBlob");
182 GrAtlasTextContext* atlasTextContext = fDrawingManager->getAtlasTextContext();
183 atlasTextContext->drawTextBlob(fContext, this, clip, skPaint, viewMatrix, fSurfaceProps, blob,
184 x, y, filter, clipBounds);
187 void GrDrawContext::discard() {
190 SkDEBUGCODE(this->validate();)
191 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::discard");
193 AutoCheckFlush acf(fDrawingManager);
194 this->getDrawTarget()->discard(fRenderTarget.get());
197 void GrDrawContext::clear(const SkIRect* rect,
199 bool canIgnoreRect) {
202 SkDEBUGCODE(this->validate();)
203 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::clear");
205 AutoCheckFlush acf(fDrawingManager);
206 this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color, canIgnoreRect);
209 void GrDrawContextPriv::clear(const GrFixedClip& clip,
211 bool canIgnoreClip) {
212 ASSERT_SINGLE_OWNER_PRIV
213 RETURN_IF_ABANDONED_PRIV
214 SkDEBUGCODE(fDrawContext->validate();)
215 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clear");
217 AutoCheckFlush acf(fDrawContext->fDrawingManager);
218 fDrawContext->internalClear(clip, color, canIgnoreClip);
221 void GrDrawContext::internalClear(const GrFixedClip& clip,
223 bool canIgnoreClip) {
225 if (!clip.hasWindowRectangles()) {
226 isFull = !clip.scissorEnabled() ||
227 (canIgnoreClip && fContext->caps()->fullClearIsFree()) ||
228 clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
231 if (fContext->caps()->useDrawInsteadOfClear()) {
232 // This works around a driver bug with clear by drawing a rect instead.
233 // The driver will ignore a clear if it is the only thing rendered to a
234 // target before the target is read.
235 SkRect clearRect = SkRect::MakeIWH(this->width(), this->height());
238 } else if (!clearRect.intersect(SkRect::Make(clip.scissorRect()))) {
243 paint.setColor4f(GrColor4f::FromGrColor(color));
244 paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::Mode::kSrc_Mode));
246 this->drawRect(clip, paint, SkMatrix::I(), clearRect);
248 this->getDrawTarget()->fullClear(this->accessRenderTarget(), color);
250 sk_sp<GrBatch> batch(GrClearBatch::Make(clip, color, this->accessRenderTarget()));
254 this->getDrawTarget()->addBatch(std::move(batch));
258 void GrDrawContext::drawPaint(const GrClip& clip,
259 const GrPaint& origPaint,
260 const SkMatrix& viewMatrix) {
263 SkDEBUGCODE(this->validate();)
264 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPaint");
266 // set rect to be big enough to fill the space, but not super-huge, so we
267 // don't overflow fixed-point implementations
269 SkRect r = fRenderTarget->getBoundsRect();
270 SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
274 // Check if we can replace a clipRRect()/drawPaint() with a drawRRect(). We only do the
275 // transformation for non-rect rrects. Rects caused a performance regression on an Android
276 // test that needs investigation. We also skip cases where there are fragment processors
277 // because they may depend on having correct local coords and this path draws in device space
278 // without a local matrix.
279 if (!paint->numTotalFragmentProcessors() &&
280 clip.isRRect(r, &rrect, &aaRRect) && !rrect.isRect()) {
281 paint.writable()->setAntiAlias(aaRRect);
282 this->drawRRect(GrNoClip(), *paint, SkMatrix::I(), rrect, GrStyle::SimpleFill());
286 // by definition this fills the entire clip, no need for AA
287 if (paint->isAntiAlias()) {
288 paint.writable()->setAntiAlias(false);
291 bool isPerspective = viewMatrix.hasPerspective();
293 // We attempt to map r by the inverse matrix and draw that. mapRect will
294 // map the four corners and bound them with a new rect. This will not
295 // produce a correct result for some perspective matrices.
296 if (!isPerspective) {
297 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
298 SkDebugf("Could not invert matrix\n");
301 this->drawRect(clip, *paint, viewMatrix, r);
303 SkMatrix localMatrix;
304 if (!viewMatrix.invert(&localMatrix)) {
305 SkDebugf("Could not invert matrix\n");
309 AutoCheckFlush acf(fDrawingManager);
311 this->drawNonAAFilledRect(clip, *paint, SkMatrix::I(), r, nullptr, &localMatrix, nullptr,
312 false /* useHWAA */);
316 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
317 return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
318 point.fY >= rect.fTop && point.fY <= rect.fBottom;
321 static bool view_matrix_ok_for_aa_fill_rect(const SkMatrix& viewMatrix) {
322 return viewMatrix.preservesRightAngles();
325 static bool should_apply_coverage_aa(const GrPaint& paint, GrRenderTarget* rt,
326 bool* useHWAA = nullptr) {
327 if (!paint.isAntiAlias()) {
334 *useHWAA = rt->isUnifiedMultisampled();
336 return !rt->isUnifiedMultisampled();
340 // Attempts to crop a rect and optional local rect to the clip boundaries.
341 // Returns false if the draw can be skipped entirely.
342 static bool crop_filled_rect(int width, int height, const GrClip& clip,
343 const SkMatrix& viewMatrix, SkRect* rect,
344 SkRect* localRect = nullptr) {
345 if (!viewMatrix.rectStaysRect()) {
349 SkIRect clipDevBounds;
352 clip.getConservativeBounds(width, height, &clipDevBounds);
353 if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
358 if (!rect->intersects(clipBounds)) {
361 const SkScalar dx = localRect->width() / rect->width();
362 const SkScalar dy = localRect->height() / rect->height();
363 if (clipBounds.fLeft > rect->fLeft) {
364 localRect->fLeft += (clipBounds.fLeft - rect->fLeft) * dx;
365 rect->fLeft = clipBounds.fLeft;
367 if (clipBounds.fTop > rect->fTop) {
368 localRect->fTop += (clipBounds.fTop - rect->fTop) * dy;
369 rect->fTop = clipBounds.fTop;
371 if (clipBounds.fRight < rect->fRight) {
372 localRect->fRight -= (rect->fRight - clipBounds.fRight) * dx;
373 rect->fRight = clipBounds.fRight;
375 if (clipBounds.fBottom < rect->fBottom) {
376 localRect->fBottom -= (rect->fBottom - clipBounds.fBottom) * dy;
377 rect->fBottom = clipBounds.fBottom;
382 return rect->intersect(clipBounds);
385 bool GrDrawContext::drawFilledRect(const GrClip& clip,
386 const GrPaint& paint,
387 const SkMatrix& viewMatrix,
389 const GrUserStencilSettings* ss) {
390 SkRect croppedRect = rect;
391 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
395 SkAutoTUnref<GrDrawBatch> batch;
398 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
399 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
400 batch.reset(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
401 paint.isAntiAlias(), fInstancedPipelineInfo,
404 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
406 pipelineBuilder.setUserStencil(ss);
408 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
413 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
414 // The fill path can handle rotation but not skew.
415 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
417 viewMatrix.mapRect(&devBoundRect, croppedRect);
419 batch.reset(GrRectBatchFactory::CreateAAFill(paint, viewMatrix, rect, croppedRect,
422 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
424 pipelineBuilder.setUserStencil(ss);
426 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
431 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr, nullptr, ss,
439 void GrDrawContext::drawRect(const GrClip& clip,
440 const GrPaint& paint,
441 const SkMatrix& viewMatrix,
443 const GrStyle* style) {
445 style = &GrStyle::SimpleFill();
449 SkDEBUGCODE(this->validate();)
450 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRect");
452 // Path effects should've been devolved to a path in SkGpuDevice
453 SkASSERT(!style->pathEffect());
455 AutoCheckFlush acf(fDrawingManager);
457 const SkStrokeRec& stroke = style->strokeRec();
458 if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
460 if (!fContext->caps()->useDrawInsteadOfClear()) {
461 // Check if this is a full RT draw and can be replaced with a clear. We don't bother
462 // checking cases where the RT is fully inside a stroke.
463 SkRect rtRect = fRenderTarget->getBoundsRect();
464 // Does the clip contain the entire RT?
465 if (clip.quickContains(rtRect)) {
467 if (!viewMatrix.invert(&invM)) {
470 // Does the rect bound the RT?
471 SkPoint srcSpaceRTQuad[4];
472 invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
473 if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
474 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
475 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
476 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
479 if (paint.isConstantBlendedColor(&clearColor)) {
480 this->clear(nullptr, clearColor, true);
487 if (this->drawFilledRect(clip, paint, viewMatrix, rect, nullptr)) {
490 } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
491 stroke.getStyle() == SkStrokeRec::kHairline_Style) {
492 if ((!rect.width() || !rect.height()) &&
493 SkStrokeRec::kHairline_Style != stroke.getStyle()) {
494 SkScalar r = stroke.getWidth() / 2;
495 // TODO: Move these stroke->fill fallbacks to GrShape?
496 switch (stroke.getJoin()) {
497 case SkPaint::kMiter_Join:
498 this->drawRect(clip, paint, viewMatrix,
499 {rect.fLeft - r, rect.fTop - r,
500 rect.fRight + r, rect.fBottom + r},
501 &GrStyle::SimpleFill());
503 case SkPaint::kRound_Join:
504 // Raster draws nothing when both dimensions are empty.
505 if (rect.width() || rect.height()){
506 SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
507 this->drawRRect(clip, paint, viewMatrix, rrect, GrStyle::SimpleFill());
510 case SkPaint::kBevel_Join:
512 this->drawRect(clip, paint, viewMatrix,
513 {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
514 &GrStyle::SimpleFill());
516 this->drawRect(clip, paint, viewMatrix,
517 {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
518 &GrStyle::SimpleFill());
525 bool snapToPixelCenters = false;
526 SkAutoTUnref<GrDrawBatch> batch;
528 GrColor color = paint.getColor();
529 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
530 // The stroke path needs the rect to remain axis aligned (no rotation or skew).
531 if (viewMatrix.rectStaysRect()) {
532 batch.reset(GrRectBatchFactory::CreateAAStroke(color, viewMatrix, rect, stroke));
535 // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
536 // hairline rects. We jam all the vertices to pixel centers to avoid this, but not
537 // when MSAA is enabled because it can cause ugly artifacts.
538 snapToPixelCenters = stroke.getStyle() == SkStrokeRec::kHairline_Style &&
539 !fRenderTarget->isUnifiedMultisampled();
540 batch.reset(GrRectBatchFactory::CreateNonAAStroke(color, viewMatrix, rect,
541 stroke, snapToPixelCenters));
545 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
547 if (snapToPixelCenters) {
548 pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
552 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
558 path.setIsVolatile(true);
560 this->internalDrawPath(clip, paint, viewMatrix, path, *style);
563 void GrDrawContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
564 ASSERT_SINGLE_OWNER_PRIV
565 RETURN_IF_ABANDONED_PRIV
566 SkDEBUGCODE(fDrawContext->validate();)
567 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContextPriv::clearStencilClip");
569 AutoCheckFlush acf(fDrawContext->fDrawingManager);
570 fDrawContext->getDrawTarget()->clearStencilClip(clip, insideStencilMask,
571 fDrawContext->accessRenderTarget());
574 void GrDrawContextPriv::stencilPath(const GrClip& clip,
576 const SkMatrix& viewMatrix,
577 const GrPath* path) {
578 fDrawContext->getDrawTarget()->stencilPath(fDrawContext, clip, useHWAA, viewMatrix, path);
581 void GrDrawContextPriv::stencilRect(const GrClip& clip,
582 const GrUserStencilSettings* ss,
584 const SkMatrix& viewMatrix,
585 const SkRect& rect) {
586 ASSERT_SINGLE_OWNER_PRIV
587 RETURN_IF_ABANDONED_PRIV
588 SkDEBUGCODE(fDrawContext->validate();)
589 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::stencilRect");
591 AutoCheckFlush acf(fDrawContext->fDrawingManager);
594 paint.setAntiAlias(useHWAA);
595 paint.setXPFactory(GrDisableColorXPFactory::Make());
597 fDrawContext->drawNonAAFilledRect(clip, paint, viewMatrix, rect, nullptr, nullptr, ss, useHWAA);
600 bool GrDrawContextPriv::drawAndStencilRect(const GrClip& clip,
601 const GrUserStencilSettings* ss,
605 const SkMatrix& viewMatrix,
606 const SkRect& rect) {
607 ASSERT_SINGLE_OWNER_PRIV
608 RETURN_FALSE_IF_ABANDONED_PRIV
609 SkDEBUGCODE(fDrawContext->validate();)
610 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawAndStencilRect");
612 AutoCheckFlush acf(fDrawContext->fDrawingManager);
615 paint.setAntiAlias(doAA);
616 paint.setCoverageSetOpXPFactory(op, invert);
618 if (fDrawContext->drawFilledRect(clip, paint, viewMatrix, rect, ss)) {
623 path.setIsVolatile(true);
625 return this->drawAndStencilPath(clip, ss, op, invert, doAA, viewMatrix, path);
628 void GrDrawContext::fillRectToRect(const GrClip& clip,
629 const GrPaint& paint,
630 const SkMatrix& viewMatrix,
631 const SkRect& rectToDraw,
632 const SkRect& localRect) {
635 SkDEBUGCODE(this->validate();)
636 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectToRect");
638 SkRect croppedRect = rectToDraw;
639 SkRect croppedLocalRect = localRect;
640 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix,
641 &croppedRect, &croppedLocalRect)) {
645 AutoCheckFlush acf(fDrawingManager);
648 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
649 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
650 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
651 croppedLocalRect, paint.isAntiAlias(),
652 fInstancedPipelineInfo, &useHWAA));
654 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
655 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
660 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
661 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, &croppedLocalRect,
662 nullptr, nullptr, useHWAA);
666 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
667 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::CreateWithLocalRect(paint.getColor(),
671 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
672 this->drawBatch(pipelineBuilder, clip, batch);
676 SkMatrix viewAndUnLocalMatrix;
677 if (!viewAndUnLocalMatrix.setRectToRect(localRect, rectToDraw, SkMatrix::kFill_ScaleToFit)) {
678 SkDebugf("fillRectToRect called with empty local matrix.\n");
681 viewAndUnLocalMatrix.postConcat(viewMatrix);
684 path.setIsVolatile(true);
685 path.addRect(localRect);
686 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
689 void GrDrawContext::fillRectWithLocalMatrix(const GrClip& clip,
690 const GrPaint& paint,
691 const SkMatrix& viewMatrix,
692 const SkRect& rectToDraw,
693 const SkMatrix& localMatrix) {
696 SkDEBUGCODE(this->validate();)
697 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::fillRectWithLocalMatrix");
699 SkRect croppedRect = rectToDraw;
700 if (!crop_filled_rect(this->width(), this->height(), clip, viewMatrix, &croppedRect)) {
704 AutoCheckFlush acf(fDrawingManager);
707 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
708 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
709 SkAutoTUnref<GrDrawBatch> batch(ir->recordRect(croppedRect, viewMatrix, paint.getColor(),
710 localMatrix, paint.isAntiAlias(),
711 fInstancedPipelineInfo, &useHWAA));
713 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
714 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
719 if (!should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
720 this->drawNonAAFilledRect(clip, paint, viewMatrix, croppedRect, nullptr,
721 &localMatrix, nullptr, useHWAA);
725 if (view_matrix_ok_for_aa_fill_rect(viewMatrix)) {
726 SkAutoTUnref<GrDrawBatch> batch(GrAAFillRectBatch::Create(paint.getColor(), viewMatrix,
727 localMatrix, croppedRect));
728 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
729 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
733 SkMatrix viewAndUnLocalMatrix;
734 if (!localMatrix.invert(&viewAndUnLocalMatrix)) {
735 SkDebugf("fillRectWithLocalMatrix called with degenerate local matrix.\n");
738 viewAndUnLocalMatrix.postConcat(viewMatrix);
741 path.setIsVolatile(true);
742 path.addRect(rectToDraw);
743 path.transform(localMatrix);
744 this->internalDrawPath(clip, paint, viewAndUnLocalMatrix, path, GrStyle());
747 void GrDrawContext::drawVertices(const GrClip& clip,
748 const GrPaint& paint,
749 const SkMatrix& viewMatrix,
750 GrPrimitiveType primitiveType,
752 const SkPoint positions[],
753 const SkPoint texCoords[],
754 const GrColor colors[],
755 const uint16_t indices[],
759 SkDEBUGCODE(this->validate();)
760 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawVertices");
762 AutoCheckFlush acf(fDrawingManager);
764 // TODO clients should give us bounds
766 if (!bounds.setBoundsCheck(positions, vertexCount)) {
767 SkDebugf("drawVertices call empty bounds\n");
771 viewMatrix.mapRect(&bounds);
773 SkAutoTUnref<GrDrawBatch> batch(new GrDrawVerticesBatch(paint.getColor(),
774 primitiveType, viewMatrix, positions,
775 vertexCount, indices, indexCount,
776 colors, texCoords, bounds));
778 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
779 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
782 ///////////////////////////////////////////////////////////////////////////////
784 void GrDrawContext::drawAtlas(const GrClip& clip,
785 const GrPaint& paint,
786 const SkMatrix& viewMatrix,
788 const SkRSXform xform[],
789 const SkRect texRect[],
790 const SkColor colors[]) {
793 SkDEBUGCODE(this->validate();)
794 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawAtlas");
796 AutoCheckFlush acf(fDrawingManager);
798 SkAutoTUnref<GrDrawBatch> batch(new GrDrawAtlasBatch(paint.getColor(), viewMatrix, spriteCount,
799 xform, texRect, colors));
801 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
802 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
805 ///////////////////////////////////////////////////////////////////////////////
807 void GrDrawContext::drawRRect(const GrClip& origClip,
808 const GrPaint& paint,
809 const SkMatrix& viewMatrix,
810 const SkRRect& rrect,
811 const GrStyle& style) {
814 SkDEBUGCODE(this->validate();)
815 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRRect");
816 if (rrect.isEmpty()) {
821 const GrClip* clip = &origClip;
822 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
823 // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
824 // draw is aa. Since our lower level clip code works from batch bounds, which are SkRects, it
825 // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
826 // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
827 // can be ignored. We'd prefer to fix this in the framework by removing the clips calls.
829 if (rrect.transform(viewMatrix, &devRRect) && clip->quickContains(devRRect)) {
833 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
835 AutoCheckFlush acf(fDrawingManager);
836 const SkStrokeRec stroke = style.strokeRec();
839 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
840 stroke.isFillStyle()) {
841 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
842 SkAutoTUnref<GrDrawBatch> batch(ir->recordRRect(rrect, viewMatrix, paint.getColor(),
843 paint.isAntiAlias(), fInstancedPipelineInfo,
846 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
847 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
852 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
853 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
854 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateRRectBatch(paint.getColor(),
860 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
861 this->getDrawTarget()->drawBatch(pipelineBuilder, this, *clip, batch);
867 path.setIsVolatile(true);
868 path.addRRect(rrect);
869 this->internalDrawPath(*clip, paint, viewMatrix, path, style);
872 bool GrDrawContext::drawFilledDRRect(const GrClip& clip,
873 const GrPaint& paintIn,
874 const SkMatrix& viewMatrix,
875 const SkRRect& origOuter,
876 const SkRRect& origInner) {
877 SkASSERT(!origInner.isEmpty());
878 SkASSERT(!origOuter.isEmpty());
880 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
882 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
883 SkAutoTUnref<GrDrawBatch> batch(ir->recordDRRect(origOuter, origInner, viewMatrix,
884 paintIn.getColor(), paintIn.isAntiAlias(),
885 fInstancedPipelineInfo, &useHWAA));
887 GrPipelineBuilder pipelineBuilder(paintIn, useHWAA);
888 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
893 bool applyAA = paintIn.isAntiAlias() && !fRenderTarget->isUnifiedMultisampled();
895 GrPrimitiveEdgeType innerEdgeType = applyAA ? kInverseFillAA_GrProcessorEdgeType :
896 kInverseFillBW_GrProcessorEdgeType;
897 GrPrimitiveEdgeType outerEdgeType = applyAA ? kFillAA_GrProcessorEdgeType :
898 kFillBW_GrProcessorEdgeType;
900 SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
902 if (!viewMatrix.isIdentity()) {
903 if (!origInner.transform(viewMatrix, inner.writable())) {
906 if (!origOuter.transform(viewMatrix, outer.writable())) {
909 if (!viewMatrix.invert(&inverseVM)) {
916 GrPaint grPaint(paintIn);
917 grPaint.setAntiAlias(false);
919 // TODO these need to be a geometry processors
920 sk_sp<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
925 sk_sp<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
930 grPaint.addCoverageFragmentProcessor(std::move(innerEffect));
931 grPaint.addCoverageFragmentProcessor(std::move(outerEffect));
933 SkRect bounds = outer->getBounds();
935 bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
938 this->fillRectWithLocalMatrix(clip, grPaint, SkMatrix::I(), bounds, inverseVM);
942 void GrDrawContext::drawDRRect(const GrClip& clip,
943 const GrPaint& paint,
944 const SkMatrix& viewMatrix,
945 const SkRRect& outer,
946 const SkRRect& inner) {
949 SkDEBUGCODE(this->validate();)
950 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawDRRect");
952 SkASSERT(!outer.isEmpty());
953 SkASSERT(!inner.isEmpty());
955 AutoCheckFlush acf(fDrawingManager);
957 if (this->drawFilledDRRect(clip, paint, viewMatrix, outer, inner)) {
962 path.setIsVolatile(true);
963 path.addRRect(inner);
964 path.addRRect(outer);
965 path.setFillType(SkPath::kEvenOdd_FillType);
967 this->internalDrawPath(clip, paint, viewMatrix, path, GrStyle::SimpleFill());
970 ///////////////////////////////////////////////////////////////////////////////
972 static inline bool is_int(float x) {
973 return x == (float) sk_float_round2int(x);
976 void GrDrawContext::drawRegion(const GrClip& clip,
977 const GrPaint& paint,
978 const SkMatrix& viewMatrix,
979 const SkRegion& region,
980 const GrStyle& style) {
983 SkDEBUGCODE(this->validate();)
984 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawRegion");
986 bool isNonTranslate = SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask));
987 bool complexStyle = !style.isSimpleFill();
988 bool antiAlias = paint.isAntiAlias() && (!is_int(viewMatrix.getTranslateX()) ||
989 !is_int(viewMatrix.getTranslateY()));
990 if (isNonTranslate || complexStyle || antiAlias) {
992 region.getBoundaryPath(&path);
993 return this->drawPath(clip, paint, viewMatrix, path, style);
996 SkAutoTUnref<GrDrawBatch> batch(GrRegionBatch::Create(paint.getColor(), viewMatrix, region));
997 GrPipelineBuilder pipelineBuilder(paint, false);
998 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1001 void GrDrawContext::drawOval(const GrClip& clip,
1002 const GrPaint& paint,
1003 const SkMatrix& viewMatrix,
1005 const GrStyle& style) {
1008 SkDEBUGCODE(this->validate();)
1009 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawOval");
1011 if (oval.isEmpty()) {
1015 SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1017 AutoCheckFlush acf(fDrawingManager);
1018 const SkStrokeRec& stroke = style.strokeRec();
1021 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport() &&
1022 stroke.isFillStyle()) {
1023 InstancedRendering* ir = this->getDrawTarget()->instancedRendering();
1024 SkAutoTUnref<GrDrawBatch> batch(ir->recordOval(oval, viewMatrix, paint.getColor(),
1025 paint.isAntiAlias(), fInstancedPipelineInfo,
1028 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1029 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1034 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
1035 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1036 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
1042 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1043 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1049 path.setIsVolatile(true);
1051 this->internalDrawPath(clip, paint, viewMatrix, path, style);
1054 void GrDrawContext::drawArc(const GrClip& clip,
1055 const GrPaint& paint,
1056 const SkMatrix& viewMatrix,
1058 SkScalar startAngle,
1059 SkScalar sweepAngle,
1061 const GrStyle& style) {
1063 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA)) {
1064 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1065 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateArcBatch(paint.getColor(),
1074 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1075 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1080 SkPathPriv::CreateDrawArcPath(&path, oval, startAngle, sweepAngle, useCenter,
1081 style.isSimpleFill());
1082 this->internalDrawPath(clip, paint, viewMatrix, path, style);
1086 void GrDrawContext::drawImageLattice(const GrClip& clip,
1087 const GrPaint& paint,
1088 const SkMatrix& viewMatrix,
1091 std::unique_ptr<SkLatticeIter> iter,
1092 const SkRect& dst) {
1095 SkDEBUGCODE(this->validate();)
1096 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawImageLattice");
1098 AutoCheckFlush acf(fDrawingManager);
1100 SkAutoTUnref<GrDrawBatch> batch(GrNinePatch::CreateNonAA(paint.getColor(), viewMatrix,
1101 imageWidth, imageHeight,
1102 std::move(iter), dst));
1104 GrPipelineBuilder pipelineBuilder(paint, this->mustUseHWAA(paint));
1105 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1108 void GrDrawContext::prepareForExternalIO() {
1111 SkDEBUGCODE(this->validate();)
1112 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::prepareForExternalIO");
1114 ASSERT_OWNED_RESOURCE(fRenderTarget);
1116 fDrawingManager->prepareSurfaceForExternalIO(fRenderTarget.get());
1119 void GrDrawContext::drawNonAAFilledRect(const GrClip& clip,
1120 const GrPaint& paint,
1121 const SkMatrix& viewMatrix,
1123 const SkRect* localRect,
1124 const SkMatrix* localMatrix,
1125 const GrUserStencilSettings* ss,
1127 SkASSERT(!useHWAA || this->isStencilBufferMultisampled());
1128 SkAutoTUnref<GrDrawBatch> batch(
1129 GrRectBatchFactory::CreateNonAAFill(paint.getColor(), viewMatrix, rect, localRect,
1131 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1133 pipelineBuilder.setUserStencil(ss);
1135 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1138 bool GrDrawContext::readPixels(const SkImageInfo& dstInfo, void* dstBuffer, size_t dstRowBytes,
1140 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1141 GrPixelConfig config = SkImageInfo2GrPixelConfig(dstInfo, *fContext->caps());
1142 if (kUnknown_GrPixelConfig == config) {
1147 if (kUnpremul_SkAlphaType == dstInfo.alphaType()) {
1148 flags = GrContext::kUnpremul_PixelOpsFlag;
1151 return fRenderTarget->readPixels(x, y, dstInfo.width(), dstInfo.height(),
1152 config, dstBuffer, dstRowBytes, flags);
1155 bool GrDrawContext::writePixels(const SkImageInfo& srcInfo, const void* srcBuffer,
1156 size_t srcRowBytes, int x, int y) {
1157 // TODO: teach fRenderTarget to take ImageInfo directly to specify the src pixels
1158 GrPixelConfig config = SkImageInfo2GrPixelConfig(srcInfo, *fContext->caps());
1159 if (kUnknown_GrPixelConfig == config) {
1163 if (kUnpremul_SkAlphaType == srcInfo.alphaType()) {
1164 flags = GrContext::kUnpremul_PixelOpsFlag;
1167 return fRenderTarget->writePixels(x, y, srcInfo.width(), srcInfo.height(),
1168 config, srcBuffer, srcRowBytes, flags);
1171 // Can 'path' be drawn as a pair of filled nested rectangles?
1172 static bool fills_as_nested_rects(const SkMatrix& viewMatrix, const SkPath& path, SkRect rects[2]) {
1174 if (path.isInverseFillType()) {
1178 // TODO: this restriction could be lifted if we were willing to apply
1179 // the matrix to all the points individually rather than just to the rect
1180 if (!viewMatrix.rectStaysRect()) {
1184 SkPath::Direction dirs[2];
1185 if (!path.isNestedFillRects(rects, dirs)) {
1189 if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1190 // The two rects need to be wound opposite to each other
1194 // Right now, nested rects where the margin is not the same width
1195 // all around do not render correctly
1196 const SkScalar* outer = rects[0].asScalars();
1197 const SkScalar* inner = rects[1].asScalars();
1201 SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
1202 bool allGoE1 = margin >= SK_Scalar1;
1204 for (int i = 1; i < 4; ++i) {
1205 SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
1206 if (temp < SK_Scalar1) {
1209 if (!SkScalarNearlyEqual(margin, temp)) {
1214 return allEq || allGoE1;
1217 void GrDrawContext::drawPath(const GrClip& clip,
1218 const GrPaint& paint,
1219 const SkMatrix& viewMatrix,
1221 const GrStyle& style) {
1224 SkDEBUGCODE(this->validate();)
1225 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawPath");
1227 if (path.isEmpty()) {
1228 if (path.isInverseFillType()) {
1229 this->drawPaint(clip, paint, viewMatrix);
1234 AutoCheckFlush acf(fDrawingManager);
1237 if (should_apply_coverage_aa(paint, fRenderTarget.get(), &useHWAA) && !style.pathEffect()) {
1238 if (style.isSimpleFill() && !path.isConvex()) {
1239 // Concave AA paths are expensive - try to avoid them for special cases
1242 if (fills_as_nested_rects(viewMatrix, path, rects)) {
1243 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
1244 paint.getColor(), viewMatrix, rects));
1246 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1247 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1253 bool isOval = path.isOval(&ovalRect);
1255 if (isOval && !path.isInverseFillType()) {
1256 GrShaderCaps* shaderCaps = fContext->caps()->shaderCaps();
1257 SkAutoTUnref<GrDrawBatch> batch(GrOvalRenderer::CreateOvalBatch(paint.getColor(),
1263 GrPipelineBuilder pipelineBuilder(paint, useHWAA);
1264 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);
1270 // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
1271 // Scratch textures can be recycled after they are returned to the texture
1272 // cache. This presents a potential hazard for buffered drawing. However,
1273 // the writePixels that uploads to the scratch will perform a flush so we're
1275 this->internalDrawPath(clip, paint, viewMatrix, path, style);
1278 bool GrDrawContextPriv::drawAndStencilPath(const GrClip& clip,
1279 const GrUserStencilSettings* ss,
1283 const SkMatrix& viewMatrix,
1284 const SkPath& path) {
1285 ASSERT_SINGLE_OWNER_PRIV
1286 RETURN_FALSE_IF_ABANDONED_PRIV
1287 SkDEBUGCODE(fDrawContext->validate();)
1288 GR_AUDIT_TRAIL_AUTO_FRAME(fDrawContext->fAuditTrail, "GrDrawContext::drawPath");
1290 if (path.isEmpty() && path.isInverseFillType()) {
1291 this->drawAndStencilRect(clip, ss, op, invert, false, SkMatrix::I(),
1292 SkRect::MakeIWH(fDrawContext->width(),
1293 fDrawContext->height()));
1297 AutoCheckFlush acf(fDrawContext->fDrawingManager);
1299 // An Assumption here is that path renderer would use some form of tweaking
1300 // the src color (either the input alpha or in the frag shader) to implement
1301 // aa. If we have some future driver-mojo path AA that can do the right
1302 // thing WRT to the blend then we'll need some query on the PR.
1303 bool useCoverageAA = doAA && !fDrawContext->isUnifiedMultisampled();
1304 bool hasUserStencilSettings = !ss->isUnused();
1305 bool isStencilBufferMSAA = fDrawContext->isStencilBufferMultisampled();
1307 const GrPathRendererChain::DrawType type =
1308 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1309 : GrPathRendererChain::kColor_DrawType;
1311 GrShape shape(path, GrStyle::SimpleFill());
1312 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1313 canDrawArgs.fShaderCaps = fDrawContext->fDrawingManager->getContext()->caps()->shaderCaps();
1314 canDrawArgs.fViewMatrix = &viewMatrix;
1315 canDrawArgs.fShape = &shape;
1316 canDrawArgs.fAntiAlias = useCoverageAA;
1317 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
1318 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1320 // Don't allow the SW renderer
1321 GrPathRenderer* pr = fDrawContext->fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1327 paint.setCoverageSetOpXPFactory(op, invert);
1329 GrPathRenderer::DrawPathArgs args;
1330 args.fResourceProvider = fDrawContext->fDrawingManager->getContext()->resourceProvider();
1331 args.fPaint = &paint;
1332 args.fUserStencilSettings = ss;
1333 args.fDrawContext = fDrawContext;
1335 args.fViewMatrix = &viewMatrix;
1336 args.fShape = &shape;
1337 args.fAntiAlias = useCoverageAA;
1338 args.fGammaCorrect = fDrawContext->isGammaCorrect();
1343 SkBudgeted GrDrawContextPriv::isBudgeted() const {
1344 ASSERT_SINGLE_OWNER_PRIV
1346 if (fDrawContext->wasAbandoned()) {
1347 return SkBudgeted::kNo;
1350 SkDEBUGCODE(fDrawContext->validate();)
1352 return fDrawContext->fRenderTarget->resourcePriv().isBudgeted();
1355 void GrDrawContext::internalDrawPath(const GrClip& clip,
1356 const GrPaint& paint,
1357 const SkMatrix& viewMatrix,
1359 const GrStyle& style) {
1362 SkASSERT(!path.isEmpty());
1364 bool useCoverageAA = should_apply_coverage_aa(paint, fRenderTarget.get());
1365 constexpr bool kHasUserStencilSettings = false;
1366 bool isStencilBufferMSAA = this->isStencilBufferMultisampled();
1368 const GrPathRendererChain::DrawType type =
1369 useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType
1370 : GrPathRendererChain::kColor_DrawType;
1372 GrShape shape(path, style);
1373 if (shape.isEmpty()) {
1376 GrPathRenderer::CanDrawPathArgs canDrawArgs;
1377 canDrawArgs.fShaderCaps = fDrawingManager->getContext()->caps()->shaderCaps();
1378 canDrawArgs.fViewMatrix = &viewMatrix;
1379 canDrawArgs.fShape = &shape;
1380 canDrawArgs.fAntiAlias = useCoverageAA;
1381 canDrawArgs.fHasUserStencilSettings = kHasUserStencilSettings;
1382 canDrawArgs.fIsStencilBufferMSAA = isStencilBufferMSAA;
1384 // Try a 1st time without applying any of the style to the geometry (and barring sw)
1385 GrPathRenderer* pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1386 SkScalar styleScale = GrStyle::MatrixToScaleFactor(viewMatrix);
1388 if (!pr && shape.style().pathEffect()) {
1389 // It didn't work above, so try again with the path effect applied.
1390 shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1391 if (shape.isEmpty()) {
1394 pr = fDrawingManager->getPathRenderer(canDrawArgs, false, type);
1397 if (shape.style().applies()) {
1398 shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1399 if (shape.isEmpty()) {
1403 // This time, allow SW renderer
1404 pr = fDrawingManager->getPathRenderer(canDrawArgs, true, type);
1409 SkDebugf("Unable to find path renderer compatible with path.\n");
1414 GrPathRenderer::DrawPathArgs args;
1415 args.fResourceProvider = fDrawingManager->getContext()->resourceProvider();
1416 args.fPaint = &paint;
1417 args.fUserStencilSettings = &GrUserStencilSettings::kUnused;
1418 args.fDrawContext = this;
1420 args.fViewMatrix = &viewMatrix;
1421 args.fShape = canDrawArgs.fShape;
1422 args.fAntiAlias = useCoverageAA;
1423 args.fGammaCorrect = this->isGammaCorrect();
1427 void GrDrawContext::drawBatch(const GrPipelineBuilder& pipelineBuilder, const GrClip& clip,
1428 GrDrawBatch* batch) {
1431 SkDEBUGCODE(this->validate();)
1432 GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::drawBatch");
1434 this->getDrawTarget()->drawBatch(pipelineBuilder, this, clip, batch);