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