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