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