1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/v1/SurfaceDrawContext_v1.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/core/SkDrawable.h"
11cb93a386Sopenharmony_ci#include "include/core/SkLog.h"
12cb93a386Sopenharmony_ci#include "include/core/SkVertices.h"
13cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSemaphore.h"
14cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
15cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h"
16cb93a386Sopenharmony_ci#include "include/private/GrImageContext.h"
17cb93a386Sopenharmony_ci#include "include/private/SkShadowFlags.h"
18cb93a386Sopenharmony_ci#include "include/private/SkVx.h"
19cb93a386Sopenharmony_ci#include "include/utils/SkShadowUtils.h"
20cb93a386Sopenharmony_ci#include "src/core/SkAutoPixmapStorage.h"
21cb93a386Sopenharmony_ci#include "src/core/SkConvertPixels.h"
22cb93a386Sopenharmony_ci#include "src/core/SkDrawProcs.h"
23cb93a386Sopenharmony_ci#include "src/core/SkDrawShadowInfo.h"
24cb93a386Sopenharmony_ci#include "src/core/SkGlyphRunPainter.h"
25cb93a386Sopenharmony_ci#include "src/core/SkLatticeIter.h"
26cb93a386Sopenharmony_ci#include "src/core/SkMatrixPriv.h"
27cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h"
28cb93a386Sopenharmony_ci#include "src/core/SkRRectPriv.h"
29cb93a386Sopenharmony_ci#include "src/gpu/GrAppliedClip.h"
30cb93a386Sopenharmony_ci#include "src/gpu/GrAttachment.h"
31cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
32cb93a386Sopenharmony_ci#include "src/gpu/GrClip.h"
33cb93a386Sopenharmony_ci#include "src/gpu/GrColor.h"
34cb93a386Sopenharmony_ci#include "src/gpu/GrDataUtils.h"
35cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
36cb93a386Sopenharmony_ci#include "src/gpu/GrDrawingManager.h"
37cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h"
38cb93a386Sopenharmony_ci#include "src/gpu/GrImageContextPriv.h"
39cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h"
40cb93a386Sopenharmony_ci#include "src/gpu/GrMemoryPool.h"
41cb93a386Sopenharmony_ci#include "src/gpu/GrProxyProvider.h"
42cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h"
43cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
44cb93a386Sopenharmony_ci#include "src/gpu/GrSemaphore.h"
45cb93a386Sopenharmony_ci#include "src/gpu/GrStencilSettings.h"
46cb93a386Sopenharmony_ci#include "src/gpu/GrStyle.h"
47cb93a386Sopenharmony_ci#include "src/gpu/GrTracing.h"
48cb93a386Sopenharmony_ci#include "src/gpu/SkGr.h"
49cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBicubicEffect.h"
50cb93a386Sopenharmony_ci#include "src/gpu/effects/GrBlendFragmentProcessor.h"
51cb93a386Sopenharmony_ci#include "src/gpu/effects/GrDisableColorXP.h"
52cb93a386Sopenharmony_ci#include "src/gpu/effects/GrRRectEffect.h"
53cb93a386Sopenharmony_ci#include "src/gpu/effects/GrTextureEffect.h"
54cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrQuad.h"
55cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrQuadUtils.h"
56cb93a386Sopenharmony_ci#include "src/gpu/geometry/GrStyledShape.h"
57cb93a386Sopenharmony_ci#include "src/gpu/ops/BlurOp.h"
58cb93a386Sopenharmony_ci#include "src/gpu/ops/ClearOp.h"
59cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawAtlasOp.h"
60cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawVerticesOp.h"
61cb93a386Sopenharmony_ci#include "src/gpu/ops/DrawableOp.h"
62cb93a386Sopenharmony_ci#include "src/gpu/ops/FillRRectOp.h"
63cb93a386Sopenharmony_ci#include "src/gpu/ops/FillRectOp.h"
64cb93a386Sopenharmony_ci#include "src/gpu/ops/GrDrawOp.h"
65cb93a386Sopenharmony_ci#include "src/gpu/ops/GrOp.h"
66cb93a386Sopenharmony_ci#include "src/gpu/ops/GrOvalOpFactory.h"
67cb93a386Sopenharmony_ci#include "src/gpu/ops/LatticeOp.h"
68cb93a386Sopenharmony_ci#include "src/gpu/ops/RegionOp.h"
69cb93a386Sopenharmony_ci#include "src/gpu/ops/ShadowRRectOp.h"
70cb93a386Sopenharmony_ci#include "src/gpu/ops/StrokeRectOp.h"
71cb93a386Sopenharmony_ci#include "src/gpu/ops/TextureOp.h"
72cb93a386Sopenharmony_ci#include "src/gpu/text/GrSDFTControl.h"
73cb93a386Sopenharmony_ci#include "src/gpu/text/GrTextBlobCache.h"
74cb93a386Sopenharmony_ci#include "src/gpu/v1/PathRenderer.h"
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_ci#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
77cb93a386Sopenharmony_ci#define ASSERT_SINGLE_OWNER        GR_ASSERT_SINGLE_OWNER(this->singleOwner())
78cb93a386Sopenharmony_ci#define RETURN_IF_ABANDONED        if (fContext->abandoned()) { return; }
79cb93a386Sopenharmony_ci#define RETURN_FALSE_IF_ABANDONED  if (fContext->abandoned()) { return false; }
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_cinamespace {
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_civoid op_bounds(SkRect* bounds, const GrOp* op) {
86cb93a386Sopenharmony_ci    *bounds = op->bounds();
87cb93a386Sopenharmony_ci    if (op->hasZeroArea()) {
88cb93a386Sopenharmony_ci        if (op->hasAABloat()) {
89cb93a386Sopenharmony_ci            bounds->outset(0.5f, 0.5f);
90cb93a386Sopenharmony_ci        } else {
91cb93a386Sopenharmony_ci            // We don't know which way the particular GPU will snap lines or points at integer
92cb93a386Sopenharmony_ci            // coords. So we ensure that the bounds is large enough for either snap.
93cb93a386Sopenharmony_ci            SkRect before = *bounds;
94cb93a386Sopenharmony_ci            bounds->roundOut(bounds);
95cb93a386Sopenharmony_ci            if (bounds->fLeft == before.fLeft) {
96cb93a386Sopenharmony_ci                bounds->fLeft -= 1;
97cb93a386Sopenharmony_ci            }
98cb93a386Sopenharmony_ci            if (bounds->fTop == before.fTop) {
99cb93a386Sopenharmony_ci                bounds->fTop -= 1;
100cb93a386Sopenharmony_ci            }
101cb93a386Sopenharmony_ci            if (bounds->fRight == before.fRight) {
102cb93a386Sopenharmony_ci                bounds->fRight += 1;
103cb93a386Sopenharmony_ci            }
104cb93a386Sopenharmony_ci            if (bounds->fBottom == before.fBottom) {
105cb93a386Sopenharmony_ci                bounds->fBottom += 1;
106cb93a386Sopenharmony_ci            }
107cb93a386Sopenharmony_ci        }
108cb93a386Sopenharmony_ci    }
109cb93a386Sopenharmony_ci}
110cb93a386Sopenharmony_ci
111cb93a386Sopenharmony_ci} // anonymous namespace
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_cinamespace skgpu::v1 {
114cb93a386Sopenharmony_ci
115cb93a386Sopenharmony_ciusing DoSimplify = GrStyledShape::DoSimplify;
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ciclass AutoCheckFlush {
118cb93a386Sopenharmony_cipublic:
119cb93a386Sopenharmony_ci    AutoCheckFlush(GrDrawingManager* drawingManager) : fDrawingManager(drawingManager) {
120cb93a386Sopenharmony_ci        SkASSERT(fDrawingManager);
121cb93a386Sopenharmony_ci    }
122cb93a386Sopenharmony_ci    ~AutoCheckFlush() { fDrawingManager->flushIfNecessary(); }
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ciprivate:
125cb93a386Sopenharmony_ci    GrDrawingManager* fDrawingManager;
126cb93a386Sopenharmony_ci};
127cb93a386Sopenharmony_ci
128cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(GrRecordingContext* rContext,
129cb93a386Sopenharmony_ci                                                             GrColorType colorType,
130cb93a386Sopenharmony_ci                                                             sk_sp<GrSurfaceProxy> proxy,
131cb93a386Sopenharmony_ci                                                             sk_sp<SkColorSpace> colorSpace,
132cb93a386Sopenharmony_ci                                                             GrSurfaceOrigin origin,
133cb93a386Sopenharmony_ci                                                             const SkSurfaceProps& surfaceProps,
134cb93a386Sopenharmony_ci                                                             bool flushTimeOpsTask) {
135cb93a386Sopenharmony_ci    if (!rContext || !proxy || colorType == GrColorType::kUnknown) {
136cb93a386Sopenharmony_ci        return nullptr;
137cb93a386Sopenharmony_ci    }
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci    const GrBackendFormat& format = proxy->backendFormat();
140cb93a386Sopenharmony_ci    GrSwizzle readSwizzle = rContext->priv().caps()->getReadSwizzle(format, colorType);
141cb93a386Sopenharmony_ci    GrSwizzle writeSwizzle = rContext->priv().caps()->getWriteSwizzle(format, colorType);
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_ci    GrSurfaceProxyView readView (          proxy,  origin, readSwizzle);
144cb93a386Sopenharmony_ci    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    return std::make_unique<SurfaceDrawContext>(rContext,
147cb93a386Sopenharmony_ci                                                std::move(readView),
148cb93a386Sopenharmony_ci                                                std::move(writeView),
149cb93a386Sopenharmony_ci                                                colorType,
150cb93a386Sopenharmony_ci                                                std::move(colorSpace),
151cb93a386Sopenharmony_ci                                                surfaceProps,
152cb93a386Sopenharmony_ci                                                flushTimeOpsTask);
153cb93a386Sopenharmony_ci}
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(
156cb93a386Sopenharmony_ci        GrRecordingContext* rContext,
157cb93a386Sopenharmony_ci        sk_sp<SkColorSpace> colorSpace,
158cb93a386Sopenharmony_ci        SkBackingFit fit,
159cb93a386Sopenharmony_ci        SkISize dimensions,
160cb93a386Sopenharmony_ci        const GrBackendFormat& format,
161cb93a386Sopenharmony_ci        int sampleCnt,
162cb93a386Sopenharmony_ci        GrMipmapped mipMapped,
163cb93a386Sopenharmony_ci        GrProtected isProtected,
164cb93a386Sopenharmony_ci        GrSwizzle readSwizzle,
165cb93a386Sopenharmony_ci        GrSwizzle writeSwizzle,
166cb93a386Sopenharmony_ci        GrSurfaceOrigin origin,
167cb93a386Sopenharmony_ci        SkBudgeted budgeted,
168cb93a386Sopenharmony_ci        const SkSurfaceProps& surfaceProps) {
169cb93a386Sopenharmony_ci    // It is probably not necessary to check if the context is abandoned here since uses of the
170cb93a386Sopenharmony_ci    // SurfaceDrawContext which need the context will mostly likely fail later on without an
171cb93a386Sopenharmony_ci    // issue. However having this hear adds some reassurance in case there is a path doesn't handle
172cb93a386Sopenharmony_ci    // an abandoned context correctly. It also lets us early out of some extra work.
173cb93a386Sopenharmony_ci    if (rContext->abandoned()) {
174cb93a386Sopenharmony_ci        return nullptr;
175cb93a386Sopenharmony_ci    }
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy = rContext->priv().proxyProvider()->createProxy(
178cb93a386Sopenharmony_ci            format,
179cb93a386Sopenharmony_ci            dimensions,
180cb93a386Sopenharmony_ci            GrRenderable::kYes,
181cb93a386Sopenharmony_ci            sampleCnt,
182cb93a386Sopenharmony_ci            mipMapped,
183cb93a386Sopenharmony_ci            fit,
184cb93a386Sopenharmony_ci            budgeted,
185cb93a386Sopenharmony_ci            isProtected);
186cb93a386Sopenharmony_ci    if (!proxy) {
187cb93a386Sopenharmony_ci        return nullptr;
188cb93a386Sopenharmony_ci    }
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci    GrSurfaceProxyView readView (           proxy, origin,  readSwizzle);
191cb93a386Sopenharmony_ci    GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle);
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ci    auto sdc = std::make_unique<SurfaceDrawContext>(rContext,
194cb93a386Sopenharmony_ci                                                    std::move(readView),
195cb93a386Sopenharmony_ci                                                    std::move(writeView),
196cb93a386Sopenharmony_ci                                                    GrColorType::kUnknown,
197cb93a386Sopenharmony_ci                                                    std::move(colorSpace),
198cb93a386Sopenharmony_ci                                                    surfaceProps);
199cb93a386Sopenharmony_ci    sdc->discard();
200cb93a386Sopenharmony_ci    return sdc;
201cb93a386Sopenharmony_ci}
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::Make(
204cb93a386Sopenharmony_ci        GrRecordingContext* rContext,
205cb93a386Sopenharmony_ci        GrColorType colorType,
206cb93a386Sopenharmony_ci        sk_sp<SkColorSpace> colorSpace,
207cb93a386Sopenharmony_ci        SkBackingFit fit,
208cb93a386Sopenharmony_ci        SkISize dimensions,
209cb93a386Sopenharmony_ci        const SkSurfaceProps& surfaceProps,
210cb93a386Sopenharmony_ci        int sampleCnt,
211cb93a386Sopenharmony_ci        GrMipmapped mipMapped,
212cb93a386Sopenharmony_ci        GrProtected isProtected,
213cb93a386Sopenharmony_ci        GrSurfaceOrigin origin,
214cb93a386Sopenharmony_ci        SkBudgeted budgeted) {
215cb93a386Sopenharmony_ci    if (!rContext) {
216cb93a386Sopenharmony_ci        return nullptr;
217cb93a386Sopenharmony_ci    }
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci    auto format = rContext->priv().caps()->getDefaultBackendFormat(colorType, GrRenderable::kYes);
220cb93a386Sopenharmony_ci    if (!format.isValid()) {
221cb93a386Sopenharmony_ci        return nullptr;
222cb93a386Sopenharmony_ci    }
223cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy = rContext->priv().proxyProvider()->createProxy(format,
224cb93a386Sopenharmony_ci                                                                                dimensions,
225cb93a386Sopenharmony_ci                                                                                GrRenderable::kYes,
226cb93a386Sopenharmony_ci                                                                                sampleCnt,
227cb93a386Sopenharmony_ci                                                                                mipMapped,
228cb93a386Sopenharmony_ci                                                                                fit,
229cb93a386Sopenharmony_ci                                                                                budgeted,
230cb93a386Sopenharmony_ci                                                                                isProtected);
231cb93a386Sopenharmony_ci    if (!proxy) {
232cb93a386Sopenharmony_ci        return nullptr;
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    return SurfaceDrawContext::Make(rContext,
236cb93a386Sopenharmony_ci                                    colorType,
237cb93a386Sopenharmony_ci                                    std::move(proxy),
238cb93a386Sopenharmony_ci                                    std::move(colorSpace),
239cb93a386Sopenharmony_ci                                    origin,
240cb93a386Sopenharmony_ci                                    surfaceProps);
241cb93a386Sopenharmony_ci}
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::MakeWithFallback(
244cb93a386Sopenharmony_ci        GrRecordingContext* rContext,
245cb93a386Sopenharmony_ci        GrColorType colorType,
246cb93a386Sopenharmony_ci        sk_sp<SkColorSpace> colorSpace,
247cb93a386Sopenharmony_ci        SkBackingFit fit,
248cb93a386Sopenharmony_ci        SkISize dimensions,
249cb93a386Sopenharmony_ci        const SkSurfaceProps& surfaceProps,
250cb93a386Sopenharmony_ci        int sampleCnt,
251cb93a386Sopenharmony_ci        GrMipmapped mipMapped,
252cb93a386Sopenharmony_ci        GrProtected isProtected,
253cb93a386Sopenharmony_ci        GrSurfaceOrigin origin,
254cb93a386Sopenharmony_ci        SkBudgeted budgeted) {
255cb93a386Sopenharmony_ci    const GrCaps* caps = rContext->priv().caps();
256cb93a386Sopenharmony_ci    auto [ct, _] = caps->getFallbackColorTypeAndFormat(colorType, sampleCnt);
257cb93a386Sopenharmony_ci    if (ct == GrColorType::kUnknown) {
258cb93a386Sopenharmony_ci        return nullptr;
259cb93a386Sopenharmony_ci    }
260cb93a386Sopenharmony_ci    return SurfaceDrawContext::Make(rContext, ct, colorSpace, fit, dimensions, surfaceProps,
261cb93a386Sopenharmony_ci                                    sampleCnt, mipMapped, isProtected, origin, budgeted);
262cb93a386Sopenharmony_ci}
263cb93a386Sopenharmony_ci
264cb93a386Sopenharmony_cistd::unique_ptr<SurfaceDrawContext> SurfaceDrawContext::MakeFromBackendTexture(
265cb93a386Sopenharmony_ci        GrRecordingContext* rContext,
266cb93a386Sopenharmony_ci        GrColorType colorType,
267cb93a386Sopenharmony_ci        sk_sp<SkColorSpace> colorSpace,
268cb93a386Sopenharmony_ci        const GrBackendTexture& tex,
269cb93a386Sopenharmony_ci        int sampleCnt,
270cb93a386Sopenharmony_ci        GrSurfaceOrigin origin,
271cb93a386Sopenharmony_ci        const SkSurfaceProps& surfaceProps,
272cb93a386Sopenharmony_ci        sk_sp<GrRefCntedCallback> releaseHelper) {
273cb93a386Sopenharmony_ci    SkASSERT(sampleCnt > 0);
274cb93a386Sopenharmony_ci    sk_sp<GrTextureProxy> proxy(rContext->priv().proxyProvider()->wrapRenderableBackendTexture(
275cb93a386Sopenharmony_ci            tex, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo,
276cb93a386Sopenharmony_ci            std::move(releaseHelper)));
277cb93a386Sopenharmony_ci    if (!proxy) {
278cb93a386Sopenharmony_ci        return nullptr;
279cb93a386Sopenharmony_ci    }
280cb93a386Sopenharmony_ci
281cb93a386Sopenharmony_ci    return SurfaceDrawContext::Make(rContext, colorType, std::move(proxy), std::move(colorSpace),
282cb93a386Sopenharmony_ci                                    origin, surfaceProps);
283cb93a386Sopenharmony_ci}
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci// In MDB mode the reffing of the 'getLastOpsTask' call's result allows in-progress
286cb93a386Sopenharmony_ci// OpsTask to be picked up and added to by SurfaceDrawContexts lower in the call
287cb93a386Sopenharmony_ci// stack. When this occurs with a closed OpsTask, a new one will be allocated
288cb93a386Sopenharmony_ci// when the surfaceDrawContext attempts to use it (via getOpsTask).
289cb93a386Sopenharmony_ciSurfaceDrawContext::SurfaceDrawContext(GrRecordingContext* rContext,
290cb93a386Sopenharmony_ci                                       GrSurfaceProxyView readView,
291cb93a386Sopenharmony_ci                                       GrSurfaceProxyView writeView,
292cb93a386Sopenharmony_ci                                       GrColorType colorType,
293cb93a386Sopenharmony_ci                                       sk_sp<SkColorSpace> colorSpace,
294cb93a386Sopenharmony_ci                                       const SkSurfaceProps& surfaceProps,
295cb93a386Sopenharmony_ci                                       bool flushTimeOpsTask)
296cb93a386Sopenharmony_ci        : SurfaceFillContext(rContext,
297cb93a386Sopenharmony_ci                             std::move(readView),
298cb93a386Sopenharmony_ci                             std::move(writeView),
299cb93a386Sopenharmony_ci                             {colorType, kPremul_SkAlphaType, std::move(colorSpace)},
300cb93a386Sopenharmony_ci                             flushTimeOpsTask)
301cb93a386Sopenharmony_ci        , fSurfaceProps(surfaceProps)
302cb93a386Sopenharmony_ci        , fCanUseDynamicMSAA(
303cb93a386Sopenharmony_ci                (fSurfaceProps.flags() & SkSurfaceProps::kDynamicMSAA_Flag) &&
304cb93a386Sopenharmony_ci                rContext->priv().caps()->supportsDynamicMSAA(this->asRenderTargetProxy()))
305cb93a386Sopenharmony_ci        , fGlyphPainter(*this) {
306cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
307cb93a386Sopenharmony_ci}
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ciSurfaceDrawContext::~SurfaceDrawContext() {
310cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
311cb93a386Sopenharmony_ci}
312cb93a386Sopenharmony_ci
313cb93a386Sopenharmony_civoid SurfaceDrawContext::willReplaceOpsTask(OpsTask* prevTask, OpsTask* nextTask) {
314cb93a386Sopenharmony_ci    if (prevTask && fNeedsStencil) {
315cb93a386Sopenharmony_ci        // Store the stencil values in memory upon completion of fOpsTask.
316cb93a386Sopenharmony_ci        prevTask->setMustPreserveStencil();
317cb93a386Sopenharmony_ci        // Reload the stencil buffer content at the beginning of newOpsTask.
318cb93a386Sopenharmony_ci        // FIXME: Could the topo sort insert a task between these two that modifies the stencil
319cb93a386Sopenharmony_ci        // values?
320cb93a386Sopenharmony_ci        nextTask->setInitialStencilContent(OpsTask::StencilContent::kPreserved);
321cb93a386Sopenharmony_ci    }
322cb93a386Sopenharmony_ci#if GR_GPU_STATS && GR_TEST_UTILS
323cb93a386Sopenharmony_ci    if (fCanUseDynamicMSAA) {
324cb93a386Sopenharmony_ci        fContext->priv().dmsaaStats().fNumRenderPasses++;
325cb93a386Sopenharmony_ci    }
326cb93a386Sopenharmony_ci#endif
327cb93a386Sopenharmony_ci}
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_civoid SurfaceDrawContext::drawGlyphRunListNoCache(const GrClip* clip,
330cb93a386Sopenharmony_ci                                                 const SkMatrixProvider& viewMatrix,
331cb93a386Sopenharmony_ci                                                 const SkGlyphRunList& glyphRunList,
332cb93a386Sopenharmony_ci                                                 const SkPaint& paint) {
333cb93a386Sopenharmony_ci    GrSDFTControl control =
334cb93a386Sopenharmony_ci            fContext->priv().getSDFTControl(fSurfaceProps.isUseDeviceIndependentFonts());
335cb93a386Sopenharmony_ci    const SkPoint drawOrigin = glyphRunList.origin();
336cb93a386Sopenharmony_ci    SkMatrix drawMatrix = viewMatrix.localToDevice();
337cb93a386Sopenharmony_ci    drawMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
338cb93a386Sopenharmony_ci    GrSubRunAllocator* const alloc = this->subRunAlloc();
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci    GrSubRunNoCachePainter painter{this, alloc, clip, viewMatrix, glyphRunList, paint};
341cb93a386Sopenharmony_ci    for (auto& glyphRun : glyphRunList) {
342cb93a386Sopenharmony_ci        // Make and add the text ops.
343cb93a386Sopenharmony_ci        fGlyphPainter.processGlyphRun(glyphRun,
344cb93a386Sopenharmony_ci                                      drawMatrix,
345cb93a386Sopenharmony_ci                                      paint,
346cb93a386Sopenharmony_ci                                      control,
347cb93a386Sopenharmony_ci                                      &painter);
348cb93a386Sopenharmony_ci    }
349cb93a386Sopenharmony_ci}
350cb93a386Sopenharmony_ci
351cb93a386Sopenharmony_civoid SurfaceDrawContext::drawGlyphRunListWithCache(const GrClip* clip,
352cb93a386Sopenharmony_ci                                                   const SkMatrixProvider& viewMatrix,
353cb93a386Sopenharmony_ci                                                   const SkGlyphRunList& glyphRunList,
354cb93a386Sopenharmony_ci                                                   const SkPaint& paint) {
355cb93a386Sopenharmony_ci    SkMatrix drawMatrix(viewMatrix.localToDevice());
356cb93a386Sopenharmony_ci    drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci    GrSDFTControl control =
359cb93a386Sopenharmony_ci            this->recordingContext()->priv().getSDFTControl(
360cb93a386Sopenharmony_ci                    this->surfaceProps().isUseDeviceIndependentFonts());
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ci    auto [canCache, key] = GrTextBlob::Key::Make(glyphRunList,
363cb93a386Sopenharmony_ci                                                 paint,
364cb93a386Sopenharmony_ci                                                 fSurfaceProps,
365cb93a386Sopenharmony_ci                                                 this->colorInfo(),
366cb93a386Sopenharmony_ci                                                 drawMatrix,
367cb93a386Sopenharmony_ci                                                 control);
368cb93a386Sopenharmony_ci
369cb93a386Sopenharmony_ci    sk_sp<GrTextBlob> blob;
370cb93a386Sopenharmony_ci    GrTextBlobCache* textBlobCache = fContext->priv().getTextBlobCache();
371cb93a386Sopenharmony_ci    if (canCache) {
372cb93a386Sopenharmony_ci        blob = textBlobCache->find(key);
373cb93a386Sopenharmony_ci    }
374cb93a386Sopenharmony_ci
375cb93a386Sopenharmony_ci    if (blob == nullptr || !blob->canReuse(paint, drawMatrix)) {
376cb93a386Sopenharmony_ci        if (blob != nullptr) {
377cb93a386Sopenharmony_ci            // We have to remake the blob because changes may invalidate our masks.
378cb93a386Sopenharmony_ci            // TODO we could probably get away with reuse most of the time if the pointer is unique,
379cb93a386Sopenharmony_ci            //      but we'd have to clear the SubRun information
380cb93a386Sopenharmony_ci            textBlobCache->remove(blob.get());
381cb93a386Sopenharmony_ci        }
382cb93a386Sopenharmony_ci
383cb93a386Sopenharmony_ci        blob = GrTextBlob::Make(glyphRunList, paint, drawMatrix, control, &fGlyphPainter);
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci        if (canCache) {
386cb93a386Sopenharmony_ci            blob->addKey(key);
387cb93a386Sopenharmony_ci            // The blob may already have been created on a different thread. Use the first one
388cb93a386Sopenharmony_ci            // that was there.
389cb93a386Sopenharmony_ci            blob = textBlobCache->addOrReturnExisting(glyphRunList, blob);
390cb93a386Sopenharmony_ci        }
391cb93a386Sopenharmony_ci    }
392cb93a386Sopenharmony_ci
393cb93a386Sopenharmony_ci    for (const GrSubRun& subRun : blob->subRunList()) {
394cb93a386Sopenharmony_ci        subRun.draw(clip, viewMatrix, glyphRunList, paint, this);
395cb93a386Sopenharmony_ci    }
396cb93a386Sopenharmony_ci}
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci// choose to use the GrTextBlob cache or not.
399cb93a386Sopenharmony_cibool gGrDrawTextNoCache = false;
400cb93a386Sopenharmony_civoid SurfaceDrawContext::drawGlyphRunList(const GrClip* clip,
401cb93a386Sopenharmony_ci                                          const SkMatrixProvider& viewMatrix,
402cb93a386Sopenharmony_ci                                          const SkGlyphRunList& glyphRunList,
403cb93a386Sopenharmony_ci                                          const SkPaint& paint) {
404cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
405cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
406cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
407cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawGlyphRunList", fContext);
408cb93a386Sopenharmony_ci
409cb93a386Sopenharmony_ci    // Drawing text can cause us to do inline uploads. This is not supported for wrapped vulkan
410cb93a386Sopenharmony_ci    // secondary command buffers because it would require stopping and starting a render pass which
411cb93a386Sopenharmony_ci    // we don't have access to.
412cb93a386Sopenharmony_ci    if (this->wrapsVkSecondaryCB()) {
413cb93a386Sopenharmony_ci        return;
414cb93a386Sopenharmony_ci    }
415cb93a386Sopenharmony_ci
416cb93a386Sopenharmony_ci    if (gGrDrawTextNoCache || glyphRunList.blob() == nullptr) {
417cb93a386Sopenharmony_ci        // If the glyphRunList does not have an associated text blob, then it was created by one of
418cb93a386Sopenharmony_ci        // the direct draw APIs (drawGlyphs, etc.). There is no need to create a GrTextBlob just
419cb93a386Sopenharmony_ci        // build the sub run directly and place it in the op.
420cb93a386Sopenharmony_ci        this->drawGlyphRunListNoCache(clip, viewMatrix, glyphRunList, paint);
421cb93a386Sopenharmony_ci    } else {
422cb93a386Sopenharmony_ci        this->drawGlyphRunListWithCache(clip, viewMatrix, glyphRunList, paint);
423cb93a386Sopenharmony_ci    }
424cb93a386Sopenharmony_ci}
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_civoid SurfaceDrawContext::drawPaint(const GrClip* clip,
427cb93a386Sopenharmony_ci                                   GrPaint&& paint,
428cb93a386Sopenharmony_ci                                   const SkMatrix& viewMatrix) {
429cb93a386Sopenharmony_ci    // Start with the render target, since that is the maximum content we could possibly fill.
430cb93a386Sopenharmony_ci    // drawFilledQuad() will automatically restrict it to clip bounds for us if possible.
431cb93a386Sopenharmony_ci    if (!paint.numTotalFragmentProcessors()) {
432cb93a386Sopenharmony_ci        // The paint is trivial so we won't need to use local coordinates, so skip calculating the
433cb93a386Sopenharmony_ci        // inverse view matrix.
434cb93a386Sopenharmony_ci        SkRect r = this->asSurfaceProxy()->getBoundsRect();
435cb93a386Sopenharmony_ci        this->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), r, r);
436cb93a386Sopenharmony_ci    } else {
437cb93a386Sopenharmony_ci        // Use the inverse view matrix to arrive at appropriate local coordinates for the paint.
438cb93a386Sopenharmony_ci        SkMatrix localMatrix;
439cb93a386Sopenharmony_ci        if (!viewMatrix.invert(&localMatrix)) {
440cb93a386Sopenharmony_ci            return;
441cb93a386Sopenharmony_ci        }
442cb93a386Sopenharmony_ci        SkIRect bounds = SkIRect::MakeSize(this->asSurfaceProxy()->dimensions());
443cb93a386Sopenharmony_ci        this->fillPixelsWithLocalMatrix(clip, std::move(paint), bounds, localMatrix);
444cb93a386Sopenharmony_ci    }
445cb93a386Sopenharmony_ci}
446cb93a386Sopenharmony_ci
447cb93a386Sopenharmony_cienum class SurfaceDrawContext::QuadOptimization {
448cb93a386Sopenharmony_ci    // The rect to draw doesn't intersect clip or render target, so no draw op should be added
449cb93a386Sopenharmony_ci    kDiscarded,
450cb93a386Sopenharmony_ci    // The rect to draw was converted to some other op and appended to the oplist, so no additional
451cb93a386Sopenharmony_ci    // op is necessary. Currently this can convert it to a clear op or a rrect op. Only valid if
452cb93a386Sopenharmony_ci    // a constColor is provided.
453cb93a386Sopenharmony_ci    kSubmitted,
454cb93a386Sopenharmony_ci    // The clip was folded into the device quad, with updated edge flags and local coords, and
455cb93a386Sopenharmony_ci    // caller is responsible for adding an appropriate op.
456cb93a386Sopenharmony_ci    kClipApplied,
457cb93a386Sopenharmony_ci    // No change to clip, but quad updated to better fit clip/render target, and caller is
458cb93a386Sopenharmony_ci    // responsible for adding an appropriate op.
459cb93a386Sopenharmony_ci    kCropped
460cb93a386Sopenharmony_ci};
461cb93a386Sopenharmony_ci
462cb93a386Sopenharmony_ciSurfaceDrawContext::QuadOptimization SurfaceDrawContext::attemptQuadOptimization(
463cb93a386Sopenharmony_ci        const GrClip* clip, const GrUserStencilSettings* stencilSettings, GrAA* aa, DrawQuad* quad,
464cb93a386Sopenharmony_ci        GrPaint* paint) {
465cb93a386Sopenharmony_ci    // Optimization requirements:
466cb93a386Sopenharmony_ci    // 1. kDiscard applies when clip bounds and quad bounds do not intersect
467cb93a386Sopenharmony_ci    // 2a. kSubmitted applies when constColor and final geom is pixel aligned rect;
468cb93a386Sopenharmony_ci    //       pixel aligned rect requires rect clip and (rect quad or quad covers clip) OR
469cb93a386Sopenharmony_ci    // 2b. kSubmitted applies when constColor and rrect clip and quad covers clip
470cb93a386Sopenharmony_ci    // 4. kClipApplied applies when rect clip and (rect quad or quad covers clip)
471cb93a386Sopenharmony_ci    // 5. kCropped in all other scenarios (although a crop may be a no-op)
472cb93a386Sopenharmony_ci    const SkPMColor4f* constColor = nullptr;
473cb93a386Sopenharmony_ci    SkPMColor4f paintColor;
474cb93a386Sopenharmony_ci    if (!stencilSettings && paint && !paint->hasCoverageFragmentProcessor() &&
475cb93a386Sopenharmony_ci        paint->isConstantBlendedColor(&paintColor)) {
476cb93a386Sopenharmony_ci        // Only consider clears/rrects when it's easy to guarantee 100% fill with single color
477cb93a386Sopenharmony_ci        constColor = &paintColor;
478cb93a386Sopenharmony_ci    }
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_ci    // Save the old AA flags since CropToRect will modify 'quad' and if kCropped is returned, it's
481cb93a386Sopenharmony_ci    // better to just keep the old flags instead of introducing mixed edge flags.
482cb93a386Sopenharmony_ci    GrQuadAAFlags oldFlags = quad->fEdgeFlags;
483cb93a386Sopenharmony_ci
484cb93a386Sopenharmony_ci    // Use the logical size of the render target, which allows for "fullscreen" clears even if
485cb93a386Sopenharmony_ci    // the render target has an approximate backing fit
486cb93a386Sopenharmony_ci    SkRect rtRect = this->asSurfaceProxy()->getBoundsRect();
487cb93a386Sopenharmony_ci
488cb93a386Sopenharmony_ci    // For historical reasons, we assume AA for exact bounds checking in IsOutsideClip.
489cb93a386Sopenharmony_ci    // TODO(michaelludwig) - Hopefully that can be revisited when the clipping optimizations are
490cb93a386Sopenharmony_ci    // refactored to work better with round rects and dmsaa.
491cb93a386Sopenharmony_ci    SkRect drawBounds = quad->fDevice.bounds();
492cb93a386Sopenharmony_ci    if (!quad->fDevice.isFinite() || drawBounds.isEmpty() ||
493cb93a386Sopenharmony_ci        GrClip::IsOutsideClip(SkIRect::MakeSize(this->dimensions()), drawBounds, GrAA::kYes)) {
494cb93a386Sopenharmony_ci        return QuadOptimization::kDiscarded;
495cb93a386Sopenharmony_ci    } else if (GrQuadUtils::WillUseHairline(quad->fDevice, GrAAType::kCoverage, quad->fEdgeFlags)) {
496cb93a386Sopenharmony_ci        // Don't try to apply the clip early if we know rendering will use hairline methods, as this
497cb93a386Sopenharmony_ci        // has an effect on the op bounds not otherwise taken into account in this function.
498cb93a386Sopenharmony_ci        return QuadOptimization::kCropped;
499cb93a386Sopenharmony_ci    }
500cb93a386Sopenharmony_ci
501cb93a386Sopenharmony_ci    auto conservativeCrop = [&]() {
502cb93a386Sopenharmony_ci        static constexpr int kLargeDrawLimit = 15000;
503cb93a386Sopenharmony_ci        // Crop the quad to the render target. This doesn't change the visual results of drawing but
504cb93a386Sopenharmony_ci        // is meant to help numerical stability for excessively large draws.
505cb93a386Sopenharmony_ci        if (drawBounds.width() > kLargeDrawLimit || drawBounds.height() > kLargeDrawLimit) {
506cb93a386Sopenharmony_ci            GrQuadUtils::CropToRect(rtRect, *aa, quad, /* compute local */ !constColor);
507cb93a386Sopenharmony_ci        }
508cb93a386Sopenharmony_ci    };
509cb93a386Sopenharmony_ci
510cb93a386Sopenharmony_ci    bool simpleColor = !stencilSettings && constColor;
511cb93a386Sopenharmony_ci    GrClip::PreClipResult result = clip ? clip->preApply(drawBounds, *aa)
512cb93a386Sopenharmony_ci                                        : GrClip::PreClipResult(GrClip::Effect::kUnclipped);
513cb93a386Sopenharmony_ci    switch(result.fEffect) {
514cb93a386Sopenharmony_ci        case GrClip::Effect::kClippedOut:
515cb93a386Sopenharmony_ci            return QuadOptimization::kDiscarded;
516cb93a386Sopenharmony_ci        case GrClip::Effect::kUnclipped:
517cb93a386Sopenharmony_ci            if (!simpleColor) {
518cb93a386Sopenharmony_ci                conservativeCrop();
519cb93a386Sopenharmony_ci                return QuadOptimization::kClipApplied;
520cb93a386Sopenharmony_ci            } else {
521cb93a386Sopenharmony_ci                // Update result to store the render target bounds in order and then fall
522cb93a386Sopenharmony_ci                // through to attempt the draw->native clear optimization
523cb93a386Sopenharmony_ci                result = GrClip::PreClipResult(SkRRect::MakeRect(rtRect), *aa);
524cb93a386Sopenharmony_ci            }
525cb93a386Sopenharmony_ci            break;
526cb93a386Sopenharmony_ci        case GrClip::Effect::kClipped:
527cb93a386Sopenharmony_ci            if (!result.fIsRRect || (stencilSettings && result.fAA != *aa) ||
528cb93a386Sopenharmony_ci                (!result.fRRect.isRect() && !simpleColor)) {
529cb93a386Sopenharmony_ci                // The clip and draw state are too complicated to try and reduce
530cb93a386Sopenharmony_ci                conservativeCrop();
531cb93a386Sopenharmony_ci                return QuadOptimization::kCropped;
532cb93a386Sopenharmony_ci            } // Else fall through to attempt to combine the draw and clip geometry together
533cb93a386Sopenharmony_ci            break;
534cb93a386Sopenharmony_ci        default:
535cb93a386Sopenharmony_ci            SkUNREACHABLE;
536cb93a386Sopenharmony_ci    }
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_ci    // If we reached here, we know we're an axis-aligned clip that is either a rect or a round rect,
539cb93a386Sopenharmony_ci    // so we can potentially combine it with the draw geometry so that no clipping is needed.
540cb93a386Sopenharmony_ci    SkASSERT(result.fEffect == GrClip::Effect::kClipped && result.fIsRRect);
541cb93a386Sopenharmony_ci    SkRect clippedBounds = result.fRRect.getBounds();
542cb93a386Sopenharmony_ci    clippedBounds.intersect(rtRect);
543cb93a386Sopenharmony_ci    if (!drawBounds.intersect(clippedBounds)) {
544cb93a386Sopenharmony_ci        // Our fractional bounds aren't actually inside the clip. GrClip::preApply() can sometimes
545cb93a386Sopenharmony_ci        // think in terms of rounded-out bounds. Discard the draw.
546cb93a386Sopenharmony_ci        return QuadOptimization::kDiscarded;
547cb93a386Sopenharmony_ci    }
548cb93a386Sopenharmony_ci    // Guard against the clipped draw turning into a hairline draw after intersection
549cb93a386Sopenharmony_ci    if (drawBounds.width() < 1.f || drawBounds.height() < 1.f) {
550cb93a386Sopenharmony_ci        return QuadOptimization::kCropped;
551cb93a386Sopenharmony_ci    }
552cb93a386Sopenharmony_ci
553cb93a386Sopenharmony_ci    if (result.fRRect.isRect()) {
554cb93a386Sopenharmony_ci        // No rounded corners, so we might be able to become a native clear or we might be able to
555cb93a386Sopenharmony_ci        // modify geometry and edge flags to represent intersected shape of clip and draw.
556cb93a386Sopenharmony_ci        if (GrQuadUtils::CropToRect(clippedBounds, result.fAA, quad,
557cb93a386Sopenharmony_ci                                    /*compute local*/ !constColor)) {
558cb93a386Sopenharmony_ci            if (simpleColor && quad->fDevice.quadType() == GrQuad::Type::kAxisAligned) {
559cb93a386Sopenharmony_ci                // Clear optimization is possible
560cb93a386Sopenharmony_ci                drawBounds = quad->fDevice.bounds();
561cb93a386Sopenharmony_ci                if (drawBounds.contains(rtRect)) {
562cb93a386Sopenharmony_ci                    // Fullscreen clear
563cb93a386Sopenharmony_ci                    this->clear(*constColor);
564cb93a386Sopenharmony_ci                    return QuadOptimization::kSubmitted;
565cb93a386Sopenharmony_ci                } else if (GrClip::IsPixelAligned(drawBounds) &&
566cb93a386Sopenharmony_ci                           drawBounds.width() > 256 && drawBounds.height() > 256) {
567cb93a386Sopenharmony_ci                    // Scissor + clear (round shouldn't do anything since we are pixel aligned)
568cb93a386Sopenharmony_ci                    SkIRect scissorRect;
569cb93a386Sopenharmony_ci                    drawBounds.round(&scissorRect);
570cb93a386Sopenharmony_ci                    this->clear(scissorRect, *constColor);
571cb93a386Sopenharmony_ci                    return QuadOptimization::kSubmitted;
572cb93a386Sopenharmony_ci                }
573cb93a386Sopenharmony_ci            }
574cb93a386Sopenharmony_ci
575cb93a386Sopenharmony_ci            // else the draw and clip were combined so just update the AA to reflect combination
576cb93a386Sopenharmony_ci            if (*aa == GrAA::kNo && result.fAA == GrAA::kYes &&
577cb93a386Sopenharmony_ci                quad->fEdgeFlags != GrQuadAAFlags::kNone) {
578cb93a386Sopenharmony_ci                // The clip was anti-aliased and now the draw needs to be upgraded to AA to
579cb93a386Sopenharmony_ci                // properly reflect the smooth edge of the clip.
580cb93a386Sopenharmony_ci                *aa = GrAA::kYes;
581cb93a386Sopenharmony_ci            }
582cb93a386Sopenharmony_ci            // We intentionally do not downgrade AA here because we don't know if we need to
583cb93a386Sopenharmony_ci            // preserve MSAA (see GrQuadAAFlags docs). But later in the pipeline, the ops can
584cb93a386Sopenharmony_ci            // use GrResolveAATypeForQuad() to turn off coverage AA when all flags are off.
585cb93a386Sopenharmony_ci            // deviceQuad is exactly the intersection of original quad and clip, so it can be
586cb93a386Sopenharmony_ci            // drawn with no clip (submitted by caller)
587cb93a386Sopenharmony_ci            return QuadOptimization::kClipApplied;
588cb93a386Sopenharmony_ci        }
589cb93a386Sopenharmony_ci    } else {
590cb93a386Sopenharmony_ci        // Rounded corners and constant filled color (limit ourselves to solid colors because
591cb93a386Sopenharmony_ci        // there is no way to use custom local coordinates with drawRRect).
592cb93a386Sopenharmony_ci        SkASSERT(simpleColor);
593cb93a386Sopenharmony_ci        if (GrQuadUtils::CropToRect(clippedBounds, result.fAA, quad,
594cb93a386Sopenharmony_ci                                    /* compute local */ false) &&
595cb93a386Sopenharmony_ci            quad->fDevice.quadType() == GrQuad::Type::kAxisAligned &&
596cb93a386Sopenharmony_ci            quad->fDevice.bounds().contains(clippedBounds)) {
597cb93a386Sopenharmony_ci            // Since the cropped quad became a rectangle which covered the bounds of the rrect,
598cb93a386Sopenharmony_ci            // we can draw the rrect directly and ignore the edge flags
599cb93a386Sopenharmony_ci            this->drawRRect(nullptr, std::move(*paint), result.fAA, SkMatrix::I(), result.fRRect,
600cb93a386Sopenharmony_ci                            GrStyle::SimpleFill());
601cb93a386Sopenharmony_ci            return QuadOptimization::kSubmitted;
602cb93a386Sopenharmony_ci        }
603cb93a386Sopenharmony_ci    }
604cb93a386Sopenharmony_ci
605cb93a386Sopenharmony_ci    // The quads have been updated to better fit the clip bounds, but can't get rid of
606cb93a386Sopenharmony_ci    // the clip entirely
607cb93a386Sopenharmony_ci    quad->fEdgeFlags = oldFlags;
608cb93a386Sopenharmony_ci    return QuadOptimization::kCropped;
609cb93a386Sopenharmony_ci}
610cb93a386Sopenharmony_ci
611cb93a386Sopenharmony_civoid SurfaceDrawContext::drawFilledQuad(const GrClip* clip,
612cb93a386Sopenharmony_ci                                        GrPaint&& paint,
613cb93a386Sopenharmony_ci                                        GrAA aa,
614cb93a386Sopenharmony_ci                                        DrawQuad* quad,
615cb93a386Sopenharmony_ci                                        const GrUserStencilSettings* ss) {
616cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
617cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
618cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
619cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFilledQuad", fContext);
620cb93a386Sopenharmony_ci
621cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
622cb93a386Sopenharmony_ci
623cb93a386Sopenharmony_ci    QuadOptimization opt = this->attemptQuadOptimization(clip, ss, &aa, quad, &paint);
624cb93a386Sopenharmony_ci    if (opt >= QuadOptimization::kClipApplied) {
625cb93a386Sopenharmony_ci        // These optimizations require caller to add an op themselves
626cb93a386Sopenharmony_ci        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
627cb93a386Sopenharmony_ci        GrAAType aaType;
628cb93a386Sopenharmony_ci        if (ss) {
629cb93a386Sopenharmony_ci            aaType = (aa == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone;
630cb93a386Sopenharmony_ci        } else if (fCanUseDynamicMSAA && aa == GrAA::kNo) {
631cb93a386Sopenharmony_ci            // The SkGpuDevice ensures GrAA is always kYes when using dmsaa. If the caller calls
632cb93a386Sopenharmony_ci            // into here with GrAA::kNo, trust that they know what they're doing and that the
633cb93a386Sopenharmony_ci            // rendering will be equal with or without msaa.
634cb93a386Sopenharmony_ci            aaType = GrAAType::kNone;
635cb93a386Sopenharmony_ci        } else {
636cb93a386Sopenharmony_ci            aaType = this->chooseAAType(aa);
637cb93a386Sopenharmony_ci        }
638cb93a386Sopenharmony_ci        this->addDrawOp(finalClip, FillRectOp::Make(fContext, std::move(paint), aaType,
639cb93a386Sopenharmony_ci                                                    quad, ss));
640cb93a386Sopenharmony_ci    }
641cb93a386Sopenharmony_ci    // All other optimization levels were completely handled inside attempt(), so no extra op needed
642cb93a386Sopenharmony_ci}
643cb93a386Sopenharmony_ci
644cb93a386Sopenharmony_civoid SurfaceDrawContext::drawTexture(const GrClip* clip,
645cb93a386Sopenharmony_ci                                     GrSurfaceProxyView view,
646cb93a386Sopenharmony_ci                                     SkAlphaType srcAlphaType,
647cb93a386Sopenharmony_ci                                     GrSamplerState::Filter filter,
648cb93a386Sopenharmony_ci                                     GrSamplerState::MipmapMode mm,
649cb93a386Sopenharmony_ci                                     SkBlendMode blendMode,
650cb93a386Sopenharmony_ci                                     const SkPMColor4f& color,
651cb93a386Sopenharmony_ci                                     const SkRect& srcRect,
652cb93a386Sopenharmony_ci                                     const SkRect& dstRect,
653cb93a386Sopenharmony_ci                                     GrAA aa,
654cb93a386Sopenharmony_ci                                     GrQuadAAFlags edgeAA,
655cb93a386Sopenharmony_ci                                     SkCanvas::SrcRectConstraint constraint,
656cb93a386Sopenharmony_ci                                     const SkMatrix& viewMatrix,
657cb93a386Sopenharmony_ci                                     sk_sp<GrColorSpaceXform> colorSpaceXform) {
658cb93a386Sopenharmony_ci    // If we are using dmsaa then go through FillRRectOp (via fillRectToRect).
659cb93a386Sopenharmony_ci    if ((this->alwaysAntialias() || this->caps()->reducedShaderMode()) && aa == GrAA::kYes) {
660cb93a386Sopenharmony_ci        GrPaint paint;
661cb93a386Sopenharmony_ci        paint.setColor4f(color);
662cb93a386Sopenharmony_ci        std::unique_ptr<GrFragmentProcessor> fp;
663cb93a386Sopenharmony_ci        if (constraint == SkCanvas::kStrict_SrcRectConstraint) {
664cb93a386Sopenharmony_ci            fp = GrTextureEffect::MakeSubset(view, srcAlphaType, SkMatrix::I(),
665cb93a386Sopenharmony_ci                                             GrSamplerState(filter, mm), srcRect,
666cb93a386Sopenharmony_ci                                             *this->caps());
667cb93a386Sopenharmony_ci        } else {
668cb93a386Sopenharmony_ci            fp = GrTextureEffect::Make(view, srcAlphaType, SkMatrix::I(), filter, mm);
669cb93a386Sopenharmony_ci        }
670cb93a386Sopenharmony_ci        if (colorSpaceXform) {
671cb93a386Sopenharmony_ci            fp = GrColorSpaceXformEffect::Make(std::move(fp), std::move(colorSpaceXform));
672cb93a386Sopenharmony_ci        }
673cb93a386Sopenharmony_ci        fp = GrBlendFragmentProcessor::Make(std::move(fp), nullptr, SkBlendMode::kModulate);
674cb93a386Sopenharmony_ci        paint.setColorFragmentProcessor(std::move(fp));
675cb93a386Sopenharmony_ci        if (blendMode != SkBlendMode::kSrcOver) {
676cb93a386Sopenharmony_ci            paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
677cb93a386Sopenharmony_ci        }
678cb93a386Sopenharmony_ci        this->fillRectToRect(clip, std::move(paint), GrAA::kYes, viewMatrix, dstRect, srcRect);
679cb93a386Sopenharmony_ci        return;
680cb93a386Sopenharmony_ci    }
681cb93a386Sopenharmony_ci
682cb93a386Sopenharmony_ci    const SkRect* subset = constraint == SkCanvas::kStrict_SrcRectConstraint ?
683cb93a386Sopenharmony_ci            &srcRect : nullptr;
684cb93a386Sopenharmony_ci    DrawQuad quad{GrQuad::MakeFromRect(dstRect, viewMatrix), GrQuad(srcRect), edgeAA};
685cb93a386Sopenharmony_ci
686cb93a386Sopenharmony_ci    this->drawTexturedQuad(clip, std::move(view), srcAlphaType, std::move(colorSpaceXform), filter,
687cb93a386Sopenharmony_ci                           mm, color, blendMode, aa, &quad, subset);
688cb93a386Sopenharmony_ci}
689cb93a386Sopenharmony_ci
690cb93a386Sopenharmony_civoid SurfaceDrawContext::drawTexturedQuad(const GrClip* clip,
691cb93a386Sopenharmony_ci                                          GrSurfaceProxyView proxyView,
692cb93a386Sopenharmony_ci                                          SkAlphaType srcAlphaType,
693cb93a386Sopenharmony_ci                                          sk_sp<GrColorSpaceXform> textureXform,
694cb93a386Sopenharmony_ci                                          GrSamplerState::Filter filter,
695cb93a386Sopenharmony_ci                                          GrSamplerState::MipmapMode mm,
696cb93a386Sopenharmony_ci                                          const SkPMColor4f& color,
697cb93a386Sopenharmony_ci                                          SkBlendMode blendMode,
698cb93a386Sopenharmony_ci                                          GrAA aa,
699cb93a386Sopenharmony_ci                                          DrawQuad* quad,
700cb93a386Sopenharmony_ci                                          const SkRect* subset) {
701cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
702cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
703cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
704cb93a386Sopenharmony_ci    SkASSERT(proxyView.asTextureProxy());
705cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawTexturedQuad", fContext);
706cb93a386Sopenharmony_ci
707cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
708cb93a386Sopenharmony_ci
709cb93a386Sopenharmony_ci    // Functionally this is very similar to drawFilledQuad except that there's no constColor to
710cb93a386Sopenharmony_ci    // enable the kSubmitted optimizations, no stencil settings support, and its a TextureOp.
711cb93a386Sopenharmony_ci    QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &aa, quad,
712cb93a386Sopenharmony_ci                                                         nullptr/*paint*/);
713cb93a386Sopenharmony_ci
714cb93a386Sopenharmony_ci    SkASSERT(opt != QuadOptimization::kSubmitted);
715cb93a386Sopenharmony_ci    if (opt != QuadOptimization::kDiscarded) {
716cb93a386Sopenharmony_ci        // And the texture op if not discarded
717cb93a386Sopenharmony_ci        const GrClip* finalClip = opt == QuadOptimization::kClipApplied ? nullptr : clip;
718cb93a386Sopenharmony_ci        GrAAType aaType = this->chooseAAType(aa);
719cb93a386Sopenharmony_ci        auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
720cb93a386Sopenharmony_ci        auto saturate = clampType == GrClampType::kManual ? TextureOp::Saturate::kYes
721cb93a386Sopenharmony_ci                                                          : TextureOp::Saturate::kNo;
722cb93a386Sopenharmony_ci        // Use the provided subset, although hypothetically we could detect that the cropped local
723cb93a386Sopenharmony_ci        // quad is sufficiently inside the subset and the constraint could be dropped.
724cb93a386Sopenharmony_ci        this->addDrawOp(finalClip,
725cb93a386Sopenharmony_ci                        TextureOp::Make(fContext, std::move(proxyView), srcAlphaType,
726cb93a386Sopenharmony_ci                                        std::move(textureXform), filter, mm, color, saturate,
727cb93a386Sopenharmony_ci                                        blendMode, aaType, quad, subset));
728cb93a386Sopenharmony_ci    }
729cb93a386Sopenharmony_ci}
730cb93a386Sopenharmony_ci
731cb93a386Sopenharmony_civoid SurfaceDrawContext::drawRect(const GrClip* clip,
732cb93a386Sopenharmony_ci                                  GrPaint&& paint,
733cb93a386Sopenharmony_ci                                  GrAA aa,
734cb93a386Sopenharmony_ci                                  const SkMatrix& viewMatrix,
735cb93a386Sopenharmony_ci                                  const SkRect& rect,
736cb93a386Sopenharmony_ci                                  const GrStyle* style) {
737cb93a386Sopenharmony_ci    if (!style) {
738cb93a386Sopenharmony_ci        style = &GrStyle::SimpleFill();
739cb93a386Sopenharmony_ci    }
740cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
741cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
742cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
743cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRect", fContext);
744cb93a386Sopenharmony_ci
745cb93a386Sopenharmony_ci    // Path effects should've been devolved to a path in SkGpuDevice
746cb93a386Sopenharmony_ci    SkASSERT(!style->pathEffect());
747cb93a386Sopenharmony_ci
748cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
749cb93a386Sopenharmony_ci
750cb93a386Sopenharmony_ci    const SkStrokeRec& stroke = style->strokeRec();
751cb93a386Sopenharmony_ci    if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
752cb93a386Sopenharmony_ci        // Fills the rect, using rect as its own local coordinates
753cb93a386Sopenharmony_ci        this->fillRectToRect(clip, std::move(paint), aa, viewMatrix, rect, rect);
754cb93a386Sopenharmony_ci        return;
755cb93a386Sopenharmony_ci    } else if ((stroke.getStyle() == SkStrokeRec::kStroke_Style ||
756cb93a386Sopenharmony_ci                stroke.getStyle() == SkStrokeRec::kHairline_Style) &&
757cb93a386Sopenharmony_ci               rect.width()                                        &&
758cb93a386Sopenharmony_ci               rect.height()                                       &&
759cb93a386Sopenharmony_ci               !this->caps()->reducedShaderMode()) {
760cb93a386Sopenharmony_ci        // Only use the StrokeRectOp for non-empty rectangles. Empty rectangles will be processed by
761cb93a386Sopenharmony_ci        // GrStyledShape to handle stroke caps and dashing properly.
762cb93a386Sopenharmony_ci        //
763cb93a386Sopenharmony_ci        // http://skbug.com/12206 -- there is a double-blend issue with the bevel version of
764cb93a386Sopenharmony_ci        // AAStrokeRectOp, and if we increase the AA bloat for MSAA it becomes more pronounced.
765cb93a386Sopenharmony_ci        // Don't use the bevel version with DMSAA.
766cb93a386Sopenharmony_ci        GrAAType aaType = (fCanUseDynamicMSAA &&
767cb93a386Sopenharmony_ci                           stroke.getJoin() == SkPaint::kMiter_Join &&
768cb93a386Sopenharmony_ci                           stroke.getMiter() >= SK_ScalarSqrt2) ? GrAAType::kCoverage
769cb93a386Sopenharmony_ci                                                                : this->chooseAAType(aa);
770cb93a386Sopenharmony_ci        GrOp::Owner op = StrokeRectOp::Make(fContext, std::move(paint), aaType, viewMatrix,
771cb93a386Sopenharmony_ci                                            rect, stroke);
772cb93a386Sopenharmony_ci        // op may be null if the stroke is not supported or if using coverage aa and the view matrix
773cb93a386Sopenharmony_ci        // does not preserve rectangles.
774cb93a386Sopenharmony_ci        if (op) {
775cb93a386Sopenharmony_ci            this->addDrawOp(clip, std::move(op));
776cb93a386Sopenharmony_ci            return;
777cb93a386Sopenharmony_ci        }
778cb93a386Sopenharmony_ci    }
779cb93a386Sopenharmony_ci    assert_alive(paint);
780cb93a386Sopenharmony_ci    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
781cb93a386Sopenharmony_ci                                     GrStyledShape(rect, *style, DoSimplify::kNo));
782cb93a386Sopenharmony_ci}
783cb93a386Sopenharmony_ci
784cb93a386Sopenharmony_civoid SurfaceDrawContext::fillRectToRect(const GrClip* clip,
785cb93a386Sopenharmony_ci                                        GrPaint&& paint,
786cb93a386Sopenharmony_ci                                        GrAA aa,
787cb93a386Sopenharmony_ci                                        const SkMatrix& viewMatrix,
788cb93a386Sopenharmony_ci                                        const SkRect& rectToDraw,
789cb93a386Sopenharmony_ci                                        const SkRect& localRect) {
790cb93a386Sopenharmony_ci    DrawQuad quad{GrQuad::MakeFromRect(rectToDraw, viewMatrix), GrQuad(localRect),
791cb93a386Sopenharmony_ci                  aa == GrAA::kYes ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone};
792cb93a386Sopenharmony_ci
793cb93a386Sopenharmony_ci    // If we are using dmsaa then attempt to draw the rect with FillRRectOp.
794cb93a386Sopenharmony_ci    if ((fContext->priv().caps()->reducedShaderMode() || this->alwaysAntialias()) &&
795cb93a386Sopenharmony_ci        this->caps()->drawInstancedSupport()                                      &&
796cb93a386Sopenharmony_ci        aa == GrAA::kYes) {  // If aa is kNo when using dmsaa, the rect is axis aligned. Don't use
797cb93a386Sopenharmony_ci                             // FillRRectOp because it might require dual source blending.
798cb93a386Sopenharmony_ci                             // http://skbug.com/11756
799cb93a386Sopenharmony_ci        QuadOptimization opt = this->attemptQuadOptimization(clip, nullptr/*stencil*/, &aa, &quad,
800cb93a386Sopenharmony_ci                                                             &paint);
801cb93a386Sopenharmony_ci        if (opt < QuadOptimization::kClipApplied) {
802cb93a386Sopenharmony_ci            // The optimization was completely handled inside attempt().
803cb93a386Sopenharmony_ci            return;
804cb93a386Sopenharmony_ci        }
805cb93a386Sopenharmony_ci
806cb93a386Sopenharmony_ci        SkRect croppedRect, croppedLocal{};
807cb93a386Sopenharmony_ci        const GrClip* optimizedClip = clip;
808cb93a386Sopenharmony_ci        if (clip && viewMatrix.isScaleTranslate() && quad.fDevice.asRect(&croppedRect) &&
809cb93a386Sopenharmony_ci            (!paint.usesLocalCoords() || quad.fLocal.asRect(&croppedLocal))) {
810cb93a386Sopenharmony_ci            // The cropped quad is still a rect, and our view matrix preserves rects. Map it back
811cb93a386Sopenharmony_ci            // to pre-matrix space.
812cb93a386Sopenharmony_ci            SkMatrix inverse;
813cb93a386Sopenharmony_ci            if (!viewMatrix.invert(&inverse)) {
814cb93a386Sopenharmony_ci                return;
815cb93a386Sopenharmony_ci            }
816cb93a386Sopenharmony_ci            SkASSERT(inverse.rectStaysRect());
817cb93a386Sopenharmony_ci            inverse.mapRect(&croppedRect);
818cb93a386Sopenharmony_ci            if (opt == QuadOptimization::kClipApplied) {
819cb93a386Sopenharmony_ci                optimizedClip = nullptr;
820cb93a386Sopenharmony_ci            }
821cb93a386Sopenharmony_ci        } else {
822cb93a386Sopenharmony_ci            // Even if attemptQuadOptimization gave us an optimized quad, FillRRectOp needs a rect
823cb93a386Sopenharmony_ci            // in pre-matrix space, so use the original rect. Also preserve the original clip.
824cb93a386Sopenharmony_ci            croppedRect = rectToDraw;
825cb93a386Sopenharmony_ci            croppedLocal = localRect;
826cb93a386Sopenharmony_ci        }
827cb93a386Sopenharmony_ci
828cb93a386Sopenharmony_ci        if (auto op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint),
829cb93a386Sopenharmony_ci                                        viewMatrix, SkRRect::MakeRect(croppedRect), croppedLocal,
830cb93a386Sopenharmony_ci                                        GrAA::kYes)) {
831cb93a386Sopenharmony_ci            this->addDrawOp(optimizedClip, std::move(op));
832cb93a386Sopenharmony_ci            return;
833cb93a386Sopenharmony_ci        }
834cb93a386Sopenharmony_ci    }
835cb93a386Sopenharmony_ci
836cb93a386Sopenharmony_ci    assert_alive(paint);
837cb93a386Sopenharmony_ci    this->drawFilledQuad(clip, std::move(paint), aa, &quad);
838cb93a386Sopenharmony_ci}
839cb93a386Sopenharmony_ci
840cb93a386Sopenharmony_civoid SurfaceDrawContext::drawQuadSet(const GrClip* clip,
841cb93a386Sopenharmony_ci                                     GrPaint&& paint,
842cb93a386Sopenharmony_ci                                     GrAA aa,
843cb93a386Sopenharmony_ci                                     const SkMatrix& viewMatrix,
844cb93a386Sopenharmony_ci                                     const GrQuadSetEntry quads[],
845cb93a386Sopenharmony_ci                                     int cnt) {
846cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(aa);
847cb93a386Sopenharmony_ci
848cb93a386Sopenharmony_ci    FillRectOp::AddFillRectOps(this, clip, fContext, std::move(paint), aaType, viewMatrix,
849cb93a386Sopenharmony_ci                               quads, cnt);
850cb93a386Sopenharmony_ci}
851cb93a386Sopenharmony_ci
852cb93a386Sopenharmony_ciint SurfaceDrawContext::maxWindowRectangles() const {
853cb93a386Sopenharmony_ci    return this->asRenderTargetProxy()->maxWindowRectangles(*this->caps());
854cb93a386Sopenharmony_ci}
855cb93a386Sopenharmony_ci
856cb93a386Sopenharmony_ciOpsTask::CanDiscardPreviousOps SurfaceDrawContext::canDiscardPreviousOpsOnFullClear() const {
857cb93a386Sopenharmony_ci#if GR_TEST_UTILS
858cb93a386Sopenharmony_ci    if (fPreserveOpsOnFullClear_TestingOnly) {
859cb93a386Sopenharmony_ci        return OpsTask::CanDiscardPreviousOps::kNo;
860cb93a386Sopenharmony_ci    }
861cb93a386Sopenharmony_ci#endif
862cb93a386Sopenharmony_ci    // Regardless of how the clear is implemented (native clear or a fullscreen quad), all prior ops
863cb93a386Sopenharmony_ci    // would normally be overwritten. The one exception is if the render target context is marked as
864cb93a386Sopenharmony_ci    // needing a stencil buffer then there may be a prior op that writes to the stencil buffer.
865cb93a386Sopenharmony_ci    // Although the clear will ignore the stencil buffer, following draw ops may not so we can't get
866cb93a386Sopenharmony_ci    // rid of all the preceding ops. Beware! If we ever add any ops that have a side effect beyond
867cb93a386Sopenharmony_ci    // modifying the stencil buffer we will need a more elaborate tracking system (skbug.com/7002).
868cb93a386Sopenharmony_ci    return OpsTask::CanDiscardPreviousOps(!fNeedsStencil);
869cb93a386Sopenharmony_ci}
870cb93a386Sopenharmony_ci
871cb93a386Sopenharmony_civoid SurfaceDrawContext::setNeedsStencil() {
872cb93a386Sopenharmony_ci    // Don't clear stencil until after we've set fNeedsStencil. This ensures we don't loop forever
873cb93a386Sopenharmony_ci    // in the event that there are driver bugs and we need to clear as a draw.
874cb93a386Sopenharmony_ci    bool hasInitializedStencil = fNeedsStencil;
875cb93a386Sopenharmony_ci    fNeedsStencil = true;
876cb93a386Sopenharmony_ci    if (!hasInitializedStencil) {
877cb93a386Sopenharmony_ci        this->asRenderTargetProxy()->setNeedsStencil();
878cb93a386Sopenharmony_ci        if (this->caps()->performStencilClearsAsDraws()) {
879cb93a386Sopenharmony_ci            // There is a driver bug with clearing stencil. We must use an op to manually clear the
880cb93a386Sopenharmony_ci            // stencil buffer before the op that required 'setNeedsStencil'.
881cb93a386Sopenharmony_ci            this->internalStencilClear(nullptr, /* inside mask */ false);
882cb93a386Sopenharmony_ci        } else {
883cb93a386Sopenharmony_ci            this->getOpsTask()->setInitialStencilContent(
884cb93a386Sopenharmony_ci                    OpsTask::StencilContent::kUserBitsCleared);
885cb93a386Sopenharmony_ci        }
886cb93a386Sopenharmony_ci    }
887cb93a386Sopenharmony_ci}
888cb93a386Sopenharmony_ci
889cb93a386Sopenharmony_civoid SurfaceDrawContext::internalStencilClear(const SkIRect* scissor, bool insideStencilMask) {
890cb93a386Sopenharmony_ci    this->setNeedsStencil();
891cb93a386Sopenharmony_ci
892cb93a386Sopenharmony_ci    GrScissorState scissorState(this->asSurfaceProxy()->backingStoreDimensions());
893cb93a386Sopenharmony_ci    if (scissor && !scissorState.set(*scissor)) {
894cb93a386Sopenharmony_ci        // The requested clear region is off screen, so nothing to do.
895cb93a386Sopenharmony_ci        return;
896cb93a386Sopenharmony_ci    }
897cb93a386Sopenharmony_ci
898cb93a386Sopenharmony_ci    bool clearWithDraw = this->caps()->performStencilClearsAsDraws() ||
899cb93a386Sopenharmony_ci                         (scissorState.enabled() && this->caps()->performPartialClearsAsDraws());
900cb93a386Sopenharmony_ci    if (clearWithDraw) {
901cb93a386Sopenharmony_ci        const GrUserStencilSettings* ss = GrStencilSettings::SetClipBitSettings(insideStencilMask);
902cb93a386Sopenharmony_ci
903cb93a386Sopenharmony_ci        // Configure the paint to have no impact on the color buffer
904cb93a386Sopenharmony_ci        GrPaint paint;
905cb93a386Sopenharmony_ci        paint.setXPFactory(GrDisableColorXPFactory::Get());
906cb93a386Sopenharmony_ci        this->addDrawOp(nullptr,
907cb93a386Sopenharmony_ci                        FillRectOp::MakeNonAARect(fContext, std::move(paint), SkMatrix::I(),
908cb93a386Sopenharmony_ci                                                  SkRect::Make(scissorState.rect()), ss));
909cb93a386Sopenharmony_ci    } else {
910cb93a386Sopenharmony_ci        this->addOp(ClearOp::MakeStencilClip(fContext, scissorState, insideStencilMask));
911cb93a386Sopenharmony_ci    }
912cb93a386Sopenharmony_ci}
913cb93a386Sopenharmony_ci
914cb93a386Sopenharmony_cibool SurfaceDrawContext::stencilPath(const GrHardClip* clip,
915cb93a386Sopenharmony_ci                                     GrAA doStencilMSAA,
916cb93a386Sopenharmony_ci                                     const SkMatrix& viewMatrix,
917cb93a386Sopenharmony_ci                                     const SkPath& path) {
918cb93a386Sopenharmony_ci    SkIRect clipBounds = clip ? clip->getConservativeBounds()
919cb93a386Sopenharmony_ci                              : SkIRect::MakeSize(this->dimensions());
920cb93a386Sopenharmony_ci    GrStyledShape shape(path, GrStyledShape::DoSimplify::kNo);
921cb93a386Sopenharmony_ci
922cb93a386Sopenharmony_ci    PathRenderer::CanDrawPathArgs canDrawArgs;
923cb93a386Sopenharmony_ci    canDrawArgs.fCaps = fContext->priv().caps();
924cb93a386Sopenharmony_ci    canDrawArgs.fProxy = this->asRenderTargetProxy();
925cb93a386Sopenharmony_ci    canDrawArgs.fClipConservativeBounds = &clipBounds;
926cb93a386Sopenharmony_ci    canDrawArgs.fViewMatrix = &viewMatrix;
927cb93a386Sopenharmony_ci    canDrawArgs.fShape = &shape;
928cb93a386Sopenharmony_ci    canDrawArgs.fPaint = nullptr;
929cb93a386Sopenharmony_ci    canDrawArgs.fSurfaceProps = &fSurfaceProps;
930cb93a386Sopenharmony_ci    canDrawArgs.fAAType = (doStencilMSAA == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone;
931cb93a386Sopenharmony_ci    canDrawArgs.fHasUserStencilSettings = false;
932cb93a386Sopenharmony_ci    auto pr = this->drawingManager()->getPathRenderer(canDrawArgs,
933cb93a386Sopenharmony_ci                                                      false,
934cb93a386Sopenharmony_ci                                                      PathRendererChain::DrawType::kStencil);
935cb93a386Sopenharmony_ci    if (!pr) {
936cb93a386Sopenharmony_ci        SkDebugf("WARNING: No path renderer to stencil path.\n");
937cb93a386Sopenharmony_ci        return false;
938cb93a386Sopenharmony_ci    }
939cb93a386Sopenharmony_ci
940cb93a386Sopenharmony_ci    PathRenderer::StencilPathArgs args;
941cb93a386Sopenharmony_ci    args.fContext = fContext;
942cb93a386Sopenharmony_ci    args.fSurfaceDrawContext = this;
943cb93a386Sopenharmony_ci    args.fClip = clip;
944cb93a386Sopenharmony_ci    args.fClipConservativeBounds = &clipBounds;
945cb93a386Sopenharmony_ci    args.fViewMatrix = &viewMatrix;
946cb93a386Sopenharmony_ci    args.fShape = &shape;
947cb93a386Sopenharmony_ci    args.fDoStencilMSAA = doStencilMSAA;
948cb93a386Sopenharmony_ci    pr->stencilPath(args);
949cb93a386Sopenharmony_ci    return true;
950cb93a386Sopenharmony_ci}
951cb93a386Sopenharmony_ci
952cb93a386Sopenharmony_civoid SurfaceDrawContext::drawTextureSet(const GrClip* clip,
953cb93a386Sopenharmony_ci                                        GrTextureSetEntry set[],
954cb93a386Sopenharmony_ci                                        int cnt,
955cb93a386Sopenharmony_ci                                        int proxyRunCnt,
956cb93a386Sopenharmony_ci                                        GrSamplerState::Filter filter,
957cb93a386Sopenharmony_ci                                        GrSamplerState::MipmapMode mm,
958cb93a386Sopenharmony_ci                                        SkBlendMode mode,
959cb93a386Sopenharmony_ci                                        GrAA aa,
960cb93a386Sopenharmony_ci                                        SkCanvas::SrcRectConstraint constraint,
961cb93a386Sopenharmony_ci                                        const SkMatrix& viewMatrix,
962cb93a386Sopenharmony_ci                                        sk_sp<GrColorSpaceXform> texXform) {
963cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
964cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
965cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
966cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawTextureSet", fContext);
967cb93a386Sopenharmony_ci
968cb93a386Sopenharmony_ci    // Create the minimum number of GrTextureOps needed to draw this set. Individual
969cb93a386Sopenharmony_ci    // GrTextureOps can rebind the texture between draws thus avoiding GrPaint (re)creation.
970cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
971cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(aa);
972cb93a386Sopenharmony_ci    auto clampType = GrColorTypeClampType(this->colorInfo().colorType());
973cb93a386Sopenharmony_ci    auto saturate = clampType == GrClampType::kManual ? TextureOp::Saturate::kYes
974cb93a386Sopenharmony_ci                                                      : TextureOp::Saturate::kNo;
975cb93a386Sopenharmony_ci    TextureOp::AddTextureSetOps(this, clip, fContext, set, cnt, proxyRunCnt, filter, mm, saturate,
976cb93a386Sopenharmony_ci                                mode, aaType, constraint, viewMatrix, std::move(texXform));
977cb93a386Sopenharmony_ci}
978cb93a386Sopenharmony_ci
979cb93a386Sopenharmony_civoid SurfaceDrawContext::drawVertices(const GrClip* clip,
980cb93a386Sopenharmony_ci                                      GrPaint&& paint,
981cb93a386Sopenharmony_ci                                      const SkMatrixProvider& matrixProvider,
982cb93a386Sopenharmony_ci                                      sk_sp<SkVertices> vertices,
983cb93a386Sopenharmony_ci                                      GrPrimitiveType* overridePrimType) {
984cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
985cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
986cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
987cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawVertices", fContext);
988cb93a386Sopenharmony_ci
989cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
990cb93a386Sopenharmony_ci
991cb93a386Sopenharmony_ci    SkASSERT(vertices);
992cb93a386Sopenharmony_ci    GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(GrAA::kNo);
993cb93a386Sopenharmony_ci    GrOp::Owner op = DrawVerticesOp::Make(fContext,
994cb93a386Sopenharmony_ci                                          std::move(paint),
995cb93a386Sopenharmony_ci                                          std::move(vertices),
996cb93a386Sopenharmony_ci                                          matrixProvider,
997cb93a386Sopenharmony_ci                                          aaType,
998cb93a386Sopenharmony_ci                                          this->colorInfo().refColorSpaceXformFromSRGB(),
999cb93a386Sopenharmony_ci                                          overridePrimType);
1000cb93a386Sopenharmony_ci    this->addDrawOp(clip, std::move(op));
1001cb93a386Sopenharmony_ci}
1002cb93a386Sopenharmony_ci
1003cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
1004cb93a386Sopenharmony_ci
1005cb93a386Sopenharmony_civoid SurfaceDrawContext::drawAtlas(const GrClip* clip,
1006cb93a386Sopenharmony_ci                                   GrPaint&& paint,
1007cb93a386Sopenharmony_ci                                   const SkMatrix& viewMatrix,
1008cb93a386Sopenharmony_ci                                   int spriteCount,
1009cb93a386Sopenharmony_ci                                   const SkRSXform xform[],
1010cb93a386Sopenharmony_ci                                   const SkRect texRect[],
1011cb93a386Sopenharmony_ci                                   const SkColor colors[]) {
1012cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1013cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1014cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1015cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawAtlas", fContext);
1016cb93a386Sopenharmony_ci
1017cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1018cb93a386Sopenharmony_ci
1019cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(GrAA::kNo);
1020cb93a386Sopenharmony_ci    GrOp::Owner op = DrawAtlasOp::Make(fContext, std::move(paint), viewMatrix,
1021cb93a386Sopenharmony_ci                                       aaType, spriteCount, xform, texRect, colors);
1022cb93a386Sopenharmony_ci    this->addDrawOp(clip, std::move(op));
1023cb93a386Sopenharmony_ci}
1024cb93a386Sopenharmony_ci
1025cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
1026cb93a386Sopenharmony_ci
1027cb93a386Sopenharmony_civoid SurfaceDrawContext::drawRRect(const GrClip* origClip,
1028cb93a386Sopenharmony_ci                                   GrPaint&& paint,
1029cb93a386Sopenharmony_ci                                   GrAA aa,
1030cb93a386Sopenharmony_ci                                   const SkMatrix& viewMatrix,
1031cb93a386Sopenharmony_ci                                   const SkRRect& rrect,
1032cb93a386Sopenharmony_ci                                   const GrStyle& style) {
1033cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1034cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1035cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1036cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRRect", fContext);
1037cb93a386Sopenharmony_ci
1038cb93a386Sopenharmony_ci    SkASSERT(!style.pathEffect()); // this should've been devolved to a path in SkGpuDevice
1039cb93a386Sopenharmony_ci
1040cb93a386Sopenharmony_ci    const SkStrokeRec& stroke = style.strokeRec();
1041cb93a386Sopenharmony_ci    if (stroke.getStyle() == SkStrokeRec::kFill_Style && rrect.isEmpty()) {
1042cb93a386Sopenharmony_ci       return;
1043cb93a386Sopenharmony_ci    }
1044cb93a386Sopenharmony_ci
1045cb93a386Sopenharmony_ci    const GrClip* clip = origClip;
1046cb93a386Sopenharmony_ci    // It is not uncommon to clip to a round rect and then draw that same round rect. Since our
1047cb93a386Sopenharmony_ci    // lower level clip code works from op bounds, which are SkRects, it doesn't detect that the
1048cb93a386Sopenharmony_ci    // clip can be ignored. The following test attempts to mitigate the stencil clip cost but only
1049cb93a386Sopenharmony_ci    // works for axis-aligned round rects. This also only works for filled rrects since the stroke
1050cb93a386Sopenharmony_ci    // width outsets beyond the rrect itself.
1051cb93a386Sopenharmony_ci    // TODO: skbug.com/10462 - There was mixed performance wins and regressions when this
1052cb93a386Sopenharmony_ci    // optimization was turned on outside of Android Framework. I (michaelludwig) believe this is
1053cb93a386Sopenharmony_ci    // do to the overhead in determining if an SkClipStack is just a rrect. Once that is improved,
1054cb93a386Sopenharmony_ci    // re-enable this and see if we avoid the regressions.
1055cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
1056cb93a386Sopenharmony_ci    SkRRect devRRect;
1057cb93a386Sopenharmony_ci    if (clip && stroke.getStyle() == SkStrokeRec::kFill_Style &&
1058cb93a386Sopenharmony_ci        rrect.transform(viewMatrix, &devRRect)) {
1059cb93a386Sopenharmony_ci        GrClip::PreClipResult result = clip->preApply(devRRect.getBounds(), aa);
1060cb93a386Sopenharmony_ci        switch(result.fEffect) {
1061cb93a386Sopenharmony_ci            case GrClip::Effect::kClippedOut:
1062cb93a386Sopenharmony_ci                return;
1063cb93a386Sopenharmony_ci            case GrClip::Effect::kUnclipped:
1064cb93a386Sopenharmony_ci                clip = nullptr;
1065cb93a386Sopenharmony_ci                break;
1066cb93a386Sopenharmony_ci            case GrClip::Effect::kClipped:
1067cb93a386Sopenharmony_ci                // Currently there's no general-purpose rrect-to-rrect contains function, and if we
1068cb93a386Sopenharmony_ci                // got here, we know the devRRect's bounds aren't fully contained by the clip.
1069cb93a386Sopenharmony_ci                // Testing for equality between the two is a reasonable stop-gap for now.
1070cb93a386Sopenharmony_ci                if (result.fIsRRect && result.fRRect == devRRect) {
1071cb93a386Sopenharmony_ci                    // NOTE: On the android framework, we allow this optimization even when the clip
1072cb93a386Sopenharmony_ci                    // is non-AA and the draw is AA.
1073cb93a386Sopenharmony_ci                    if (result.fAA == aa || (result.fAA == GrAA::kNo && aa == GrAA::kYes)) {
1074cb93a386Sopenharmony_ci                        clip = nullptr;
1075cb93a386Sopenharmony_ci                    }
1076cb93a386Sopenharmony_ci                }
1077cb93a386Sopenharmony_ci                break;
1078cb93a386Sopenharmony_ci            default:
1079cb93a386Sopenharmony_ci                SkUNREACHABLE;
1080cb93a386Sopenharmony_ci        }
1081cb93a386Sopenharmony_ci    }
1082cb93a386Sopenharmony_ci#endif
1083cb93a386Sopenharmony_ci
1084cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1085cb93a386Sopenharmony_ci
1086cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(aa);
1087cb93a386Sopenharmony_ci
1088cb93a386Sopenharmony_ci    GrOp::Owner op;
1089cb93a386Sopenharmony_ci    if (aaType == GrAAType::kCoverage                          &&
1090cb93a386Sopenharmony_ci        !fCanUseDynamicMSAA                                    &&
1091cb93a386Sopenharmony_ci        !this->caps()->reducedShaderMode()                     &&
1092cb93a386Sopenharmony_ci        rrect.isSimple()                                       &&
1093cb93a386Sopenharmony_ci        rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY &&
1094cb93a386Sopenharmony_ci        viewMatrix.rectStaysRect() && viewMatrix.isSimilarity()) {
1095cb93a386Sopenharmony_ci        // In specific cases we use a dedicated circular round rect op to try and get better perf.
1096cb93a386Sopenharmony_ci        assert_alive(paint);
1097cb93a386Sopenharmony_ci        op = GrOvalOpFactory::MakeCircularRRectOp(fContext, std::move(paint), viewMatrix, rrect,
1098cb93a386Sopenharmony_ci                                                  stroke, this->caps()->shaderCaps());
1099cb93a386Sopenharmony_ci    }
1100cb93a386Sopenharmony_ci    if (!op && style.isSimpleFill()) {
1101cb93a386Sopenharmony_ci        assert_alive(paint);
1102cb93a386Sopenharmony_ci        op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix, rrect,
1103cb93a386Sopenharmony_ci                               rrect.rect(), GrAA(aaType != GrAAType::kNone));
1104cb93a386Sopenharmony_ci    }
1105cb93a386Sopenharmony_ci    if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) {
1106cb93a386Sopenharmony_ci        assert_alive(paint);
1107cb93a386Sopenharmony_ci        op = GrOvalOpFactory::MakeRRectOp(
1108cb93a386Sopenharmony_ci                fContext, std::move(paint), viewMatrix, rrect, stroke, this->caps()->shaderCaps());
1109cb93a386Sopenharmony_ci    }
1110cb93a386Sopenharmony_ci    if (op) {
1111cb93a386Sopenharmony_ci        this->addDrawOp(clip, std::move(op));
1112cb93a386Sopenharmony_ci        return;
1113cb93a386Sopenharmony_ci    }
1114cb93a386Sopenharmony_ci
1115cb93a386Sopenharmony_ci    assert_alive(paint);
1116cb93a386Sopenharmony_ci    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
1117cb93a386Sopenharmony_ci                                     GrStyledShape(rrect, style, DoSimplify::kNo));
1118cb93a386Sopenharmony_ci}
1119cb93a386Sopenharmony_ci
1120cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
1121cb93a386Sopenharmony_ci
1122cb93a386Sopenharmony_cibool SurfaceDrawContext::drawFastShadow(const GrClip* clip,
1123cb93a386Sopenharmony_ci                                        const SkMatrix& viewMatrix,
1124cb93a386Sopenharmony_ci                                        const SkPath& path,
1125cb93a386Sopenharmony_ci                                        const SkDrawShadowRec& rec) {
1126cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1127cb93a386Sopenharmony_ci    if (fContext->abandoned()) {
1128cb93a386Sopenharmony_ci        return true;
1129cb93a386Sopenharmony_ci    }
1130cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1131cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawFastShadow", fContext);
1132cb93a386Sopenharmony_ci
1133cb93a386Sopenharmony_ci    // check z plane
1134cb93a386Sopenharmony_ci    bool tiltZPlane = SkToBool(!SkScalarNearlyZero(rec.fZPlaneParams.fX) ||
1135cb93a386Sopenharmony_ci                               !SkScalarNearlyZero(rec.fZPlaneParams.fY));
1136cb93a386Sopenharmony_ci    bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
1137cb93a386Sopenharmony_ci    if (tiltZPlane || skipAnalytic || !viewMatrix.rectStaysRect() || !viewMatrix.isSimilarity()) {
1138cb93a386Sopenharmony_ci        return false;
1139cb93a386Sopenharmony_ci    }
1140cb93a386Sopenharmony_ci
1141cb93a386Sopenharmony_ci    SkRRect rrect;
1142cb93a386Sopenharmony_ci    SkRect rect;
1143cb93a386Sopenharmony_ci    // we can only handle rects, circles, and simple rrects with circular corners
1144cb93a386Sopenharmony_ci    bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsNearlySimpleCircular(rrect) &&
1145cb93a386Sopenharmony_ci                   rrect.getSimpleRadii().fX > SK_ScalarNearlyZero;
1146cb93a386Sopenharmony_ci    if (!isRRect &&
1147cb93a386Sopenharmony_ci        path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
1148cb93a386Sopenharmony_ci        rect.width() > SK_ScalarNearlyZero) {
1149cb93a386Sopenharmony_ci        rrect.setOval(rect);
1150cb93a386Sopenharmony_ci        isRRect = true;
1151cb93a386Sopenharmony_ci    }
1152cb93a386Sopenharmony_ci    if (!isRRect && path.isRect(&rect)) {
1153cb93a386Sopenharmony_ci        rrect.setRect(rect);
1154cb93a386Sopenharmony_ci        isRRect = true;
1155cb93a386Sopenharmony_ci    }
1156cb93a386Sopenharmony_ci
1157cb93a386Sopenharmony_ci    if (!isRRect) {
1158cb93a386Sopenharmony_ci        return false;
1159cb93a386Sopenharmony_ci    }
1160cb93a386Sopenharmony_ci
1161cb93a386Sopenharmony_ci    if (rrect.isEmpty()) {
1162cb93a386Sopenharmony_ci        return true;
1163cb93a386Sopenharmony_ci    }
1164cb93a386Sopenharmony_ci
1165cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1166cb93a386Sopenharmony_ci
1167cb93a386Sopenharmony_ci    SkPoint3 devLightPos = rec.fLightPos;
1168cb93a386Sopenharmony_ci    bool directional = SkToBool(rec.fFlags & kDirectionalLight_ShadowFlag);
1169cb93a386Sopenharmony_ci    if (!directional) {
1170cb93a386Sopenharmony_ci        // transform light
1171cb93a386Sopenharmony_ci        viewMatrix.mapPoints((SkPoint*)&devLightPos.fX, 1);
1172cb93a386Sopenharmony_ci    }
1173cb93a386Sopenharmony_ci
1174cb93a386Sopenharmony_ci    // 1/scale
1175cb93a386Sopenharmony_ci    SkScalar devToSrcScale = viewMatrix.isScaleTranslate() ?
1176cb93a386Sopenharmony_ci        SkScalarInvert(SkScalarAbs(viewMatrix[SkMatrix::kMScaleX])) :
1177cb93a386Sopenharmony_ci        sk_float_rsqrt(viewMatrix[SkMatrix::kMScaleX] * viewMatrix[SkMatrix::kMScaleX] +
1178cb93a386Sopenharmony_ci                       viewMatrix[SkMatrix::kMSkewX] * viewMatrix[SkMatrix::kMSkewX]);
1179cb93a386Sopenharmony_ci
1180cb93a386Sopenharmony_ci    SkScalar occluderHeight = rec.fZPlaneParams.fZ;
1181cb93a386Sopenharmony_ci    bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
1182cb93a386Sopenharmony_ci
1183cb93a386Sopenharmony_ci    if (SkColorGetA(rec.fAmbientColor) > 0) {
1184cb93a386Sopenharmony_ci        SkScalar devSpaceInsetWidth = SkDrawShadowMetrics::AmbientBlurRadius(occluderHeight);
1185cb93a386Sopenharmony_ci        const SkScalar umbraRecipAlpha = SkDrawShadowMetrics::AmbientRecipAlpha(occluderHeight);
1186cb93a386Sopenharmony_ci        const SkScalar devSpaceAmbientBlur = devSpaceInsetWidth * umbraRecipAlpha;
1187cb93a386Sopenharmony_ci
1188cb93a386Sopenharmony_ci        // Outset the shadow rrect to the border of the penumbra
1189cb93a386Sopenharmony_ci        SkScalar ambientPathOutset = devSpaceInsetWidth * devToSrcScale;
1190cb93a386Sopenharmony_ci        SkRRect ambientRRect;
1191cb93a386Sopenharmony_ci        SkRect outsetRect = rrect.rect().makeOutset(ambientPathOutset, ambientPathOutset);
1192cb93a386Sopenharmony_ci        // If the rrect was an oval then its outset will also be one.
1193cb93a386Sopenharmony_ci        // We set it explicitly to avoid errors.
1194cb93a386Sopenharmony_ci        if (rrect.isOval()) {
1195cb93a386Sopenharmony_ci            ambientRRect = SkRRect::MakeOval(outsetRect);
1196cb93a386Sopenharmony_ci        } else {
1197cb93a386Sopenharmony_ci            SkScalar outsetRad = SkRRectPriv::GetSimpleRadii(rrect).fX + ambientPathOutset;
1198cb93a386Sopenharmony_ci            ambientRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1199cb93a386Sopenharmony_ci        }
1200cb93a386Sopenharmony_ci
1201cb93a386Sopenharmony_ci        GrColor ambientColor = SkColorToPremulGrColor(rec.fAmbientColor);
1202cb93a386Sopenharmony_ci        if (transparent) {
1203cb93a386Sopenharmony_ci            // set a large inset to force a fill
1204cb93a386Sopenharmony_ci            devSpaceInsetWidth = ambientRRect.width();
1205cb93a386Sopenharmony_ci        }
1206cb93a386Sopenharmony_ci
1207cb93a386Sopenharmony_ci        GrOp::Owner op = ShadowRRectOp::Make(fContext,
1208cb93a386Sopenharmony_ci                                             ambientColor,
1209cb93a386Sopenharmony_ci                                             viewMatrix,
1210cb93a386Sopenharmony_ci                                             ambientRRect,
1211cb93a386Sopenharmony_ci                                             devSpaceAmbientBlur,
1212cb93a386Sopenharmony_ci                                             devSpaceInsetWidth);
1213cb93a386Sopenharmony_ci        if (op) {
1214cb93a386Sopenharmony_ci            this->addDrawOp(clip, std::move(op));
1215cb93a386Sopenharmony_ci        }
1216cb93a386Sopenharmony_ci    }
1217cb93a386Sopenharmony_ci
1218cb93a386Sopenharmony_ci    if (SkColorGetA(rec.fSpotColor) > 0) {
1219cb93a386Sopenharmony_ci        SkScalar devSpaceSpotBlur;
1220cb93a386Sopenharmony_ci        SkScalar spotScale;
1221cb93a386Sopenharmony_ci        SkVector spotOffset;
1222cb93a386Sopenharmony_ci        if (directional) {
1223cb93a386Sopenharmony_ci            SkDrawShadowMetrics::GetDirectionalParams(occluderHeight, devLightPos.fX,
1224cb93a386Sopenharmony_ci                                                      devLightPos.fY, devLightPos.fZ,
1225cb93a386Sopenharmony_ci                                                      rec.fLightRadius, &devSpaceSpotBlur,
1226cb93a386Sopenharmony_ci                                                      &spotScale, &spotOffset);
1227cb93a386Sopenharmony_ci        } else {
1228cb93a386Sopenharmony_ci            SkDrawShadowMetrics::GetSpotParams(occluderHeight, devLightPos.fX, devLightPos.fY,
1229cb93a386Sopenharmony_ci                                               devLightPos.fZ, rec.fLightRadius,
1230cb93a386Sopenharmony_ci                                               &devSpaceSpotBlur, &spotScale, &spotOffset, rec.isLimitElevation);
1231cb93a386Sopenharmony_ci        }
1232cb93a386Sopenharmony_ci        // handle scale of radius due to CTM
1233cb93a386Sopenharmony_ci        const SkScalar srcSpaceSpotBlur = devSpaceSpotBlur * devToSrcScale;
1234cb93a386Sopenharmony_ci
1235cb93a386Sopenharmony_ci        // Adjust translate for the effect of the scale.
1236cb93a386Sopenharmony_ci        spotOffset.fX += spotScale*viewMatrix[SkMatrix::kMTransX];
1237cb93a386Sopenharmony_ci        spotOffset.fY += spotScale*viewMatrix[SkMatrix::kMTransY];
1238cb93a386Sopenharmony_ci        // This offset is in dev space, need to transform it into source space.
1239cb93a386Sopenharmony_ci        SkMatrix ctmInverse;
1240cb93a386Sopenharmony_ci        if (viewMatrix.invert(&ctmInverse)) {
1241cb93a386Sopenharmony_ci            ctmInverse.mapPoints(&spotOffset, 1);
1242cb93a386Sopenharmony_ci        } else {
1243cb93a386Sopenharmony_ci            // Since the matrix is a similarity, this should never happen, but just in case...
1244cb93a386Sopenharmony_ci            SkDebugf("Matrix is degenerate. Will not render spot shadow correctly!\n");
1245cb93a386Sopenharmony_ci            SkASSERT(false);
1246cb93a386Sopenharmony_ci        }
1247cb93a386Sopenharmony_ci
1248cb93a386Sopenharmony_ci        // Compute the transformed shadow rrect
1249cb93a386Sopenharmony_ci        SkRRect spotShadowRRect;
1250cb93a386Sopenharmony_ci        SkMatrix shadowTransform;
1251cb93a386Sopenharmony_ci        shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
1252cb93a386Sopenharmony_ci        rrect.transform(shadowTransform, &spotShadowRRect);
1253cb93a386Sopenharmony_ci        SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX;
1254cb93a386Sopenharmony_ci
1255cb93a386Sopenharmony_ci        // Compute the insetWidth
1256cb93a386Sopenharmony_ci        SkScalar blurOutset = srcSpaceSpotBlur;
1257cb93a386Sopenharmony_ci        SkScalar insetWidth = blurOutset;
1258cb93a386Sopenharmony_ci        if (transparent) {
1259cb93a386Sopenharmony_ci            // If transparent, just do a fill
1260cb93a386Sopenharmony_ci            insetWidth += spotShadowRRect.width();
1261cb93a386Sopenharmony_ci        } else {
1262cb93a386Sopenharmony_ci            // For shadows, instead of using a stroke we specify an inset from the penumbra
1263cb93a386Sopenharmony_ci            // border. We want to extend this inset area so that it meets up with the caster
1264cb93a386Sopenharmony_ci            // geometry. The inset geometry will by default already be inset by the blur width.
1265cb93a386Sopenharmony_ci            //
1266cb93a386Sopenharmony_ci            // We compare the min and max corners inset by the radius between the original
1267cb93a386Sopenharmony_ci            // rrect and the shadow rrect. The distance between the two plus the difference
1268cb93a386Sopenharmony_ci            // between the scaled radius and the original radius gives the distance from the
1269cb93a386Sopenharmony_ci            // transformed shadow shape to the original shape in that corner. The max
1270cb93a386Sopenharmony_ci            // of these gives the maximum distance we need to cover.
1271cb93a386Sopenharmony_ci            //
1272cb93a386Sopenharmony_ci            // Since we are outsetting by 1/2 the blur distance, we just add the maxOffset to
1273cb93a386Sopenharmony_ci            // that to get the full insetWidth.
1274cb93a386Sopenharmony_ci            SkScalar maxOffset;
1275cb93a386Sopenharmony_ci            if (rrect.isRect()) {
1276cb93a386Sopenharmony_ci                // Manhattan distance works better for rects
1277cb93a386Sopenharmony_ci                maxOffset = std::max(std::max(SkTAbs(spotShadowRRect.rect().fLeft -
1278cb93a386Sopenharmony_ci                                                 rrect.rect().fLeft),
1279cb93a386Sopenharmony_ci                                          SkTAbs(spotShadowRRect.rect().fTop -
1280cb93a386Sopenharmony_ci                                                 rrect.rect().fTop)),
1281cb93a386Sopenharmony_ci                                   std::max(SkTAbs(spotShadowRRect.rect().fRight -
1282cb93a386Sopenharmony_ci                                                 rrect.rect().fRight),
1283cb93a386Sopenharmony_ci                                          SkTAbs(spotShadowRRect.rect().fBottom -
1284cb93a386Sopenharmony_ci                                                 rrect.rect().fBottom)));
1285cb93a386Sopenharmony_ci            } else {
1286cb93a386Sopenharmony_ci                SkScalar dr = spotRadius - SkRRectPriv::GetSimpleRadii(rrect).fX;
1287cb93a386Sopenharmony_ci                SkPoint upperLeftOffset = SkPoint::Make(spotShadowRRect.rect().fLeft -
1288cb93a386Sopenharmony_ci                                                        rrect.rect().fLeft + dr,
1289cb93a386Sopenharmony_ci                                                        spotShadowRRect.rect().fTop -
1290cb93a386Sopenharmony_ci                                                        rrect.rect().fTop + dr);
1291cb93a386Sopenharmony_ci                SkPoint lowerRightOffset = SkPoint::Make(spotShadowRRect.rect().fRight -
1292cb93a386Sopenharmony_ci                                                         rrect.rect().fRight - dr,
1293cb93a386Sopenharmony_ci                                                         spotShadowRRect.rect().fBottom -
1294cb93a386Sopenharmony_ci                                                         rrect.rect().fBottom - dr);
1295cb93a386Sopenharmony_ci                maxOffset = SkScalarSqrt(std::max(SkPointPriv::LengthSqd(upperLeftOffset),
1296cb93a386Sopenharmony_ci                                                  SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
1297cb93a386Sopenharmony_ci            }
1298cb93a386Sopenharmony_ci            insetWidth += std::max(blurOutset, maxOffset);
1299cb93a386Sopenharmony_ci        }
1300cb93a386Sopenharmony_ci
1301cb93a386Sopenharmony_ci        // Outset the shadow rrect to the border of the penumbra
1302cb93a386Sopenharmony_ci        SkRect outsetRect = spotShadowRRect.rect().makeOutset(blurOutset, blurOutset);
1303cb93a386Sopenharmony_ci        if (spotShadowRRect.isOval()) {
1304cb93a386Sopenharmony_ci            spotShadowRRect = SkRRect::MakeOval(outsetRect);
1305cb93a386Sopenharmony_ci        } else {
1306cb93a386Sopenharmony_ci            SkScalar outsetRad = spotRadius + blurOutset;
1307cb93a386Sopenharmony_ci            spotShadowRRect = SkRRect::MakeRectXY(outsetRect, outsetRad, outsetRad);
1308cb93a386Sopenharmony_ci        }
1309cb93a386Sopenharmony_ci
1310cb93a386Sopenharmony_ci        GrColor spotColor = SkColorToPremulGrColor(rec.fSpotColor);
1311cb93a386Sopenharmony_ci
1312cb93a386Sopenharmony_ci        GrOp::Owner op = ShadowRRectOp::Make(fContext,
1313cb93a386Sopenharmony_ci                                             spotColor,
1314cb93a386Sopenharmony_ci                                             viewMatrix,
1315cb93a386Sopenharmony_ci                                             spotShadowRRect,
1316cb93a386Sopenharmony_ci                                             2.0f * devSpaceSpotBlur,
1317cb93a386Sopenharmony_ci                                             insetWidth);
1318cb93a386Sopenharmony_ci        if (op) {
1319cb93a386Sopenharmony_ci            this->addDrawOp(clip, std::move(op));
1320cb93a386Sopenharmony_ci        }
1321cb93a386Sopenharmony_ci    }
1322cb93a386Sopenharmony_ci
1323cb93a386Sopenharmony_ci    return true;
1324cb93a386Sopenharmony_ci}
1325cb93a386Sopenharmony_ci
1326cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
1327cb93a386Sopenharmony_ci
1328cb93a386Sopenharmony_civoid SurfaceDrawContext::drawRegion(const GrClip* clip,
1329cb93a386Sopenharmony_ci                                    GrPaint&& paint,
1330cb93a386Sopenharmony_ci                                    GrAA aa,
1331cb93a386Sopenharmony_ci                                    const SkMatrix& viewMatrix,
1332cb93a386Sopenharmony_ci                                    const SkRegion& region,
1333cb93a386Sopenharmony_ci                                    const GrStyle& style,
1334cb93a386Sopenharmony_ci                                    const GrUserStencilSettings* ss) {
1335cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1336cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1337cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1338cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawRegion", fContext);
1339cb93a386Sopenharmony_ci
1340cb93a386Sopenharmony_ci    if (GrAA::kYes == aa) {
1341cb93a386Sopenharmony_ci        // GrRegionOp performs no antialiasing but is much faster, so here we check the matrix
1342cb93a386Sopenharmony_ci        // to see whether aa is really required.
1343cb93a386Sopenharmony_ci        if (!SkToBool(viewMatrix.getType() & ~(SkMatrix::kTranslate_Mask)) &&
1344cb93a386Sopenharmony_ci            SkScalarIsInt(viewMatrix.getTranslateX()) &&
1345cb93a386Sopenharmony_ci            SkScalarIsInt(viewMatrix.getTranslateY())) {
1346cb93a386Sopenharmony_ci            aa = GrAA::kNo;
1347cb93a386Sopenharmony_ci        }
1348cb93a386Sopenharmony_ci    }
1349cb93a386Sopenharmony_ci    bool complexStyle = !style.isSimpleFill();
1350cb93a386Sopenharmony_ci    if (complexStyle || GrAA::kYes == aa) {
1351cb93a386Sopenharmony_ci        SkPath path;
1352cb93a386Sopenharmony_ci        region.getBoundaryPath(&path);
1353cb93a386Sopenharmony_ci        path.setIsVolatile(true);
1354cb93a386Sopenharmony_ci
1355cb93a386Sopenharmony_ci        return this->drawPath(clip, std::move(paint), aa, viewMatrix, path, style);
1356cb93a386Sopenharmony_ci    }
1357cb93a386Sopenharmony_ci
1358cb93a386Sopenharmony_ci    GrAAType aaType = (this->numSamples() > 1) ? GrAAType::kMSAA : GrAAType::kNone;
1359cb93a386Sopenharmony_ci    GrOp::Owner op = RegionOp::Make(fContext, std::move(paint), viewMatrix, region, aaType, ss);
1360cb93a386Sopenharmony_ci    this->addDrawOp(clip, std::move(op));
1361cb93a386Sopenharmony_ci}
1362cb93a386Sopenharmony_ci
1363cb93a386Sopenharmony_civoid SurfaceDrawContext::drawOval(const GrClip* clip,
1364cb93a386Sopenharmony_ci                                  GrPaint&& paint,
1365cb93a386Sopenharmony_ci                                  GrAA aa,
1366cb93a386Sopenharmony_ci                                  const SkMatrix& viewMatrix,
1367cb93a386Sopenharmony_ci                                  const SkRect& oval,
1368cb93a386Sopenharmony_ci                                  const GrStyle& style) {
1369cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1370cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1371cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1372cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawOval", fContext);
1373cb93a386Sopenharmony_ci
1374cb93a386Sopenharmony_ci    const SkStrokeRec& stroke = style.strokeRec();
1375cb93a386Sopenharmony_ci
1376cb93a386Sopenharmony_ci    if (oval.isEmpty() && !style.pathEffect()) {
1377cb93a386Sopenharmony_ci        if (stroke.getStyle() == SkStrokeRec::kFill_Style) {
1378cb93a386Sopenharmony_ci            return;
1379cb93a386Sopenharmony_ci        }
1380cb93a386Sopenharmony_ci
1381cb93a386Sopenharmony_ci        this->drawRect(clip, std::move(paint), aa, viewMatrix, oval, &style);
1382cb93a386Sopenharmony_ci        return;
1383cb93a386Sopenharmony_ci    }
1384cb93a386Sopenharmony_ci
1385cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1386cb93a386Sopenharmony_ci
1387cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(aa);
1388cb93a386Sopenharmony_ci
1389cb93a386Sopenharmony_ci    GrOp::Owner op;
1390cb93a386Sopenharmony_ci    if (aaType == GrAAType::kCoverage      &&
1391cb93a386Sopenharmony_ci        !fCanUseDynamicMSAA                &&
1392cb93a386Sopenharmony_ci        !this->caps()->reducedShaderMode() &&
1393cb93a386Sopenharmony_ci        oval.width() > SK_ScalarNearlyZero &&
1394cb93a386Sopenharmony_ci        oval.width() == oval.height()      &&
1395cb93a386Sopenharmony_ci        viewMatrix.isSimilarity()) {
1396cb93a386Sopenharmony_ci        // In specific cases we use a dedicated circle op to try and get better perf.
1397cb93a386Sopenharmony_ci        assert_alive(paint);
1398cb93a386Sopenharmony_ci        op = GrOvalOpFactory::MakeCircleOp(fContext, std::move(paint), viewMatrix, oval, style,
1399cb93a386Sopenharmony_ci                                           this->caps()->shaderCaps());
1400cb93a386Sopenharmony_ci    }
1401cb93a386Sopenharmony_ci    if (!op && style.isSimpleFill()) {
1402cb93a386Sopenharmony_ci        // FillRRectOp has special geometry and a fragment-shader branch to conditionally evaluate
1403cb93a386Sopenharmony_ci        // the arc equation. This same special geometry and fragment branch also turn out to be a
1404cb93a386Sopenharmony_ci        // substantial optimization for drawing ovals (namely, by not evaluating the arc equation
1405cb93a386Sopenharmony_ci        // inside the oval's inner diamond). Given these optimizations, it's a clear win to draw
1406cb93a386Sopenharmony_ci        // ovals the exact same way we do round rects.
1407cb93a386Sopenharmony_ci        assert_alive(paint);
1408cb93a386Sopenharmony_ci        op = FillRRectOp::Make(fContext, this->arenaAlloc(), std::move(paint), viewMatrix,
1409cb93a386Sopenharmony_ci                               SkRRect::MakeOval(oval), oval, GrAA(aaType != GrAAType::kNone));
1410cb93a386Sopenharmony_ci    }
1411cb93a386Sopenharmony_ci    if (!op && (aaType == GrAAType::kCoverage || fCanUseDynamicMSAA)) {
1412cb93a386Sopenharmony_ci        assert_alive(paint);
1413cb93a386Sopenharmony_ci        op = GrOvalOpFactory::MakeOvalOp(fContext, std::move(paint), viewMatrix, oval, style,
1414cb93a386Sopenharmony_ci                                         this->caps()->shaderCaps());
1415cb93a386Sopenharmony_ci    }
1416cb93a386Sopenharmony_ci    if (op) {
1417cb93a386Sopenharmony_ci        this->addDrawOp(clip, std::move(op));
1418cb93a386Sopenharmony_ci        return;
1419cb93a386Sopenharmony_ci    }
1420cb93a386Sopenharmony_ci
1421cb93a386Sopenharmony_ci    assert_alive(paint);
1422cb93a386Sopenharmony_ci    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
1423cb93a386Sopenharmony_ci                                     GrStyledShape(SkRRect::MakeOval(oval), SkPathDirection::kCW, 2,
1424cb93a386Sopenharmony_ci                                                   false, style, DoSimplify::kNo));
1425cb93a386Sopenharmony_ci}
1426cb93a386Sopenharmony_ci
1427cb93a386Sopenharmony_civoid SurfaceDrawContext::drawArc(const GrClip* clip,
1428cb93a386Sopenharmony_ci                                 GrPaint&& paint,
1429cb93a386Sopenharmony_ci                                 GrAA aa,
1430cb93a386Sopenharmony_ci                                 const SkMatrix& viewMatrix,
1431cb93a386Sopenharmony_ci                                 const SkRect& oval,
1432cb93a386Sopenharmony_ci                                 SkScalar startAngle,
1433cb93a386Sopenharmony_ci                                 SkScalar sweepAngle,
1434cb93a386Sopenharmony_ci                                 bool useCenter,
1435cb93a386Sopenharmony_ci                                 const GrStyle& style) {
1436cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1437cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1438cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1439cb93a386Sopenharmony_ci            GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawArc", fContext);
1440cb93a386Sopenharmony_ci
1441cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1442cb93a386Sopenharmony_ci
1443cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(aa);
1444cb93a386Sopenharmony_ci    if (aaType == GrAAType::kCoverage) {
1445cb93a386Sopenharmony_ci        const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
1446cb93a386Sopenharmony_ci        GrOp::Owner op = GrOvalOpFactory::MakeArcOp(fContext,
1447cb93a386Sopenharmony_ci                                                    std::move(paint),
1448cb93a386Sopenharmony_ci                                                    viewMatrix,
1449cb93a386Sopenharmony_ci                                                    oval,
1450cb93a386Sopenharmony_ci                                                    startAngle,
1451cb93a386Sopenharmony_ci                                                    sweepAngle,
1452cb93a386Sopenharmony_ci                                                    useCenter,
1453cb93a386Sopenharmony_ci                                                    style,
1454cb93a386Sopenharmony_ci                                                    shaderCaps);
1455cb93a386Sopenharmony_ci        if (op) {
1456cb93a386Sopenharmony_ci            this->addDrawOp(clip, std::move(op));
1457cb93a386Sopenharmony_ci            return;
1458cb93a386Sopenharmony_ci        }
1459cb93a386Sopenharmony_ci        assert_alive(paint);
1460cb93a386Sopenharmony_ci    }
1461cb93a386Sopenharmony_ci    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix,
1462cb93a386Sopenharmony_ci                                     GrStyledShape::MakeArc(oval, startAngle, sweepAngle, useCenter,
1463cb93a386Sopenharmony_ci                                                            style, DoSimplify::kNo));
1464cb93a386Sopenharmony_ci}
1465cb93a386Sopenharmony_ci
1466cb93a386Sopenharmony_civoid SurfaceDrawContext::drawImageLattice(const GrClip* clip,
1467cb93a386Sopenharmony_ci                                          GrPaint&& paint,
1468cb93a386Sopenharmony_ci                                          const SkMatrix& viewMatrix,
1469cb93a386Sopenharmony_ci                                          GrSurfaceProxyView view,
1470cb93a386Sopenharmony_ci                                          SkAlphaType alphaType,
1471cb93a386Sopenharmony_ci                                          sk_sp<GrColorSpaceXform> csxf,
1472cb93a386Sopenharmony_ci                                          GrSamplerState::Filter filter,
1473cb93a386Sopenharmony_ci                                          std::unique_ptr<SkLatticeIter> iter,
1474cb93a386Sopenharmony_ci                                          const SkRect& dst) {
1475cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1476cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1477cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1478cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawImageLattice", fContext);
1479cb93a386Sopenharmony_ci
1480cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1481cb93a386Sopenharmony_ci
1482cb93a386Sopenharmony_ci    GrOp::Owner op =
1483cb93a386Sopenharmony_ci              LatticeOp::MakeNonAA(fContext, std::move(paint), viewMatrix, std::move(view),
1484cb93a386Sopenharmony_ci                                   alphaType, std::move(csxf), filter, std::move(iter), dst);
1485cb93a386Sopenharmony_ci    this->addDrawOp(clip, std::move(op));
1486cb93a386Sopenharmony_ci}
1487cb93a386Sopenharmony_ci
1488cb93a386Sopenharmony_civoid SurfaceDrawContext::drawDrawable(std::unique_ptr<SkDrawable::GpuDrawHandler> drawable,
1489cb93a386Sopenharmony_ci                                      const SkRect& bounds) {
1490cb93a386Sopenharmony_ci    GrOp::Owner op(DrawableOp::Make(fContext, std::move(drawable), bounds));
1491cb93a386Sopenharmony_ci    SkASSERT(op);
1492cb93a386Sopenharmony_ci    this->addOp(std::move(op));
1493cb93a386Sopenharmony_ci}
1494cb93a386Sopenharmony_ci
1495cb93a386Sopenharmony_civoid SurfaceDrawContext::setLastClip(uint32_t clipStackGenID,
1496cb93a386Sopenharmony_ci                                     const SkIRect& devClipBounds,
1497cb93a386Sopenharmony_ci                                     int numClipAnalyticElements) {
1498cb93a386Sopenharmony_ci    auto opsTask = this->getOpsTask();
1499cb93a386Sopenharmony_ci    opsTask->fLastClipStackGenID = clipStackGenID;
1500cb93a386Sopenharmony_ci    opsTask->fLastDevClipBounds = devClipBounds;
1501cb93a386Sopenharmony_ci    opsTask->fLastClipNumAnalyticElements = numClipAnalyticElements;
1502cb93a386Sopenharmony_ci}
1503cb93a386Sopenharmony_ci
1504cb93a386Sopenharmony_cibool SurfaceDrawContext::mustRenderClip(uint32_t clipStackGenID,
1505cb93a386Sopenharmony_ci                                        const SkIRect& devClipBounds,
1506cb93a386Sopenharmony_ci                                        int numClipAnalyticElements) {
1507cb93a386Sopenharmony_ci    auto opsTask = this->getOpsTask();
1508cb93a386Sopenharmony_ci    return opsTask->fLastClipStackGenID != clipStackGenID ||
1509cb93a386Sopenharmony_ci           !opsTask->fLastDevClipBounds.contains(devClipBounds) ||
1510cb93a386Sopenharmony_ci           opsTask->fLastClipNumAnalyticElements != numClipAnalyticElements;
1511cb93a386Sopenharmony_ci}
1512cb93a386Sopenharmony_ci
1513cb93a386Sopenharmony_cibool SurfaceDrawContext::waitOnSemaphores(int numSemaphores,
1514cb93a386Sopenharmony_ci                                          const GrBackendSemaphore waitSemaphores[],
1515cb93a386Sopenharmony_ci                                          bool deleteSemaphoresAfterWait) {
1516cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1517cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
1518cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1519cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "waitOnSemaphores", fContext);
1520cb93a386Sopenharmony_ci
1521cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1522cb93a386Sopenharmony_ci
1523cb93a386Sopenharmony_ci    if (numSemaphores && !this->caps()->semaphoreSupport()) {
1524cb93a386Sopenharmony_ci        return false;
1525cb93a386Sopenharmony_ci    }
1526cb93a386Sopenharmony_ci
1527cb93a386Sopenharmony_ci    auto direct = fContext->asDirectContext();
1528cb93a386Sopenharmony_ci    if (!direct) {
1529cb93a386Sopenharmony_ci        return false;
1530cb93a386Sopenharmony_ci    }
1531cb93a386Sopenharmony_ci
1532cb93a386Sopenharmony_ci    auto resourceProvider = direct->priv().resourceProvider();
1533cb93a386Sopenharmony_ci
1534cb93a386Sopenharmony_ci    GrWrapOwnership ownership =
1535cb93a386Sopenharmony_ci            deleteSemaphoresAfterWait ? kAdopt_GrWrapOwnership : kBorrow_GrWrapOwnership;
1536cb93a386Sopenharmony_ci
1537cb93a386Sopenharmony_ci    std::unique_ptr<std::unique_ptr<GrSemaphore>[]> grSemaphores(
1538cb93a386Sopenharmony_ci            new std::unique_ptr<GrSemaphore>[numSemaphores]);
1539cb93a386Sopenharmony_ci    for (int i = 0; i < numSemaphores; ++i) {
1540cb93a386Sopenharmony_ci        grSemaphores[i] = resourceProvider->wrapBackendSemaphore(waitSemaphores[i],
1541cb93a386Sopenharmony_ci                                                                 GrSemaphoreWrapType::kWillWait,
1542cb93a386Sopenharmony_ci                                                                 ownership);
1543cb93a386Sopenharmony_ci    }
1544cb93a386Sopenharmony_ci    this->drawingManager()->newWaitRenderTask(this->asSurfaceProxyRef(), std::move(grSemaphores),
1545cb93a386Sopenharmony_ci                                              numSemaphores);
1546cb93a386Sopenharmony_ci    return true;
1547cb93a386Sopenharmony_ci}
1548cb93a386Sopenharmony_ci
1549cb93a386Sopenharmony_civoid SurfaceDrawContext::drawPath(const GrClip* clip,
1550cb93a386Sopenharmony_ci                                  GrPaint&& paint,
1551cb93a386Sopenharmony_ci                                  GrAA aa,
1552cb93a386Sopenharmony_ci                                  const SkMatrix& viewMatrix,
1553cb93a386Sopenharmony_ci                                  const SkPath& path,
1554cb93a386Sopenharmony_ci                                  const GrStyle& style) {
1555cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1556cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1557cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1558cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawPath", fContext);
1559cb93a386Sopenharmony_ci
1560cb93a386Sopenharmony_ci    GrStyledShape shape(path, style, DoSimplify::kNo);
1561cb93a386Sopenharmony_ci    this->drawShape(clip, std::move(paint), aa, viewMatrix, std::move(shape));
1562cb93a386Sopenharmony_ci}
1563cb93a386Sopenharmony_ci
1564cb93a386Sopenharmony_civoid SurfaceDrawContext::drawShape(const GrClip* clip,
1565cb93a386Sopenharmony_ci                                   GrPaint&& paint,
1566cb93a386Sopenharmony_ci                                   GrAA aa,
1567cb93a386Sopenharmony_ci                                   const SkMatrix& viewMatrix,
1568cb93a386Sopenharmony_ci                                   GrStyledShape&& shape) {
1569cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1570cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1571cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1572cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawShape", fContext);
1573cb93a386Sopenharmony_ci
1574cb93a386Sopenharmony_ci    if (shape.isEmpty()) {
1575cb93a386Sopenharmony_ci        if (shape.inverseFilled()) {
1576cb93a386Sopenharmony_ci            this->drawPaint(clip, std::move(paint), viewMatrix);
1577cb93a386Sopenharmony_ci        }
1578cb93a386Sopenharmony_ci        return;
1579cb93a386Sopenharmony_ci    }
1580cb93a386Sopenharmony_ci
1581cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1582cb93a386Sopenharmony_ci
1583cb93a386Sopenharmony_ci    // If we get here in drawShape(), we definitely need to use path rendering
1584cb93a386Sopenharmony_ci    this->drawShapeUsingPathRenderer(clip, std::move(paint), aa, viewMatrix, std::move(shape),
1585cb93a386Sopenharmony_ci                                     /* attemptDrawSimple */ true);
1586cb93a386Sopenharmony_ci}
1587cb93a386Sopenharmony_ci
1588cb93a386Sopenharmony_cistatic SkIRect get_clip_bounds(const SurfaceDrawContext* sdc, const GrClip* clip) {
1589cb93a386Sopenharmony_ci    return clip ? clip->getConservativeBounds() : SkIRect::MakeWH(sdc->width(), sdc->height());
1590cb93a386Sopenharmony_ci}
1591cb93a386Sopenharmony_ci
1592cb93a386Sopenharmony_cibool SurfaceDrawContext::drawAndStencilPath(const GrHardClip* clip,
1593cb93a386Sopenharmony_ci                                            const GrUserStencilSettings* ss,
1594cb93a386Sopenharmony_ci                                            SkRegion::Op op,
1595cb93a386Sopenharmony_ci                                            bool invert,
1596cb93a386Sopenharmony_ci                                            GrAA aa,
1597cb93a386Sopenharmony_ci                                            const SkMatrix& viewMatrix,
1598cb93a386Sopenharmony_ci                                            const SkPath& path) {
1599cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1600cb93a386Sopenharmony_ci    RETURN_FALSE_IF_ABANDONED
1601cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1602cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "drawAndStencilPath", fContext);
1603cb93a386Sopenharmony_ci
1604cb93a386Sopenharmony_ci    if (path.isEmpty() && path.isInverseFillType()) {
1605cb93a386Sopenharmony_ci        GrPaint paint;
1606cb93a386Sopenharmony_ci        paint.setCoverageSetOpXPFactory(op, invert);
1607cb93a386Sopenharmony_ci        this->stencilRect(clip, ss, std::move(paint), GrAA::kNo, SkMatrix::I(),
1608cb93a386Sopenharmony_ci                          SkRect::Make(this->dimensions()));
1609cb93a386Sopenharmony_ci        return true;
1610cb93a386Sopenharmony_ci    }
1611cb93a386Sopenharmony_ci
1612cb93a386Sopenharmony_ci    AutoCheckFlush acf(this->drawingManager());
1613cb93a386Sopenharmony_ci
1614cb93a386Sopenharmony_ci    // An Assumption here is that path renderer would use some form of tweaking
1615cb93a386Sopenharmony_ci    // the src color (either the input alpha or in the frag shader) to implement
1616cb93a386Sopenharmony_ci    // aa. If we have some future driver-mojo path AA that can do the right
1617cb93a386Sopenharmony_ci    // thing WRT to the blend then we'll need some query on the PR.
1618cb93a386Sopenharmony_ci    GrAAType aaType = this->chooseAAType(aa);
1619cb93a386Sopenharmony_ci    bool hasUserStencilSettings = !ss->isUnused();
1620cb93a386Sopenharmony_ci
1621cb93a386Sopenharmony_ci    SkIRect clipConservativeBounds = get_clip_bounds(this, clip);
1622cb93a386Sopenharmony_ci
1623cb93a386Sopenharmony_ci    GrPaint paint;
1624cb93a386Sopenharmony_ci    paint.setCoverageSetOpXPFactory(op, invert);
1625cb93a386Sopenharmony_ci
1626cb93a386Sopenharmony_ci    GrStyledShape shape(path, GrStyle::SimpleFill());
1627cb93a386Sopenharmony_ci    PathRenderer::CanDrawPathArgs canDrawArgs;
1628cb93a386Sopenharmony_ci    canDrawArgs.fCaps = this->caps();
1629cb93a386Sopenharmony_ci    canDrawArgs.fProxy = this->asRenderTargetProxy();
1630cb93a386Sopenharmony_ci    canDrawArgs.fViewMatrix = &viewMatrix;
1631cb93a386Sopenharmony_ci    canDrawArgs.fShape = &shape;
1632cb93a386Sopenharmony_ci    canDrawArgs.fPaint = &paint;
1633cb93a386Sopenharmony_ci    canDrawArgs.fSurfaceProps = &fSurfaceProps;
1634cb93a386Sopenharmony_ci    canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
1635cb93a386Sopenharmony_ci    canDrawArgs.fAAType = aaType;
1636cb93a386Sopenharmony_ci    canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
1637cb93a386Sopenharmony_ci
1638cb93a386Sopenharmony_ci    using DrawType = PathRendererChain::DrawType;
1639cb93a386Sopenharmony_ci
1640cb93a386Sopenharmony_ci    // Don't allow the SW renderer
1641cb93a386Sopenharmony_ci    auto pr = this->drawingManager()->getPathRenderer(canDrawArgs,
1642cb93a386Sopenharmony_ci                                                      false,
1643cb93a386Sopenharmony_ci                                                      DrawType::kStencilAndColor);
1644cb93a386Sopenharmony_ci    if (!pr) {
1645cb93a386Sopenharmony_ci        return false;
1646cb93a386Sopenharmony_ci    }
1647cb93a386Sopenharmony_ci
1648cb93a386Sopenharmony_ci    PathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
1649cb93a386Sopenharmony_ci                                    std::move(paint),
1650cb93a386Sopenharmony_ci                                    ss,
1651cb93a386Sopenharmony_ci                                    this,
1652cb93a386Sopenharmony_ci                                    clip,
1653cb93a386Sopenharmony_ci                                    &clipConservativeBounds,
1654cb93a386Sopenharmony_ci                                    &viewMatrix,
1655cb93a386Sopenharmony_ci                                    &shape,
1656cb93a386Sopenharmony_ci                                    aaType,
1657cb93a386Sopenharmony_ci                                    this->colorInfo().isLinearlyBlended()};
1658cb93a386Sopenharmony_ci    pr->drawPath(args);
1659cb93a386Sopenharmony_ci    return true;
1660cb93a386Sopenharmony_ci}
1661cb93a386Sopenharmony_ci
1662cb93a386Sopenharmony_ciSkBudgeted SurfaceDrawContext::isBudgeted() const {
1663cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1664cb93a386Sopenharmony_ci
1665cb93a386Sopenharmony_ci    if (fContext->abandoned()) {
1666cb93a386Sopenharmony_ci        return SkBudgeted::kNo;
1667cb93a386Sopenharmony_ci    }
1668cb93a386Sopenharmony_ci
1669cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1670cb93a386Sopenharmony_ci
1671cb93a386Sopenharmony_ci    return this->asSurfaceProxy()->isBudgeted();
1672cb93a386Sopenharmony_ci}
1673cb93a386Sopenharmony_ci
1674cb93a386Sopenharmony_civoid SurfaceDrawContext::drawStrokedLine(const GrClip* clip,
1675cb93a386Sopenharmony_ci                                         GrPaint&& paint,
1676cb93a386Sopenharmony_ci                                         GrAA aa,
1677cb93a386Sopenharmony_ci                                         const SkMatrix& viewMatrix,
1678cb93a386Sopenharmony_ci                                         const SkPoint points[2],
1679cb93a386Sopenharmony_ci                                         const SkStrokeRec& stroke) {
1680cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1681cb93a386Sopenharmony_ci
1682cb93a386Sopenharmony_ci    SkASSERT(stroke.getStyle() == SkStrokeRec::kStroke_Style);
1683cb93a386Sopenharmony_ci    SkASSERT(stroke.getWidth() > 0);
1684cb93a386Sopenharmony_ci    // Adding support for round capping would require a
1685cb93a386Sopenharmony_ci    // SurfaceDrawContext::fillRRectWithLocalMatrix entry point
1686cb93a386Sopenharmony_ci    SkASSERT(SkPaint::kRound_Cap != stroke.getCap());
1687cb93a386Sopenharmony_ci
1688cb93a386Sopenharmony_ci    const SkScalar halfWidth = 0.5f * stroke.getWidth();
1689cb93a386Sopenharmony_ci    if (halfWidth <= 0.f) {
1690cb93a386Sopenharmony_ci        // Prevents underflow when stroke width is epsilon > 0 (so technically not a hairline).
1691cb93a386Sopenharmony_ci        // The CTM would need to have a scale near 1/epsilon in order for this to have meaningful
1692cb93a386Sopenharmony_ci        // coverage (although that would likely overflow elsewhere and cause the draw to drop due
1693cb93a386Sopenharmony_ci        // to non-finite bounds). At any other scale, this line is so thin, it's coverage is
1694cb93a386Sopenharmony_ci        // negligible, so discarding the draw is visually equivalent.
1695cb93a386Sopenharmony_ci        return;
1696cb93a386Sopenharmony_ci    }
1697cb93a386Sopenharmony_ci
1698cb93a386Sopenharmony_ci    SkVector parallel = points[1] - points[0];
1699cb93a386Sopenharmony_ci
1700cb93a386Sopenharmony_ci    if (!SkPoint::Normalize(&parallel)) {
1701cb93a386Sopenharmony_ci        parallel.fX = 1.0f;
1702cb93a386Sopenharmony_ci        parallel.fY = 0.0f;
1703cb93a386Sopenharmony_ci    }
1704cb93a386Sopenharmony_ci    parallel *= halfWidth;
1705cb93a386Sopenharmony_ci
1706cb93a386Sopenharmony_ci    SkVector ortho = { parallel.fY, -parallel.fX };
1707cb93a386Sopenharmony_ci    if (SkPaint::kButt_Cap == stroke.getCap()) {
1708cb93a386Sopenharmony_ci        // No extra extension for butt caps
1709cb93a386Sopenharmony_ci        parallel = {0.f, 0.f};
1710cb93a386Sopenharmony_ci    }
1711cb93a386Sopenharmony_ci    // Order is TL, TR, BR, BL where arbitrarily "down" is p0 to p1 and "right" is positive
1712cb93a386Sopenharmony_ci    SkPoint corners[4] = { points[0] - ortho - parallel,
1713cb93a386Sopenharmony_ci                           points[0] + ortho - parallel,
1714cb93a386Sopenharmony_ci                           points[1] + ortho + parallel,
1715cb93a386Sopenharmony_ci                           points[1] - ortho + parallel };
1716cb93a386Sopenharmony_ci
1717cb93a386Sopenharmony_ci    GrQuadAAFlags edgeAA = (aa == GrAA::kYes) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
1718cb93a386Sopenharmony_ci    this->fillQuadWithEdgeAA(clip, std::move(paint), aa, edgeAA, viewMatrix, corners, nullptr);
1719cb93a386Sopenharmony_ci}
1720cb93a386Sopenharmony_ci
1721cb93a386Sopenharmony_cibool SurfaceDrawContext::drawSimpleShape(const GrClip* clip,
1722cb93a386Sopenharmony_ci                                         GrPaint* paint,
1723cb93a386Sopenharmony_ci                                         GrAA aa,
1724cb93a386Sopenharmony_ci                                         const SkMatrix& viewMatrix,
1725cb93a386Sopenharmony_ci                                         const GrStyledShape& shape) {
1726cb93a386Sopenharmony_ci    if (!shape.style().hasPathEffect()) {
1727cb93a386Sopenharmony_ci        GrAAType aaType = this->chooseAAType(aa);
1728cb93a386Sopenharmony_ci        SkPoint linePts[2];
1729cb93a386Sopenharmony_ci        SkRRect rrect;
1730cb93a386Sopenharmony_ci        // We can ignore the starting point and direction since there is no path effect.
1731cb93a386Sopenharmony_ci        bool inverted;
1732cb93a386Sopenharmony_ci        if (shape.asLine(linePts, &inverted) && !inverted &&
1733cb93a386Sopenharmony_ci            shape.style().strokeRec().getStyle() == SkStrokeRec::kStroke_Style &&
1734cb93a386Sopenharmony_ci            shape.style().strokeRec().getCap() != SkPaint::kRound_Cap) {
1735cb93a386Sopenharmony_ci            // The stroked line is an oriented rectangle, which looks the same or better (if
1736cb93a386Sopenharmony_ci            // perspective) compared to path rendering. The exception is subpixel/hairline lines
1737cb93a386Sopenharmony_ci            // that are non-AA or MSAA, in which case the default path renderer achieves higher
1738cb93a386Sopenharmony_ci            // quality.
1739cb93a386Sopenharmony_ci            // FIXME(michaelludwig): If the fill rect op could take an external coverage, or checks
1740cb93a386Sopenharmony_ci            // for and outsets thin non-aa rects to 1px, the path renderer could be skipped.
1741cb93a386Sopenharmony_ci            SkScalar coverage;
1742cb93a386Sopenharmony_ci            if (aaType == GrAAType::kCoverage ||
1743cb93a386Sopenharmony_ci                !SkDrawTreatAAStrokeAsHairline(shape.style().strokeRec().getWidth(), viewMatrix,
1744cb93a386Sopenharmony_ci                                               &coverage)) {
1745cb93a386Sopenharmony_ci                this->drawStrokedLine(clip, std::move(*paint), aa, viewMatrix, linePts,
1746cb93a386Sopenharmony_ci                                      shape.style().strokeRec());
1747cb93a386Sopenharmony_ci                return true;
1748cb93a386Sopenharmony_ci            }
1749cb93a386Sopenharmony_ci        } else if (shape.asRRect(&rrect, nullptr, nullptr, &inverted) && !inverted) {
1750cb93a386Sopenharmony_ci            if (rrect.isRect()) {
1751cb93a386Sopenharmony_ci                this->drawRect(clip, std::move(*paint), aa, viewMatrix, rrect.rect(),
1752cb93a386Sopenharmony_ci                               &shape.style());
1753cb93a386Sopenharmony_ci                return true;
1754cb93a386Sopenharmony_ci            } else if (rrect.isOval()) {
1755cb93a386Sopenharmony_ci                this->drawOval(clip, std::move(*paint), aa, viewMatrix, rrect.rect(),
1756cb93a386Sopenharmony_ci                               shape.style());
1757cb93a386Sopenharmony_ci                return true;
1758cb93a386Sopenharmony_ci            }
1759cb93a386Sopenharmony_ci            this->drawRRect(clip, std::move(*paint), aa, viewMatrix, rrect, shape.style());
1760cb93a386Sopenharmony_ci            return true;
1761cb93a386Sopenharmony_ci        } else if (GrAAType::kCoverage == aaType &&
1762cb93a386Sopenharmony_ci                   shape.style().isSimpleFill()  &&
1763cb93a386Sopenharmony_ci                   viewMatrix.rectStaysRect()    &&
1764cb93a386Sopenharmony_ci                   !this->caps()->reducedShaderMode()) {
1765cb93a386Sopenharmony_ci            // TODO: the rectStaysRect restriction could be lifted if we were willing to apply the
1766cb93a386Sopenharmony_ci            // matrix to all the points individually rather than just to the rect
1767cb93a386Sopenharmony_ci            SkRect rects[2];
1768cb93a386Sopenharmony_ci            if (shape.asNestedRects(rects)) {
1769cb93a386Sopenharmony_ci                // Concave AA paths are expensive - try to avoid them for special cases
1770cb93a386Sopenharmony_ci                GrOp::Owner op = StrokeRectOp::MakeNested(fContext, std::move(*paint),
1771cb93a386Sopenharmony_ci                                                          viewMatrix, rects);
1772cb93a386Sopenharmony_ci                if (op) {
1773cb93a386Sopenharmony_ci                    this->addDrawOp(clip, std::move(op));
1774cb93a386Sopenharmony_ci                    return true;
1775cb93a386Sopenharmony_ci                }
1776cb93a386Sopenharmony_ci                // Fall through to let path renderer handle subpixel nested rects with unequal
1777cb93a386Sopenharmony_ci                // stroke widths along X/Y.
1778cb93a386Sopenharmony_ci            }
1779cb93a386Sopenharmony_ci        }
1780cb93a386Sopenharmony_ci    }
1781cb93a386Sopenharmony_ci    return false;
1782cb93a386Sopenharmony_ci}
1783cb93a386Sopenharmony_ci
1784cb93a386Sopenharmony_civoid SurfaceDrawContext::drawShapeUsingPathRenderer(const GrClip* clip,
1785cb93a386Sopenharmony_ci                                                    GrPaint&& paint,
1786cb93a386Sopenharmony_ci                                                    GrAA aa,
1787cb93a386Sopenharmony_ci                                                    const SkMatrix& viewMatrix,
1788cb93a386Sopenharmony_ci                                                    GrStyledShape&& shape,
1789cb93a386Sopenharmony_ci                                                    bool attemptDrawSimple) {
1790cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1791cb93a386Sopenharmony_ci    RETURN_IF_ABANDONED
1792cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "internalDrawPath", fContext);
1793cb93a386Sopenharmony_ci
1794cb93a386Sopenharmony_ci    if (!viewMatrix.isFinite() || !shape.bounds().isFinite()) {
1795cb93a386Sopenharmony_ci        return;
1796cb93a386Sopenharmony_ci    }
1797cb93a386Sopenharmony_ci
1798cb93a386Sopenharmony_ci    SkIRect clipConservativeBounds = get_clip_bounds(this, clip);
1799cb93a386Sopenharmony_ci
1800cb93a386Sopenharmony_ci    // Always allow paths to trigger DMSAA.
1801cb93a386Sopenharmony_ci    GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(aa);
1802cb93a386Sopenharmony_ci
1803cb93a386Sopenharmony_ci    PathRenderer::CanDrawPathArgs canDrawArgs;
1804cb93a386Sopenharmony_ci    canDrawArgs.fCaps = this->caps();
1805cb93a386Sopenharmony_ci    canDrawArgs.fProxy = this->asRenderTargetProxy();
1806cb93a386Sopenharmony_ci    canDrawArgs.fViewMatrix = &viewMatrix;
1807cb93a386Sopenharmony_ci    canDrawArgs.fShape = &shape;
1808cb93a386Sopenharmony_ci    canDrawArgs.fPaint = &paint;
1809cb93a386Sopenharmony_ci    canDrawArgs.fSurfaceProps = &fSurfaceProps;
1810cb93a386Sopenharmony_ci    canDrawArgs.fClipConservativeBounds = &clipConservativeBounds;
1811cb93a386Sopenharmony_ci    canDrawArgs.fHasUserStencilSettings = false;
1812cb93a386Sopenharmony_ci    canDrawArgs.fAAType = aaType;
1813cb93a386Sopenharmony_ci
1814cb93a386Sopenharmony_ci    constexpr static bool kDisallowSWPathRenderer = false;
1815cb93a386Sopenharmony_ci    constexpr static bool kAllowSWPathRenderer = true;
1816cb93a386Sopenharmony_ci    using DrawType = PathRendererChain::DrawType;
1817cb93a386Sopenharmony_ci
1818cb93a386Sopenharmony_ci    PathRenderer* pr = nullptr;
1819cb93a386Sopenharmony_ci
1820cb93a386Sopenharmony_ci    if (!shape.style().strokeRec().isFillStyle() && !shape.isEmpty()) {
1821cb93a386Sopenharmony_ci        // Give the tessellation path renderer a chance to claim this stroke before we simplify it.
1822cb93a386Sopenharmony_ci        PathRenderer* tess = this->drawingManager()->getTessellationPathRenderer();
1823cb93a386Sopenharmony_ci        if (tess && tess->canDrawPath(canDrawArgs) == PathRenderer::CanDrawPath::kYes) {
1824cb93a386Sopenharmony_ci            pr = tess;
1825cb93a386Sopenharmony_ci        }
1826cb93a386Sopenharmony_ci    }
1827cb93a386Sopenharmony_ci
1828cb93a386Sopenharmony_ci    if (!pr) {
1829cb93a386Sopenharmony_ci        // The shape isn't a stroke that can be drawn directly. Simplify if possible.
1830cb93a386Sopenharmony_ci        shape.simplify();
1831cb93a386Sopenharmony_ci
1832cb93a386Sopenharmony_ci        if (shape.isEmpty() && !shape.inverseFilled()) {
1833cb93a386Sopenharmony_ci            return;
1834cb93a386Sopenharmony_ci        }
1835cb93a386Sopenharmony_ci
1836cb93a386Sopenharmony_ci        if (attemptDrawSimple || shape.simplified()) {
1837cb93a386Sopenharmony_ci            // Usually we enter drawShapeUsingPathRenderer() because the shape+style was too complex
1838cb93a386Sopenharmony_ci            // for dedicated draw ops. However, if GrStyledShape was able to reduce something we
1839cb93a386Sopenharmony_ci            // ought to try again instead of going right to path rendering.
1840cb93a386Sopenharmony_ci            if (this->drawSimpleShape(clip, &paint, aa, viewMatrix, shape)) {
1841cb93a386Sopenharmony_ci                return;
1842cb93a386Sopenharmony_ci            }
1843cb93a386Sopenharmony_ci        }
1844cb93a386Sopenharmony_ci
1845cb93a386Sopenharmony_ci        // Try a 1st time without applying any of the style to the geometry (and barring sw)
1846cb93a386Sopenharmony_ci        pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer,
1847cb93a386Sopenharmony_ci                                                     DrawType::kColor);
1848cb93a386Sopenharmony_ci    }
1849cb93a386Sopenharmony_ci
1850cb93a386Sopenharmony_ci    SkScalar styleScale =  GrStyle::MatrixToScaleFactor(viewMatrix);
1851cb93a386Sopenharmony_ci    if (styleScale == 0.0f) {
1852cb93a386Sopenharmony_ci        return;
1853cb93a386Sopenharmony_ci    }
1854cb93a386Sopenharmony_ci
1855cb93a386Sopenharmony_ci    if (!pr && shape.style().pathEffect()) {
1856cb93a386Sopenharmony_ci        // It didn't work above, so try again with the path effect applied.
1857cb93a386Sopenharmony_ci        shape = shape.applyStyle(GrStyle::Apply::kPathEffectOnly, styleScale);
1858cb93a386Sopenharmony_ci        if (shape.isEmpty()) {
1859cb93a386Sopenharmony_ci            return;
1860cb93a386Sopenharmony_ci        }
1861cb93a386Sopenharmony_ci        pr = this->drawingManager()->getPathRenderer(canDrawArgs, kDisallowSWPathRenderer,
1862cb93a386Sopenharmony_ci                                                     DrawType::kColor);
1863cb93a386Sopenharmony_ci    }
1864cb93a386Sopenharmony_ci    if (!pr) {
1865cb93a386Sopenharmony_ci        if (shape.style().applies()) {
1866cb93a386Sopenharmony_ci            shape = shape.applyStyle(GrStyle::Apply::kPathEffectAndStrokeRec, styleScale);
1867cb93a386Sopenharmony_ci            if (shape.isEmpty()) {
1868cb93a386Sopenharmony_ci                return;
1869cb93a386Sopenharmony_ci            }
1870cb93a386Sopenharmony_ci            // This time, allow SW renderer
1871cb93a386Sopenharmony_ci            pr = this->drawingManager()->getPathRenderer(canDrawArgs, kAllowSWPathRenderer,
1872cb93a386Sopenharmony_ci                                                         DrawType::kColor);
1873cb93a386Sopenharmony_ci        } else {
1874cb93a386Sopenharmony_ci            pr = this->drawingManager()->getSoftwarePathRenderer();
1875cb93a386Sopenharmony_ci#if GR_PATH_RENDERER_SPEW
1876cb93a386Sopenharmony_ci            SkDebugf("falling back to: %s\n", pr->name());
1877cb93a386Sopenharmony_ci#endif
1878cb93a386Sopenharmony_ci        }
1879cb93a386Sopenharmony_ci    }
1880cb93a386Sopenharmony_ci
1881cb93a386Sopenharmony_ci    if (!pr) {
1882cb93a386Sopenharmony_ci#ifdef SK_DEBUG
1883cb93a386Sopenharmony_ci        SkDebugf("Unable to find path renderer compatible with path.\n");
1884cb93a386Sopenharmony_ci#endif
1885cb93a386Sopenharmony_ci        return;
1886cb93a386Sopenharmony_ci    }
1887cb93a386Sopenharmony_ci
1888cb93a386Sopenharmony_ci    PathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
1889cb93a386Sopenharmony_ci                                    std::move(paint),
1890cb93a386Sopenharmony_ci                                    &GrUserStencilSettings::kUnused,
1891cb93a386Sopenharmony_ci                                    this,
1892cb93a386Sopenharmony_ci                                    clip,
1893cb93a386Sopenharmony_ci                                    &clipConservativeBounds,
1894cb93a386Sopenharmony_ci                                    &viewMatrix,
1895cb93a386Sopenharmony_ci                                    canDrawArgs.fShape,
1896cb93a386Sopenharmony_ci                                    aaType,
1897cb93a386Sopenharmony_ci                                    this->colorInfo().isLinearlyBlended()};
1898cb93a386Sopenharmony_ci    pr->drawPath(args);
1899cb93a386Sopenharmony_ci}
1900cb93a386Sopenharmony_ci
1901cb93a386Sopenharmony_civoid SurfaceDrawContext::addDrawOp(const GrClip* clip,
1902cb93a386Sopenharmony_ci                                   GrOp::Owner op,
1903cb93a386Sopenharmony_ci                                   const std::function<WillAddOpFn>& willAddFn) {
1904cb93a386Sopenharmony_ci    ASSERT_SINGLE_OWNER
1905cb93a386Sopenharmony_ci    if (fContext->abandoned()) {
1906cb93a386Sopenharmony_ci        return;
1907cb93a386Sopenharmony_ci    }
1908cb93a386Sopenharmony_ci    GrDrawOp* drawOp = (GrDrawOp*)op.get();
1909cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
1910cb93a386Sopenharmony_ci    SkDEBUGCODE(drawOp->fAddDrawOpCalled = true;)
1911cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("SurfaceDrawContext", "addDrawOp", fContext);
1912cb93a386Sopenharmony_ci
1913cb93a386Sopenharmony_ci    // Setup clip
1914cb93a386Sopenharmony_ci    SkRect bounds;
1915cb93a386Sopenharmony_ci    op_bounds(&bounds, op.get());
1916cb93a386Sopenharmony_ci    GrAppliedClip appliedClip(this->dimensions(), this->asSurfaceProxy()->backingStoreDimensions());
1917cb93a386Sopenharmony_ci    const bool opUsesMSAA = drawOp->usesMSAA();
1918cb93a386Sopenharmony_ci    bool skipDraw = false;
1919cb93a386Sopenharmony_ci    if (clip) {
1920cb93a386Sopenharmony_ci        // Have a complex clip, so defer to its early clip culling
1921cb93a386Sopenharmony_ci        GrAAType aaType;
1922cb93a386Sopenharmony_ci        if (opUsesMSAA) {
1923cb93a386Sopenharmony_ci            aaType = GrAAType::kMSAA;
1924cb93a386Sopenharmony_ci        } else {
1925cb93a386Sopenharmony_ci            aaType = op->hasAABloat() ? GrAAType::kCoverage : GrAAType::kNone;
1926cb93a386Sopenharmony_ci        }
1927cb93a386Sopenharmony_ci        skipDraw = clip->apply(fContext, this, drawOp, aaType,
1928cb93a386Sopenharmony_ci                               &appliedClip, &bounds) == GrClip::Effect::kClippedOut;
1929cb93a386Sopenharmony_ci    } else {
1930cb93a386Sopenharmony_ci        // No clipping, so just clip the bounds against the logical render target dimensions
1931cb93a386Sopenharmony_ci        skipDraw = !bounds.intersect(this->asSurfaceProxy()->getBoundsRect());
1932cb93a386Sopenharmony_ci    }
1933cb93a386Sopenharmony_ci
1934cb93a386Sopenharmony_ci    if (skipDraw) {
1935cb93a386Sopenharmony_ci        return;
1936cb93a386Sopenharmony_ci    }
1937cb93a386Sopenharmony_ci
1938cb93a386Sopenharmony_ci    GrClampType clampType = GrColorTypeClampType(this->colorInfo().colorType());
1939cb93a386Sopenharmony_ci    GrProcessorSet::Analysis analysis = drawOp->finalize(*this->caps(), &appliedClip, clampType);
1940cb93a386Sopenharmony_ci
1941cb93a386Sopenharmony_ci    const bool opUsesStencil = drawOp->usesStencil();
1942cb93a386Sopenharmony_ci
1943cb93a386Sopenharmony_ci    // Always trigger DMSAA when there is stencil. This ensures stencil contents get properly
1944cb93a386Sopenharmony_ci    // preserved between render passes, if needed.
1945cb93a386Sopenharmony_ci    const bool drawNeedsMSAA = opUsesMSAA || (fCanUseDynamicMSAA && opUsesStencil);
1946cb93a386Sopenharmony_ci
1947cb93a386Sopenharmony_ci    // Must be called before setDstProxyView so that it sees the final bounds of the op.
1948cb93a386Sopenharmony_ci    op->setClippedBounds(bounds);
1949cb93a386Sopenharmony_ci
1950cb93a386Sopenharmony_ci    // Determine if the Op will trigger the use of a separate DMSAA attachment that requires manual
1951cb93a386Sopenharmony_ci    // resolves.
1952cb93a386Sopenharmony_ci    // TODO: Currently usesAttachmentIfDMSAA checks if this is a textureProxy or not. This check is
1953cb93a386Sopenharmony_ci    // really only for GL which uses a normal texture sampling when using barriers. For Vulkan it
1954cb93a386Sopenharmony_ci    // is possible to use the msaa buffer as an input attachment even if this is not a texture.
1955cb93a386Sopenharmony_ci    // However, support for that is not fully implemented yet in Vulkan. Once it is, this check
1956cb93a386Sopenharmony_ci    // should change to a virtual caps check that returns whether we need to break up an OpsTask
1957cb93a386Sopenharmony_ci    // if it has barriers and we are about to promote to MSAA.
1958cb93a386Sopenharmony_ci    bool usesAttachmentIfDMSAA =
1959cb93a386Sopenharmony_ci            fCanUseDynamicMSAA &&
1960cb93a386Sopenharmony_ci            (!this->caps()->msaaResolvesAutomatically() || !this->asTextureProxy());
1961cb93a386Sopenharmony_ci    bool opRequiresDMSAAAttachment = usesAttachmentIfDMSAA && drawNeedsMSAA;
1962cb93a386Sopenharmony_ci    bool opTriggersDMSAAAttachment =
1963cb93a386Sopenharmony_ci            opRequiresDMSAAAttachment && !this->getOpsTask()->usesMSAASurface();
1964cb93a386Sopenharmony_ci    if (opTriggersDMSAAAttachment) {
1965cb93a386Sopenharmony_ci        // This will be the op that actually triggers use of a DMSAA attachment. Texture barriers
1966cb93a386Sopenharmony_ci        // can't be moved to a DMSAA attachment, so if there already are any on the current opsTask
1967cb93a386Sopenharmony_ci        // then we need to split.
1968cb93a386Sopenharmony_ci        if (this->getOpsTask()->renderPassXferBarriers() & GrXferBarrierFlags::kTexture) {
1969cb93a386Sopenharmony_ci            SkASSERT(!this->getOpsTask()->isColorNoOp());
1970cb93a386Sopenharmony_ci            this->replaceOpsTask()->setCannotMergeBackward();
1971cb93a386Sopenharmony_ci        }
1972cb93a386Sopenharmony_ci    }
1973cb93a386Sopenharmony_ci
1974cb93a386Sopenharmony_ci    GrDstProxyView dstProxyView;
1975cb93a386Sopenharmony_ci    if (analysis.requiresDstTexture()) {
1976cb93a386Sopenharmony_ci        if (!this->setupDstProxyView(drawOp->bounds(), drawNeedsMSAA, &dstProxyView)) {
1977cb93a386Sopenharmony_ci            return;
1978cb93a386Sopenharmony_ci        }
1979cb93a386Sopenharmony_ci#ifdef SK_DEBUG
1980cb93a386Sopenharmony_ci        if (fCanUseDynamicMSAA && drawNeedsMSAA && !this->caps()->msaaResolvesAutomatically()) {
1981cb93a386Sopenharmony_ci            // Since we aren't literally writing to the render target texture while using a DMSAA
1982cb93a386Sopenharmony_ci            // attachment, we need to resolve that texture before sampling it. Ensure the current
1983cb93a386Sopenharmony_ci            // opsTask got closed off in order to initiate an implicit resolve.
1984cb93a386Sopenharmony_ci            SkASSERT(this->getOpsTask()->isEmpty());
1985cb93a386Sopenharmony_ci        }
1986cb93a386Sopenharmony_ci#endif
1987cb93a386Sopenharmony_ci    }
1988cb93a386Sopenharmony_ci
1989cb93a386Sopenharmony_ci    auto opsTask = this->getOpsTask();
1990cb93a386Sopenharmony_ci    if (willAddFn) {
1991cb93a386Sopenharmony_ci        willAddFn(op.get(), opsTask->uniqueID());
1992cb93a386Sopenharmony_ci    }
1993cb93a386Sopenharmony_ci
1994cb93a386Sopenharmony_ci    // Note if the op needs stencil. Stencil clipping already called setNeedsStencil for itself, if
1995cb93a386Sopenharmony_ci    // needed.
1996cb93a386Sopenharmony_ci    if (opUsesStencil) {
1997cb93a386Sopenharmony_ci        this->setNeedsStencil();
1998cb93a386Sopenharmony_ci    }
1999cb93a386Sopenharmony_ci
2000cb93a386Sopenharmony_ci#if GR_GPU_STATS && GR_TEST_UTILS
2001cb93a386Sopenharmony_ci    if (fCanUseDynamicMSAA && drawNeedsMSAA) {
2002cb93a386Sopenharmony_ci        if (!opsTask->usesMSAASurface()) {
2003cb93a386Sopenharmony_ci            fContext->priv().dmsaaStats().fNumMultisampleRenderPasses++;
2004cb93a386Sopenharmony_ci        }
2005cb93a386Sopenharmony_ci        fContext->priv().dmsaaStats().fTriggerCounts[op->name()]++;
2006cb93a386Sopenharmony_ci    }
2007cb93a386Sopenharmony_ci#endif
2008cb93a386Sopenharmony_ci    auto direct = fContext->priv().asDirectContext();
2009cb93a386Sopenharmony_ci    if (direct && op) {
2010cb93a386Sopenharmony_ci        op->setGrOpTag(direct->getCurrentGrResourceTag());
2011cb93a386Sopenharmony_ci    }
2012cb93a386Sopenharmony_ci    opsTask->addDrawOp(this->drawingManager(), std::move(op), drawNeedsMSAA, analysis,
2013cb93a386Sopenharmony_ci                       std::move(appliedClip), dstProxyView,
2014cb93a386Sopenharmony_ci                       GrTextureResolveManager(this->drawingManager()), *this->caps());
2015cb93a386Sopenharmony_ci
2016cb93a386Sopenharmony_ci#ifdef SK_DEBUG
2017cb93a386Sopenharmony_ci    if (fCanUseDynamicMSAA && drawNeedsMSAA) {
2018cb93a386Sopenharmony_ci        SkASSERT(opsTask->usesMSAASurface());
2019cb93a386Sopenharmony_ci    }
2020cb93a386Sopenharmony_ci#endif
2021cb93a386Sopenharmony_ci}
2022cb93a386Sopenharmony_ci
2023cb93a386Sopenharmony_cibool SurfaceDrawContext::setupDstProxyView(const SkRect& opBounds,
2024cb93a386Sopenharmony_ci                                           bool opRequiresMSAA,
2025cb93a386Sopenharmony_ci                                           GrDstProxyView* dstProxyView) {
2026cb93a386Sopenharmony_ci    // If we are wrapping a vulkan secondary command buffer, we can't make a dst copy because we
2027cb93a386Sopenharmony_ci    // don't actually have a VkImage to make a copy of. Additionally we don't have the power to
2028cb93a386Sopenharmony_ci    // start and stop the render pass in order to make the copy.
2029cb93a386Sopenharmony_ci    if (this->asRenderTargetProxy()->wrapsVkSecondaryCB()) {
2030cb93a386Sopenharmony_ci        return false;
2031cb93a386Sopenharmony_ci    }
2032cb93a386Sopenharmony_ci
2033cb93a386Sopenharmony_ci    // First get the dstSampleFlags as if we will put the draw into the current OpsTask
2034cb93a386Sopenharmony_ci    auto dstSampleFlags = this->caps()->getDstSampleFlagsForProxy(
2035cb93a386Sopenharmony_ci            this->asRenderTargetProxy(), this->getOpsTask()->usesMSAASurface() || opRequiresMSAA);
2036cb93a386Sopenharmony_ci
2037cb93a386Sopenharmony_ci    // If we don't have barriers for this draw then we will definitely be breaking up the OpsTask.
2038cb93a386Sopenharmony_ci    // However, if using dynamic MSAA, the new OpsTask will not have MSAA already enabled on it
2039cb93a386Sopenharmony_ci    // and that may allow us to use texture barriers. So we check if we can use barriers on the new
2040cb93a386Sopenharmony_ci    // ops task and then break it up if so.
2041cb93a386Sopenharmony_ci    if (!(dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) &&
2042cb93a386Sopenharmony_ci        fCanUseDynamicMSAA && this->getOpsTask()->usesMSAASurface() && !opRequiresMSAA) {
2043cb93a386Sopenharmony_ci        auto newFlags =
2044cb93a386Sopenharmony_ci                this->caps()->getDstSampleFlagsForProxy(this->asRenderTargetProxy(),
2045cb93a386Sopenharmony_ci                                                        false/*=opRequiresMSAA*/);
2046cb93a386Sopenharmony_ci        if (newFlags & GrDstSampleFlags::kRequiresTextureBarrier) {
2047cb93a386Sopenharmony_ci            // We can't have an empty ops task if we are in DMSAA and the ops task already returns
2048cb93a386Sopenharmony_ci            // true for usesMSAASurface.
2049cb93a386Sopenharmony_ci            SkASSERT(!this->getOpsTask()->isColorNoOp());
2050cb93a386Sopenharmony_ci            this->replaceOpsTask()->setCannotMergeBackward();
2051cb93a386Sopenharmony_ci            dstSampleFlags = newFlags;
2052cb93a386Sopenharmony_ci        }
2053cb93a386Sopenharmony_ci    }
2054cb93a386Sopenharmony_ci
2055cb93a386Sopenharmony_ci    if (dstSampleFlags & GrDstSampleFlags::kRequiresTextureBarrier) {
2056cb93a386Sopenharmony_ci        // If we require a barrier to sample the dst it means we are sampling the RT itself
2057cb93a386Sopenharmony_ci        // either as a texture or input attachment. In this case we don't need to break up the
2058cb93a386Sopenharmony_ci        // OpsTask.
2059cb93a386Sopenharmony_ci        dstProxyView->setProxyView(this->readSurfaceView());
2060cb93a386Sopenharmony_ci        dstProxyView->setOffset(0, 0);
2061cb93a386Sopenharmony_ci        dstProxyView->setDstSampleFlags(dstSampleFlags);
2062cb93a386Sopenharmony_ci        return true;
2063cb93a386Sopenharmony_ci    }
2064cb93a386Sopenharmony_ci    SkASSERT(dstSampleFlags == GrDstSampleFlags::kNone);
2065cb93a386Sopenharmony_ci
2066cb93a386Sopenharmony_ci    // We are using a different surface from the main color attachment to sample the dst from. If we
2067cb93a386Sopenharmony_ci    // are in DMSAA we can just use the single sampled RT texture itself. Otherwise, we must do a
2068cb93a386Sopenharmony_ci    // copy.
2069cb93a386Sopenharmony_ci    // We do have to check if we ended up here becasue we don't have texture barriers but do have
2070cb93a386Sopenharmony_ci    // msaaResolvesAutomatically (i.e. render-to-msaa-texture). In that case there will be no op or
2071cb93a386Sopenharmony_ci    // barrier between draws to flush the render target before being used as a texture in the next
2072cb93a386Sopenharmony_ci    // draw. So in that case we just fall through to doing a copy.
2073cb93a386Sopenharmony_ci    if (fCanUseDynamicMSAA && opRequiresMSAA && this->asTextureProxy() &&
2074cb93a386Sopenharmony_ci        !this->caps()->msaaResolvesAutomatically() &&
2075cb93a386Sopenharmony_ci        this->caps()->dmsaaResolveCanBeUsedAsTextureInSameRenderPass()) {
2076cb93a386Sopenharmony_ci        this->replaceOpsTaskIfModifiesColor()->setCannotMergeBackward();
2077cb93a386Sopenharmony_ci        dstProxyView->setProxyView(this->readSurfaceView());
2078cb93a386Sopenharmony_ci        dstProxyView->setOffset(0, 0);
2079cb93a386Sopenharmony_ci        dstProxyView->setDstSampleFlags(dstSampleFlags);
2080cb93a386Sopenharmony_ci        return true;
2081cb93a386Sopenharmony_ci    }
2082cb93a386Sopenharmony_ci
2083cb93a386Sopenharmony_ci    // Now we fallback to doing a copy.
2084cb93a386Sopenharmony_ci
2085cb93a386Sopenharmony_ci    GrColorType colorType = this->colorInfo().colorType();
2086cb93a386Sopenharmony_ci    // MSAA consideration: When there is support for reading MSAA samples in the shader we could
2087cb93a386Sopenharmony_ci    // have per-sample dst values by making the copy multisampled.
2088cb93a386Sopenharmony_ci    GrCaps::DstCopyRestrictions restrictions = this->caps()->getDstCopyRestrictions(
2089cb93a386Sopenharmony_ci            this->asRenderTargetProxy(), colorType);
2090cb93a386Sopenharmony_ci
2091cb93a386Sopenharmony_ci    SkIRect copyRect = SkIRect::MakeSize(this->asSurfaceProxy()->backingStoreDimensions());
2092cb93a386Sopenharmony_ci    if (!restrictions.fMustCopyWholeSrc) {
2093cb93a386Sopenharmony_ci        // If we don't need the whole source, restrict to the op's bounds. We add an extra pixel
2094cb93a386Sopenharmony_ci        // of padding to account for AA bloat and the unpredictable rounding of coords near pixel
2095cb93a386Sopenharmony_ci        // centers during rasterization.
2096cb93a386Sopenharmony_ci        SkIRect conservativeDrawBounds = opBounds.roundOut();
2097cb93a386Sopenharmony_ci        conservativeDrawBounds.outset(1, 1);
2098cb93a386Sopenharmony_ci        SkAssertResult(copyRect.intersect(conservativeDrawBounds));
2099cb93a386Sopenharmony_ci    }
2100cb93a386Sopenharmony_ci
2101cb93a386Sopenharmony_ci    SkIPoint dstOffset;
2102cb93a386Sopenharmony_ci    SkBackingFit fit;
2103cb93a386Sopenharmony_ci    if (restrictions.fRectsMustMatch == GrSurfaceProxy::RectsMustMatch::kYes) {
2104cb93a386Sopenharmony_ci        dstOffset = {0, 0};
2105cb93a386Sopenharmony_ci        fit = SkBackingFit::kExact;
2106cb93a386Sopenharmony_ci    } else {
2107cb93a386Sopenharmony_ci        dstOffset = {copyRect.fLeft, copyRect.fTop};
2108cb93a386Sopenharmony_ci        fit = SkBackingFit::kApprox;
2109cb93a386Sopenharmony_ci    }
2110cb93a386Sopenharmony_ci    auto copy = GrSurfaceProxy::Copy(fContext,
2111cb93a386Sopenharmony_ci                                     this->asSurfaceProxyRef(),
2112cb93a386Sopenharmony_ci                                     this->origin(),
2113cb93a386Sopenharmony_ci                                     GrMipmapped::kNo,
2114cb93a386Sopenharmony_ci                                     copyRect,
2115cb93a386Sopenharmony_ci                                     fit,
2116cb93a386Sopenharmony_ci                                     SkBudgeted::kYes,
2117cb93a386Sopenharmony_ci                                     restrictions.fRectsMustMatch);
2118cb93a386Sopenharmony_ci    SkASSERT(copy);
2119cb93a386Sopenharmony_ci
2120cb93a386Sopenharmony_ci    dstProxyView->setProxyView({std::move(copy), this->origin(), this->readSwizzle()});
2121cb93a386Sopenharmony_ci    dstProxyView->setOffset(dstOffset);
2122cb93a386Sopenharmony_ci    dstProxyView->setDstSampleFlags(dstSampleFlags);
2123cb93a386Sopenharmony_ci    return true;
2124cb93a386Sopenharmony_ci}
2125cb93a386Sopenharmony_ci
2126cb93a386Sopenharmony_ciOpsTask* SurfaceDrawContext::replaceOpsTaskIfModifiesColor() {
2127cb93a386Sopenharmony_ci    if (!this->getOpsTask()->isColorNoOp()) {
2128cb93a386Sopenharmony_ci        this->replaceOpsTask();
2129cb93a386Sopenharmony_ci    }
2130cb93a386Sopenharmony_ci    return this->getOpsTask();
2131cb93a386Sopenharmony_ci}
2132cb93a386Sopenharmony_ci
2133cb93a386Sopenharmony_cibool SurfaceDrawContext::drawBlurImage(GrSurfaceProxyView proxyView, const SkBlurArg& blurArg)
2134cb93a386Sopenharmony_ci{
2135cb93a386Sopenharmony_ci    if (!this->caps()->supportsHpsBlur(&proxyView)) {
2136cb93a386Sopenharmony_ci        SK_LOGD("ERROR: check HpsBlur fail.\n");
2137cb93a386Sopenharmony_ci        return false;
2138cb93a386Sopenharmony_ci    }
2139cb93a386Sopenharmony_ci    this->addOp(GrOp::Make<BlurOp>(fContext, std::move(proxyView), blurArg));
2140cb93a386Sopenharmony_ci    return true;
2141cb93a386Sopenharmony_ci}
2142cb93a386Sopenharmony_ci
2143cb93a386Sopenharmony_ci} // namespace skgpu::v1
2144