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