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