• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/gpu/GrRenderTargetContext.h"
9 
10 #include "include/core/SkDrawable.h"
11 #include "include/gpu/GrBackendSemaphore.h"
12 #include "include/private/GrRecordingContext.h"
13 #include "include/private/SkShadowFlags.h"
14 #include "include/utils/SkShadowUtils.h"
15 #include "src/core/SkAutoPixmapStorage.h"
16 #include "src/core/SkConvertPixels.h"
17 #include "src/core/SkDrawShadowInfo.h"
18 #include "src/core/SkGlyphRunPainter.h"
19 #include "src/core/SkLatticeIter.h"
20 #include "src/core/SkMatrixPriv.h"
21 #include "src/core/SkRRectPriv.h"
22 #include "src/core/SkSurfacePriv.h"
23 #include "src/core/SkYUVMath.h"
24 #include "src/gpu/GrAppliedClip.h"
25 #include "src/gpu/GrAuditTrail.h"
26 #include "src/gpu/GrBlurUtils.h"
27 #include "src/gpu/GrCaps.h"
28 #include "src/gpu/GrClientMappedBufferManager.h"
29 #include "src/gpu/GrColor.h"
30 #include "src/gpu/GrContextPriv.h"
31 #include "src/gpu/GrDataUtils.h"
32 #include "src/gpu/GrDrawingManager.h"
33 #include "src/gpu/GrFixedClip.h"
34 #include "src/gpu/GrGpuResourcePriv.h"
35 #include "src/gpu/GrImageInfo.h"
36 #include "src/gpu/GrMemoryPool.h"
37 #include "src/gpu/GrPathRenderer.h"
38 #include "src/gpu/GrRecordingContextPriv.h"
39 #include "src/gpu/GrRenderTarget.h"
40 #include "src/gpu/GrRenderTargetContextPriv.h"
41 #include "src/gpu/GrResourceProvider.h"
42 #include "src/gpu/GrStencilAttachment.h"
43 #include "src/gpu/GrStyle.h"
44 #include "src/gpu/GrTracing.h"
45 #include "src/gpu/SkGr.h"
46 #include "src/gpu/effects/GrBicubicEffect.h"
47 #include "src/gpu/effects/GrRRectEffect.h"
48 #include "src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h"
49 #include "src/gpu/geometry/GrQuad.h"
50 #include "src/gpu/geometry/GrQuadUtils.h"
51 #include "src/gpu/geometry/GrShape.h"
52 #include "src/gpu/ops/GrAtlasTextOp.h"
53 #include "src/gpu/ops/GrClearOp.h"
54 #include "src/gpu/ops/GrClearStencilClipOp.h"
55 #include "src/gpu/ops/GrDrawAtlasOp.h"
56 #include "src/gpu/ops/GrDrawOp.h"
57 #include "src/gpu/ops/GrDrawVerticesOp.h"
58 #include "src/gpu/ops/GrDrawableOp.h"
59 #include "src/gpu/ops/GrFillRRectOp.h"
60 #include "src/gpu/ops/GrFillRectOp.h"
61 #include "src/gpu/ops/GrLatticeOp.h"
62 #include "src/gpu/ops/GrOp.h"
63 #include "src/gpu/ops/GrOvalOpFactory.h"
64 #include "src/gpu/ops/GrRegionOp.h"
65 #include "src/gpu/ops/GrShadowRRectOp.h"
66 #include "src/gpu/ops/GrStencilPathOp.h"
67 #include "src/gpu/ops/GrStrokeRectOp.h"
68 #include "src/gpu/ops/GrTextureOp.h"
69 #include "src/gpu/text/GrTextContext.h"
70 #include "src/gpu/text/GrTextTarget.h"
71 
72 class GrRenderTargetContext::TextTarget : public GrTextTarget {
73 public:
TextTarget(GrRenderTargetContext * renderTargetContext)74     TextTarget(GrRenderTargetContext* renderTargetContext)
75             : GrTextTarget(renderTargetContext->width(), renderTargetContext->height(),
76                            renderTargetContext->colorInfo())
77             , fRenderTargetContext(renderTargetContext)
78             , fGlyphPainter{*renderTargetContext} {}
79 
addDrawOp(const GrClip & clip,std::unique_ptr<GrAtlasTextOp> op)80     void addDrawOp(const GrClip& clip, std::unique_ptr<GrAtlasTextOp> op) override {
81         fRenderTargetContext->addDrawOp(clip, std::move(op));
82     }
83 
drawShape(const GrClip & clip,const SkPaint & paint,const SkMatrix & viewMatrix,const GrShape & shape)84     void drawShape(const GrClip& clip, const SkPaint& paint,
85                   const SkMatrix& viewMatrix, const GrShape& shape) override {
86         GrBlurUtils::drawShapeWithMaskFilter(fRenderTargetContext->fContext, fRenderTargetContext,
87                                              clip, paint, viewMatrix, shape);
88     }
89 
makeGrPaint(GrMaskFormat maskFormat,const SkPaint & skPaint,const SkMatrix & viewMatrix,GrPaint * grPaint)90     void makeGrPaint(GrMaskFormat maskFormat, const SkPaint& skPaint, const SkMatrix& viewMatrix,
91                      GrPaint* grPaint) override {
92         auto context = fRenderTargetContext->fContext;
93         const GrColorInfo& colorInfo = fRenderTargetContext->colorInfo();
94         if (kARGB_GrMaskFormat == maskFormat) {
95             SkPaintToGrPaintWithPrimitiveColor(context, colorInfo, skPaint, grPaint);
96         } else {
97             SkPaintToGrPaint(context, colorInfo, skPaint, viewMatrix, grPaint);
98         }
99     }
100 
getContext()101     GrRecordingContext* getContext() override {
102         return fRenderTargetContext->fContext;
103     }
104 
glyphPainter()105     SkGlyphRunListPainter* glyphPainter() override {
106         return &fGlyphPainter;
107     }
108 
109 private:
110     GrRenderTargetContext* fRenderTargetContext;
111     SkGlyphRunListPainter fGlyphPainter;
112 
113 };
114 
115 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
116 #define ASSERT_SINGLE_OWNER \
117     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
118 #define ASSERT_SINGLE_OWNER_PRIV \
119     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
120 #define RETURN_IF_ABANDONED        if (fContext->priv().abandoned()) { return; }
121 #define RETURN_IF_ABANDONED_PRIV   if (fRenderTargetContext->fContext->priv().abandoned()) { return; }
122 #define RETURN_FALSE_IF_ABANDONED  if (fContext->priv().abandoned()) { return false; }
123 #define RETURN_FALSE_IF_ABANDONED_PRIV  if (fRenderTargetContext->fContext->priv().abandoned()) { return false; }
124 #define RETURN_NULL_IF_ABANDONED   if (fContext->priv().abandoned()) { return nullptr; }
125 
126 //////////////////////////////////////////////////////////////////////////////
127 
128 class AutoCheckFlush {
129 public:
AutoCheckFlush(GrDrawingManager * drawingManager)130     AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
131         SkASSERT(fDrawingManager);
132     }
~AutoCheckFlush()133     ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
134 
135 private:
136     GrDrawingManager* fDrawingManager;
137 };
138 
Make(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,sk_sp<GrSurfaceProxy> proxy,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,bool managedOps)139 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::Make(
140         GrRecordingContext* context,
141         GrColorType colorType,
142         sk_sp<SkColorSpace> colorSpace,
143         sk_sp<GrSurfaceProxy> proxy,
144         GrSurfaceOrigin origin,
145         const SkSurfaceProps* surfaceProps,
146         bool managedOps) {
147     if (!proxy) {
148         return nullptr;
149     }
150 
151     const GrBackendFormat& format = proxy->backendFormat();
152     GrSwizzle readSwizzle = context->priv().caps()->getReadSwizzle(format, colorType);
153     GrSwizzle outSwizzle = context->priv().caps()->getOutputSwizzle(format, colorType);
154 
155     GrSurfaceProxyView readView(proxy, origin, readSwizzle);
156     GrSurfaceProxyView outputView(std::move(proxy), origin, outSwizzle);
157 
158     return std::make_unique<GrRenderTargetContext>(context, std::move(readView),
159                                                    std::move(outputView), colorType,
160                                                    std::move(colorSpace), surfaceProps, managedOps);
161 }
162 
Make(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,SkBackingFit fit,SkISize dimensions,const GrBackendFormat & format,int sampleCnt,GrMipMapped mipMapped,GrProtected isProtected,GrSurfaceOrigin origin,SkBudgeted budgeted,const SkSurfaceProps * surfaceProps)163 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::Make(
164         GrRecordingContext* context,
165         GrColorType colorType,
166         sk_sp<SkColorSpace> colorSpace,
167         SkBackingFit fit,
168         SkISize dimensions,
169         const GrBackendFormat& format,
170         int sampleCnt,
171         GrMipMapped mipMapped,
172         GrProtected isProtected,
173         GrSurfaceOrigin origin,
174         SkBudgeted budgeted,
175         const SkSurfaceProps* surfaceProps) {
176     // It is probably not necessary to check if the context is abandoned here since uses of the
177     // GrRenderTargetContext which need the context will mostly likely fail later on without an
178     // issue. However having this hear adds some reassurance in case there is a path doesn't handle
179     // an abandoned context correctly. It also lets us early out of some extra work.
180     if (context->priv().abandoned()) {
181         return nullptr;
182     }
183 
184     GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(format, colorType);
185 
186     sk_sp<GrTextureProxy> proxy = context->priv().proxyProvider()->createProxy(
187             format, dimensions, swizzle, GrRenderable::kYes, sampleCnt, mipMapped, fit, budgeted,
188             isProtected);
189     if (!proxy) {
190         return nullptr;
191     }
192 
193     auto rtc = GrRenderTargetContext::Make(context, colorType, std::move(colorSpace),
194                                            std::move(proxy), origin, surfaceProps, true);
195     if (!rtc) {
196         return nullptr;
197     }
198     rtc->discard();
199     return rtc;
200 }
201 
Make(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,SkBackingFit fit,SkISize dimensions,int sampleCnt,GrMipMapped mipMapped,GrProtected isProtected,GrSurfaceOrigin origin,SkBudgeted budgeted,const SkSurfaceProps * surfaceProps)202 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::Make(
203         GrRecordingContext* context,
204         GrColorType colorType,
205         sk_sp<SkColorSpace> colorSpace,
206         SkBackingFit fit,
207         SkISize dimensions,
208         int sampleCnt,
209         GrMipMapped mipMapped,
210         GrProtected isProtected,
211         GrSurfaceOrigin origin,
212         SkBudgeted budgeted,
213         const SkSurfaceProps* surfaceProps) {
214     auto format = context->priv().caps()->getDefaultBackendFormat(colorType, GrRenderable::kYes);
215     if (!format.isValid()) {
216         return nullptr;
217     }
218 
219     return GrRenderTargetContext::Make(context, colorType, std::move(colorSpace), fit, dimensions,
220                                        format, sampleCnt, mipMapped, isProtected, origin, budgeted,
221                                        surfaceProps);
222 }
223 
color_type_fallback(GrColorType ct)224 static inline GrColorType color_type_fallback(GrColorType ct) {
225     switch (ct) {
226         // kRGBA_8888 is our default fallback for many color types that may not have renderable
227         // backend formats.
228         case GrColorType::kAlpha_8:
229         case GrColorType::kBGR_565:
230         case GrColorType::kABGR_4444:
231         case GrColorType::kBGRA_8888:
232         case GrColorType::kRGBA_1010102:
233         case GrColorType::kRGBA_F16:
234         case GrColorType::kRGBA_F16_Clamped:
235             return GrColorType::kRGBA_8888;
236         case GrColorType::kAlpha_F16:
237             return GrColorType::kRGBA_F16;
238         case GrColorType::kGray_8:
239             return GrColorType::kRGB_888x;
240         default:
241             return GrColorType::kUnknown;
242     }
243 }
244 
MakeWithFallback(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,SkBackingFit fit,SkISize dimensions,int sampleCnt,GrMipMapped mipMapped,GrProtected isProtected,GrSurfaceOrigin origin,SkBudgeted budgeted,const SkSurfaceProps * surfaceProps)245 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeWithFallback(
246         GrRecordingContext* context,
247         GrColorType colorType,
248         sk_sp<SkColorSpace> colorSpace,
249         SkBackingFit fit,
250         SkISize dimensions,
251         int sampleCnt,
252         GrMipMapped mipMapped,
253         GrProtected isProtected,
254         GrSurfaceOrigin origin,
255         SkBudgeted budgeted,
256         const SkSurfaceProps* surfaceProps) {
257     std::unique_ptr<GrRenderTargetContext> rtc;
258     do {
259         rtc = GrRenderTargetContext::Make(context, colorType, colorSpace, fit, dimensions,
260                                           sampleCnt, mipMapped, isProtected, origin, budgeted,
261                                           surfaceProps);
262         colorType = color_type_fallback(colorType);
263     } while (!rtc && colorType != GrColorType::kUnknown);
264     return rtc;
265 }
266 
MakeFromBackendTexture(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const GrBackendTexture & tex,int sampleCnt,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,ReleaseProc releaseProc,ReleaseContext releaseCtx)267 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendTexture(
268         GrRecordingContext* context,
269         GrColorType colorType,
270         sk_sp<SkColorSpace> colorSpace,
271         const GrBackendTexture& tex,
272         int sampleCnt,
273         GrSurfaceOrigin origin,
274         const SkSurfaceProps* surfaceProps,
275         ReleaseProc releaseProc,
276         ReleaseContext releaseCtx) {
277     SkASSERT(sampleCnt > 0);
278     sk_sp<GrTextureProxy> proxy(context->priv().proxyProvider()->wrapRenderableBackendTexture(
279             tex, sampleCnt, colorType, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc,
280             releaseCtx));
281     if (!proxy) {
282         return nullptr;
283     }
284 
285     return GrRenderTargetContext::Make(context, colorType, std::move(colorSpace), std::move(proxy),
286                                        origin, surfaceProps);
287 }
288 
MakeFromBackendTextureAsRenderTarget(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const GrBackendTexture & tex,int sampleCnt,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps)289 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendTextureAsRenderTarget(
290         GrRecordingContext* context,
291         GrColorType colorType,
292         sk_sp<SkColorSpace> colorSpace,
293         const GrBackendTexture& tex,
294         int sampleCnt,
295         GrSurfaceOrigin origin,
296         const SkSurfaceProps* surfaceProps) {
297     SkASSERT(sampleCnt > 0);
298     sk_sp<GrSurfaceProxy> proxy(context->priv().proxyProvider()->wrapBackendTextureAsRenderTarget(
299             tex, colorType, sampleCnt));
300     if (!proxy) {
301         return nullptr;
302     }
303 
304     return GrRenderTargetContext::Make(context, colorType, std::move(colorSpace), std::move(proxy),
305                                        origin, surfaceProps);
306 }
307 
MakeFromBackendRenderTarget(GrRecordingContext * context,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const GrBackendRenderTarget & rt,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,ReleaseProc releaseProc,ReleaseContext releaseCtx)308 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromBackendRenderTarget(
309         GrRecordingContext* context,
310         GrColorType colorType,
311         sk_sp<SkColorSpace> colorSpace,
312         const GrBackendRenderTarget& rt,
313         GrSurfaceOrigin origin,
314         const SkSurfaceProps* surfaceProps,
315         ReleaseProc releaseProc,
316         ReleaseContext releaseCtx) {
317     sk_sp<GrSurfaceProxy> proxy(context->priv().proxyProvider()->wrapBackendRenderTarget(
318             rt, colorType, releaseProc, releaseCtx));
319     if (!proxy) {
320         return nullptr;
321     }
322 
323     return GrRenderTargetContext::Make(context, colorType, std::move(colorSpace), std::move(proxy),
324                                        origin, surfaceProps);
325 }
326 
MakeFromVulkanSecondaryCB(GrRecordingContext * context,const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)327 std::unique_ptr<GrRenderTargetContext> GrRenderTargetContext::MakeFromVulkanSecondaryCB(
328         GrRecordingContext* context,
329         const SkImageInfo& imageInfo,
330         const GrVkDrawableInfo& vkInfo,
331         const SkSurfaceProps* props) {
332     sk_sp<GrSurfaceProxy> proxy(
333             context->priv().proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
334                                                                                  vkInfo));
335     if (!proxy) {
336         return nullptr;
337     }
338 
339     return GrRenderTargetContext::Make(context, SkColorTypeToGrColorType(imageInfo.colorType()),
340                                        imageInfo.refColorSpace(), std::move(proxy),
341                                        kTopLeft_GrSurfaceOrigin, props);
342 }
343 
344 // In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress
345 // GrOpsTask to be picked up and added to by renderTargetContexts lower in the call
346 // stack. When this occurs with a closed GrOpsTask, a new one will be allocated
347 // when the renderTargetContext attempts to use it (via getOpsTask).
GrRenderTargetContext(GrRecordingContext * context,GrSurfaceProxyView readView,GrSurfaceProxyView outputView,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps,bool managedOpsTask)348 GrRenderTargetContext::GrRenderTargetContext(GrRecordingContext* context,
349                                              GrSurfaceProxyView readView,
350                                              GrSurfaceProxyView outputView,
351                                              GrColorType colorType,
352                                              sk_sp<SkColorSpace> colorSpace,
353                                              const SkSurfaceProps* surfaceProps,
354                                              bool managedOpsTask)
355         : GrSurfaceContext(context, std::move(readView), colorType, kPremul_SkAlphaType,
356                            std::move(colorSpace))
357         , fOutputView(std::move(outputView))
358         , fOpsTask(sk_ref_sp(this->asSurfaceProxy()->getLastOpsTask()))
359         , fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps))
360         , fManagedOpsTask(managedOpsTask) {
361     SkASSERT(this->asSurfaceProxy() == fOutputView.proxy());
362     SkASSERT(this->origin() == fOutputView.origin());
363 
364     fTextTarget.reset(new TextTarget(this));
365     SkDEBUGCODE(this->validate();)
366 }
367 
368 #ifdef SK_DEBUG
onValidate() const369 void GrRenderTargetContext::onValidate() const {
370     if (fOpsTask && !fOpsTask->isClosed()) {
371         SkASSERT(fOutputView.proxy()->getLastRenderTask() == fOpsTask.get());
372     }
373 }
374 #endif
375 
~GrRenderTargetContext()376 GrRenderTargetContext::~GrRenderTargetContext() {
377     ASSERT_SINGLE_OWNER
378 }
379 
chooseAAType(GrAA aa)380 inline GrAAType GrRenderTargetContext::chooseAAType(GrAA aa) {
381     if (GrAA::kNo == aa) {
382         // On some devices we cannot disable MSAA if it is enabled so we make the AA type reflect
383         // that.
384         if (this->numSamples() > 1 && !this->caps()->multisampleDisableSupport()) {
385             return GrAAType::kMSAA;
386         }
387         return GrAAType::kNone;
388     }
389     return (this->numSamples() > 1) ? GrAAType::kMSAA : GrAAType::kCoverage;
390 }
391 
mipMapped() const392 GrMipMapped GrRenderTargetContext::mipMapped() const {
393     if (const GrTextureProxy* proxy = this->asTextureProxy()) {
394         return proxy->mipMapped();
395     }
396     return GrMipMapped::kNo;
397 }
398 
getOpsTask()399 GrOpsTask* GrRenderTargetContext::getOpsTask() {
400     ASSERT_SINGLE_OWNER
401     SkDEBUGCODE(this->validate();)
402 
403     if (!fOpsTask || fOpsTask->isClosed()) {
404         sk_sp<GrOpsTask> newOpsTask =
405                 this->drawingManager()->newOpsTask(this->outputSurfaceView(), fManagedOpsTask);
406         if (fOpsTask && fNumStencilSamples > 0) {
407             // Store the stencil values in memory upon completion of fOpsTask.
408             fOpsTask->setMustPreserveStencil();
409             // Reload the stencil buffer content at the beginning of newOpsTask.
410             // FIXME: Could the topo sort insert a task between these two that modifies the stencil
411             // values?
412             newOpsTask->setInitialStencilContent(GrOpsTask::StencilContent::kPreserved);
413         }
414         fOpsTask = std::move(newOpsTask);
415     }
416 
417     return fOpsTask.get();
418 }
419 
drawGlyphRunList(const GrClip & clip,const SkMatrix & viewMatrix,const SkGlyphRunList & blob)420 void GrRenderTargetContext::drawGlyphRunList(
421         const GrClip& clip, const SkMatrix& viewMatrix,
422         const SkGlyphRunList& blob) {
423     ASSERT_SINGLE_OWNER
424     RETURN_IF_ABANDONED
425     SkDEBUGCODE(this->validate();)
426     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawGlyphRunList", fContext);
427 
428     // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
429     // secondary command buffers because it would require stopping and starting a render pass which
430     // we don't have access to.
431     if (this->wrapsVkSecondaryCB()) {
432         return;
433     }
434 
435     GrTextContext* atlasTextContext = this->drawingManager()->getTextContext();
436     atlasTextContext->drawGlyphRunList(fContext, fTextTarget.get(), clip, viewMatrix,
437                                        fSurfaceProps, blob);
438 }
439 
discard()440 void GrRenderTargetContext::discard() {
441     ASSERT_SINGLE_OWNER
442     RETURN_IF_ABANDONED
443     SkDEBUGCODE(this->validate();)
444     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "discard", fContext);
445 
446     AutoCheckFlush acf(this->drawingManager());
447 
448     this->getOpsTask()->discard();
449 }
450 
clear(const SkIRect * rect,const SkPMColor4f & color,CanClearFullscreen canClearFullscreen)451 void GrRenderTargetContext::clear(const SkIRect* rect,
452                                   const SkPMColor4f& color,
453                                   CanClearFullscreen canClearFullscreen) {
454     ASSERT_SINGLE_OWNER
455     RETURN_IF_ABANDONED
456     SkDEBUGCODE(this->validate();)
457     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "clear", fContext);
458 
459     AutoCheckFlush acf(this->drawingManager());
460     this->internalClear(rect ? GrFixedClip(*rect) : GrFixedClip::Disabled(), color,
461                         canClearFullscreen);
462 }
463 
clear(const GrFixedClip & clip,const SkPMColor4f & color,CanClearFullscreen canClearFullscreen)464 void GrRenderTargetContextPriv::clear(const GrFixedClip& clip,
465                                       const SkPMColor4f& color,
466                                       CanClearFullscreen canClearFullscreen) {
467     ASSERT_SINGLE_OWNER_PRIV
468     RETURN_IF_ABANDONED_PRIV
469     SkDEBUGCODE(fRenderTargetContext->validate();)
470     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clear",
471                                    fRenderTargetContext->fContext);
472 
473     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
474     fRenderTargetContext->internalClear(clip, color, canClearFullscreen);
475 }
476 
clear_to_grpaint(const SkPMColor4f & color,GrPaint * paint)477 static void clear_to_grpaint(const SkPMColor4f& color, GrPaint* paint) {
478     paint->setColor4f(color);
479     if (color.isOpaque()) {
480         // Can just rely on the src-over blend mode to do the right thing
481         paint->setPorterDuffXPFactory(SkBlendMode::kSrcOver);
482     } else {
483         // A clear overwrites the prior color, so even if it's transparent, it behaves as if it
484         // were src blended
485         paint->setPorterDuffXPFactory(SkBlendMode::kSrc);
486     }
487 }
488 
internalClear(const GrFixedClip & clip,const SkPMColor4f & color,CanClearFullscreen canClearFullscreen)489 void GrRenderTargetContext::internalClear(const GrFixedClip& clip,
490                                           const SkPMColor4f& color,
491                                           CanClearFullscreen canClearFullscreen) {
492     bool isFull = false;
493     if (!clip.hasWindowRectangles()) {
494         // TODO: wrt the shouldInitializeTextures path, it would be more performant to
495         // only clear the entire target if we knew it had not been cleared before. As
496         // is this could end up doing a lot of redundant clears.
497         isFull = !clip.scissorEnabled() ||
498                  (CanClearFullscreen::kYes == canClearFullscreen &&
499                   (this->caps()->preferFullscreenClears() || this->caps()->shouldInitializeTextures())) ||
500                  clip.scissorRect().contains(SkIRect::MakeWH(this->width(), this->height()));
501     }
502 
503     if (isFull) {
504         GrOpsTask* opsTask = this->getOpsTask();
505         if (opsTask->resetForFullscreenClear(this->canDiscardPreviousOpsOnFullClear()) &&
506             !this->caps()->performColorClearsAsDraws()) {
507             // The op list was emptied and native clears are allowed, so just use the load op
508             opsTask->setColorLoadOp(GrLoadOp::kClear, color);
509             return;
510         } else {
511             // Will use an op for the clear, reset the load op to discard since the op will
512             // blow away the color buffer contents
513             opsTask->setColorLoadOp(GrLoadOp::kDiscard);
514         }
515 
516         // Must add an op to the list (either because we couldn't use a load op, or because the
517         // clear load op isn't supported)
518         if (this->caps()->performColorClearsAsDraws()) {
519             SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
520             GrPaint paint;
521             clear_to_grpaint(color, &paint);
522             this->addDrawOp(GrFixedClip::Disabled(),
523                             GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
524                                                         rtRect));
525         } else {
526             this->addOp(GrClearOp::Make(
527                     fContext, SkIRect::MakeEmpty(), color, /* fullscreen */ true));
528         }
529     } else {
530         if (this->caps()->performPartialClearsAsDraws()) {
531             // performPartialClearsAsDraws() also returns true if any clear has to be a draw.
532             GrPaint paint;
533             clear_to_grpaint(color, &paint);
534 
535             this->addDrawOp(clip,
536                             GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
537                                                         SkRect::Make(clip.scissorRect())));
538         } else {
539             std::unique_ptr<GrOp> op(GrClearOp::Make(fContext, clip, color,
540                                                      this->asSurfaceProxy()));
541             // This version of the clear op factory can return null if the clip doesn't intersect
542             // with the surface proxy's boundary
543             if (!op) {
544                 return;
545             }
546             this->addOp(std::move(op));
547         }
548     }
549 }
550 
drawPaint(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix)551 void GrRenderTargetContext::drawPaint(const GrClip& clip,
552                                       GrPaint&& paint,
553                                       const SkMatrix& viewMatrix) {
554     // Start with the render target, since that is the maximum content we could possibly fill.
555     // drawFilledQuad() will automatically restrict it to clip bounds for us if possible.
556     SkRect r = this->asSurfaceProxy()->getBoundsRect();
557     if (!paint.numTotalFragmentProcessors()) {
558         // The paint is trivial so we won't need to use local coordinates, so skip calculating the
559         // inverse view matrix.
560         this->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), r, r);
561     } else {
562         // Use the inverse view matrix to arrive at appropriate local coordinates for the paint.
563         SkMatrix localMatrix;
564         if (!viewMatrix.invert(&localMatrix)) {
565             return;
566         }
567         this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), r,
568                                       localMatrix);
569     }
570 }
571 
572 enum class GrRenderTargetContext::QuadOptimization {
573     // The rect to draw doesn't intersect clip or render target, so no draw op should be added
574     kDiscarded,
575     // The rect to draw was converted to some other op and appended to the oplist, so no additional
576     // op is necessary. Currently this can convert it to a clear op or a rrect op. Only valid if
577     // a constColor is provided.
578     kSubmitted,
579     // The clip was folded into the device quad, with updated edge flags and local coords, and
580     // caller is responsible for adding an appropriate op.
581     kClipApplied,
582     // No change to clip, but quad updated to better fit clip/render target, and caller is
583     // responsible for adding an appropriate op.
584     kCropped
585 };
586 
make_vertex_finite(float * value)587 static bool make_vertex_finite(float* value) {
588     if (SkScalarIsNaN(*value)) {
589         return false;
590     }
591 
592     if (!SkScalarIsFinite(*value)) {
593         // +/- infinity at this point. Don't use exactly SK_ScalarMax so that we have some precision
594         // left when calculating crops.
595         static constexpr float kNearInfinity = SK_ScalarMax / 4.f;
596         *value = *value < 0.f ? -kNearInfinity : kNearInfinity;
597     }
598 
599     return true;
600 }
601 
attemptQuadOptimization(const GrClip & clip,const SkPMColor4f * constColor,const GrUserStencilSettings * stencilSettings,GrAA * aa,DrawQuad * quad)602 GrRenderTargetContext::QuadOptimization GrRenderTargetContext::attemptQuadOptimization(
603         const GrClip& clip, const SkPMColor4f* constColor,
604         const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad) {
605     // Optimization requirements:
606     // 1. kDiscard applies when clip bounds and quad bounds do not intersect
607     // 2a. kSubmitted applies when constColor and final geom is pixel aligned rect;
608     //       pixel aligned rect requires rect clip and (rect quad or quad covers clip) OR
609     // 2b. kSubmitted applies when constColor and rrect clip and quad covers clip
610     // 4. kClipApplied applies when rect clip and (rect quad or quad covers clip)
611     // 5. kCropped in all other scenarios (although a crop may be a no-op)
612 
613     // Save the old AA flags since CropToRect will modify 'quad' and if kCropped is returned, it's
614     // better to just keep the old flags instead of introducing mixed edge flags.
615     GrQuadAAFlags oldFlags = quad->fEdgeFlags;
616 
617     SkRect rtRect;
618     if (stencilSettings) {
619         // Must use size at which the rendertarget will ultimately be allocated so that stencil
620         // buffer updates on approximately sized render targets don't get corrupted.
621         rtRect = this->asSurfaceProxy()->backingStoreBoundsRect();
622     } else {
623         // Use the logical size of the render target, which allows for "fullscreen" clears even if
624         // the render target has an approximate backing fit
625         rtRect = SkRect::MakeWH(this->width(), this->height());
626     }
627 
628     SkRect drawBounds = quad->fDevice.bounds();
629     if (constColor) {
630         // If the device quad is not finite, coerce into a finite quad. This is acceptable since it
631         // will be cropped to the finite 'clip' or render target and there is no local space mapping
632         if (!quad->fDevice.isFinite()) {
633             for (int i = 0; i < 4; ++i) {
634                 if (!make_vertex_finite(quad->fDevice.xs() + i) ||
635                     !make_vertex_finite(quad->fDevice.ys() + i) ||
636                     !make_vertex_finite(quad->fDevice.ws() + i)) {
637                     // Discard if we see a nan
638                     return QuadOptimization::kDiscarded;
639                 }
640             }
641             SkASSERT(quad->fDevice.isFinite());
642         }
643     } else {
644         // CropToRect requires the quads to be finite. If they are not finite and we have local
645         // coordinates, the mapping from local space to device space is poorly defined so drop it
646         if (!quad->fDevice.isFinite()) {
647             return QuadOptimization::kDiscarded;
648         }
649     }
650 
651     // If the quad is entirely off screen, it doesn't matter what the clip does
652     if (!rtRect.intersects(drawBounds)) {
653         return QuadOptimization::kDiscarded;
654     }
655 
656     // Check if clip can be represented as a rounded rect (initialize as if clip fully contained
657     // the render target).
658     SkRRect clipRRect = SkRRect::MakeRect(rtRect);
659     // We initialize clipAA to *aa when there are stencil settings so that we don't artificially
660     // encounter mixed-aa edges (not allowed for stencil), but we want to start as non-AA for
661     // regular draws so that if we fully cover the render target, that can stop being anti-aliased.
662     GrAA clipAA = stencilSettings ? *aa : GrAA::kNo;
663     bool axisAlignedClip = true;
664     if (!clip.quickContains(rtRect)) {
665         if (!clip.isRRect(rtRect, &clipRRect, &clipAA)) {
666             axisAlignedClip = false;
667         }
668     }
669 
670     // If the clip rrect is valid (i.e. axis-aligned), we can potentially combine it with the
671     // draw geometry so that no clip is needed when drawing.
672     if (axisAlignedClip && (!stencilSettings || clipAA == *aa)) {
673         // Tighten clip bounds (if clipRRect.isRect() is true, clipBounds now holds the intersection
674         // of the render target and the clip rect)
675         SkRect clipBounds = rtRect;
676         if (!clipBounds.intersect(clipRRect.rect()) || !clipBounds.intersects(drawBounds)) {
677             return QuadOptimization::kDiscarded;
678         }
679 
680         if (clipRRect.isRect()) {
681             // No rounded corners, so the kClear and kExplicitClip optimizations are possible
682             if (GrQuadUtils::CropToRect(clipBounds, clipAA, quad, /*compute local*/ !constColor)) {
683                 if (!stencilSettings && constColor &&
684                     quad->fDevice.quadType() == GrQuad::Type::kAxisAligned) {
685                     // Clear optimization is possible
686                     drawBounds = quad->fDevice.bounds();
687                     if (drawBounds.contains(rtRect)) {
688                         // Fullscreen clear
689                         this->clear(nullptr, *constColor, CanClearFullscreen::kYes);
690                         return QuadOptimization::kSubmitted;
691                     } else if (GrClip::IsPixelAligned(drawBounds) &&
692                                drawBounds.width() > 256 && drawBounds.height() > 256) {
693                         // Scissor + clear (round shouldn't do anything since we are pixel aligned)
694                         SkIRect scissorRect;
695                         drawBounds.round(&scissorRect);
696                         this->clear(&scissorRect, *constColor, CanClearFullscreen::kNo);
697                         return QuadOptimization::kSubmitted;
698                     }
699                 }
700 
701                 // Update overall AA setting.
702                 if (*aa == GrAA::kNo && clipAA == GrAA::kYes &&
703                     quad->fEdgeFlags != GrQuadAAFlags::kNone) {
704                     // The clip was anti-aliased and now the draw needs to be upgraded to AA to
705                     // properly reflect the smooth edge of the clip.
706                     *aa = GrAA::kYes;
707                 }
708                 // We intentionally do not downgrade AA here because we don't know if we need to
709                 // preserve MSAA (see GrQuadAAFlags docs). But later in the pipeline, the ops can
710                 // use GrResolveAATypeForQuad() to turn off coverage AA when all flags are off.
711 
712                 // deviceQuad is exactly the intersection of original quad and clip, so it can be
713                 // drawn with no clip (submitted by caller)
714                 return QuadOptimization::kClipApplied;
715             } else {
716                 // The quads have been updated to better fit the clip bounds, but can't get rid of
717                 // the clip entirely
718                 quad->fEdgeFlags = oldFlags;
719                 return QuadOptimization::kCropped;
720             }
721         } else if (!stencilSettings && constColor) {
722             // Rounded corners and constant filled color (limit ourselves to solid colors because
723             // there is no way to use custom local coordinates with drawRRect).
724             if (GrQuadUtils::CropToRect(clipBounds, clipAA, quad, /* compute local */ false) &&
725                 quad->fDevice.quadType() == GrQuad::Type::kAxisAligned &&
726                 quad->fDevice.bounds().contains(clipBounds)) {
727                 // Since the cropped quad became a rectangle which covered the bounds of the rrect,
728                 // we can draw the rrect directly and ignore the edge flags
729                 GrPaint paint;
730                 clear_to_grpaint(*constColor, &paint);
731                 this->drawRRect(GrFixedClip::Disabled(), std::move(paint), clipAA, SkMatrix::I(),
732                                 clipRRect, GrStyle::SimpleFill());
733                 return QuadOptimization::kSubmitted;
734             } else {
735                 // The quad has been updated to better fit clip bounds, but can't remove the clip
736                 quad->fEdgeFlags = oldFlags;
737                 return QuadOptimization::kCropped;
738             }
739         }
740     }
741 
742     // Crop the quad to the conservative bounds of the clip.
743     SkIRect clipDevBounds;
744     clip.getConservativeBounds(rtRect.width(), rtRect.height(), &clipDevBounds);
745     SkRect clipBounds = SkRect::Make(clipDevBounds);
746 
747     // One final check for discarding, since we may have gone here directly due to a complex clip
748     if (!clipBounds.intersects(drawBounds)) {
749         return QuadOptimization::kDiscarded;
750     }
751 
752     // Even if this were to return true, the crop rect does not exactly match the clip, so can not
753     // report explicit-clip. Since these edges aren't visible, don't update the final edge flags.
754     GrQuadUtils::CropToRect(clipBounds, clipAA, quad, /* compute local */ !constColor);
755     quad->fEdgeFlags = oldFlags;
756 
757     return QuadOptimization::kCropped;
758 }
759 
drawFilledQuad(const GrClip & clip,GrPaint && paint,GrAA aa,DrawQuad * quad,const GrUserStencilSettings * ss)760 void GrRenderTargetContext::drawFilledQuad(const GrClip& clip,
761                                            GrPaint&& paint,
762                                            GrAA aa,
763                                            DrawQuad* quad,
764                                            const GrUserStencilSettings* ss) {
765     ASSERT_SINGLE_OWNER
766     RETURN_IF_ABANDONED
767     SkDEBUGCODE(this->validate();)
768     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFilledQuad", fContext);
769 
770     AutoCheckFlush acf(this->drawingManager());
771 
772     SkPMColor4f* constColor = nullptr;
773     SkPMColor4f paintColor;
774     if (!ss && !paint.numCoverageFragmentProcessors() &&
775         paint.isConstantBlendedColor(&paintColor)) {
776         // Only consider clears/rrects when it's easy to guarantee 100% fill with single color
777         constColor = &paintColor;
778     }
779 
780     QuadOptimization opt = this->attemptQuadOptimization(clip, constColor, ss, &aa, quad);
781     if (opt >= QuadOptimization::kClipApplied) {
782         // These optimizations require caller to add an op themselves
783         const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
784                                                                         : clip;
785         GrAAType aaType = ss ? (aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone)
786                              : this->chooseAAType(aa);
787         this->addDrawOp(finalClip, GrFillRectOp::Make(fContext, std::move(paint), aaType,
788                                                       quad, ss));
789     }
790     // All other optimization levels were completely handled inside attempt(), so no extra op needed
791 }
792 
drawTexturedQuad(const GrClip & clip,GrSurfaceProxyView proxyView,SkAlphaType srcAlphaType,sk_sp<GrColorSpaceXform> textureXform,GrSamplerState::Filter filter,const SkPMColor4f & color,SkBlendMode blendMode,GrAA aa,DrawQuad * quad,const SkRect * domain)793 void GrRenderTargetContext::drawTexturedQuad(const GrClip& clip,
794                                              GrSurfaceProxyView proxyView,
795                                              SkAlphaType srcAlphaType,
796                                              sk_sp<GrColorSpaceXform> textureXform,
797                                              GrSamplerState::Filter filter,
798                                              const SkPMColor4f& color,
799                                              SkBlendMode blendMode,
800                                              GrAA aa,
801                                              DrawQuad* quad,
802                                              const SkRect* domain) {
803     ASSERT_SINGLE_OWNER
804     RETURN_IF_ABANDONED
805     SkDEBUGCODE(this->validate();)
806     SkASSERT(proxyView.asTextureProxy());
807     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTexturedQuad", fContext);
808 
809     AutoCheckFlush acf(this->drawingManager());
810 
811     // Functionally this is very similar to drawFilledQuad except that there's no constColor to
812     // enable the kSubmitted optimizations, no stencil settings support, and its a GrTextureOp.
813     QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr, nullptr, &aa, quad);
814 
815     SkASSERT(opt != QuadOptimization::kSubmitted);
816     if (opt != QuadOptimization::kDiscarded) {
817         // And the texture op if not discarded
818         const GrClip& finalClip = opt == QuadOptimization::kClipApplied ? GrFixedClip::Disabled()
819                                                                         : clip;
820         GrAAType aaType = this->chooseAAType(aa);
821         auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
822         auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
823                                                           : GrTextureOp::Saturate::kNo;
824         // Use the provided domain, although hypothetically we could detect that the cropped local
825         // quad is sufficiently inside the domain and the constraint could be dropped.
826         this->addDrawOp(finalClip,
827                         GrTextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
828                                           std::move(textureXform), filter, color, saturate,
829                                           blendMode, aaType, quad, domain));
830     }
831 }
832 
drawRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & rect,const GrStyle * style)833 void GrRenderTargetContext::drawRect(const GrClip& clip,
834                                      GrPaint&& paint,
835                                      GrAA aa,
836                                      const SkMatrix& viewMatrix,
837                                      const SkRect& rect,
838                                      const GrStyle* style) {
839     if (!style) {
840         style = &GrStyle::SimpleFill();
841     }
842     ASSERT_SINGLE_OWNER
843     RETURN_IF_ABANDONED
844     SkDEBUGCODE(this->validate();)
845     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRect", fContext);
846 
847     // Path effects should've been devolved to a path in SkGpuDevice
848     SkASSERT(!style->pathEffect());
849 
850     AutoCheckFlush acf(this->drawingManager());
851 
852     const SkStrokeRec& stroke = style->strokeRec();
853     if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
854         // Fills the rect, using rect as its own local coordinates
855         this->fillRectToRect(clip, std::move(paint), aa, viewMatrix, rect, rect);
856         return;
857     } else if (stroke.getStyle() == SkStrokeRec::kStroke_Style ||
858                stroke.getStyle() == SkStrokeRec::kHairline_Style) {
859         if ((!rect.width() || !rect.height()) &&
860             SkStrokeRec::kHairline_Style != stroke.getStyle()) {
861             SkScalar r = stroke.getWidth() / 2;
862             // TODO: Move these stroke->fill fallbacks to GrShape?
863             switch (stroke.getJoin()) {
864                 case SkPaint::kMiter_Join:
865                     this->drawRect(
866                             clip, std::move(paint), aa, viewMatrix,
867                             {rect.fLeft - r, rect.fTop - r, rect.fRight + r, rect.fBottom + r},
868                             &GrStyle::SimpleFill());
869                     return;
870                 case SkPaint::kRound_Join:
871                     // Raster draws nothing when both dimensions are empty.
872                     if (rect.width() || rect.height()){
873                         SkRRect rrect = SkRRect::MakeRectXY(rect.makeOutset(r, r), r, r);
874                         this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect,
875                                         GrStyle::SimpleFill());
876                         return;
877                     }
878                 case SkPaint::kBevel_Join:
879                     if (!rect.width()) {
880                         this->drawRect(clip, std::move(paint), aa, viewMatrix,
881                                        {rect.fLeft - r, rect.fTop, rect.fRight + r, rect.fBottom},
882                                        &GrStyle::SimpleFill());
883                     } else {
884                         this->drawRect(clip, std::move(paint), aa, viewMatrix,
885                                        {rect.fLeft, rect.fTop - r, rect.fRight, rect.fBottom + r},
886                                        &GrStyle::SimpleFill());
887                     }
888                     return;
889                 }
890         }
891 
892         std::unique_ptr<GrDrawOp> op;
893 
894         GrAAType aaType = this->chooseAAType(aa);
895         op = GrStrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix, rect, stroke);
896         // op may be null if the stroke is not supported or if using coverage aa and the view matrix
897         // does not preserve rectangles.
898         if (op) {
899             this->addDrawOp(clip, std::move(op));
900             return;
901         }
902     }
903     assert_alive(paint);
904     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(rect, *style));
905 }
906 
drawQuadSet(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const QuadSetEntry quads[],int cnt)907 void GrRenderTargetContext::drawQuadSet(const GrClip& clip, GrPaint&& paint, GrAA aa,
908                                         const SkMatrix& viewMatrix, const QuadSetEntry quads[],
909                                         int cnt) {
910     GrAAType aaType = this->chooseAAType(aa);
911 
912     GrFillRectOp::AddFillRectOps(this, clip, fContext, std::move(paint), aaType, viewMatrix,
913                                  quads, cnt);
914 }
915 
maxWindowRectangles() const916 int GrRenderTargetContextPriv::maxWindowRectangles() const {
917     return fRenderTargetContext->asRenderTargetProxy()->maxWindowRectangles(
918             *fRenderTargetContext->caps());
919 }
920 
canDiscardPreviousOpsOnFullClear() const921 GrOpsTask::CanDiscardPreviousOps GrRenderTargetContext::canDiscardPreviousOpsOnFullClear(
922         ) const {
923 #if GR_TEST_UTILS
924     if (fPreserveOpsOnFullClear_TestingOnly) {
925         return GrOpsTask::CanDiscardPreviousOps::kNo;
926     }
927 #endif
928     // Regardless of how the clear is implemented (native clear or a fullscreen quad), all prior ops
929     // would normally be overwritten. The one exception is if the render target context is marked as
930     // needing a stencil buffer then there may be a prior op that writes to the stencil buffer.
931     // Although the clear will ignore the stencil buffer, following draw ops may not so we can't get
932     // rid of all the preceding ops. Beware! If we ever add any ops that have a side effect beyond
933     // modifying the stencil buffer we will need a more elaborate tracking system (skbug.com/7002).
934     return GrOpsTask::CanDiscardPreviousOps(!fNumStencilSamples);
935 }
936 
setNeedsStencil(bool useMixedSamplesIfNotMSAA)937 void GrRenderTargetContext::setNeedsStencil(bool useMixedSamplesIfNotMSAA) {
938     // Don't clear stencil until after we've changed fNumStencilSamples. This ensures we don't loop
939     // forever in the event that there are driver bugs and we need to clear as a draw.
940     bool hasInitializedStencil = fNumStencilSamples > 0;
941 
942     int numRequiredSamples = this->numSamples();
943     if (useMixedSamplesIfNotMSAA && 1 == numRequiredSamples) {
944         SkASSERT(this->asRenderTargetProxy()->canUseMixedSamples(*this->caps()));
945         numRequiredSamples = this->caps()->internalMultisampleCount(
946                 this->asSurfaceProxy()->backendFormat());
947     }
948     SkASSERT(numRequiredSamples > 0);
949 
950     if (numRequiredSamples > fNumStencilSamples) {
951         fNumStencilSamples = numRequiredSamples;
952         this->asRenderTargetProxy()->setNeedsStencil(fNumStencilSamples);
953     }
954 
955     if (!hasInitializedStencil) {
956         if (this->caps()->performStencilClearsAsDraws()) {
957             // There is a driver bug with clearing stencil. We must use an op to manually clear the
958             // stencil buffer before the op that required 'setNeedsStencil'.
959             this->internalStencilClear(GrFixedClip::Disabled(), /* inside mask */ false);
960         } else {
961             this->getOpsTask()->setInitialStencilContent(
962                     GrOpsTask::StencilContent::kUserBitsCleared);
963         }
964     }
965 }
966 
clearStencilClip(const GrFixedClip & clip,bool insideStencilMask)967 void GrRenderTargetContextPriv::clearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
968     ASSERT_SINGLE_OWNER_PRIV
969     RETURN_IF_ABANDONED_PRIV
970     SkDEBUGCODE(fRenderTargetContext->validate();)
971     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "clearStencilClip",
972                                    fRenderTargetContext->fContext);
973 
974     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
975 
976     fRenderTargetContext->internalStencilClear(clip, insideStencilMask);
977 }
978 
internalStencilClear(const GrFixedClip & clip,bool insideStencilMask)979 void GrRenderTargetContext::internalStencilClear(const GrFixedClip& clip, bool insideStencilMask) {
980     this->setNeedsStencil(/* useMixedSamplesIfNotMSAA = */ false);
981 
982     if (this->caps()->performStencilClearsAsDraws()) {
983         const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
984         SkRect rtRect = SkRect::MakeWH(this->width(), this->height());
985 
986         // Configure the paint to have no impact on the color buffer
987         GrPaint paint;
988         paint.setXPFactory(GrDisableColorXPFactory::Get());
989         this->addDrawOp(clip, GrFillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
990                                                           rtRect, ss));
991     } else {
992         std::unique_ptr<GrOp> op(GrClearStencilClipOp::Make(fContext, clip, insideStencilMask,
993                                                             this->asRenderTargetProxy()));
994         if (!op) {
995             return;
996         }
997         this->addOp(std::move(op));
998     }
999 }
1000 
stencilPath(const GrHardClip & clip,GrAA doStencilMSAA,const SkMatrix & viewMatrix,sk_sp<const GrPath> path)1001 void GrRenderTargetContextPriv::stencilPath(const GrHardClip& clip,
1002                                             GrAA doStencilMSAA,
1003                                             const SkMatrix& viewMatrix,
1004                                             sk_sp<const GrPath> path) {
1005     ASSERT_SINGLE_OWNER_PRIV
1006     RETURN_IF_ABANDONED_PRIV
1007     SkDEBUGCODE(fRenderTargetContext->validate();)
1008     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "stencilPath",
1009                                    fRenderTargetContext->fContext);
1010 
1011     // TODO: extract portions of checkDraw that are relevant to path stenciling.
1012     SkASSERT(path);
1013     SkASSERT(fRenderTargetContext->caps()->shaderCaps()->pathRenderingSupport());
1014 
1015     // FIXME: Use path bounds instead of this WAR once
1016     // https://bugs.chromium.org/p/skia/issues/detail?id=5640 is resolved.
1017     SkRect bounds = SkRect::MakeIWH(fRenderTargetContext->width(), fRenderTargetContext->height());
1018 
1019     // Setup clip
1020     GrAppliedHardClip appliedClip;
1021     if (!clip.apply(fRenderTargetContext->width(), fRenderTargetContext->height(), &appliedClip,
1022                     &bounds)) {
1023         return;
1024     }
1025 
1026     std::unique_ptr<GrOp> op = GrStencilPathOp::Make(fRenderTargetContext->fContext,
1027                                                      viewMatrix,
1028                                                      GrAA::kYes == doStencilMSAA,
1029                                                      appliedClip.hasStencilClip(),
1030                                                      appliedClip.scissorState(),
1031                                                      std::move(path));
1032     if (!op) {
1033         return;
1034     }
1035     op->setClippedBounds(bounds);
1036 
1037     fRenderTargetContext->setNeedsStencil(GrAA::kYes == doStencilMSAA);
1038     fRenderTargetContext->addOp(std::move(op));
1039 }
1040 
drawTextureSet(const GrClip & clip,TextureSetEntry set[],int cnt,int proxyRunCnt,GrSamplerState::Filter filter,SkBlendMode mode,GrAA aa,SkCanvas::SrcRectConstraint constraint,const SkMatrix & viewMatrix,sk_sp<GrColorSpaceXform> texXform)1041 void GrRenderTargetContext::drawTextureSet(const GrClip& clip, TextureSetEntry set[],
1042                                            int cnt, int proxyRunCnt,
1043                                            GrSamplerState::Filter filter, SkBlendMode mode,
1044                                            GrAA aa, SkCanvas::SrcRectConstraint constraint,
1045                                            const SkMatrix& viewMatrix,
1046                                            sk_sp<GrColorSpaceXform> texXform) {
1047     ASSERT_SINGLE_OWNER
1048     RETURN_IF_ABANDONED
1049     SkDEBUGCODE(this->validate();)
1050     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawTextureSet", fContext);
1051 
1052     // Create the minimum number of GrTextureOps needed to draw this set. Individual
1053     // GrTextureOps can rebind the texture between draws thus avoiding GrPaint (re)creation.
1054     AutoCheckFlush acf(this->drawingManager());
1055     GrAAType aaType = this->chooseAAType(aa);
1056     auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
1057     auto saturate = clampType == GrClampType::kManual ? GrTextureOp::Saturate::kYes
1058                                                       : GrTextureOp::Saturate::kNo;
1059     GrTextureOp::AddTextureSetOps(this, clip, fContext, set, cnt, proxyRunCnt, filter, saturate,
1060                                   mode, aaType, constraint, viewMatrix, std::move(texXform));
1061 }
1062 
drawVertices(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,sk_sp<SkVertices> vertices,const SkVertices::Bone bones[],int boneCount,GrPrimitiveType * overridePrimType)1063 void GrRenderTargetContext::drawVertices(const GrClip& clip,
1064                                          GrPaint&& paint,
1065                                          const SkMatrix& viewMatrix,
1066                                          sk_sp<SkVertices> vertices,
1067                                          const SkVertices::Bone bones[],
1068                                          int boneCount,
1069                                          GrPrimitiveType* overridePrimType) {
1070     ASSERT_SINGLE_OWNER
1071     RETURN_IF_ABANDONED
1072     SkDEBUGCODE(this->validate();)
1073     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawVertices", fContext);
1074 
1075     AutoCheckFlush acf(this->drawingManager());
1076 
1077     SkASSERT(vertices);
1078     GrAAType aaType = this->chooseAAType(GrAA::kNo);
1079     std::unique_ptr<GrDrawOp> op = GrDrawVerticesOp::Make(
1080             fContext, std::move(paint), std::move(vertices), bones, boneCount, viewMatrix, aaType,
1081             this->colorInfo().refColorSpaceXformFromSRGB(), overridePrimType);
1082     this->addDrawOp(clip, std::move(op));
1083 }
1084 
1085 ///////////////////////////////////////////////////////////////////////////////
1086 
drawAtlas(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,int spriteCount,const SkRSXform xform[],const SkRect texRect[],const SkColor colors[])1087 void GrRenderTargetContext::drawAtlas(const GrClip& clip,
1088                                       GrPaint&& paint,
1089                                       const SkMatrix& viewMatrix,
1090                                       int spriteCount,
1091                                       const SkRSXform xform[],
1092                                       const SkRect texRect[],
1093                                       const SkColor colors[]) {
1094     ASSERT_SINGLE_OWNER
1095     RETURN_IF_ABANDONED
1096     SkDEBUGCODE(this->validate();)
1097     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawAtlas", fContext);
1098 
1099     AutoCheckFlush acf(this->drawingManager());
1100 
1101     GrAAType aaType = this->chooseAAType(GrAA::kNo);
1102     std::unique_ptr<GrDrawOp> op = GrDrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
1103                                                        aaType, spriteCount, xform, texRect, colors);
1104     this->addDrawOp(clip, std::move(op));
1105 }
1106 
1107 ///////////////////////////////////////////////////////////////////////////////
1108 
drawRRect(const GrClip & origClip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & rrect,const GrStyle & style)1109 void GrRenderTargetContext::drawRRect(const GrClip& origClip,
1110                                       GrPaint&& paint,
1111                                       GrAA aa,
1112                                       const SkMatrix& viewMatrix,
1113                                       const SkRRect& rrect,
1114                                       const GrStyle& style) {
1115     ASSERT_SINGLE_OWNER
1116     RETURN_IF_ABANDONED
1117     SkDEBUGCODE(this->validate();)
1118     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRRect", fContext);
1119 
1120     const SkStrokeRec& stroke = style.strokeRec();
1121     if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
1122        return;
1123     }
1124 
1125     GrNoClip noclip;
1126     const GrClip* clip = &origClip;
1127 #ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1128     // The Android framework frequently clips rrects to themselves where the clip is non-aa and the
1129     // draw is aa. Since our lower level clip code works from op bounds, which are SkRects, it
1130     // doesn't detect that the clip can be ignored (modulo antialiasing). The following test
1131     // attempts to mitigate the stencil clip cost but will only help when the entire clip stack
1132     // can be ignored. We'd prefer to fix this in the framework by removing the clips calls. This
1133     // only works for filled rrects since the stroke width outsets beyond the rrect itself.
1134     SkRRect devRRect;
1135     if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.transform(viewMatrix, &devRRect) &&
1136         clip->quickContains(devRRect)) {
1137         clip = &noclip;
1138     }
1139 #endif
1140     SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1141 
1142     AutoCheckFlush acf(this->drawingManager());
1143 
1144     GrAAType aaType = this->chooseAAType(aa);
1145 
1146     std::unique_ptr<GrDrawOp> op;
1147     if (GrAAType::kCoverage == aaType && rrect.isSimple() &&
1148         rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY &&
1149         viewMatrix.rectStaysRect() && viewMatrix.isSimilarity()) {
1150         // In coverage mode, we draw axis-aligned circular roundrects with the GrOvalOpFactory
1151         // to avoid perf regressions on some platforms.
1152         assert_alive(paint);
1153         op = GrOvalOpFactory::MakeCircularRRectOp(
1154                 fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
1155     }
1156     if (!op && style.isSimpleFill()) {
1157         assert_alive(paint);
1158         op = GrFillRRectOp::Make(
1159                 fContext, aaType, viewMatrix, rrect, *this->caps(), std::move(paint));
1160     }
1161     if (!op && GrAAType::kCoverage == aaType) {
1162         assert_alive(paint);
1163         op = GrOvalOpFactory::MakeRRectOp(
1164                 fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
1165     }
1166     if (op) {
1167         this->addDrawOp(*clip, std::move(op));
1168         return;
1169     }
1170 
1171     assert_alive(paint);
1172     this->drawShapeUsingPathRenderer(*clip, std::move(paint), aa, viewMatrix,
1173                                      GrShape(rrect, style));
1174 }
1175 
1176 ///////////////////////////////////////////////////////////////////////////////
1177 
map(const SkMatrix & m,const SkPoint3 & pt)1178 static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
1179     SkPoint3 result;
1180     m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
1181     result.fZ = pt.fZ;
1182     return result;
1183 }
1184 
drawFastShadow(const GrClip & clip,const SkMatrix & viewMatrix,const SkPath & path,const SkDrawShadowRec & rec)1185 bool GrRenderTargetContext::drawFastShadow(const GrClip& clip,
1186                                            const SkMatrix& viewMatrix,
1187                                            const SkPath& path,
1188                                            const SkDrawShadowRec& rec) {
1189     ASSERT_SINGLE_OWNER
1190     if (fContext->priv().abandoned()) {
1191         return true;
1192     }
1193     SkDEBUGCODE(this->validate();)
1194     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawFastShadow", fContext);
1195 
1196     // check z plane
1197     bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
1198                                !SkScalarNearlyZero(rec.fZPlaneParams.fY));
1199     bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1200     if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
1201         return false;
1202     }
1203 
1204     SkRRect rrect;
1205     SkRect rect;
1206     // we can only handle rects, circles, and rrects with circular corners
1207     bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
1208         rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
1209     if (!isRRect &&
1210         path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
1211         rect.width() > SK_ScalarNearlyZero) {
1212         rrect.setOval(rect);
1213         isRRect = true;
1214     }
1215     if (!isRRect && path.isRect(&rect)) {
1216         rrect.setRect(rect);
1217         isRRect = true;
1218     }
1219 
1220     if (!isRRect) {
1221         return false;
1222     }
1223 
1224     if (rrect.isEmpty()) {
1225         return true;
1226     }
1227 
1228     AutoCheckFlush acf(this->drawingManager());
1229 
1230     // transform light
1231     SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
1232 
1233     // 1/scale
1234     SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1235         SkScalarInvert(SkScalarAbs(viewMatrix[SkMatrix::kMScaleX])) :
1236         sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1237                        viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1238 
1239     SkScalar occluderHeight = rec.fZPlaneParams.fZ;
1240     bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1241 
1242     if (SkColorGetA(rec.fAmbientColor) > 0) {
1243         SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1244         const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1245         const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
1246 
1247         // Outset the shadow rrect to the border of the penumbra
1248         SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1249         SkRRect ambientRRect;
1250         SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1251         // If the rrect was an oval then its outset will also be one.
1252         // We set it explicitly to avoid errors.
1253         if (rrect.isOval()) {
1254             ambientRRect = SkRRect::MakeOval(outsetRect);
1255         } else {
1256             SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
1257             ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1258         }
1259 
1260         GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
1261         if (transparent) {
1262             // set a large inset to force a fill
1263             devSpaceInsetWidth = ambientRRect.width();
1264         }
1265 
1266         std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1267                                                              ambientColor,
1268                                                              viewMatrix,
1269                                                              ambientRRect,
1270                                                              devSpaceAmbientBlur,
1271                                                              devSpaceInsetWidth);
1272         if (op) {
1273             this->addDrawOp(clip, std::move(op));
1274         }
1275     }
1276 
1277     if (SkColorGetA(rec.fSpotColor) > 0) {
1278         SkScalar devSpaceSpotBlur;
1279         SkScalar spotScale;
1280         SkVector spotOffset;
1281         SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1282                                            devLightPos.fZ, rec.fLightRadius,
1283                                            &devSpaceSpotBlur, &spotScale, &spotOffset);
1284         // handle scale of radius due to CTM
1285         const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1286 
1287         // Adjust translate for the effect of the scale.
1288         spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1289         spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1290         // This offset is in dev space, need to transform it into source space.
1291         SkMatrix ctmInverse;
1292         if (viewMatrix.invert(&ctmInverse)) {
1293             ctmInverse.mapPoints(&spotOffset, 1);
1294         } else {
1295             // Since the matrix is a similarity, this should never happen, but just in case...
1296             SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1297             SkASSERT(false);
1298         }
1299 
1300         // Compute the transformed shadow rrect
1301         SkRRect spotShadowRRect;
1302         SkMatrix shadowTransform;
1303         shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1304         rrect.transform(shadowTransform, &spotShadowRRect);
1305         SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
1306 
1307         // Compute the insetWidth
1308         SkScalar blurOutset = srcSpaceSpotBlur;
1309         SkScalar insetWidth = blurOutset;
1310         if (transparent) {
1311             // If transparent, just do a fill
1312             insetWidth += spotShadowRRect.width();
1313         } else {
1314             // For shadows, instead of using a stroke we specify an inset from the penumbra
1315             // border. We want to extend this inset area so that it meets up with the caster
1316             // geometry. The inset geometry will by default already be inset by the blur width.
1317             //
1318             // We compare the min and max corners inset by the radius between the original
1319             // rrect and the shadow rrect. The distance between the two plus the difference
1320             // between the scaled radius and the original radius gives the distance from the
1321             // transformed shadow shape to the original shape in that corner. The max
1322             // of these gives the maximum distance we need to cover.
1323             //
1324             // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1325             // that to get the full insetWidth.
1326             SkScalar maxOffset;
1327             if (rrect.isRect()) {
1328                 // Manhattan distance works better for rects
1329                 maxOffset = std::max(std::max(SkTAbs(spotShadowRRect.rect().fLeft -
1330                                                  rrect.rect().fLeft),
1331                                           SkTAbs(spotShadowRRect.rect().fTop -
1332                                                  rrect.rect().fTop)),
1333                                    std::max(SkTAbs(spotShadowRRect.rect().fRight -
1334                                                  rrect.rect().fRight),
1335                                           SkTAbs(spotShadowRRect.rect().fBottom -
1336                                                  rrect.rect().fBottom)));
1337             } else {
1338                 SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
1339                 SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1340                                                         rrect.rect().fLeft + dr,
1341                                                         spotShadowRRect.rect().fTop -
1342                                                         rrect.rect().fTop + dr);
1343                 SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1344                                                          rrect.rect().fRight - dr,
1345                                                          spotShadowRRect.rect().fBottom -
1346                                                          rrect.rect().fBottom - dr);
1347                 maxOffset = SkScalarSqrt(std::max(SkPointPriv::LengthSqd(upperLeftOffset),
1348                                                 SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
1349             }
1350             insetWidth += std::max(blurOutset, maxOffset);
1351         }
1352 
1353         // Outset the shadow rrect to the border of the penumbra
1354         SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1355         if (spotShadowRRect.isOval()) {
1356             spotShadowRRect = SkRRect::MakeOval(outsetRect);
1357         } else {
1358             SkScalar outsetRad = spotRadius + blurOutset;
1359             spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1360         }
1361 
1362         GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
1363 
1364         std::unique_ptr<GrDrawOp> op = GrShadowRRectOp::Make(fContext,
1365                                                              spotColor,
1366                                                              viewMatrix,
1367                                                              spotShadowRRect,
1368                                                              2.0f * devSpaceSpotBlur,
1369                                                              insetWidth);
1370         if (op) {
1371             this->addDrawOp(clip, std::move(op));
1372         }
1373     }
1374 
1375     return true;
1376 }
1377 
1378 ///////////////////////////////////////////////////////////////////////////////
1379 
drawFilledDRRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & origOuter,const SkRRect & origInner)1380 bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
1381                                              GrPaint&& paint,
1382                                              GrAA aa,
1383                                              const SkMatrix& viewMatrix,
1384                                              const SkRRect& origOuter,
1385                                              const SkRRect& origInner) {
1386     SkASSERT(!origInner.isEmpty());
1387     SkASSERT(!origOuter.isEmpty());
1388 
1389     SkTCopyOnFirstWrite<SkRRect> inner(origInner), outer(origOuter);
1390 
1391     GrAAType aaType = this->chooseAAType(aa);
1392 
1393     if (GrAAType::kMSAA == aaType) {
1394         return false;
1395     }
1396 
1397     if (GrAAType::kCoverage == aaType && SkRRectPriv::IsCircle(*inner)
1398                                       && SkRRectPriv::IsCircle(*outer)) {
1399         auto outerR = outer->width() / 2.f;
1400         auto innerR = inner->width() / 2.f;
1401         auto cx = outer->getBounds().fLeft + outerR;
1402         auto cy = outer->getBounds().fTop + outerR;
1403         if (SkScalarNearlyEqual(cx, inner->getBounds().fLeft + innerR) &&
1404             SkScalarNearlyEqual(cy, inner->getBounds().fTop + innerR)) {
1405             auto avgR = (innerR + outerR) / 2.f;
1406             auto circleBounds = SkRect::MakeLTRB(cx - avgR, cy - avgR, cx + avgR, cy + avgR);
1407             SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
1408             stroke.setStrokeStyle(outerR - innerR);
1409             auto op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix,
1410                                                   circleBounds, GrStyle(stroke, nullptr),
1411                                                   this->caps()->shaderCaps());
1412             if (op) {
1413                 this->addDrawOp(clip, std::move(op));
1414                 return true;
1415             }
1416             assert_alive(paint);
1417         }
1418     }
1419 
1420     GrClipEdgeType innerEdgeType, outerEdgeType;
1421     if (GrAAType::kCoverage == aaType) {
1422         innerEdgeType = GrClipEdgeType::kInverseFillAA;
1423         outerEdgeType = GrClipEdgeType::kFillAA;
1424     } else {
1425         innerEdgeType = GrClipEdgeType::kInverseFillBW;
1426         outerEdgeType = GrClipEdgeType::kFillBW;
1427     }
1428 
1429     SkMatrix inverseVM;
1430     if (!viewMatrix.isIdentity()) {
1431         if (!origInner.transform(viewMatrix, inner.writable())) {
1432             return false;
1433         }
1434         if (!origOuter.transform(viewMatrix, outer.writable())) {
1435             return false;
1436         }
1437         if (!viewMatrix.invert(&inverseVM)) {
1438             return false;
1439         }
1440     } else {
1441         inverseVM.reset();
1442     }
1443 
1444     const auto& caps = *this->caps()->shaderCaps();
1445     // TODO these need to be a geometry processors
1446     auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
1447     if (!innerEffect) {
1448         return false;
1449     }
1450 
1451     auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
1452     if (!outerEffect) {
1453         return false;
1454     }
1455 
1456     paint.addCoverageFragmentProcessor(std::move(innerEffect));
1457     paint.addCoverageFragmentProcessor(std::move(outerEffect));
1458 
1459     SkRect bounds = outer->getBounds();
1460     if (GrAAType::kCoverage == aaType) {
1461         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
1462     }
1463 
1464     this->fillRectWithLocalMatrix(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), bounds,
1465                                   inverseVM);
1466     return true;
1467 }
1468 
drawDRRect(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRRect & outer,const SkRRect & inner)1469 void GrRenderTargetContext::drawDRRect(const GrClip& clip,
1470                                        GrPaint&& paint,
1471                                        GrAA aa,
1472                                        const SkMatrix& viewMatrix,
1473                                        const SkRRect& outer,
1474                                        const SkRRect& inner) {
1475     ASSERT_SINGLE_OWNER
1476     RETURN_IF_ABANDONED
1477     SkDEBUGCODE(this->validate();)
1478     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawDRRect", fContext);
1479 
1480     SkASSERT(!outer.isEmpty());
1481     SkASSERT(!inner.isEmpty());
1482 
1483     AutoCheckFlush acf(this->drawingManager());
1484 
1485     if (this->drawFilledDRRect(clip, std::move(paint), aa, viewMatrix, outer, inner)) {
1486         return;
1487     }
1488     assert_alive(paint);
1489 
1490     SkPath path;
1491     path.setIsVolatile(true);
1492     path.addRRect(inner);
1493     path.addRRect(outer);
1494     path.setFillType(SkPathFillType::kEvenOdd);
1495     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, GrShape(path));
1496 }
1497 
1498 ///////////////////////////////////////////////////////////////////////////////
1499 
drawRegion(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRegion & region,const GrStyle & style,const GrUserStencilSettings * ss)1500 void GrRenderTargetContext::drawRegion(const GrClip& clip,
1501                                        GrPaint&& paint,
1502                                        GrAA aa,
1503                                        const SkMatrix& viewMatrix,
1504                                        const SkRegion& region,
1505                                        const GrStyle& style,
1506                                        const GrUserStencilSettings* ss) {
1507     ASSERT_SINGLE_OWNER
1508     RETURN_IF_ABANDONED
1509     SkDEBUGCODE(this->validate();)
1510     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawRegion", fContext);
1511 
1512     if (GrAA::kYes == aa) {
1513         // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
1514         // to see whether aa is really required.
1515         if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1516             SkScalarIsInt(viewMatrix.getTranslateX()) &&
1517             SkScalarIsInt(viewMatrix.getTranslateY())) {
1518             aa = GrAA::kNo;
1519         }
1520     }
1521     bool complexStyle = !style.isSimpleFill();
1522     if (complexStyle || GrAA::kYes == aa) {
1523         SkPath path;
1524         region.getBoundaryPath(&path);
1525         path.setIsVolatile(true);
1526 
1527         return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
1528     }
1529 
1530     GrAAType aaType = this->chooseAAType(GrAA::kNo);
1531     std::unique_ptr<GrDrawOp> op = GrRegionOp::Make(fContext, std::move(paint), viewMatrix, region,
1532                                                     aaType, ss);
1533     this->addDrawOp(clip, std::move(op));
1534 }
1535 
drawOval(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & oval,const GrStyle & style)1536 void GrRenderTargetContext::drawOval(const GrClip& clip,
1537                                      GrPaint&& paint,
1538                                      GrAA aa,
1539                                      const SkMatrix& viewMatrix,
1540                                      const SkRect& oval,
1541                                      const GrStyle& style) {
1542     ASSERT_SINGLE_OWNER
1543     RETURN_IF_ABANDONED
1544     SkDEBUGCODE(this->validate();)
1545     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawOval", fContext);
1546 
1547     const SkStrokeRec& stroke = style.strokeRec();
1548 
1549     if (oval.isEmpty() && !style.pathEffect()) {
1550         if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1551             return;
1552         }
1553 
1554         this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
1555         return;
1556     }
1557 
1558     AutoCheckFlush acf(this->drawingManager());
1559 
1560     GrAAType aaType = this->chooseAAType(aa);
1561 
1562     std::unique_ptr<GrDrawOp> op;
1563     if (GrAAType::kCoverage == aaType && oval.width() > SK_ScalarNearlyZero &&
1564         oval.width() == oval.height() && viewMatrix.isSimilarity()) {
1565         // We don't draw true circles as round rects in coverage mode, because it can
1566         // cause perf regressions on some platforms as compared to the dedicated circle Op.
1567         assert_alive(paint);
1568         op = GrOvalOpFactory::MakeCircleOp(fContext, std::move(paint), viewMatrix, oval, style,
1569                                            this->caps()->shaderCaps());
1570     }
1571     if (!op && style.isSimpleFill()) {
1572         // GrFillRRectOp has special geometry and a fragment-shader branch to conditionally evaluate
1573         // the arc equation. This same special geometry and fragment branch also turn out to be a
1574         // substantial optimization for drawing ovals (namely, by not evaluating the arc equation
1575         // inside the oval's inner diamond). Given these optimizations, it's a clear win to draw
1576         // ovals the exact same way we do round rects.
1577         assert_alive(paint);
1578         op = GrFillRRectOp::Make(fContext, aaType, viewMatrix, SkRRect::MakeOval(oval),
1579                                  *this->caps(), std::move(paint));
1580     }
1581     if (!op && GrAAType::kCoverage == aaType) {
1582         assert_alive(paint);
1583         op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
1584                                          this->caps()->shaderCaps());
1585     }
1586     if (op) {
1587         this->addDrawOp(clip, std::move(op));
1588         return;
1589     }
1590 
1591     assert_alive(paint);
1592     this->drawShapeUsingPathRenderer(
1593             clip, std::move(paint), aa, viewMatrix,
1594             GrShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2, false, style));
1595 }
1596 
drawArc(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkRect & oval,SkScalar startAngle,SkScalar sweepAngle,bool useCenter,const GrStyle & style)1597 void GrRenderTargetContext::drawArc(const GrClip& clip,
1598                                     GrPaint&& paint,
1599                                     GrAA aa,
1600                                     const SkMatrix& viewMatrix,
1601                                     const SkRect& oval,
1602                                     SkScalar startAngle,
1603                                     SkScalar sweepAngle,
1604                                     bool useCenter,
1605                                     const GrStyle& style) {
1606     ASSERT_SINGLE_OWNER
1607     RETURN_IF_ABANDONED
1608     SkDEBUGCODE(this->validate();)
1609             GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawArc", fContext);
1610 
1611     AutoCheckFlush acf(this->drawingManager());
1612 
1613     GrAAType aaType = this->chooseAAType(aa);
1614     if (GrAAType::kCoverage == aaType) {
1615         const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
1616         std::unique_ptr<GrDrawOp> op = GrOvalOpFactory::MakeArcOp(fContext,
1617                                                                   std::move(paint),
1618                                                                   viewMatrix,
1619                                                                   oval,
1620                                                                   startAngle,
1621                                                                   sweepAngle,
1622                                                                   useCenter,
1623                                                                   style,
1624                                                                   shaderCaps);
1625         if (op) {
1626             this->addDrawOp(clip, std::move(op));
1627             return;
1628         }
1629         assert_alive(paint);
1630     }
1631     this->drawShapeUsingPathRenderer(
1632             clip, std::move(paint), aa, viewMatrix,
1633             GrShape::MakeArc(oval, startAngle, sweepAngle, useCenter, style));
1634 }
1635 
drawImageLattice(const GrClip & clip,GrPaint && paint,const SkMatrix & viewMatrix,GrSurfaceProxyView view,SkAlphaType alphaType,sk_sp<GrColorSpaceXform> csxf,GrSamplerState::Filter filter,std::unique_ptr<SkLatticeIter> iter,const SkRect & dst)1636 void GrRenderTargetContext::drawImageLattice(const GrClip& clip,
1637                                              GrPaint&& paint,
1638                                              const SkMatrix& viewMatrix,
1639                                              GrSurfaceProxyView view,
1640                                              SkAlphaType alphaType,
1641                                              sk_sp<GrColorSpaceXform> csxf,
1642                                              GrSamplerState::Filter filter,
1643                                              std::unique_ptr<SkLatticeIter> iter,
1644                                              const SkRect& dst) {
1645     ASSERT_SINGLE_OWNER
1646     RETURN_IF_ABANDONED
1647     SkDEBUGCODE(this->validate();)
1648     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawImageLattice", fContext);
1649 
1650     AutoCheckFlush acf(this->drawingManager());
1651 
1652     std::unique_ptr<GrDrawOp> op =
1653             GrLatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(view),
1654                                    alphaType, std::move(csxf), filter, std::move(iter), dst);
1655     this->addDrawOp(clip, std::move(op));
1656 }
1657 
drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,const SkRect & bounds)1658 void GrRenderTargetContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
1659                                          const SkRect& bounds) {
1660     std::unique_ptr<GrOp> op(GrDrawableOp::Make(fContext, std::move(drawable), bounds));
1661     SkASSERT(op);
1662     this->addOp(std::move(op));
1663 }
1664 
asyncRescaleAndReadPixels(const SkImageInfo & info,const SkIRect & srcRect,SkSurface::RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallback callback,ReadPixelsContext context)1665 void GrRenderTargetContext::asyncRescaleAndReadPixels(
1666         const SkImageInfo& info, const SkIRect& srcRect, SkSurface::RescaleGamma rescaleGamma,
1667         SkFilterQuality rescaleQuality, ReadPixelsCallback callback, ReadPixelsContext context) {
1668     auto direct = fContext->priv().asDirectContext();
1669     if (!direct) {
1670         callback(context, nullptr);
1671         return;
1672     }
1673     if (this->asRenderTargetProxy()->wrapsVkSecondaryCB()) {
1674         callback(context, nullptr);
1675         return;
1676     }
1677     if (this->asRenderTargetProxy()->framebufferOnly()) {
1678         callback(context, nullptr);
1679         return;
1680     }
1681     auto dstCT = SkColorTypeToGrColorType(info.colorType());
1682     if (dstCT == GrColorType::kUnknown) {
1683         callback(context, nullptr);
1684         return;
1685     }
1686     bool needsRescale = srcRect.width() != info.width() || srcRect.height() != info.height();
1687     auto colorTypeOfFinalContext = this->colorInfo().colorType();
1688     auto backendFormatOfFinalContext = this->asSurfaceProxy()->backendFormat();
1689     if (needsRescale) {
1690         colorTypeOfFinalContext = dstCT;
1691         backendFormatOfFinalContext = this->caps()->getDefaultBackendFormat(dstCT,
1692                                                                             GrRenderable::kYes);
1693     }
1694     auto readInfo = this->caps()->supportedReadPixelsColorType(colorTypeOfFinalContext,
1695                                                                backendFormatOfFinalContext, dstCT);
1696     // Fail if we can't read from the source surface's color type.
1697     if (readInfo.fColorType == GrColorType::kUnknown) {
1698         callback(context, nullptr);
1699         return;
1700     }
1701     // Fail if read color type does not have all of dstCT's color channels and those missing color
1702     // channels are in the src.
1703     uint32_t dstComponents = GrColorTypeComponentFlags(dstCT);
1704     uint32_t legalReadComponents = GrColorTypeComponentFlags(readInfo.fColorType);
1705     uint32_t srcComponents = GrColorTypeComponentFlags(this->colorInfo().colorType());
1706     if ((~legalReadComponents & dstComponents) & srcComponents) {
1707         callback(context, nullptr);
1708         return;
1709     }
1710 
1711     std::unique_ptr<GrRenderTargetContext> tempRTC;
1712     int x = srcRect.fLeft;
1713     int y = srcRect.fTop;
1714     if (needsRescale) {
1715         tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality);
1716         if (!tempRTC) {
1717             callback(context, nullptr);
1718             return;
1719         }
1720         SkASSERT(SkColorSpace::Equals(tempRTC->colorInfo().colorSpace(), info.colorSpace()));
1721         SkASSERT(tempRTC->origin() == kTopLeft_GrSurfaceOrigin);
1722         x = y = 0;
1723     } else {
1724         sk_sp<GrColorSpaceXform> xform = GrColorSpaceXform::Make(this->colorInfo().colorSpace(),
1725                                                                  this->colorInfo().alphaType(),
1726                                                                  info.colorSpace(),
1727                                                                  info.alphaType());
1728         // Insert a draw to a temporary surface if we need to do a y-flip or color space conversion.
1729         if (this->origin() == kBottomLeft_GrSurfaceOrigin || xform) {
1730             // We flip or color convert by drawing and we don't currently support drawing to
1731             // kPremul.
1732             if (info.alphaType() == kUnpremul_SkAlphaType) {
1733                 callback(context, nullptr);
1734                 return;
1735             }
1736             GrSurfaceProxyView texProxyView = this->readSurfaceView();
1737             SkRect srcRectToDraw = SkRect::Make(srcRect);
1738             // If the src is not texturable first try to make a copy to a texture.
1739             if (!texProxyView.asTextureProxy()) {
1740                 texProxyView = GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(),
1741                                                     this->origin(), this->colorInfo().colorType(),
1742                                                     GrMipMapped::kNo, srcRect,
1743                                                     SkBackingFit::kApprox, SkBudgeted::kNo);
1744                 if (!texProxyView.asTextureProxy()) {
1745                     callback(context, nullptr);
1746                     return;
1747                 }
1748                 srcRectToDraw = SkRect::MakeWH(srcRect.width(), srcRect.height());
1749             }
1750             tempRTC = GrRenderTargetContext::Make(
1751                     direct, this->colorInfo().colorType(), info.refColorSpace(),
1752                     SkBackingFit::kApprox, srcRect.size(), 1, GrMipMapped::kNo, GrProtected::kNo,
1753                     kTopLeft_GrSurfaceOrigin);
1754             if (!tempRTC) {
1755                 callback(context, nullptr);
1756                 return;
1757             }
1758             tempRTC->drawTexture(GrNoClip(), std::move(texProxyView), this->colorInfo().alphaType(),
1759                                  GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
1760                                  SK_PMColor4fWHITE, srcRectToDraw,
1761                                  SkRect::MakeWH(srcRect.width(), srcRect.height()), GrAA::kNo,
1762                                  GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
1763                                  SkMatrix::I(), std::move(xform));
1764             x = y = 0;
1765         }
1766     }
1767     auto rtc = tempRTC ? tempRTC.get() : this;
1768     return rtc->asyncReadPixels(SkIRect::MakeXYWH(x, y, info.width(), info.height()),
1769                                 info.colorType(), callback, context);
1770 }
1771 
1772 class GrRenderTargetContext::AsyncReadResult : public SkSurface::AsyncReadResult {
1773 public:
AsyncReadResult(uint32_t inboxID)1774     AsyncReadResult(uint32_t inboxID) : fInboxID(inboxID) {}
~AsyncReadResult()1775     ~AsyncReadResult() override {
1776         for (int i = 0; i < fPlanes.count(); ++i) {
1777             if (!fPlanes[i].fMappedBuffer) {
1778                 delete[] static_cast<const char*>(fPlanes[i].fData);
1779             } else {
1780                 GrClientMappedBufferManager::BufferFinishedMessageBus::Post(
1781                         {std::move(fPlanes[i].fMappedBuffer), fInboxID});
1782             }
1783         }
1784     }
1785 
count() const1786     int count() const override { return fPlanes.count(); }
data(int i) const1787     const void* data(int i) const override { return fPlanes[i].fData; }
rowBytes(int i) const1788     size_t rowBytes(int i) const override { return fPlanes[i].fRowBytes; }
1789 
addTransferResult(const PixelTransferResult & result,SkISize dimensions,size_t rowBytes,GrClientMappedBufferManager * manager)1790     bool addTransferResult(const PixelTransferResult& result,
1791                            SkISize dimensions,
1792                            size_t rowBytes,
1793                            GrClientMappedBufferManager* manager) {
1794         SkASSERT(!result.fTransferBuffer->isMapped());
1795         const void* mappedData = result.fTransferBuffer->map();
1796         if (!mappedData) {
1797             return false;
1798         }
1799         if (result.fPixelConverter) {
1800             std::unique_ptr<char[]> convertedData(new char[rowBytes * dimensions.height()]);
1801             result.fPixelConverter(convertedData.get(), mappedData);
1802             this->addCpuPlane(std::move(convertedData), rowBytes);
1803             result.fTransferBuffer->unmap();
1804         } else {
1805             manager->insert(result.fTransferBuffer);
1806             this->addMappedPlane(mappedData, rowBytes, std::move(result.fTransferBuffer));
1807         }
1808         return true;
1809     }
1810 
addCpuPlane(std::unique_ptr<const char[]> data,size_t rowBytes)1811     void addCpuPlane(std::unique_ptr<const char[]> data, size_t rowBytes) {
1812         SkASSERT(data);
1813         SkASSERT(rowBytes > 0);
1814         fPlanes.emplace_back(data.release(), rowBytes, nullptr);
1815     }
1816 
1817 private:
addMappedPlane(const void * data,size_t rowBytes,sk_sp<GrGpuBuffer> mappedBuffer)1818     void addMappedPlane(const void* data, size_t rowBytes, sk_sp<GrGpuBuffer> mappedBuffer) {
1819         SkASSERT(data);
1820         SkASSERT(rowBytes > 0);
1821         SkASSERT(mappedBuffer);
1822         SkASSERT(mappedBuffer->isMapped());
1823         fPlanes.emplace_back(data, rowBytes, std::move(mappedBuffer));
1824     }
1825 
1826     struct Plane {
PlaneGrRenderTargetContext::AsyncReadResult::Plane1827         Plane(const void* data, size_t rowBytes, sk_sp<GrGpuBuffer> buffer)
1828                 : fData(data), fRowBytes(rowBytes), fMappedBuffer(std::move(buffer)) {}
1829         const void* fData;
1830         size_t fRowBytes;
1831         // If this is null then fData is heap alloc and must be delete[]ed as const char[].
1832         sk_sp<GrGpuBuffer> fMappedBuffer;
1833     };
1834     SkSTArray<3, Plane> fPlanes;
1835     uint32_t fInboxID;
1836 };
1837 
asyncReadPixels(const SkIRect & rect,SkColorType colorType,ReadPixelsCallback callback,ReadPixelsContext context)1838 void GrRenderTargetContext::asyncReadPixels(const SkIRect& rect, SkColorType colorType,
1839                                             ReadPixelsCallback callback,
1840                                             ReadPixelsContext context) {
1841     SkASSERT(rect.fLeft >= 0 && rect.fRight <= this->width());
1842     SkASSERT(rect.fTop >= 0 && rect.fBottom <= this->height());
1843 
1844     if (this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
1845         callback(context, nullptr);
1846         return;
1847     }
1848 
1849     auto directContext = fContext->priv().asDirectContext();
1850     SkASSERT(directContext);
1851     auto mappedBufferManager = directContext->priv().clientMappedBufferManager();
1852 
1853     auto transferResult = this->transferPixels(SkColorTypeToGrColorType(colorType), rect);
1854 
1855     if (!transferResult.fTransferBuffer) {
1856         auto ii = SkImageInfo::Make(rect.size(), colorType,
1857                                     this->colorInfo().alphaType(),
1858                                     this->colorInfo().refColorSpace());
1859         auto result = std::make_unique<AsyncReadResult>(0);
1860         std::unique_ptr<char[]> data(new char[ii.computeMinByteSize()]);
1861         SkPixmap pm(ii, data.get(), ii.minRowBytes());
1862         result->addCpuPlane(std::move(data), pm.rowBytes());
1863 
1864         if (!this->readPixels(ii, pm.writable_addr(), pm.rowBytes(), {rect.fLeft, rect.fTop})) {
1865             callback(context, nullptr);
1866             return;
1867         }
1868         callback(context, std::move(result));
1869         return;
1870     }
1871 
1872     struct FinishContext {
1873         ReadPixelsCallback* fClientCallback;
1874         ReadPixelsContext fClientContext;
1875         SkISize fSize;
1876         SkColorType fColorType;
1877         GrClientMappedBufferManager* fMappedBufferManager;
1878         PixelTransferResult fTransferResult;
1879     };
1880     // Assumption is that the caller would like to flush. We could take a parameter or require an
1881     // explicit flush from the caller. We'd have to have a way to defer attaching the finish
1882     // callback to GrGpu until after the next flush that flushes our op list, though.
1883     auto* finishContext = new FinishContext{callback,
1884                                             context,
1885                                             rect.size(),
1886                                             colorType,
1887                                             mappedBufferManager,
1888                                             std::move(transferResult)};
1889     auto finishCallback = [](GrGpuFinishedContext c) {
1890         const auto* context = reinterpret_cast<const FinishContext*>(c);
1891         auto result = std::make_unique<AsyncReadResult>(context->fMappedBufferManager->inboxID());
1892         size_t rowBytes = context->fSize.width() * SkColorTypeBytesPerPixel(context->fColorType);
1893         if (!result->addTransferResult(context->fTransferResult, context->fSize, rowBytes,
1894                                        context->fMappedBufferManager)) {
1895             result.reset();
1896         }
1897         (*context->fClientCallback)(context->fClientContext, std::move(result));
1898         delete context;
1899     };
1900     GrFlushInfo flushInfo;
1901     flushInfo.fFinishedContext = finishContext;
1902     flushInfo.fFinishedProc = finishCallback;
1903     this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
1904 }
1905 
asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,sk_sp<SkColorSpace> dstColorSpace,const SkIRect & srcRect,SkISize dstSize,RescaleGamma rescaleGamma,SkFilterQuality rescaleQuality,ReadPixelsCallback callback,ReadPixelsContext context)1906 void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvColorSpace,
1907                                                             sk_sp<SkColorSpace> dstColorSpace,
1908                                                             const SkIRect& srcRect,
1909                                                             SkISize dstSize,
1910                                                             RescaleGamma rescaleGamma,
1911                                                             SkFilterQuality rescaleQuality,
1912                                                             ReadPixelsCallback callback,
1913                                                             ReadPixelsContext context) {
1914     SkASSERT(srcRect.fLeft >= 0 && srcRect.fRight <= this->width());
1915     SkASSERT(srcRect.fTop >= 0 && srcRect.fBottom <= this->height());
1916     SkASSERT(!dstSize.isZero());
1917     SkASSERT((dstSize.width() % 2 == 0) && (dstSize.height() % 2 == 0));
1918 
1919     auto direct = fContext->priv().asDirectContext();
1920     if (!direct) {
1921         callback(context, nullptr);
1922         return;
1923     }
1924     if (this->asRenderTargetProxy()->wrapsVkSecondaryCB()) {
1925         callback(context, nullptr);
1926         return;
1927     }
1928     if (this->asRenderTargetProxy()->framebufferOnly()) {
1929         callback(context, nullptr);
1930         return;
1931     }
1932     if (this->asSurfaceProxy()->isProtected() == GrProtected::kYes) {
1933         callback(context, nullptr);
1934         return;
1935     }
1936     int x = srcRect.fLeft;
1937     int y = srcRect.fTop;
1938     bool needsRescale = srcRect.size() != dstSize;
1939     GrSurfaceProxyView srcView;
1940     if (needsRescale) {
1941         // We assume the caller wants kPremul. There is no way to indicate a preference.
1942         auto info = SkImageInfo::Make(dstSize, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
1943                                       dstColorSpace);
1944         // TODO: Incorporate the YUV conversion into last pass of rescaling.
1945         auto tempRTC = this->rescale(info, srcRect, rescaleGamma, rescaleQuality);
1946         if (!tempRTC) {
1947             callback(context, nullptr);
1948             return;
1949         }
1950         SkASSERT(SkColorSpace::Equals(tempRTC->colorInfo().colorSpace(), info.colorSpace()));
1951         SkASSERT(tempRTC->origin() == kTopLeft_GrSurfaceOrigin);
1952         x = y = 0;
1953         srcView = tempRTC->readSurfaceView();
1954     } else {
1955         srcView = this->readSurfaceView();
1956         if (!srcView.asTextureProxy()) {
1957             srcView = GrSurfaceProxy::Copy(fContext, fReadView.proxy(), this->origin(),
1958                                            this->colorInfo().colorType(), GrMipMapped::kNo,
1959                                            srcRect, SkBackingFit::kApprox, SkBudgeted::kYes);
1960             if (!srcView.asTextureProxy()) {
1961                 // If we can't get a texture copy of the contents then give up.
1962                 callback(context, nullptr);
1963                 return;
1964             }
1965             x = y = 0;
1966         }
1967         // We assume the caller wants kPremul. There is no way to indicate a preference.
1968         sk_sp<GrColorSpaceXform> xform = GrColorSpaceXform::Make(
1969                 this->colorInfo().colorSpace(), this->colorInfo().alphaType(), dstColorSpace.get(),
1970                 kPremul_SkAlphaType);
1971         if (xform) {
1972             SkRect srcRectToDraw = SkRect::MakeXYWH(x, y, srcRect.width(), srcRect.height());
1973             auto tempRTC = GrRenderTargetContext::Make(
1974                     direct, this->colorInfo().colorType(), dstColorSpace, SkBackingFit::kApprox,
1975                     dstSize, 1, GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
1976             if (!tempRTC) {
1977                 callback(context, nullptr);
1978                 return;
1979             }
1980             tempRTC->drawTexture(GrNoClip(), std::move(srcView), this->colorInfo().alphaType(),
1981                                  GrSamplerState::Filter::kNearest, SkBlendMode::kSrc,
1982                                  SK_PMColor4fWHITE, srcRectToDraw, SkRect::Make(srcRect.size()),
1983                                  GrAA::kNo, GrQuadAAFlags::kNone, SkCanvas::kFast_SrcRectConstraint,
1984                                  SkMatrix::I(), std::move(xform));
1985             srcView = tempRTC->readSurfaceView();
1986             SkASSERT(srcView.asTextureProxy());
1987             x = y = 0;
1988         }
1989     }
1990 
1991     auto yRTC = GrRenderTargetContext::MakeWithFallback(
1992             direct, GrColorType::kAlpha_8, dstColorSpace, SkBackingFit::kApprox, dstSize, 1,
1993             GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
1994     int halfW = dstSize.width()/2;
1995     int halfH = dstSize.height()/2;
1996     auto uRTC = GrRenderTargetContext::MakeWithFallback(
1997             direct, GrColorType::kAlpha_8, dstColorSpace, SkBackingFit::kApprox, {halfW, halfH}, 1,
1998             GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
1999     auto vRTC = GrRenderTargetContext::MakeWithFallback(
2000             direct, GrColorType::kAlpha_8, dstColorSpace, SkBackingFit::kApprox, {halfW, halfH}, 1,
2001             GrMipMapped::kNo, GrProtected::kNo, kTopLeft_GrSurfaceOrigin);
2002     if (!yRTC || !uRTC || !vRTC) {
2003         callback(context, nullptr);
2004         return;
2005     }
2006 
2007     float baseM[20];
2008     SkColorMatrix_RGB2YUV(yuvColorSpace, baseM);
2009 
2010     // TODO: Use one transfer buffer for all three planes to reduce map/unmap cost?
2011 
2012     auto texMatrix = SkMatrix::MakeTrans(x, y);
2013 
2014     SkRect dstRectY = SkRect::Make(dstSize);
2015     SkRect dstRectUV = SkRect::MakeWH(halfW, halfH);
2016 
2017     bool doSynchronousRead = !this->caps()->transferFromSurfaceToBufferSupport();
2018     PixelTransferResult yTransfer, uTransfer, vTransfer;
2019 
2020     // This matrix generates (r,g,b,a) = (0, 0, 0, y)
2021     float yM[20];
2022     std::fill_n(yM, 15, 0.f);
2023     std::copy_n(baseM + 0, 5, yM + 15);
2024     GrPaint yPaint;
2025     yPaint.addColorFragmentProcessor(
2026             GrTextureEffect::Make(srcView, this->colorInfo().alphaType(), texMatrix));
2027     auto yFP = GrColorMatrixFragmentProcessor::Make(yM, false, true, false);
2028     yPaint.addColorFragmentProcessor(std::move(yFP));
2029     yPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
2030     yRTC->fillRectToRect(GrNoClip(), std::move(yPaint), GrAA::kNo, SkMatrix::I(),
2031                          dstRectY, dstRectY);
2032     if (!doSynchronousRead) {
2033         yTransfer = yRTC->transferPixels(GrColorType::kAlpha_8,
2034                                          SkIRect::MakeWH(yRTC->width(), yRTC->height()));
2035         if (!yTransfer.fTransferBuffer) {
2036             callback(context, nullptr);
2037             return;
2038         }
2039     }
2040 
2041     texMatrix.preScale(2.f, 2.f);
2042     // This matrix generates (r,g,b,a) = (0, 0, 0, u)
2043     float uM[20];
2044     std::fill_n(uM, 15, 0.f);
2045     std::copy_n(baseM + 5, 5, uM + 15);
2046     GrPaint uPaint;
2047     uPaint.addColorFragmentProcessor(GrTextureEffect::Make(
2048             srcView, this->colorInfo().alphaType(), texMatrix, GrSamplerState::Filter::kBilerp));
2049     auto uFP = GrColorMatrixFragmentProcessor::Make(uM, false, true, false);
2050     uPaint.addColorFragmentProcessor(std::move(uFP));
2051     uPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
2052     uRTC->fillRectToRect(GrNoClip(), std::move(uPaint), GrAA::kNo, SkMatrix::I(),
2053                          dstRectUV, dstRectUV);
2054     if (!doSynchronousRead) {
2055         uTransfer = uRTC->transferPixels(GrColorType::kAlpha_8,
2056                                          SkIRect::MakeWH(uRTC->width(), uRTC->height()));
2057         if (!uTransfer.fTransferBuffer) {
2058             callback(context, nullptr);
2059             return;
2060         }
2061     }
2062 
2063     // This matrix generates (r,g,b,a) = (0, 0, 0, v)
2064     float vM[20];
2065     std::fill_n(vM, 15, 0.f);
2066     std::copy_n(baseM + 10, 5, vM + 15);
2067     GrPaint vPaint;
2068     vPaint.addColorFragmentProcessor(GrTextureEffect::Make(std::move(srcView),
2069                                                            this->colorInfo().alphaType(), texMatrix,
2070                                                            GrSamplerState::Filter::kBilerp));
2071     auto vFP = GrColorMatrixFragmentProcessor::Make(vM, false, true, false);
2072     vPaint.addColorFragmentProcessor(std::move(vFP));
2073     vPaint.setPorterDuffXPFactory(SkBlendMode::kSrc);
2074     vRTC->fillRectToRect(GrNoClip(), std::move(vPaint), GrAA::kNo, SkMatrix::I(),
2075                          dstRectUV, dstRectUV);
2076     if (!doSynchronousRead) {
2077         vTransfer = vRTC->transferPixels(GrColorType::kAlpha_8,
2078                                          SkIRect::MakeWH(vRTC->width(), vRTC->height()));
2079         if (!vTransfer.fTransferBuffer) {
2080             callback(context, nullptr);
2081             return;
2082         }
2083     }
2084 
2085     if (doSynchronousRead) {
2086         GrImageInfo yInfo(GrColorType::kAlpha_8, kPremul_SkAlphaType, nullptr, dstSize);
2087         GrImageInfo uvInfo = yInfo.makeWH(halfW, halfH);
2088         size_t yRB  = yInfo.minRowBytes();
2089         size_t uvRB = uvInfo.minRowBytes();
2090         std::unique_ptr<char[]> y(new char[yRB * yInfo.height()]);
2091         std::unique_ptr<char[]> u(new char[uvRB*uvInfo.height()]);
2092         std::unique_ptr<char[]> v(new char[uvRB*uvInfo.height()]);
2093         if (!yRTC->readPixels(yInfo,  y.get(), yRB,  {0, 0}, direct) ||
2094             !uRTC->readPixels(uvInfo, u.get(), uvRB, {0, 0}, direct) ||
2095             !vRTC->readPixels(uvInfo, v.get(), uvRB, {0, 0}, direct)) {
2096             callback(context, nullptr);
2097             return;
2098         }
2099         auto result = std::make_unique<AsyncReadResult>(direct->priv().contextID());
2100         result->addCpuPlane(std::move(y), yRB );
2101         result->addCpuPlane(std::move(u), uvRB);
2102         result->addCpuPlane(std::move(v), uvRB);
2103         callback(context, std::move(result));
2104         return;
2105     }
2106 
2107     struct FinishContext {
2108         ReadPixelsCallback* fClientCallback;
2109         ReadPixelsContext fClientContext;
2110         GrClientMappedBufferManager* fMappedBufferManager;
2111         SkISize fSize;
2112         PixelTransferResult fYTransfer;
2113         PixelTransferResult fUTransfer;
2114         PixelTransferResult fVTransfer;
2115     };
2116     // Assumption is that the caller would like to flush. We could take a parameter or require an
2117     // explicit flush from the caller. We'd have to have a way to defer attaching the finish
2118     // callback to GrGpu until after the next flush that flushes our op list, though.
2119     auto* finishContext = new FinishContext{callback,
2120                                             context,
2121                                             direct->priv().clientMappedBufferManager(),
2122                                             dstSize,
2123                                             std::move(yTransfer),
2124                                             std::move(uTransfer),
2125                                             std::move(vTransfer)};
2126     auto finishCallback = [](GrGpuFinishedContext c) {
2127         const auto* context = reinterpret_cast<const FinishContext*>(c);
2128         auto result = std::make_unique<AsyncReadResult>(context->fMappedBufferManager->inboxID());
2129         auto manager = context->fMappedBufferManager;
2130         size_t rowBytes = SkToSizeT(context->fSize.width());
2131         if (!result->addTransferResult(context->fYTransfer, context->fSize, rowBytes, manager)) {
2132             (*context->fClientCallback)(context->fClientContext, nullptr);
2133             delete context;
2134             return;
2135         }
2136         rowBytes /= 2;
2137         SkISize uvSize = {context->fSize.width()/2, context->fSize.height()/2};
2138         if (!result->addTransferResult(context->fUTransfer, uvSize, rowBytes, manager)) {
2139             (*context->fClientCallback)(context->fClientContext, nullptr);
2140             delete context;
2141             return;
2142         }
2143         if (!result->addTransferResult(context->fVTransfer, uvSize, rowBytes, manager)) {
2144             (*context->fClientCallback)(context->fClientContext, nullptr);
2145             delete context;
2146             return;
2147         }
2148         (*context->fClientCallback)(context->fClientContext, std::move(result));
2149         delete context;
2150     };
2151     GrFlushInfo flushInfo;
2152     flushInfo.fFinishedContext = finishContext;
2153     flushInfo.fFinishedProc = finishCallback;
2154     this->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
2155 }
2156 
flush(SkSurface::BackendSurfaceAccess access,const GrFlushInfo & info)2157 GrSemaphoresSubmitted GrRenderTargetContext::flush(SkSurface::BackendSurfaceAccess access,
2158                                                    const GrFlushInfo& info) {
2159     ASSERT_SINGLE_OWNER
2160     if (fContext->priv().abandoned()) {
2161         return GrSemaphoresSubmitted::kNo;
2162     }
2163     SkDEBUGCODE(this->validate();)
2164     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "flush", fContext);
2165 
2166     return this->drawingManager()->flushSurface(this->asSurfaceProxy(), access, info);
2167 }
2168 
waitOnSemaphores(int numSemaphores,const GrBackendSemaphore waitSemaphores[])2169 bool GrRenderTargetContext::waitOnSemaphores(int numSemaphores,
2170                                              const GrBackendSemaphore waitSemaphores[]) {
2171     ASSERT_SINGLE_OWNER
2172     RETURN_FALSE_IF_ABANDONED
2173     SkDEBUGCODE(this->validate();)
2174     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "waitOnSemaphores", fContext);
2175 
2176     AutoCheckFlush acf(this->drawingManager());
2177 
2178     if (numSemaphores && !this->caps()->semaphoreSupport()) {
2179         return false;
2180     }
2181 
2182     auto direct = fContext->priv().asDirectContext();
2183     if (!direct) {
2184         return false;
2185     }
2186 
2187     auto resourceProvider = direct->priv().resourceProvider();
2188 
2189     std::unique_ptr<std::unique_ptr<GrSemaphore>[]> grSemaphores(
2190             new std::unique_ptr<GrSemaphore>[numSemaphores]);
2191     for (int i = 0; i < numSemaphores; ++i) {
2192         grSemaphores[i] = resourceProvider->wrapBackendSemaphore(
2193                 waitSemaphores[i], GrResourceProvider::SemaphoreWrapType::kWillWait,
2194                 kAdopt_GrWrapOwnership);
2195     }
2196     this->drawingManager()->newWaitRenderTask(this->asSurfaceProxyRef(), std::move(grSemaphores),
2197                                               numSemaphores);
2198     return true;
2199 }
2200 
drawPath(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const SkPath & path,const GrStyle & style)2201 void GrRenderTargetContext::drawPath(const GrClip& clip,
2202                                      GrPaint&& paint,
2203                                      GrAA aa,
2204                                      const SkMatrix& viewMatrix,
2205                                      const SkPath& path,
2206                                      const GrStyle& style) {
2207     ASSERT_SINGLE_OWNER
2208     RETURN_IF_ABANDONED
2209     SkDEBUGCODE(this->validate();)
2210     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawPath", fContext);
2211 
2212     GrShape shape(path, style);
2213 
2214     this->drawShape(clip, std::move(paint), aa, viewMatrix, shape);
2215 }
2216 
drawShape(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const GrShape & shape)2217 void GrRenderTargetContext::drawShape(const GrClip& clip,
2218                                       GrPaint&& paint,
2219                                       GrAA aa,
2220                                       const SkMatrix& viewMatrix,
2221                                       const GrShape& shape) {
2222     ASSERT_SINGLE_OWNER
2223     RETURN_IF_ABANDONED
2224     SkDEBUGCODE(this->validate();)
2225     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "drawShape", fContext);
2226 
2227     if (shape.isEmpty()) {
2228         if (shape.inverseFilled()) {
2229             this->drawPaint(clip, std::move(paint), viewMatrix);
2230         }
2231         return;
2232     }
2233 
2234     AutoCheckFlush acf(this->drawingManager());
2235 
2236     if (!shape.style().hasPathEffect()) {
2237         GrAAType aaType = this->chooseAAType(aa);
2238         SkRRect rrect;
2239         // We can ignore the starting point and direction since there is no path effect.
2240         bool inverted;
2241         if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
2242             if (rrect.isRect()) {
2243                 this->drawRect(clip, std::move(paint), aa, viewMatrix, rrect.rect(),
2244                                &shape.style());
2245                 return;
2246             } else if (rrect.isOval()) {
2247                 this->drawOval(clip, std::move(paint), aa, viewMatrix, rrect.rect(), shape.style());
2248                 return;
2249             }
2250             this->drawRRect(clip, std::move(paint), aa, viewMatrix, rrect, shape.style());
2251             return;
2252         } else if (GrAAType::kCoverage == aaType && shape.style().isSimpleFill() &&
2253                    viewMatrix.rectStaysRect()) {
2254             // TODO: the rectStaysRect restriction could be lifted if we were willing to apply
2255             // the matrix to all the points individually rather than just to the rect
2256             SkRect rects[2];
2257             if (shape.asNestedRects(rects)) {
2258                 // Concave AA paths are expensive - try to avoid them for special cases
2259                 std::unique_ptr<GrDrawOp> op = GrStrokeRectOp::MakeNested(
2260                                 fContext, std::move(paint), viewMatrix, rects);
2261                 if (op) {
2262                     this->addDrawOp(clip, std::move(op));
2263                 }
2264                 // Returning here indicates that there is nothing to draw in this case.
2265                 return;
2266             }
2267         }
2268     }
2269 
2270     this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, shape);
2271 }
2272 
drawAndStencilPath(const GrHardClip & clip,const GrUserStencilSettings * ss,SkRegion::Op op,bool invert,GrAA aa,const SkMatrix & viewMatrix,const SkPath & path)2273 bool GrRenderTargetContextPriv::drawAndStencilPath(const GrHardClip& clip,
2274                                                    const GrUserStencilSettings* ss,
2275                                                    SkRegion::Op op,
2276                                                    bool invert,
2277                                                    GrAA aa,
2278                                                    const SkMatrix& viewMatrix,
2279                                                    const SkPath& path) {
2280     ASSERT_SINGLE_OWNER_PRIV
2281     RETURN_FALSE_IF_ABANDONED_PRIV
2282     SkDEBUGCODE(fRenderTargetContext->validate();)
2283     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContextPriv", "drawAndStencilPath",
2284                                    fRenderTargetContext->fContext);
2285 
2286     if (path.isEmpty() && path.isInverseFillType()) {
2287         GrPaint paint;
2288         paint.setCoverageSetOpXPFactory(op, invert);
2289         this->stencilRect(clip, ss, std::move(paint), GrAA::kNo, SkMatrix::I(),
2290                           SkRect::MakeIWH(fRenderTargetContext->width(),
2291                                           fRenderTargetContext->height()));
2292         return true;
2293     }
2294 
2295     AutoCheckFlush acf(fRenderTargetContext->drawingManager());
2296 
2297     // An Assumption here is that path renderer would use some form of tweaking
2298     // the src color (either the input alpha or in the frag shader) to implement
2299     // aa. If we have some future driver-mojo path AA that can do the right
2300     // thing WRT to the blend then we'll need some query on the PR.
2301     GrAAType aaType = fRenderTargetContext->chooseAAType(aa);
2302     bool hasUserStencilSettings = !ss->isUnused();
2303 
2304     SkIRect clipConservativeBounds;
2305     clip.getConservativeBounds(fRenderTargetContext->width(), fRenderTargetContext->height(),
2306                                &clipConservativeBounds, nullptr);
2307 
2308     GrShape shape(path, GrStyle::SimpleFill());
2309     GrPathRenderer::CanDrawPathArgs canDrawArgs;
2310     canDrawArgs.fCaps = fRenderTargetContext->caps();
2311     canDrawArgs.fProxy = fRenderTargetContext->asRenderTargetProxy();
2312     canDrawArgs.fViewMatrix = &viewMatrix;
2313     canDrawArgs.fShape = &shape;
2314     canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
2315     canDrawArgs.fAAType = aaType;
2316     SkASSERT(!fRenderTargetContext->wrapsVkSecondaryCB());
2317     canDrawArgs.fTargetIsWrappedVkSecondaryCB = false;
2318     canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
2319 
2320     // Don't allow the SW renderer
2321     GrPathRenderer* pr = fRenderTargetContext->drawingManager()->getPathRenderer(
2322             canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
2323     if (!pr) {
2324         return false;
2325     }
2326 
2327     GrPaint paint;
2328     paint.setCoverageSetOpXPFactory(op, invert);
2329 
2330     GrPathRenderer::DrawPathArgs args{fRenderTargetContext->drawingManager()->getContext(),
2331                                       std::move(paint),
2332                                       ss,
2333                                       fRenderTargetContext,
2334                                       &clip,
2335                                       &clipConservativeBounds,
2336                                       &viewMatrix,
2337                                       &shape,
2338                                       aaType,
2339                                       fRenderTargetContext->colorInfo().isLinearlyBlended()};
2340     pr->drawPath(args);
2341     return true;
2342 }
2343 
isBudgeted() const2344 SkBudgeted GrRenderTargetContextPriv::isBudgeted() const {
2345     ASSERT_SINGLE_OWNER_PRIV
2346 
2347     if (fRenderTargetContext->fContext->priv().abandoned()) {
2348         return SkBudgeted::kNo;
2349     }
2350 
2351     SkDEBUGCODE(fRenderTargetContext->validate();)
2352 
2353     return fRenderTargetContext->asSurfaceProxy()->isBudgeted();
2354 }
2355 
drawShapeUsingPathRenderer(const GrClip & clip,GrPaint && paint,GrAA aa,const SkMatrix & viewMatrix,const GrShape & originalShape)2356 void GrRenderTargetContext::drawShapeUsingPathRenderer(const GrClip& clip,
2357                                                        GrPaint&& paint,
2358                                                        GrAA aa,
2359                                                        const SkMatrix& viewMatrix,
2360                                                        const GrShape& originalShape) {
2361     ASSERT_SINGLE_OWNER
2362     RETURN_IF_ABANDONED
2363     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "internalDrawPath", fContext);
2364 
2365     if (!viewMatrix.isFinite() || !originalShape.bounds().isFinite()) {
2366         return;
2367     }
2368 
2369     SkIRect clipConservativeBounds;
2370     clip.getConservativeBounds(this->width(), this->height(), &clipConservativeBounds, nullptr);
2371 
2372     GrShape tempShape;
2373     GrAAType aaType = this->chooseAAType(aa);
2374 
2375     GrPathRenderer::CanDrawPathArgs canDrawArgs;
2376     canDrawArgs.fCaps = this->caps();
2377     canDrawArgs.fProxy = this->asRenderTargetProxy();
2378     canDrawArgs.fViewMatrix = &viewMatrix;
2379     canDrawArgs.fShape = &originalShape;
2380     canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
2381     canDrawArgs.fTargetIsWrappedVkSecondaryCB = this->wrapsVkSecondaryCB();
2382     canDrawArgs.fHasUserStencilSettings = false;
2383 
2384     GrPathRenderer* pr;
2385     static constexpr GrPathRendererChain::DrawType kType = GrPathRendererChain::DrawType::kColor;
2386     if (originalShape.isEmpty() && !originalShape.inverseFilled()) {
2387         return;
2388     }
2389 
2390     canDrawArgs.fAAType = aaType;
2391 
2392     // Try a 1st time without applying any of the style to the geometry (and barring sw)
2393     pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
2394     SkScalar styleScale =  GrStyle::MatrixToScaleFactor(viewMatrix);
2395 
2396     if (!pr && originalShape.style().pathEffect()) {
2397         // It didn't work above, so try again with the path effect applied.
2398         tempShape = originalShape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
2399         if (tempShape.isEmpty()) {
2400             return;
2401         }
2402         canDrawArgs.fShape = &tempShape;
2403         pr = this->drawingManager()->getPathRenderer(canDrawArgs, false, kType);
2404     }
2405     if (!pr) {
2406         if (canDrawArgs.fShape->style().applies()) {
2407             tempShape = canDrawArgs.fShape->applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec,
2408                                                        styleScale);
2409             if (tempShape.isEmpty()) {
2410                 return;
2411             }
2412             canDrawArgs.fShape = &tempShape;
2413             // This time, allow SW renderer
2414             pr = this->drawingManager()->getPathRenderer(canDrawArgs, true, kType);
2415         } else {
2416             pr = this->drawingManager()->getSoftwarePathRenderer();
2417         }
2418     }
2419 
2420     if (!pr) {
2421 #ifdef SK_DEBUG
2422         SkDebugf("Unable to find path renderer compatible with path.\n");
2423 #endif
2424         return;
2425     }
2426 
2427     GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
2428                                       std::move(paint),
2429                                       &GrUserStencilSettings::kUnused,
2430                                       this,
2431                                       &clip,
2432                                       &clipConservativeBounds,
2433                                       &viewMatrix,
2434                                       canDrawArgs.fShape,
2435                                       aaType,
2436                                       this->colorInfo().isLinearlyBlended()};
2437     pr->drawPath(args);
2438 }
2439 
op_bounds(SkRect * bounds,const GrOp * op)2440 static void op_bounds(SkRect* bounds, const GrOp* op) {
2441     *bounds = op->bounds();
2442     if (op->hasZeroArea()) {
2443         if (op->hasAABloat()) {
2444             bounds->outset(0.5f, 0.5f);
2445         } else {
2446             // We don't know which way the particular GPU will snap lines or points at integer
2447             // coords. So we ensure that the bounds is large enough for either snap.
2448             SkRect before = *bounds;
2449             bounds->roundOut(bounds);
2450             if (bounds->fLeft == before.fLeft) {
2451                 bounds->fLeft -= 1;
2452             }
2453             if (bounds->fTop == before.fTop) {
2454                 bounds->fTop -= 1;
2455             }
2456             if (bounds->fRight == before.fRight) {
2457                 bounds->fRight += 1;
2458             }
2459             if (bounds->fBottom == before.fBottom) {
2460                 bounds->fBottom += 1;
2461             }
2462         }
2463     }
2464 }
2465 
addOp(std::unique_ptr<GrOp> op)2466 void GrRenderTargetContext::addOp(std::unique_ptr<GrOp> op) {
2467     this->getOpsTask()->addOp(
2468             std::move(op), GrTextureResolveManager(this->drawingManager()), *this->caps());
2469 }
2470 
addDrawOp(const GrClip & clip,std::unique_ptr<GrDrawOp> op,const std::function<WillAddOpFn> & willAddFn)2471 void GrRenderTargetContext::addDrawOp(const GrClip& clip, std::unique_ptr<GrDrawOp> op,
2472                                       const std::function<WillAddOpFn>& willAddFn) {
2473     ASSERT_SINGLE_OWNER
2474     if (fContext->priv().abandoned()) {
2475         fContext->priv().opMemoryPool()->release(std::move(op));
2476         return;
2477     }
2478     SkDEBUGCODE(this->validate();)
2479     SkDEBUGCODE(op->fAddDrawOpCalled = true;)
2480     GR_CREATE_TRACE_MARKER_CONTEXT("GrRenderTargetContext", "addDrawOp", fContext);
2481 
2482     // Setup clip
2483     SkRect bounds;
2484     op_bounds(&bounds, op.get());
2485     GrAppliedClip appliedClip;
2486     GrDrawOp::FixedFunctionFlags fixedFunctionFlags = op->fixedFunctionFlags();
2487     bool usesHWAA = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesHWAA;
2488     bool usesUserStencilBits = fixedFunctionFlags & GrDrawOp::FixedFunctionFlags::kUsesStencil;
2489 
2490     if (usesUserStencilBits) {  // Stencil clipping will call setNeedsStencil on its own, if needed.
2491         this->setNeedsStencil(usesHWAA);
2492     }
2493 
2494     if (!clip.apply(fContext, this, usesHWAA, usesUserStencilBits, &appliedClip, &bounds)) {
2495         fContext->priv().opMemoryPool()->release(std::move(op));
2496         return;
2497     }
2498 
2499     bool willUseStencil = usesUserStencilBits || appliedClip.hasStencilClip();
2500     SkASSERT(!willUseStencil || fNumStencilSamples > 0);
2501 
2502     // If stencil is enabled and the framebuffer is mixed sampled, then the graphics pipeline will
2503     // have mixed sampled coverage, regardless of whether HWAA is enabled. (e.g., a non-aa draw
2504     // that uses a stencil test when the stencil buffer is multisampled.)
2505     bool hasMixedSampledCoverage = (
2506             willUseStencil && fNumStencilSamples > this->numSamples());
2507     SkASSERT(!hasMixedSampledCoverage ||
2508              this->asRenderTargetProxy()->canUseMixedSamples(*this->caps()));
2509 
2510     GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType());
2511     GrProcessorSet::Analysis analysis = op->finalize(
2512             *this->caps(), &appliedClip, hasMixedSampledCoverage, clampType);
2513 
2514     GrXferProcessor::DstProxyView dstProxyView;
2515     if (analysis.requiresDstTexture()) {
2516         if (!this->setupDstProxyView(clip, *op, &dstProxyView)) {
2517             fContext->priv().opMemoryPool()->release(std::move(op));
2518             return;
2519         }
2520     }
2521 
2522     op->setClippedBounds(bounds);
2523     auto opsTask = this->getOpsTask();
2524     if (willAddFn) {
2525         willAddFn(op.get(), opsTask->uniqueID());
2526     }
2527     opsTask->addDrawOp(std::move(op), analysis, std::move(appliedClip), dstProxyView,
2528                        GrTextureResolveManager(this->drawingManager()), *this->caps());
2529 }
2530 
setupDstProxyView(const GrClip & clip,const GrOp & op,GrXferProcessor::DstProxyView * dstProxyView)2531 bool GrRenderTargetContext::setupDstProxyView(const GrClip& clip, const GrOp& op,
2532                                               GrXferProcessor::DstProxyView* dstProxyView) {
2533     // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
2534     // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
2535     // start and stop the render pass in order to make the copy.
2536     if (this->asRenderTargetProxy()->wrapsVkSecondaryCB()) {
2537         return false;
2538     }
2539 
2540     if (this->caps()->textureBarrierSupport() &&
2541         !this->asSurfaceProxy()->requiresManualMSAAResolve()) {
2542         if (this->asTextureProxy()) {
2543             // The render target is a texture, so we can read from it directly in the shader. The XP
2544             // will be responsible to detect this situation and request a texture barrier.
2545             dstProxyView->setProxyView(this->readSurfaceView());
2546             dstProxyView->setOffset(0, 0);
2547             return true;
2548         }
2549     }
2550 
2551     SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions());
2552 
2553     SkIRect clippedRect;
2554     clip.getConservativeBounds(
2555             this->width(), this->height(), &clippedRect);
2556     SkRect opBounds = op.bounds();
2557     // If the op has aa bloating or is a infinitely thin geometry (hairline) outset the bounds by
2558     // 0.5 pixels.
2559     if (op.hasAABloat() || op.hasZeroArea()) {
2560         opBounds.outset(0.5f, 0.5f);
2561         // An antialiased/hairline draw can sometimes bleed outside of the clips bounds. For
2562         // performance we may ignore the clip when the draw is entirely inside the clip is float
2563         // space but will hit pixels just outside the clip when actually rasterizing.
2564         clippedRect.outset(1, 1);
2565         clippedRect.intersect(SkIRect::MakeSize(this->asSurfaceProxy()->dimensions()));
2566     }
2567     SkIRect opIBounds;
2568     opBounds.roundOut(&opIBounds);
2569     if (!clippedRect.intersect(opIBounds)) {
2570 #ifdef SK_DEBUG
2571         GrCapsDebugf(this->caps(), "setupDstTexture: Missed an early reject bailing on draw.");
2572 #endif
2573         return false;
2574     }
2575 
2576     GrColorType colorType = this->colorInfo().colorType();
2577     // MSAA consideration: When there is support for reading MSAA samples in the shader we could
2578     // have per-sample dst values by making the copy multisampled.
2579     GrCaps::DstCopyRestrictions restrictions = this->caps()->getDstCopyRestrictions(
2580             this->asRenderTargetProxy(), colorType);
2581 
2582     if (!restrictions.fMustCopyWholeSrc) {
2583         copyRect = clippedRect;
2584     }
2585 
2586     SkIPoint dstOffset;
2587     SkBackingFit fit;
2588     if (restrictions.fRectsMustMatch == GrSurfaceProxy::RectsMustMatch::kYes) {
2589         dstOffset = {0, 0};
2590         fit = SkBackingFit::kExact;
2591     } else {
2592         dstOffset = {copyRect.fLeft, copyRect.fTop};
2593         fit = SkBackingFit::kApprox;
2594     }
2595     GrSurfaceProxyView newProxyView =
2596             GrSurfaceProxy::Copy(fContext, this->asSurfaceProxy(), this->origin(), colorType,
2597                                  GrMipMapped::kNo, copyRect, fit, SkBudgeted::kYes,
2598                                  restrictions.fRectsMustMatch);
2599     SkASSERT(newProxyView.proxy());
2600 
2601     dstProxyView->setProxyView(std::move(newProxyView));
2602     dstProxyView->setOffset(dstOffset);
2603     return true;
2604 }
2605 
blitTexture(GrSurfaceProxyView view,const SkIRect & srcRect,const SkIPoint & dstPoint)2606 bool GrRenderTargetContext::blitTexture(GrSurfaceProxyView view, const SkIRect& srcRect,
2607                                         const SkIPoint& dstPoint) {
2608     SkASSERT(view.asTextureProxy());
2609     SkIRect clippedSrcRect;
2610     SkIPoint clippedDstPoint;
2611     if (!GrClipSrcRectAndDstPoint(this->asSurfaceProxy()->dimensions(), view.proxy()->dimensions(),
2612                                   srcRect, dstPoint, &clippedSrcRect, &clippedDstPoint)) {
2613         return false;
2614     }
2615 
2616     GrPaint paint;
2617     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
2618 
2619     auto fp = GrTextureEffect::Make(std::move(view), kUnknown_SkAlphaType);
2620     if (!fp) {
2621         return false;
2622     }
2623     paint.addColorFragmentProcessor(std::move(fp));
2624 
2625     this->fillRectToRect(
2626             GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
2627             SkRect::MakeXYWH(clippedDstPoint.fX, clippedDstPoint.fY, clippedSrcRect.width(),
2628                              clippedSrcRect.height()),
2629             SkRect::Make(clippedSrcRect));
2630     return true;
2631 }
2632