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