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