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/GrDrawingManager.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include <algorithm>
11cb93a386Sopenharmony_ci#include <memory>
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include "include/core/SkDeferredDisplayList.h"
14cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSemaphore.h"
15cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
16cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h"
17cb93a386Sopenharmony_ci#include "src/core/SkDeferredDisplayListPriv.h"
18cb93a386Sopenharmony_ci#include "src/core/SkTInternalLList.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrClientMappedBufferManager.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrCopyRenderTask.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrDDLTask.h"
22cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
23cb93a386Sopenharmony_ci#include "src/gpu/GrGpu.h"
24cb93a386Sopenharmony_ci#include "src/gpu/GrMemoryPool.h"
25cb93a386Sopenharmony_ci#include "src/gpu/GrOnFlushResourceProvider.h"
26cb93a386Sopenharmony_ci#include "src/gpu/GrOpFlushState.h"
27cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
28cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTargetProxy.h"
29cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTask.h"
30cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTaskCluster.h"
31cb93a386Sopenharmony_ci#include "src/gpu/GrResourceAllocator.h"
32cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
33cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h"
34cb93a386Sopenharmony_ci#include "src/gpu/GrTTopoSort.h"
35cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h"
36cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h"
37cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxyPriv.h"
38cb93a386Sopenharmony_ci#include "src/gpu/GrTextureResolveRenderTask.h"
39cb93a386Sopenharmony_ci#include "src/gpu/GrTracing.h"
40cb93a386Sopenharmony_ci#include "src/gpu/GrTransferFromRenderTask.h"
41cb93a386Sopenharmony_ci#include "src/gpu/GrWaitRenderTask.h"
42cb93a386Sopenharmony_ci#include "src/gpu/GrWritePixelsRenderTask.h"
43cb93a386Sopenharmony_ci#include "src/gpu/text/GrSDFTControl.h"
44cb93a386Sopenharmony_ci#include "src/image/SkSurface_Gpu.h"
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci#if SK_GPU_V1
47cb93a386Sopenharmony_ci#include "src/gpu/ops/OpsTask.h"
48cb93a386Sopenharmony_ci#include "src/gpu/ops/SoftwarePathRenderer.h"
49cb93a386Sopenharmony_ci#endif
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////////////////////////
52cb93a386Sopenharmony_ci#if SK_GPU_V1
53cb93a386Sopenharmony_ciGrDrawingManager::GrDrawingManager(GrRecordingContext* rContext,
54cb93a386Sopenharmony_ci                                   const PathRendererChain::Options& optionsForPathRendererChain,
55cb93a386Sopenharmony_ci                                   bool reduceOpsTaskSplitting)
56cb93a386Sopenharmony_ci        : fContext(rContext)
57cb93a386Sopenharmony_ci        , fOptionsForPathRendererChain(optionsForPathRendererChain)
58cb93a386Sopenharmony_ci        , fPathRendererChain(nullptr)
59cb93a386Sopenharmony_ci        , fSoftwarePathRenderer(nullptr)
60cb93a386Sopenharmony_ci        , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) {
61cb93a386Sopenharmony_ci}
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci#else
64cb93a386Sopenharmony_ci
65cb93a386Sopenharmony_ciGrDrawingManager::GrDrawingManager(GrRecordingContext* rContext, bool reduceOpsTaskSplitting)
66cb93a386Sopenharmony_ci        : fContext(rContext)
67cb93a386Sopenharmony_ci        , fReduceOpsTaskSplitting(reduceOpsTaskSplitting) {
68cb93a386Sopenharmony_ci}
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci#endif
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ciGrDrawingManager::~GrDrawingManager() {
73cb93a386Sopenharmony_ci    this->closeAllTasks();
74cb93a386Sopenharmony_ci    this->removeRenderTasks();
75cb93a386Sopenharmony_ci}
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_cibool GrDrawingManager::wasAbandoned() const {
78cb93a386Sopenharmony_ci    return fContext->abandoned();
79cb93a386Sopenharmony_ci}
80cb93a386Sopenharmony_ci
81cb93a386Sopenharmony_civoid GrDrawingManager::freeGpuResources() {
82cb93a386Sopenharmony_ci    for (int i = fOnFlushCBObjects.count() - 1; i >= 0; --i) {
83cb93a386Sopenharmony_ci        if (!fOnFlushCBObjects[i]->retainOnFreeGpuResources()) {
84cb93a386Sopenharmony_ci            // it's safe to just do this because we're iterating in reverse
85cb93a386Sopenharmony_ci            fOnFlushCBObjects.removeShuffle(i);
86cb93a386Sopenharmony_ci        }
87cb93a386Sopenharmony_ci    }
88cb93a386Sopenharmony_ci
89cb93a386Sopenharmony_ci#if SK_GPU_V1
90cb93a386Sopenharmony_ci    // a path renderer may be holding onto resources
91cb93a386Sopenharmony_ci    fPathRendererChain = nullptr;
92cb93a386Sopenharmony_ci    fSoftwarePathRenderer = nullptr;
93cb93a386Sopenharmony_ci#endif
94cb93a386Sopenharmony_ci}
95cb93a386Sopenharmony_ci
96cb93a386Sopenharmony_ci// MDB TODO: make use of the 'proxies' parameter.
97cb93a386Sopenharmony_cibool GrDrawingManager::flush(
98cb93a386Sopenharmony_ci        SkSpan<GrSurfaceProxy*> proxies,
99cb93a386Sopenharmony_ci        SkSurface::BackendSurfaceAccess access,
100cb93a386Sopenharmony_ci        const GrFlushInfo& info,
101cb93a386Sopenharmony_ci        const GrBackendSurfaceMutableState* newState) {
102cb93a386Sopenharmony_ci    GR_CREATE_TRACE_MARKER_CONTEXT("GrDrawingManager", "flush", fContext);
103cb93a386Sopenharmony_ci
104cb93a386Sopenharmony_ci    if (fFlushing || this->wasAbandoned()) {
105cb93a386Sopenharmony_ci        if (info.fSubmittedProc) {
106cb93a386Sopenharmony_ci            info.fSubmittedProc(info.fSubmittedContext, false);
107cb93a386Sopenharmony_ci        }
108cb93a386Sopenharmony_ci        if (info.fFinishedProc) {
109cb93a386Sopenharmony_ci            info.fFinishedProc(info.fFinishedContext);
110cb93a386Sopenharmony_ci        }
111cb93a386Sopenharmony_ci        return false;
112cb93a386Sopenharmony_ci    }
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci    // As of now we only short-circuit if we got an explicit list of surfaces to flush.
117cb93a386Sopenharmony_ci    if (!proxies.empty() && !info.fNumSemaphores && !info.fFinishedProc &&
118cb93a386Sopenharmony_ci        access == SkSurface::BackendSurfaceAccess::kNoAccess && !newState) {
119cb93a386Sopenharmony_ci        bool allUnused = std::all_of(proxies.begin(), proxies.end(), [&](GrSurfaceProxy* proxy) {
120cb93a386Sopenharmony_ci            bool used = std::any_of(fDAG.begin(), fDAG.end(), [&](auto& task) {
121cb93a386Sopenharmony_ci                return task && task->isUsed(proxy);
122cb93a386Sopenharmony_ci            });
123cb93a386Sopenharmony_ci            return !used;
124cb93a386Sopenharmony_ci        });
125cb93a386Sopenharmony_ci        if (allUnused) {
126cb93a386Sopenharmony_ci            if (info.fSubmittedProc) {
127cb93a386Sopenharmony_ci                info.fSubmittedProc(info.fSubmittedContext, true);
128cb93a386Sopenharmony_ci            }
129cb93a386Sopenharmony_ci            return false;
130cb93a386Sopenharmony_ci        }
131cb93a386Sopenharmony_ci    }
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    auto dContext = fContext->asDirectContext();
134cb93a386Sopenharmony_ci    SkASSERT(dContext);
135cb93a386Sopenharmony_ci    dContext->priv().clientMappedBufferManager()->process();
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    GrGpu* gpu = dContext->priv().getGpu();
138cb93a386Sopenharmony_ci    // We have a non abandoned and direct GrContext. It must have a GrGpu.
139cb93a386Sopenharmony_ci    SkASSERT(gpu);
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_ci    fFlushing = true;
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_ci    auto resourceProvider = dContext->priv().resourceProvider();
144cb93a386Sopenharmony_ci    auto resourceCache = dContext->priv().getResourceCache();
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci    // Semi-usually the GrRenderTasks are already closed at this point, but sometimes Ganesh needs
147cb93a386Sopenharmony_ci    // to flush mid-draw. In that case, the SkGpuDevice's opsTasks won't be closed but need to be
148cb93a386Sopenharmony_ci    // flushed anyway. Closing such opsTasks here will mean new ones will be created to replace them
149cb93a386Sopenharmony_ci    // if the SkGpuDevice(s) write to them again.
150cb93a386Sopenharmony_ci    this->closeAllTasks();
151cb93a386Sopenharmony_ci    fActiveOpsTask = nullptr;
152cb93a386Sopenharmony_ci
153cb93a386Sopenharmony_ci    this->sortTasks();
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci    if (!fCpuBufferCache) {
156cb93a386Sopenharmony_ci        // We cache more buffers when the backend is using client side arrays. Otherwise, we
157cb93a386Sopenharmony_ci        // expect each pool will use a CPU buffer as a staging buffer before uploading to a GPU
158cb93a386Sopenharmony_ci        // buffer object. Each pool only requires one staging buffer at a time.
159cb93a386Sopenharmony_ci        int maxCachedBuffers = fContext->priv().caps()->preferClientSideDynamicBuffers() ? 2 : 6;
160cb93a386Sopenharmony_ci        fCpuBufferCache = GrBufferAllocPool::CpuBufferCache::Make(maxCachedBuffers);
161cb93a386Sopenharmony_ci    }
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci    GrOpFlushState flushState(gpu, resourceProvider, &fTokenTracker, fCpuBufferCache);
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci    GrOnFlushResourceProvider onFlushProvider(this);
166cb93a386Sopenharmony_ci
167cb93a386Sopenharmony_ci    // Prepare any onFlush op lists (e.g. atlases).
168cb93a386Sopenharmony_ci    if (!fOnFlushCBObjects.empty()) {
169cb93a386Sopenharmony_ci        fFlushingRenderTaskIDs.reserve_back(fDAG.count());
170cb93a386Sopenharmony_ci        for (const auto& task : fDAG) {
171cb93a386Sopenharmony_ci            if (task) {
172cb93a386Sopenharmony_ci                task->gatherIDs(&fFlushingRenderTaskIDs);
173cb93a386Sopenharmony_ci            }
174cb93a386Sopenharmony_ci        }
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ci        for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
177cb93a386Sopenharmony_ci            onFlushCBObject->preFlush(&onFlushProvider, SkMakeSpan(fFlushingRenderTaskIDs));
178cb93a386Sopenharmony_ci        }
179cb93a386Sopenharmony_ci        for (const auto& onFlushRenderTask : fOnFlushRenderTasks) {
180cb93a386Sopenharmony_ci            onFlushRenderTask->makeClosed(fContext);
181cb93a386Sopenharmony_ci#ifdef SK_DEBUG
182cb93a386Sopenharmony_ci            // OnFlush callbacks are invoked during flush, and are therefore expected to handle
183cb93a386Sopenharmony_ci            // resource allocation & usage on their own. (No deferred or lazy proxies!)
184cb93a386Sopenharmony_ci            onFlushRenderTask->visitTargetAndSrcProxies_debugOnly(
185cb93a386Sopenharmony_ci                    [](GrSurfaceProxy* p, GrMipmapped mipMapped) {
186cb93a386Sopenharmony_ci                SkASSERT(!p->asTextureProxy() || !p->asTextureProxy()->texPriv().isDeferred());
187cb93a386Sopenharmony_ci                SkASSERT(!p->isLazy());
188cb93a386Sopenharmony_ci                if (p->requiresManualMSAAResolve()) {
189cb93a386Sopenharmony_ci                    // The onFlush callback is responsible for ensuring MSAA gets resolved.
190cb93a386Sopenharmony_ci                    SkASSERT(p->asRenderTargetProxy() && !p->asRenderTargetProxy()->isMSAADirty());
191cb93a386Sopenharmony_ci                }
192cb93a386Sopenharmony_ci                if (GrMipmapped::kYes == mipMapped) {
193cb93a386Sopenharmony_ci                    // The onFlush callback is responsible for regenerating mips if needed.
194cb93a386Sopenharmony_ci                    SkASSERT(p->asTextureProxy() && !p->asTextureProxy()->mipmapsAreDirty());
195cb93a386Sopenharmony_ci                }
196cb93a386Sopenharmony_ci            });
197cb93a386Sopenharmony_ci#endif
198cb93a386Sopenharmony_ci            onFlushRenderTask->prepare(&flushState);
199cb93a386Sopenharmony_ci        }
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci    bool usingReorderedDAG = false;
203cb93a386Sopenharmony_ci    GrResourceAllocator resourceAllocator(dContext);
204cb93a386Sopenharmony_ci    if (fReduceOpsTaskSplitting) {
205cb93a386Sopenharmony_ci        usingReorderedDAG = this->reorderTasks(&resourceAllocator);
206cb93a386Sopenharmony_ci        if (!usingReorderedDAG) {
207cb93a386Sopenharmony_ci            resourceAllocator.reset();
208cb93a386Sopenharmony_ci        }
209cb93a386Sopenharmony_ci    }
210cb93a386Sopenharmony_ci
211cb93a386Sopenharmony_ci#if 0
212cb93a386Sopenharmony_ci    // Enable this to print out verbose GrOp information
213cb93a386Sopenharmony_ci    SkDEBUGCODE(SkDebugf("onFlush renderTasks (%d):\n", fOnFlushRenderTasks.count()));
214cb93a386Sopenharmony_ci    for (const auto& onFlushRenderTask : fOnFlushRenderTasks) {
215cb93a386Sopenharmony_ci        SkDEBUGCODE(onFlushRenderTask->dump(/* printDependencies */ true);)
216cb93a386Sopenharmony_ci    }
217cb93a386Sopenharmony_ci    SkDEBUGCODE(SkDebugf("Normal renderTasks (%d):\n", fDAG.count()));
218cb93a386Sopenharmony_ci    for (const auto& task : fDAG) {
219cb93a386Sopenharmony_ci        SkDEBUGCODE(task->dump(/* printDependencies */ true);)
220cb93a386Sopenharmony_ci    }
221cb93a386Sopenharmony_ci#endif
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci    if (!resourceAllocator.failedInstantiation()) {
224cb93a386Sopenharmony_ci        if (!usingReorderedDAG) {
225cb93a386Sopenharmony_ci            for (const auto& task : fDAG) {
226cb93a386Sopenharmony_ci                SkASSERT(task);
227cb93a386Sopenharmony_ci                task->gatherProxyIntervals(&resourceAllocator);
228cb93a386Sopenharmony_ci            }
229cb93a386Sopenharmony_ci            resourceAllocator.planAssignment();
230cb93a386Sopenharmony_ci        }
231cb93a386Sopenharmony_ci        resourceAllocator.assign();
232cb93a386Sopenharmony_ci    }
233cb93a386Sopenharmony_ci    bool flushed = !resourceAllocator.failedInstantiation() &&
234cb93a386Sopenharmony_ci                    this->executeRenderTasks(&flushState);
235cb93a386Sopenharmony_ci    this->removeRenderTasks();
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ci    gpu->executeFlushInfo(proxies, access, info, newState);
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_ci    // Give the cache a chance to purge resources that become purgeable due to flushing.
240cb93a386Sopenharmony_ci    if (flushed) {
241cb93a386Sopenharmony_ci        resourceCache->purgeAsNeeded();
242cb93a386Sopenharmony_ci        flushed = false;
243cb93a386Sopenharmony_ci    }
244cb93a386Sopenharmony_ci    for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
245cb93a386Sopenharmony_ci        onFlushCBObject->postFlush(fTokenTracker.nextTokenToFlush(),
246cb93a386Sopenharmony_ci                                   SkMakeSpan(fFlushingRenderTaskIDs));
247cb93a386Sopenharmony_ci        flushed = true;
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci    if (flushed) {
250cb93a386Sopenharmony_ci        resourceCache->purgeAsNeeded();
251cb93a386Sopenharmony_ci    }
252cb93a386Sopenharmony_ci    fFlushingRenderTaskIDs.reset();
253cb93a386Sopenharmony_ci    fFlushing = false;
254cb93a386Sopenharmony_ci
255cb93a386Sopenharmony_ci    return true;
256cb93a386Sopenharmony_ci}
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_cibool GrDrawingManager::submitToGpu(bool syncToCpu) {
259cb93a386Sopenharmony_ci    if (fFlushing || this->wasAbandoned()) {
260cb93a386Sopenharmony_ci        return false;
261cb93a386Sopenharmony_ci    }
262cb93a386Sopenharmony_ci
263cb93a386Sopenharmony_ci    auto direct = fContext->asDirectContext();
264cb93a386Sopenharmony_ci    if (!direct) {
265cb93a386Sopenharmony_ci        return false; // Can't submit while DDL recording
266cb93a386Sopenharmony_ci    }
267cb93a386Sopenharmony_ci    GrGpu* gpu = direct->priv().getGpu();
268cb93a386Sopenharmony_ci    return gpu->submitToGpu(syncToCpu);
269cb93a386Sopenharmony_ci}
270cb93a386Sopenharmony_ci
271cb93a386Sopenharmony_cibool GrDrawingManager::executeRenderTasks(GrOpFlushState* flushState) {
272cb93a386Sopenharmony_ci#if GR_FLUSH_TIME_OP_SPEW
273cb93a386Sopenharmony_ci    SkDebugf("Flushing %d opsTasks\n", fDAG.count());
274cb93a386Sopenharmony_ci    for (int i = 0; i < fDAG.count(); ++i) {
275cb93a386Sopenharmony_ci        if (fDAG[i]) {
276cb93a386Sopenharmony_ci            SkString label;
277cb93a386Sopenharmony_ci            label.printf("task %d/%d", i, fDAG.count());
278cb93a386Sopenharmony_ci            fDAG[i]->dump(label, {}, true, true);
279cb93a386Sopenharmony_ci        }
280cb93a386Sopenharmony_ci    }
281cb93a386Sopenharmony_ci#endif
282cb93a386Sopenharmony_ci
283cb93a386Sopenharmony_ci    bool anyRenderTasksExecuted = false;
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    for (const auto& renderTask : fDAG) {
286cb93a386Sopenharmony_ci        if (!renderTask || !renderTask->isInstantiated()) {
287cb93a386Sopenharmony_ci             continue;
288cb93a386Sopenharmony_ci        }
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci        SkASSERT(renderTask->deferredProxiesAreInstantiated());
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci        renderTask->prepare(flushState);
293cb93a386Sopenharmony_ci    }
294cb93a386Sopenharmony_ci
295cb93a386Sopenharmony_ci    // Upload all data to the GPU
296cb93a386Sopenharmony_ci    flushState->preExecuteDraws();
297cb93a386Sopenharmony_ci
298cb93a386Sopenharmony_ci    // For Vulkan, if we have too many oplists to be flushed we end up allocating a lot of resources
299cb93a386Sopenharmony_ci    // for each command buffer associated with the oplists. If this gets too large we can cause the
300cb93a386Sopenharmony_ci    // devices to go OOM. In practice we usually only hit this case in our tests, but to be safe we
301cb93a386Sopenharmony_ci    // put a cap on the number of oplists we will execute before flushing to the GPU to relieve some
302cb93a386Sopenharmony_ci    // memory pressure.
303cb93a386Sopenharmony_ci    static constexpr int kMaxRenderTasksBeforeFlush = 100;
304cb93a386Sopenharmony_ci    int numRenderTasksExecuted = 0;
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    // Execute the onFlush renderTasks first, if any.
307cb93a386Sopenharmony_ci    for (sk_sp<GrRenderTask>& onFlushRenderTask : fOnFlushRenderTasks) {
308cb93a386Sopenharmony_ci        if (!onFlushRenderTask->execute(flushState)) {
309cb93a386Sopenharmony_ci            SkDebugf("WARNING: onFlushRenderTask failed to execute.\n");
310cb93a386Sopenharmony_ci        }
311cb93a386Sopenharmony_ci        SkASSERT(onFlushRenderTask->unique());
312cb93a386Sopenharmony_ci        onFlushRenderTask->disown(this);
313cb93a386Sopenharmony_ci        onFlushRenderTask = nullptr;
314cb93a386Sopenharmony_ci        if (++numRenderTasksExecuted >= kMaxRenderTasksBeforeFlush) {
315cb93a386Sopenharmony_ci            flushState->gpu()->submitToGpu(false);
316cb93a386Sopenharmony_ci            numRenderTasksExecuted = 0;
317cb93a386Sopenharmony_ci        }
318cb93a386Sopenharmony_ci    }
319cb93a386Sopenharmony_ci    fOnFlushRenderTasks.reset();
320cb93a386Sopenharmony_ci
321cb93a386Sopenharmony_ci    // Execute the normal op lists.
322cb93a386Sopenharmony_ci    for (const auto& renderTask : fDAG) {
323cb93a386Sopenharmony_ci        SkASSERT(renderTask);
324cb93a386Sopenharmony_ci        if (!renderTask->isInstantiated()) {
325cb93a386Sopenharmony_ci            continue;
326cb93a386Sopenharmony_ci        }
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_ci        if (renderTask->execute(flushState)) {
329cb93a386Sopenharmony_ci            anyRenderTasksExecuted = true;
330cb93a386Sopenharmony_ci        }
331cb93a386Sopenharmony_ci        if (++numRenderTasksExecuted >= kMaxRenderTasksBeforeFlush) {
332cb93a386Sopenharmony_ci            flushState->gpu()->submitToGpu(false);
333cb93a386Sopenharmony_ci            numRenderTasksExecuted = 0;
334cb93a386Sopenharmony_ci        }
335cb93a386Sopenharmony_ci    }
336cb93a386Sopenharmony_ci
337cb93a386Sopenharmony_ci    SkASSERT(!flushState->opsRenderPass());
338cb93a386Sopenharmony_ci    SkASSERT(fTokenTracker.nextDrawToken() == fTokenTracker.nextTokenToFlush());
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci    // We reset the flush state before the RenderTasks so that the last resources to be freed are
341cb93a386Sopenharmony_ci    // those that are written to in the RenderTasks. This helps to make sure the most recently used
342cb93a386Sopenharmony_ci    // resources are the last to be purged by the resource cache.
343cb93a386Sopenharmony_ci    flushState->reset();
344cb93a386Sopenharmony_ci
345cb93a386Sopenharmony_ci    return anyRenderTasksExecuted;
346cb93a386Sopenharmony_ci}
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_civoid GrDrawingManager::removeRenderTasks() {
349cb93a386Sopenharmony_ci    for (const auto& task : fDAG) {
350cb93a386Sopenharmony_ci        SkASSERT(task);
351cb93a386Sopenharmony_ci        if (!task->unique() || task->requiresExplicitCleanup()) {
352cb93a386Sopenharmony_ci            // TODO: Eventually uniqueness should be guaranteed: http://skbug.com/7111.
353cb93a386Sopenharmony_ci            // DDLs, however, will always require an explicit notification for when they
354cb93a386Sopenharmony_ci            // can clean up resources.
355cb93a386Sopenharmony_ci            task->endFlush(this);
356cb93a386Sopenharmony_ci        }
357cb93a386Sopenharmony_ci        task->disown(this);
358cb93a386Sopenharmony_ci    }
359cb93a386Sopenharmony_ci    fDAG.reset();
360cb93a386Sopenharmony_ci    fLastRenderTasks.reset();
361cb93a386Sopenharmony_ci    for (const sk_sp<GrRenderTask>& onFlushRenderTask : fOnFlushRenderTasks) {
362cb93a386Sopenharmony_ci        onFlushRenderTask->disown(this);
363cb93a386Sopenharmony_ci    }
364cb93a386Sopenharmony_ci    fOnFlushRenderTasks.reset();
365cb93a386Sopenharmony_ci}
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_civoid GrDrawingManager::sortTasks() {
368cb93a386Sopenharmony_ci    if (!GrTTopoSort<GrRenderTask, GrRenderTask::TopoSortTraits>(&fDAG)) {
369cb93a386Sopenharmony_ci        SkDEBUGFAIL("Render task topo sort failed.");
370cb93a386Sopenharmony_ci        return;
371cb93a386Sopenharmony_ci    }
372cb93a386Sopenharmony_ci
373cb93a386Sopenharmony_ci#if SK_GPU_V1 && defined(SK_DEBUG)
374cb93a386Sopenharmony_ci    // This block checks for any unnecessary splits in the opsTasks. If two sequential opsTasks
375cb93a386Sopenharmony_ci    // could have merged it means the opsTask was artificially split.
376cb93a386Sopenharmony_ci    if (!fDAG.empty()) {
377cb93a386Sopenharmony_ci        auto prevOpsTask = fDAG[0]->asOpsTask();
378cb93a386Sopenharmony_ci        for (int i = 1; i < fDAG.count(); ++i) {
379cb93a386Sopenharmony_ci            auto curOpsTask = fDAG[i]->asOpsTask();
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_ci            if (prevOpsTask && curOpsTask) {
382cb93a386Sopenharmony_ci                SkASSERT(!prevOpsTask->canMerge(curOpsTask));
383cb93a386Sopenharmony_ci            }
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci            prevOpsTask = curOpsTask;
386cb93a386Sopenharmony_ci        }
387cb93a386Sopenharmony_ci    }
388cb93a386Sopenharmony_ci#endif
389cb93a386Sopenharmony_ci}
390cb93a386Sopenharmony_ci
391cb93a386Sopenharmony_ci// Reorder the array to match the llist without reffing & unreffing sk_sp's.
392cb93a386Sopenharmony_ci// Both args must contain the same objects.
393cb93a386Sopenharmony_ci// This is basically a shim because clustering uses LList but the rest of drawmgr uses array.
394cb93a386Sopenharmony_citemplate <typename T>
395cb93a386Sopenharmony_cistatic void reorder_array_by_llist(const SkTInternalLList<T>& llist, SkTArray<sk_sp<T>>* array) {
396cb93a386Sopenharmony_ci    int i = 0;
397cb93a386Sopenharmony_ci    for (T* t : llist) {
398cb93a386Sopenharmony_ci        // Release the pointer that used to live here so it doesn't get unreffed.
399cb93a386Sopenharmony_ci        [[maybe_unused]] T* old = array->at(i).release();
400cb93a386Sopenharmony_ci        array->at(i++).reset(t);
401cb93a386Sopenharmony_ci    }
402cb93a386Sopenharmony_ci    SkASSERT(i == array->count());
403cb93a386Sopenharmony_ci}
404cb93a386Sopenharmony_ci
405cb93a386Sopenharmony_cibool GrDrawingManager::reorderTasks(GrResourceAllocator* resourceAllocator) {
406cb93a386Sopenharmony_ci    SkASSERT(fReduceOpsTaskSplitting);
407cb93a386Sopenharmony_ci    SkTInternalLList<GrRenderTask> llist;
408cb93a386Sopenharmony_ci    bool clustered = GrClusterRenderTasks(SkMakeSpan(fDAG), &llist);
409cb93a386Sopenharmony_ci    if (!clustered) {
410cb93a386Sopenharmony_ci        return false;
411cb93a386Sopenharmony_ci    }
412cb93a386Sopenharmony_ci
413cb93a386Sopenharmony_ci    for (GrRenderTask* task : llist) {
414cb93a386Sopenharmony_ci        task->gatherProxyIntervals(resourceAllocator);
415cb93a386Sopenharmony_ci    }
416cb93a386Sopenharmony_ci    if (!resourceAllocator->planAssignment()) {
417cb93a386Sopenharmony_ci        return false;
418cb93a386Sopenharmony_ci    }
419cb93a386Sopenharmony_ci    if (!resourceAllocator->makeBudgetHeadroom()) {
420cb93a386Sopenharmony_ci        auto dContext = fContext->asDirectContext();
421cb93a386Sopenharmony_ci        SkASSERT(dContext);
422cb93a386Sopenharmony_ci        dContext->priv().getGpu()->stats()->incNumReorderedDAGsOverBudget();
423cb93a386Sopenharmony_ci        return false;
424cb93a386Sopenharmony_ci    }
425cb93a386Sopenharmony_ci    reorder_array_by_llist(llist, &fDAG);
426cb93a386Sopenharmony_ci
427cb93a386Sopenharmony_ci    int newCount = 0;
428cb93a386Sopenharmony_ci    for (int i = 0; i < fDAG.count(); i++) {
429cb93a386Sopenharmony_ci        sk_sp<GrRenderTask>& task = fDAG[i];
430cb93a386Sopenharmony_ci#if SK_GPU_V1
431cb93a386Sopenharmony_ci        if (auto opsTask = task->asOpsTask()) {
432cb93a386Sopenharmony_ci            size_t remaining = fDAG.size() - i - 1;
433cb93a386Sopenharmony_ci            SkSpan<sk_sp<GrRenderTask>> nextTasks{fDAG.end() - remaining, remaining};
434cb93a386Sopenharmony_ci            int removeCount = opsTask->mergeFrom(nextTasks);
435cb93a386Sopenharmony_ci            for (const auto& removed : nextTasks.first(removeCount)) {
436cb93a386Sopenharmony_ci                removed->disown(this);
437cb93a386Sopenharmony_ci            }
438cb93a386Sopenharmony_ci            i += removeCount;
439cb93a386Sopenharmony_ci        }
440cb93a386Sopenharmony_ci#endif
441cb93a386Sopenharmony_ci        fDAG[newCount++] = std::move(task);
442cb93a386Sopenharmony_ci    }
443cb93a386Sopenharmony_ci    fDAG.resize_back(newCount);
444cb93a386Sopenharmony_ci    return true;
445cb93a386Sopenharmony_ci}
446cb93a386Sopenharmony_ci
447cb93a386Sopenharmony_civoid GrDrawingManager::closeAllTasks() {
448cb93a386Sopenharmony_ci    for (auto& task : fDAG) {
449cb93a386Sopenharmony_ci        if (task) {
450cb93a386Sopenharmony_ci            task->makeClosed(fContext);
451cb93a386Sopenharmony_ci        }
452cb93a386Sopenharmony_ci    }
453cb93a386Sopenharmony_ci}
454cb93a386Sopenharmony_ci
455cb93a386Sopenharmony_ciGrRenderTask* GrDrawingManager::insertTaskBeforeLast(sk_sp<GrRenderTask> task) {
456cb93a386Sopenharmony_ci    if (!task) {
457cb93a386Sopenharmony_ci        return nullptr;
458cb93a386Sopenharmony_ci    }
459cb93a386Sopenharmony_ci    if (fDAG.empty()) {
460cb93a386Sopenharmony_ci        return fDAG.push_back(std::move(task)).get();
461cb93a386Sopenharmony_ci    }
462cb93a386Sopenharmony_ci    // Release 'fDAG.back()' and grab the raw pointer, in case the SkTArray grows
463cb93a386Sopenharmony_ci    // and reallocates during emplace_back.
464cb93a386Sopenharmony_ci    // TODO: Either use std::vector that can do this for us, or use SkSTArray to get the
465cb93a386Sopenharmony_ci    // perf win.
466cb93a386Sopenharmony_ci    fDAG.emplace_back(fDAG.back().release());
467cb93a386Sopenharmony_ci    return (fDAG[fDAG.count() - 2] = std::move(task)).get();
468cb93a386Sopenharmony_ci}
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_ciGrRenderTask* GrDrawingManager::appendTask(sk_sp<GrRenderTask> task) {
471cb93a386Sopenharmony_ci    if (!task) {
472cb93a386Sopenharmony_ci        return nullptr;
473cb93a386Sopenharmony_ci    }
474cb93a386Sopenharmony_ci    return fDAG.push_back(std::move(task)).get();
475cb93a386Sopenharmony_ci}
476cb93a386Sopenharmony_ci
477cb93a386Sopenharmony_cistatic void resolve_and_mipmap(GrGpu* gpu, GrSurfaceProxy* proxy) {
478cb93a386Sopenharmony_ci    if (!proxy->isInstantiated()) {
479cb93a386Sopenharmony_ci        return;
480cb93a386Sopenharmony_ci    }
481cb93a386Sopenharmony_ci
482cb93a386Sopenharmony_ci    // In the flushSurfaces case, we need to resolve MSAA immediately after flush. This is
483cb93a386Sopenharmony_ci    // because clients expect the flushed surface's backing texture to be fully resolved
484cb93a386Sopenharmony_ci    // upon return.
485cb93a386Sopenharmony_ci    if (proxy->requiresManualMSAAResolve()) {
486cb93a386Sopenharmony_ci        auto* rtProxy = proxy->asRenderTargetProxy();
487cb93a386Sopenharmony_ci        SkASSERT(rtProxy);
488cb93a386Sopenharmony_ci        if (rtProxy->isMSAADirty()) {
489cb93a386Sopenharmony_ci            SkASSERT(rtProxy->peekRenderTarget());
490cb93a386Sopenharmony_ci            gpu->resolveRenderTarget(rtProxy->peekRenderTarget(), rtProxy->msaaDirtyRect());
491cb93a386Sopenharmony_ci            gpu->submitToGpu(false);
492cb93a386Sopenharmony_ci            rtProxy->markMSAAResolved();
493cb93a386Sopenharmony_ci        }
494cb93a386Sopenharmony_ci    }
495cb93a386Sopenharmony_ci    // If, after a flush, any of the proxies of interest have dirty mipmaps, regenerate them in
496cb93a386Sopenharmony_ci    // case their backend textures are being stolen.
497cb93a386Sopenharmony_ci    // (This special case is exercised by the ReimportImageTextureWithMipLevels test.)
498cb93a386Sopenharmony_ci    // FIXME: It may be more ideal to plumb down a "we're going to steal the backends" flag.
499cb93a386Sopenharmony_ci    if (auto* textureProxy = proxy->asTextureProxy()) {
500cb93a386Sopenharmony_ci        if (textureProxy->mipmapsAreDirty()) {
501cb93a386Sopenharmony_ci            SkASSERT(textureProxy->peekTexture());
502cb93a386Sopenharmony_ci            gpu->regenerateMipMapLevels(textureProxy->peekTexture());
503cb93a386Sopenharmony_ci            textureProxy->markMipmapsClean();
504cb93a386Sopenharmony_ci        }
505cb93a386Sopenharmony_ci    }
506cb93a386Sopenharmony_ci}
507cb93a386Sopenharmony_ci
508cb93a386Sopenharmony_ciGrSemaphoresSubmitted GrDrawingManager::flushSurfaces(
509cb93a386Sopenharmony_ci        SkSpan<GrSurfaceProxy*> proxies,
510cb93a386Sopenharmony_ci        SkSurface::BackendSurfaceAccess access,
511cb93a386Sopenharmony_ci        const GrFlushInfo& info,
512cb93a386Sopenharmony_ci        const GrBackendSurfaceMutableState* newState) {
513cb93a386Sopenharmony_ci    if (this->wasAbandoned()) {
514cb93a386Sopenharmony_ci        if (info.fSubmittedProc) {
515cb93a386Sopenharmony_ci            info.fSubmittedProc(info.fSubmittedContext, false);
516cb93a386Sopenharmony_ci        }
517cb93a386Sopenharmony_ci        if (info.fFinishedProc) {
518cb93a386Sopenharmony_ci            info.fFinishedProc(info.fFinishedContext);
519cb93a386Sopenharmony_ci        }
520cb93a386Sopenharmony_ci        return GrSemaphoresSubmitted::kNo;
521cb93a386Sopenharmony_ci    }
522cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
523cb93a386Sopenharmony_ci
524cb93a386Sopenharmony_ci    auto direct = fContext->asDirectContext();
525cb93a386Sopenharmony_ci    SkASSERT(direct);
526cb93a386Sopenharmony_ci    GrGpu* gpu = direct->priv().getGpu();
527cb93a386Sopenharmony_ci    // We have a non abandoned and direct GrContext. It must have a GrGpu.
528cb93a386Sopenharmony_ci    SkASSERT(gpu);
529cb93a386Sopenharmony_ci
530cb93a386Sopenharmony_ci    // TODO: It is important to upgrade the drawingmanager to just flushing the
531cb93a386Sopenharmony_ci    // portion of the DAG required by 'proxies' in order to restore some of the
532cb93a386Sopenharmony_ci    // semantics of this method.
533cb93a386Sopenharmony_ci    bool didFlush = this->flush(proxies, access, info, newState);
534cb93a386Sopenharmony_ci    for (GrSurfaceProxy* proxy : proxies) {
535cb93a386Sopenharmony_ci        resolve_and_mipmap(gpu, proxy);
536cb93a386Sopenharmony_ci    }
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
539cb93a386Sopenharmony_ci
540cb93a386Sopenharmony_ci    if (!didFlush || (!direct->priv().caps()->semaphoreSupport() && info.fNumSemaphores)) {
541cb93a386Sopenharmony_ci        return GrSemaphoresSubmitted::kNo;
542cb93a386Sopenharmony_ci    }
543cb93a386Sopenharmony_ci    return GrSemaphoresSubmitted::kYes;
544cb93a386Sopenharmony_ci}
545cb93a386Sopenharmony_ci
546cb93a386Sopenharmony_civoid GrDrawingManager::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
547cb93a386Sopenharmony_ci    fOnFlushCBObjects.push_back(onFlushCBObject);
548cb93a386Sopenharmony_ci}
549cb93a386Sopenharmony_ci
550cb93a386Sopenharmony_ci#if GR_TEST_UTILS
551cb93a386Sopenharmony_civoid GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
552cb93a386Sopenharmony_ci    int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) -
553cb93a386Sopenharmony_ci            fOnFlushCBObjects.begin();
554cb93a386Sopenharmony_ci    SkASSERT(n < fOnFlushCBObjects.count());
555cb93a386Sopenharmony_ci    fOnFlushCBObjects.removeShuffle(n);
556cb93a386Sopenharmony_ci}
557cb93a386Sopenharmony_ci#endif
558cb93a386Sopenharmony_ci
559cb93a386Sopenharmony_civoid GrDrawingManager::setLastRenderTask(const GrSurfaceProxy* proxy, GrRenderTask* task) {
560cb93a386Sopenharmony_ci#ifdef SK_DEBUG
561cb93a386Sopenharmony_ci    if (auto prior = this->getLastRenderTask(proxy)) {
562cb93a386Sopenharmony_ci        SkASSERT(prior->isClosed() || prior == task);
563cb93a386Sopenharmony_ci    }
564cb93a386Sopenharmony_ci#endif
565cb93a386Sopenharmony_ci    uint32_t key = proxy->uniqueID().asUInt();
566cb93a386Sopenharmony_ci    if (task) {
567cb93a386Sopenharmony_ci        fLastRenderTasks.set(key, task);
568cb93a386Sopenharmony_ci    } else if (fLastRenderTasks.find(key)) {
569cb93a386Sopenharmony_ci        fLastRenderTasks.remove(key);
570cb93a386Sopenharmony_ci    }
571cb93a386Sopenharmony_ci}
572cb93a386Sopenharmony_ci
573cb93a386Sopenharmony_ciGrRenderTask* GrDrawingManager::getLastRenderTask(const GrSurfaceProxy* proxy) const {
574cb93a386Sopenharmony_ci    auto entry = fLastRenderTasks.find(proxy->uniqueID().asUInt());
575cb93a386Sopenharmony_ci    return entry ? *entry : nullptr;
576cb93a386Sopenharmony_ci}
577cb93a386Sopenharmony_ci
578cb93a386Sopenharmony_ciskgpu::v1::OpsTask* GrDrawingManager::getLastOpsTask(const GrSurfaceProxy* proxy) const {
579cb93a386Sopenharmony_ci    GrRenderTask* task = this->getLastRenderTask(proxy);
580cb93a386Sopenharmony_ci    return task ? task->asOpsTask() : nullptr;
581cb93a386Sopenharmony_ci}
582cb93a386Sopenharmony_ci
583cb93a386Sopenharmony_ci
584cb93a386Sopenharmony_civoid GrDrawingManager::moveRenderTasksToDDL(SkDeferredDisplayList* ddl) {
585cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
586cb93a386Sopenharmony_ci
587cb93a386Sopenharmony_ci    // no renderTask should receive a new command after this
588cb93a386Sopenharmony_ci    this->closeAllTasks();
589cb93a386Sopenharmony_ci    fActiveOpsTask = nullptr;
590cb93a386Sopenharmony_ci
591cb93a386Sopenharmony_ci    this->sortTasks();
592cb93a386Sopenharmony_ci
593cb93a386Sopenharmony_ci    fDAG.swap(ddl->fRenderTasks);
594cb93a386Sopenharmony_ci    SkASSERT(fDAG.empty());
595cb93a386Sopenharmony_ci
596cb93a386Sopenharmony_ci    for (auto& renderTask : ddl->fRenderTasks) {
597cb93a386Sopenharmony_ci        renderTask->disown(this);
598cb93a386Sopenharmony_ci        renderTask->prePrepare(fContext);
599cb93a386Sopenharmony_ci    }
600cb93a386Sopenharmony_ci
601cb93a386Sopenharmony_ci    ddl->fArenas = std::move(fContext->priv().detachArenas());
602cb93a386Sopenharmony_ci
603cb93a386Sopenharmony_ci    fContext->priv().detachProgramData(&ddl->fProgramData);
604cb93a386Sopenharmony_ci
605cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
606cb93a386Sopenharmony_ci}
607cb93a386Sopenharmony_ci
608cb93a386Sopenharmony_civoid GrDrawingManager::createDDLTask(sk_sp<const SkDeferredDisplayList> ddl,
609cb93a386Sopenharmony_ci                                     sk_sp<GrRenderTargetProxy> newDest,
610cb93a386Sopenharmony_ci                                     SkIPoint offset) {
611cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
612cb93a386Sopenharmony_ci
613cb93a386Sopenharmony_ci#if SK_GPU_V1
614cb93a386Sopenharmony_ci    if (fActiveOpsTask) {
615cb93a386Sopenharmony_ci        // This is a temporary fix for the partial-MDB world. In that world we're not
616cb93a386Sopenharmony_ci        // reordering so ops that (in the single opsTask world) would've just glommed onto the
617cb93a386Sopenharmony_ci        // end of the single opsTask but referred to a far earlier RT need to appear in their
618cb93a386Sopenharmony_ci        // own opsTask.
619cb93a386Sopenharmony_ci        fActiveOpsTask->makeClosed(fContext);
620cb93a386Sopenharmony_ci        fActiveOpsTask = nullptr;
621cb93a386Sopenharmony_ci    }
622cb93a386Sopenharmony_ci#endif
623cb93a386Sopenharmony_ci
624cb93a386Sopenharmony_ci    // Propagate the DDL proxy's state information to the replay target.
625cb93a386Sopenharmony_ci    if (ddl->priv().targetProxy()->isMSAADirty()) {
626cb93a386Sopenharmony_ci        auto nativeRect = GrNativeRect::MakeIRectRelativeTo(
627cb93a386Sopenharmony_ci                ddl->characterization().origin(),
628cb93a386Sopenharmony_ci                ddl->priv().targetProxy()->backingStoreDimensions().height(),
629cb93a386Sopenharmony_ci                ddl->priv().targetProxy()->msaaDirtyRect());
630cb93a386Sopenharmony_ci        newDest->markMSAADirty(nativeRect);
631cb93a386Sopenharmony_ci    }
632cb93a386Sopenharmony_ci    GrTextureProxy* newTextureProxy = newDest->asTextureProxy();
633cb93a386Sopenharmony_ci    if (newTextureProxy && GrMipmapped::kYes == newTextureProxy->mipmapped()) {
634cb93a386Sopenharmony_ci        newTextureProxy->markMipmapsDirty();
635cb93a386Sopenharmony_ci    }
636cb93a386Sopenharmony_ci
637cb93a386Sopenharmony_ci    // Here we jam the proxy that backs the current replay SkSurface into the LazyProxyData.
638cb93a386Sopenharmony_ci    // The lazy proxy that references it (in the DDL opsTasks) will then steal its GrTexture.
639cb93a386Sopenharmony_ci    ddl->fLazyProxyData->fReplayDest = newDest.get();
640cb93a386Sopenharmony_ci
641cb93a386Sopenharmony_ci    // Add a task to handle drawing and lifetime management of the DDL.
642cb93a386Sopenharmony_ci    SkDEBUGCODE(auto ddlTask =) this->appendTask(sk_make_sp<GrDDLTask>(this,
643cb93a386Sopenharmony_ci                                                                       std::move(newDest),
644cb93a386Sopenharmony_ci                                                                       std::move(ddl),
645cb93a386Sopenharmony_ci                                                                       offset));
646cb93a386Sopenharmony_ci    SkASSERT(ddlTask->isClosed());
647cb93a386Sopenharmony_ci
648cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
649cb93a386Sopenharmony_ci}
650cb93a386Sopenharmony_ci
651cb93a386Sopenharmony_ci#ifdef SK_DEBUG
652cb93a386Sopenharmony_civoid GrDrawingManager::validate() const {
653cb93a386Sopenharmony_ci#if SK_GPU_V1
654cb93a386Sopenharmony_ci    if (fActiveOpsTask) {
655cb93a386Sopenharmony_ci        SkASSERT(!fDAG.empty());
656cb93a386Sopenharmony_ci        SkASSERT(!fActiveOpsTask->isClosed());
657cb93a386Sopenharmony_ci        SkASSERT(fActiveOpsTask == fDAG.back().get());
658cb93a386Sopenharmony_ci    }
659cb93a386Sopenharmony_ci
660cb93a386Sopenharmony_ci    for (int i = 0; i < fDAG.count(); ++i) {
661cb93a386Sopenharmony_ci        if (fActiveOpsTask != fDAG[i].get()) {
662cb93a386Sopenharmony_ci            // The resolveTask associated with the activeTask remains open for as long as the
663cb93a386Sopenharmony_ci            // activeTask does.
664cb93a386Sopenharmony_ci            bool isActiveResolveTask =
665cb93a386Sopenharmony_ci                fActiveOpsTask && fActiveOpsTask->fTextureResolveTask == fDAG[i].get();
666cb93a386Sopenharmony_ci            bool isAtlas = fDAG[i]->isSetFlag(GrRenderTask::kAtlas_Flag);
667cb93a386Sopenharmony_ci            SkASSERT(isActiveResolveTask || isAtlas || fDAG[i]->isClosed());
668cb93a386Sopenharmony_ci        }
669cb93a386Sopenharmony_ci    }
670cb93a386Sopenharmony_ci
671cb93a386Sopenharmony_ci    // The active opsTask, if any, should always be at the back of the DAG.
672cb93a386Sopenharmony_ci    if (!fDAG.empty()) {
673cb93a386Sopenharmony_ci        if (fDAG.back()->isSetFlag(GrRenderTask::kAtlas_Flag)) {
674cb93a386Sopenharmony_ci            SkASSERT(fActiveOpsTask == nullptr);
675cb93a386Sopenharmony_ci            SkASSERT(!fDAG.back()->isClosed());
676cb93a386Sopenharmony_ci        } else if (fDAG.back()->isClosed()) {
677cb93a386Sopenharmony_ci            SkASSERT(fActiveOpsTask == nullptr);
678cb93a386Sopenharmony_ci        } else {
679cb93a386Sopenharmony_ci            SkASSERT(fActiveOpsTask == fDAG.back().get());
680cb93a386Sopenharmony_ci        }
681cb93a386Sopenharmony_ci    } else {
682cb93a386Sopenharmony_ci        SkASSERT(fActiveOpsTask == nullptr);
683cb93a386Sopenharmony_ci    }
684cb93a386Sopenharmony_ci#endif // SK_GPU_V1
685cb93a386Sopenharmony_ci}
686cb93a386Sopenharmony_ci#endif // SK_DEBUG
687cb93a386Sopenharmony_ci
688cb93a386Sopenharmony_civoid GrDrawingManager::closeActiveOpsTask() {
689cb93a386Sopenharmony_ci#if SK_GPU_V1
690cb93a386Sopenharmony_ci    if (fActiveOpsTask) {
691cb93a386Sopenharmony_ci        // This is a temporary fix for the partial-MDB world. In that world we're not
692cb93a386Sopenharmony_ci        // reordering so ops that (in the single opsTask world) would've just glommed onto the
693cb93a386Sopenharmony_ci        // end of the single opsTask but referred to a far earlier RT need to appear in their
694cb93a386Sopenharmony_ci        // own opsTask.
695cb93a386Sopenharmony_ci        fActiveOpsTask->makeClosed(fContext);
696cb93a386Sopenharmony_ci        fActiveOpsTask = nullptr;
697cb93a386Sopenharmony_ci    }
698cb93a386Sopenharmony_ci#endif
699cb93a386Sopenharmony_ci}
700cb93a386Sopenharmony_ci
701cb93a386Sopenharmony_ci#if SK_GPU_V1
702cb93a386Sopenharmony_cisk_sp<skgpu::v1::OpsTask> GrDrawingManager::newOpsTask(GrSurfaceProxyView surfaceView,
703cb93a386Sopenharmony_ci                                                       sk_sp<GrArenas> arenas,
704cb93a386Sopenharmony_ci                                                       bool flushTimeOpsTask) {
705cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
706cb93a386Sopenharmony_ci    SkASSERT(fContext);
707cb93a386Sopenharmony_ci
708cb93a386Sopenharmony_ci    this->closeActiveOpsTask();
709cb93a386Sopenharmony_ci
710cb93a386Sopenharmony_ci    sk_sp<skgpu::v1::OpsTask> opsTask(new skgpu::v1::OpsTask(this,
711cb93a386Sopenharmony_ci                                                             std::move(surfaceView),
712cb93a386Sopenharmony_ci                                                             fContext->priv().auditTrail(),
713cb93a386Sopenharmony_ci                                                             std::move(arenas)));
714cb93a386Sopenharmony_ci
715cb93a386Sopenharmony_ci    SkASSERT(this->getLastRenderTask(opsTask->target(0)) == opsTask.get());
716cb93a386Sopenharmony_ci
717cb93a386Sopenharmony_ci    if (flushTimeOpsTask) {
718cb93a386Sopenharmony_ci        fOnFlushRenderTasks.push_back(opsTask);
719cb93a386Sopenharmony_ci    } else {
720cb93a386Sopenharmony_ci        this->appendTask(opsTask);
721cb93a386Sopenharmony_ci
722cb93a386Sopenharmony_ci        fActiveOpsTask = opsTask.get();
723cb93a386Sopenharmony_ci    }
724cb93a386Sopenharmony_ci
725cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
726cb93a386Sopenharmony_ci    return opsTask;
727cb93a386Sopenharmony_ci}
728cb93a386Sopenharmony_ci
729cb93a386Sopenharmony_civoid GrDrawingManager::addAtlasTask(sk_sp<GrRenderTask> atlasTask,
730cb93a386Sopenharmony_ci                                    GrRenderTask* previousAtlasTask) {
731cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
732cb93a386Sopenharmony_ci    SkASSERT(fContext);
733cb93a386Sopenharmony_ci
734cb93a386Sopenharmony_ci    if (previousAtlasTask) {
735cb93a386Sopenharmony_ci        previousAtlasTask->makeClosed(fContext);
736cb93a386Sopenharmony_ci        for (GrRenderTask* previousAtlasUser : previousAtlasTask->dependents()) {
737cb93a386Sopenharmony_ci            // Make the new atlas depend on everybody who used the old atlas, and close their tasks.
738cb93a386Sopenharmony_ci            // This guarantees that the previous atlas is totally out of service before we render
739cb93a386Sopenharmony_ci            // the next one, meaning there is only ever one atlas active at a time and that they can
740cb93a386Sopenharmony_ci            // all share the same texture.
741cb93a386Sopenharmony_ci            atlasTask->addDependency(previousAtlasUser);
742cb93a386Sopenharmony_ci            previousAtlasUser->makeClosed(fContext);
743cb93a386Sopenharmony_ci            if (previousAtlasUser == fActiveOpsTask) {
744cb93a386Sopenharmony_ci                fActiveOpsTask = nullptr;
745cb93a386Sopenharmony_ci            }
746cb93a386Sopenharmony_ci        }
747cb93a386Sopenharmony_ci    }
748cb93a386Sopenharmony_ci
749cb93a386Sopenharmony_ci    atlasTask->setFlag(GrRenderTask::kAtlas_Flag);
750cb93a386Sopenharmony_ci    this->insertTaskBeforeLast(std::move(atlasTask));
751cb93a386Sopenharmony_ci
752cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
753cb93a386Sopenharmony_ci}
754cb93a386Sopenharmony_ci#endif // SK_GPU_V1
755cb93a386Sopenharmony_ci
756cb93a386Sopenharmony_ciGrTextureResolveRenderTask* GrDrawingManager::newTextureResolveRenderTask(const GrCaps& caps) {
757cb93a386Sopenharmony_ci    // Unlike in the "new opsTask" case, we do not want to close the active opsTask, nor (if we are
758cb93a386Sopenharmony_ci    // in sorting and opsTask reduction mode) the render tasks that depend on any proxy's current
759cb93a386Sopenharmony_ci    // state. This is because those opsTasks can still receive new ops and because if they refer to
760cb93a386Sopenharmony_ci    // the mipmapped version of 'proxy', they will then come to depend on the render task being
761cb93a386Sopenharmony_ci    // created here.
762cb93a386Sopenharmony_ci    //
763cb93a386Sopenharmony_ci    // Add the new textureResolveTask before the fActiveOpsTask (if not in
764cb93a386Sopenharmony_ci    // sorting/opsTask-splitting-reduction mode) because it will depend upon this resolve task.
765cb93a386Sopenharmony_ci    // NOTE: Putting it here will also reduce the amount of work required by the topological sort.
766cb93a386Sopenharmony_ci    GrRenderTask* task = this->insertTaskBeforeLast(sk_make_sp<GrTextureResolveRenderTask>());
767cb93a386Sopenharmony_ci    return static_cast<GrTextureResolveRenderTask*>(task);
768cb93a386Sopenharmony_ci}
769cb93a386Sopenharmony_ci
770cb93a386Sopenharmony_civoid GrDrawingManager::newWaitRenderTask(sk_sp<GrSurfaceProxy> proxy,
771cb93a386Sopenharmony_ci                                         std::unique_ptr<std::unique_ptr<GrSemaphore>[]> semaphores,
772cb93a386Sopenharmony_ci                                         int numSemaphores) {
773cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
774cb93a386Sopenharmony_ci    SkASSERT(fContext);
775cb93a386Sopenharmony_ci
776cb93a386Sopenharmony_ci    sk_sp<GrWaitRenderTask> waitTask = sk_make_sp<GrWaitRenderTask>(GrSurfaceProxyView(proxy),
777cb93a386Sopenharmony_ci                                                                    std::move(semaphores),
778cb93a386Sopenharmony_ci                                                                    numSemaphores);
779cb93a386Sopenharmony_ci
780cb93a386Sopenharmony_ci#if SK_GPU_V1
781cb93a386Sopenharmony_ci    if (fActiveOpsTask && (fActiveOpsTask->target(0) == proxy.get())) {
782cb93a386Sopenharmony_ci        SkASSERT(this->getLastRenderTask(proxy.get()) == fActiveOpsTask);
783cb93a386Sopenharmony_ci        this->insertTaskBeforeLast(waitTask);
784cb93a386Sopenharmony_ci        // In this case we keep the current renderTask open but just insert the new waitTask
785cb93a386Sopenharmony_ci        // before it in the list. The waitTask will never need to trigger any resolves or mip
786cb93a386Sopenharmony_ci        // map generation which is the main advantage of going through the proxy version.
787cb93a386Sopenharmony_ci        // Additionally we would've had to temporarily set the wait task as the lastRenderTask
788cb93a386Sopenharmony_ci        // on the proxy, add the dependency, and then reset the lastRenderTask to
789cb93a386Sopenharmony_ci        // fActiveOpsTask. Additionally we make the waitTask depend on all of fActiveOpsTask
790cb93a386Sopenharmony_ci        // dependencies so that we don't unnecessarily reorder the waitTask before them.
791cb93a386Sopenharmony_ci        // Note: Any previous Ops already in fActiveOpsTask will get blocked by the wait
792cb93a386Sopenharmony_ci        // semaphore even though they don't need to be for correctness.
793cb93a386Sopenharmony_ci
794cb93a386Sopenharmony_ci        // Make sure we add the dependencies of fActiveOpsTask to waitTask first or else we'll
795cb93a386Sopenharmony_ci        // get a circular self dependency of waitTask on waitTask.
796cb93a386Sopenharmony_ci        waitTask->addDependenciesFromOtherTask(fActiveOpsTask);
797cb93a386Sopenharmony_ci        fActiveOpsTask->addDependency(waitTask.get());
798cb93a386Sopenharmony_ci    } else
799cb93a386Sopenharmony_ci#endif
800cb93a386Sopenharmony_ci    {
801cb93a386Sopenharmony_ci        // In this case we just close the previous RenderTask and start and append the waitTask
802cb93a386Sopenharmony_ci        // to the DAG. Since it is the last task now we call setLastRenderTask on the proxy. If
803cb93a386Sopenharmony_ci        // there is a lastTask on the proxy we make waitTask depend on that task. This
804cb93a386Sopenharmony_ci        // dependency isn't strictly needed but it does keep the DAG from reordering the
805cb93a386Sopenharmony_ci        // waitTask earlier and blocking more tasks.
806cb93a386Sopenharmony_ci        if (GrRenderTask* lastTask = this->getLastRenderTask(proxy.get())) {
807cb93a386Sopenharmony_ci            waitTask->addDependency(lastTask);
808cb93a386Sopenharmony_ci        }
809cb93a386Sopenharmony_ci        this->setLastRenderTask(proxy.get(), waitTask.get());
810cb93a386Sopenharmony_ci        this->closeActiveOpsTask();
811cb93a386Sopenharmony_ci        this->appendTask(waitTask);
812cb93a386Sopenharmony_ci    }
813cb93a386Sopenharmony_ci    waitTask->makeClosed(fContext);
814cb93a386Sopenharmony_ci
815cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
816cb93a386Sopenharmony_ci}
817cb93a386Sopenharmony_ci
818cb93a386Sopenharmony_civoid GrDrawingManager::newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy,
819cb93a386Sopenharmony_ci                                                 const SkIRect& srcRect,
820cb93a386Sopenharmony_ci                                                 GrColorType surfaceColorType,
821cb93a386Sopenharmony_ci                                                 GrColorType dstColorType,
822cb93a386Sopenharmony_ci                                                 sk_sp<GrGpuBuffer> dstBuffer,
823cb93a386Sopenharmony_ci                                                 size_t dstOffset) {
824cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
825cb93a386Sopenharmony_ci    SkASSERT(fContext);
826cb93a386Sopenharmony_ci    this->closeActiveOpsTask();
827cb93a386Sopenharmony_ci
828cb93a386Sopenharmony_ci    GrRenderTask* task = this->appendTask(sk_make_sp<GrTransferFromRenderTask>(
829cb93a386Sopenharmony_ci            srcProxy, srcRect, surfaceColorType, dstColorType,
830cb93a386Sopenharmony_ci            std::move(dstBuffer), dstOffset));
831cb93a386Sopenharmony_ci
832cb93a386Sopenharmony_ci    const GrCaps& caps = *fContext->priv().caps();
833cb93a386Sopenharmony_ci
834cb93a386Sopenharmony_ci    // We always say GrMipmapped::kNo here since we are always just copying from the base layer. We
835cb93a386Sopenharmony_ci    // don't need to make sure the whole mip map chain is valid.
836cb93a386Sopenharmony_ci    task->addDependency(this, srcProxy.get(), GrMipmapped::kNo,
837cb93a386Sopenharmony_ci                        GrTextureResolveManager(this), caps);
838cb93a386Sopenharmony_ci    task->makeClosed(fContext);
839cb93a386Sopenharmony_ci
840cb93a386Sopenharmony_ci    // We have closed the previous active oplist but since a new oplist isn't being added there
841cb93a386Sopenharmony_ci    // shouldn't be an active one.
842cb93a386Sopenharmony_ci    SkASSERT(!fActiveOpsTask);
843cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
844cb93a386Sopenharmony_ci}
845cb93a386Sopenharmony_ci
846cb93a386Sopenharmony_cisk_sp<GrRenderTask> GrDrawingManager::newCopyRenderTask(sk_sp<GrSurfaceProxy> src,
847cb93a386Sopenharmony_ci                                                        SkIRect srcRect,
848cb93a386Sopenharmony_ci                                                        sk_sp<GrSurfaceProxy> dst,
849cb93a386Sopenharmony_ci                                                        SkIPoint dstPoint,
850cb93a386Sopenharmony_ci                                                        GrSurfaceOrigin origin) {
851cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
852cb93a386Sopenharmony_ci    SkASSERT(fContext);
853cb93a386Sopenharmony_ci
854cb93a386Sopenharmony_ci    // It'd be nicer to check this in GrCopyRenderTask::Make. This gets complicated because of
855cb93a386Sopenharmony_ci    // "active ops task" tracking. dst will be the target of our copy task but it might also be the
856cb93a386Sopenharmony_ci    // target of the active ops task. We currently require the active ops task to be closed before
857cb93a386Sopenharmony_ci    // making a new task that targets the same proxy. However, if we first close the active ops
858cb93a386Sopenharmony_ci    // task, then fail to make a copy task, the next active ops task may target the same proxy. This
859cb93a386Sopenharmony_ci    // will trip an assert related to unnecessary ops task splitting.
860cb93a386Sopenharmony_ci    if (src->framebufferOnly()) {
861cb93a386Sopenharmony_ci        return nullptr;
862cb93a386Sopenharmony_ci    }
863cb93a386Sopenharmony_ci
864cb93a386Sopenharmony_ci    this->closeActiveOpsTask();
865cb93a386Sopenharmony_ci
866cb93a386Sopenharmony_ci    sk_sp<GrRenderTask> task = GrCopyRenderTask::Make(this,
867cb93a386Sopenharmony_ci                                                      src,
868cb93a386Sopenharmony_ci                                                      srcRect,
869cb93a386Sopenharmony_ci                                                      std::move(dst),
870cb93a386Sopenharmony_ci                                                      dstPoint,
871cb93a386Sopenharmony_ci                                                      origin);
872cb93a386Sopenharmony_ci    if (!task) {
873cb93a386Sopenharmony_ci        return nullptr;
874cb93a386Sopenharmony_ci    }
875cb93a386Sopenharmony_ci
876cb93a386Sopenharmony_ci    this->appendTask(task);
877cb93a386Sopenharmony_ci
878cb93a386Sopenharmony_ci    const GrCaps& caps = *fContext->priv().caps();
879cb93a386Sopenharmony_ci    // We always say GrMipmapped::kNo here since we are always just copying from the base layer to
880cb93a386Sopenharmony_ci    // another base layer. We don't need to make sure the whole mip map chain is valid.
881cb93a386Sopenharmony_ci    task->addDependency(this, src.get(), GrMipmapped::kNo, GrTextureResolveManager(this), caps);
882cb93a386Sopenharmony_ci    task->makeClosed(fContext);
883cb93a386Sopenharmony_ci
884cb93a386Sopenharmony_ci    // We have closed the previous active oplist but since a new oplist isn't being added there
885cb93a386Sopenharmony_ci    // shouldn't be an active one.
886cb93a386Sopenharmony_ci    SkASSERT(!fActiveOpsTask);
887cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
888cb93a386Sopenharmony_ci    return task;
889cb93a386Sopenharmony_ci}
890cb93a386Sopenharmony_ci
891cb93a386Sopenharmony_cibool GrDrawingManager::newWritePixelsTask(sk_sp<GrSurfaceProxy> dst,
892cb93a386Sopenharmony_ci                                          SkIRect rect,
893cb93a386Sopenharmony_ci                                          GrColorType srcColorType,
894cb93a386Sopenharmony_ci                                          GrColorType dstColorType,
895cb93a386Sopenharmony_ci                                          const GrMipLevel levels[],
896cb93a386Sopenharmony_ci                                          int levelCount) {
897cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
898cb93a386Sopenharmony_ci    SkASSERT(fContext);
899cb93a386Sopenharmony_ci
900cb93a386Sopenharmony_ci    this->closeActiveOpsTask();
901cb93a386Sopenharmony_ci    const GrCaps& caps = *fContext->priv().caps();
902cb93a386Sopenharmony_ci
903cb93a386Sopenharmony_ci    // On platforms that prefer flushes over VRAM use (i.e., ANGLE) we're better off forcing a
904cb93a386Sopenharmony_ci    // complete flush here.
905cb93a386Sopenharmony_ci    if (!caps.preferVRAMUseOverFlushes()) {
906cb93a386Sopenharmony_ci        this->flushSurfaces(SkSpan<GrSurfaceProxy*>{},
907cb93a386Sopenharmony_ci                            SkSurface::BackendSurfaceAccess::kNoAccess,
908cb93a386Sopenharmony_ci                            GrFlushInfo{},
909cb93a386Sopenharmony_ci                            nullptr);
910cb93a386Sopenharmony_ci    }
911cb93a386Sopenharmony_ci
912cb93a386Sopenharmony_ci    GrRenderTask* task = this->appendTask(GrWritePixelsTask::Make(this,
913cb93a386Sopenharmony_ci                                                                  std::move(dst),
914cb93a386Sopenharmony_ci                                                                  rect,
915cb93a386Sopenharmony_ci                                                                  srcColorType,
916cb93a386Sopenharmony_ci                                                                  dstColorType,
917cb93a386Sopenharmony_ci                                                                  levels,
918cb93a386Sopenharmony_ci                                                                  levelCount));
919cb93a386Sopenharmony_ci    if (!task) {
920cb93a386Sopenharmony_ci        return false;
921cb93a386Sopenharmony_ci    }
922cb93a386Sopenharmony_ci
923cb93a386Sopenharmony_ci    task->makeClosed(fContext);
924cb93a386Sopenharmony_ci
925cb93a386Sopenharmony_ci    // We have closed the previous active oplist but since a new oplist isn't being added there
926cb93a386Sopenharmony_ci    // shouldn't be an active one.
927cb93a386Sopenharmony_ci    SkASSERT(!fActiveOpsTask);
928cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate());
929cb93a386Sopenharmony_ci    return true;
930cb93a386Sopenharmony_ci}
931cb93a386Sopenharmony_ci
932cb93a386Sopenharmony_ci#if SK_GPU_V1
933cb93a386Sopenharmony_ci/*
934cb93a386Sopenharmony_ci * This method finds a path renderer that can draw the specified path on
935cb93a386Sopenharmony_ci * the provided target.
936cb93a386Sopenharmony_ci * Due to its expense, the software path renderer has split out so it can
937cb93a386Sopenharmony_ci * can be individually allowed/disallowed via the "allowSW" boolean.
938cb93a386Sopenharmony_ci */
939cb93a386Sopenharmony_ciskgpu::v1::PathRenderer* GrDrawingManager::getPathRenderer(
940cb93a386Sopenharmony_ci        const PathRenderer::CanDrawPathArgs& args,
941cb93a386Sopenharmony_ci        bool allowSW,
942cb93a386Sopenharmony_ci        PathRendererChain::DrawType drawType,
943cb93a386Sopenharmony_ci        PathRenderer::StencilSupport* stencilSupport) {
944cb93a386Sopenharmony_ci
945cb93a386Sopenharmony_ci    if (!fPathRendererChain) {
946cb93a386Sopenharmony_ci        fPathRendererChain =
947cb93a386Sopenharmony_ci                std::make_unique<PathRendererChain>(fContext, fOptionsForPathRendererChain);
948cb93a386Sopenharmony_ci    }
949cb93a386Sopenharmony_ci
950cb93a386Sopenharmony_ci    auto pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
951cb93a386Sopenharmony_ci    if (!pr && allowSW) {
952cb93a386Sopenharmony_ci        auto swPR = this->getSoftwarePathRenderer();
953cb93a386Sopenharmony_ci        if (PathRenderer::CanDrawPath::kNo != swPR->canDrawPath(args)) {
954cb93a386Sopenharmony_ci            pr = swPR;
955cb93a386Sopenharmony_ci        }
956cb93a386Sopenharmony_ci    }
957cb93a386Sopenharmony_ci
958cb93a386Sopenharmony_ci#if GR_PATH_RENDERER_SPEW
959cb93a386Sopenharmony_ci    if (pr) {
960cb93a386Sopenharmony_ci        SkDebugf("getPathRenderer: %s\n", pr->name());
961cb93a386Sopenharmony_ci    }
962cb93a386Sopenharmony_ci#endif
963cb93a386Sopenharmony_ci
964cb93a386Sopenharmony_ci    return pr;
965cb93a386Sopenharmony_ci}
966cb93a386Sopenharmony_ci
967cb93a386Sopenharmony_ciskgpu::v1::PathRenderer* GrDrawingManager::getSoftwarePathRenderer() {
968cb93a386Sopenharmony_ci    if (!fSoftwarePathRenderer) {
969cb93a386Sopenharmony_ci        fSoftwarePathRenderer.reset(new skgpu::v1::SoftwarePathRenderer(
970cb93a386Sopenharmony_ci            fContext->priv().proxyProvider(), fOptionsForPathRendererChain.fAllowPathMaskCaching));
971cb93a386Sopenharmony_ci    }
972cb93a386Sopenharmony_ci    return fSoftwarePathRenderer.get();
973cb93a386Sopenharmony_ci}
974cb93a386Sopenharmony_ci
975cb93a386Sopenharmony_ciskgpu::v1::AtlasPathRenderer* GrDrawingManager::getAtlasPathRenderer() {
976cb93a386Sopenharmony_ci    if (!fPathRendererChain) {
977cb93a386Sopenharmony_ci        fPathRendererChain = std::make_unique<PathRendererChain>(fContext,
978cb93a386Sopenharmony_ci                                                                 fOptionsForPathRendererChain);
979cb93a386Sopenharmony_ci    }
980cb93a386Sopenharmony_ci    return fPathRendererChain->getAtlasPathRenderer();
981cb93a386Sopenharmony_ci}
982cb93a386Sopenharmony_ci
983cb93a386Sopenharmony_ciskgpu::v1::PathRenderer* GrDrawingManager::getTessellationPathRenderer() {
984cb93a386Sopenharmony_ci    if (!fPathRendererChain) {
985cb93a386Sopenharmony_ci        fPathRendererChain = std::make_unique<PathRendererChain>(fContext,
986cb93a386Sopenharmony_ci                                                                 fOptionsForPathRendererChain);
987cb93a386Sopenharmony_ci    }
988cb93a386Sopenharmony_ci    return fPathRendererChain->getTessellationPathRenderer();
989cb93a386Sopenharmony_ci}
990cb93a386Sopenharmony_ci
991cb93a386Sopenharmony_ci#endif // SK_GPU_V1
992cb93a386Sopenharmony_ci
993cb93a386Sopenharmony_civoid GrDrawingManager::flushIfNecessary() {
994cb93a386Sopenharmony_ci    auto direct = fContext->asDirectContext();
995cb93a386Sopenharmony_ci    if (!direct) {
996cb93a386Sopenharmony_ci        return;
997cb93a386Sopenharmony_ci    }
998cb93a386Sopenharmony_ci
999cb93a386Sopenharmony_ci    auto resourceCache = direct->priv().getResourceCache();
1000cb93a386Sopenharmony_ci    if (resourceCache && resourceCache->requestsFlush()) {
1001cb93a386Sopenharmony_ci        if (this->flush({}, SkSurface::BackendSurfaceAccess::kNoAccess, GrFlushInfo(), nullptr)) {
1002cb93a386Sopenharmony_ci            this->submitToGpu(false);
1003cb93a386Sopenharmony_ci        }
1004cb93a386Sopenharmony_ci        resourceCache->purgeAsNeeded();
1005cb93a386Sopenharmony_ci    }
1006cb93a386Sopenharmony_ci}
1007