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