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