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