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