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