xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrTextureResolveRenderTask.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2019 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #include "src/gpu/ganesh/GrTextureResolveRenderTask.h"
8 
9 #include "include/gpu/GpuTypes.h"
10 #include "include/private/base/SkAssert.h"
11 #include "include/private/base/SkMacros.h"
12 #include "src/gpu/ganesh/GrDrawingManager.h"
13 #include "src/gpu/ganesh/GrGpu.h"
14 #include "src/gpu/ganesh/GrOpFlushState.h"
15 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
16 #include "src/gpu/ganesh/GrResourceAllocator.h"
17 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
18 #include "src/gpu/ganesh/GrTexture.h"
19 #include "src/gpu/ganesh/GrTextureProxy.h"
20 #include "src/gpu/ganesh/GrTextureResolveManager.h"
21 
22 #include <algorithm>
23 #include <cstddef>
24 #include <utility>
25 
26 class GrRenderTarget;
27 
addProxy(GrDrawingManager * drawingMgr,sk_sp<GrSurfaceProxy> proxyRef,GrSurfaceProxy::ResolveFlags flags,const GrCaps & caps)28 void GrTextureResolveRenderTask::addProxy(GrDrawingManager* drawingMgr,
29                                           sk_sp<GrSurfaceProxy> proxyRef,
30                                           GrSurfaceProxy::ResolveFlags flags,
31                                           const GrCaps& caps) {
32     GrSurfaceProxy::ResolveFlags newFlags = flags;
33     GrSurfaceProxy* proxy = proxyRef.get();
34     Resolve* resolve;
35     bool newProxy = false;
36 
37     // We might just need to update the flags for an existing dependency.
38     if (auto found = std::find(fTargets.begin(), fTargets.end(), proxyRef);
39         found != fTargets.end()) {
40         size_t index = found - fTargets.begin();
41         resolve = &fResolves[index];
42         newFlags = ~resolve->fFlags & flags;
43         resolve->fFlags |= flags;
44     } else {
45         // Ensure the last render task that operated on the proxy is closed. That's where msaa and
46         // mipmaps should have been marked dirty.
47         SkASSERT(!drawingMgr->getLastRenderTask(proxy)
48                  || drawingMgr->getLastRenderTask(proxy)->isClosed());
49         SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
50         resolve = &fResolves.emplace_back(flags);
51         newProxy = true;
52     }
53 
54     if (GrSurfaceProxy::ResolveFlags::kMSAA & newFlags) {
55         GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
56         SkASSERT(renderTargetProxy);
57         SkASSERT(renderTargetProxy->isMSAADirty());
58         resolve->fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
59         renderTargetProxy->markMSAAResolved();
60     }
61 
62     if (GrSurfaceProxy::ResolveFlags::kMipMaps & newFlags) {
63         GrTextureProxy* textureProxy = proxy->asTextureProxy();
64         SkASSERT(skgpu::Mipmapped::kYes == textureProxy->mipmapped());
65         SkASSERT(textureProxy->mipmapsAreDirty());
66         textureProxy->markMipmapsClean();
67     }
68 
69     // We must do this after updating the proxy state because of assertions that the proxy isn't
70     // dirty.
71     if (newProxy) {
72         // Add the proxy as a dependency: We will read the existing contents of this texture while
73         // generating mipmap levels and/or resolving MSAA.
74         this->addDependency(
75                 drawingMgr, proxy, skgpu::Mipmapped::kNo, GrTextureResolveManager(nullptr), caps);
76         this->addTarget(drawingMgr, GrSurfaceProxyView(std::move(proxyRef)));
77     }
78 }
79 
gatherProxyIntervals(GrResourceAllocator * alloc) const80 void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
81     // This renderTask doesn't have "normal" ops, however we still need to add intervals so
82     // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
83     // manipulate the resolve proxies.
84     auto fakeOp = alloc->curOp();
85     SkASSERT(fResolves.size() == this->numTargets());
86     for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
87         alloc->addInterval(target.get(), fakeOp, fakeOp, GrResourceAllocator::ActualUse::kYes,
88                            GrResourceAllocator::AllowRecycling::kYes);
89     }
90     alloc->incOps();
91 }
92 
onExecute(GrOpFlushState * flushState)93 bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
94     // Resolve all msaa back-to-back, before regenerating mipmaps.
95     SkASSERT(fResolves.size() == this->numTargets());
96     for (int i = 0; i < fResolves.size(); ++i) {
97         const Resolve& resolve = fResolves[i];
98         if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
99             GrSurfaceProxy* proxy = this->target(i);
100             // peekRenderTarget might be null if there was an instantiation error.
101             if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
102                 flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect);
103             }
104         }
105     }
106     // Regenerate all mipmaps back-to-back.
107     for (int i = 0; i < fResolves.size(); ++i) {
108         const Resolve& resolve = fResolves[i];
109         if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
110             // peekTexture might be null if there was an instantiation error.
111             GrTexture* texture = this->target(i)->peekTexture();
112             if (texture && texture->mipmapsAreDirty()) {
113                 flushState->gpu()->regenerateMipMapLevels(texture);
114                 SkASSERT(!texture->mipmapsAreDirty());
115             }
116         }
117     }
118 
119     return true;
120 }
121 
122 #ifdef SK_DEBUG
visitProxies_debugOnly(const GrVisitProxyFunc &) const123 void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrVisitProxyFunc&) const {}
124 #endif
125 
126 #if defined(GPU_TEST_UTILS)
127 GrSurfaceProxy::ResolveFlags
flagsForProxy(sk_sp<GrSurfaceProxy> proxy) const128 GrTextureResolveRenderTask::flagsForProxy(sk_sp<GrSurfaceProxy> proxy) const {
129     if (auto found = std::find(fTargets.begin(), fTargets.end(), proxy);
130         found != fTargets.end()) {
131         return fResolves[found - fTargets.begin()].fFlags;
132     }
133     return GrSurfaceProxy::ResolveFlags::kNone;
134 }
135 #endif
136