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