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