• 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/GrTextureResolveRenderTask.h"
9 
10 #include "src/gpu/GrGpu.h"
11 #include "src/gpu/GrMemoryPool.h"
12 #include "src/gpu/GrOpFlushState.h"
13 #include "src/gpu/GrRenderTarget.h"
14 #include "src/gpu/GrResourceAllocator.h"
15 #include "src/gpu/GrTexturePriv.h"
16 
~GrTextureResolveRenderTask()17 GrTextureResolveRenderTask::~GrTextureResolveRenderTask() {
18     for (const auto& resolve : fResolves) {
19         // Ensure the proxy doesn't keep hold of a dangling back pointer.
20         resolve.fProxy->setLastRenderTask(nullptr);
21     }
22 }
23 
addProxy(sk_sp<GrSurfaceProxy> proxyRef,GrSurfaceProxy::ResolveFlags flags,const GrCaps & caps)24 void GrTextureResolveRenderTask::addProxy(
25         sk_sp<GrSurfaceProxy> proxyRef, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
26     fResolves.emplace_back(std::move(proxyRef), flags);
27     GrSurfaceProxy* proxy = fResolves.back().fProxy.get();
28 
29     // Ensure the last render task that operated on the proxy is closed. That's where msaa and
30     // mipmaps should have been marked dirty.
31     SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
32     SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
33 
34     if (GrSurfaceProxy::ResolveFlags::kMSAA & flags) {
35         GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
36         SkASSERT(renderTargetProxy);
37         SkASSERT(renderTargetProxy->isMSAADirty());
38         fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
39         renderTargetProxy->markMSAAResolved();
40     }
41 
42     if (GrSurfaceProxy::ResolveFlags::kMipMaps & flags) {
43         GrTextureProxy* textureProxy = proxy->asTextureProxy();
44         SkASSERT(GrMipMapped::kYes == textureProxy->mipMapped());
45         SkASSERT(textureProxy->mipMapsAreDirty());
46         textureProxy->markMipMapsClean();
47     }
48 
49     // Add the proxy as a dependency: We will read the existing contents of this texture while
50     // generating mipmap levels and/or resolving MSAA.
51     this->addDependency(proxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
52     proxy->setLastRenderTask(this);
53 }
54 
gatherProxyIntervals(GrResourceAllocator * alloc) const55 void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
56     // This renderTask doesn't have "normal" ops, however we still need to add intervals so
57     // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
58     // manipulate the resolve proxies.
59     auto fakeOp = alloc->curOp();
60     for (const auto& resolve : fResolves) {
61         alloc->addInterval(resolve.fProxy.get(), fakeOp, fakeOp,
62                            GrResourceAllocator::ActualUse::kYes);
63     }
64     alloc->incOps();
65 }
66 
onExecute(GrOpFlushState * flushState)67 bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
68     // Resolve all msaa back-to-back, before regenerating mipmaps.
69     for (const auto& resolve : fResolves) {
70         if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
71             GrSurfaceProxy* proxy = resolve.fProxy.get();
72             // peekRenderTarget might be null if there was an instantiation error.
73             if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
74                 flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
75                                                        GrGpu::ForExternalIO::kNo);
76             }
77         }
78     }
79     // Regenerate all mipmaps back-to-back.
80     for (const auto& resolve : fResolves) {
81         if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
82             // peekTexture might be null if there was an instantiation error.
83             GrTexture* texture = resolve.fProxy->peekTexture();
84             if (texture && texture->texturePriv().mipMapsAreDirty()) {
85                 flushState->gpu()->regenerateMipMapLevels(texture);
86                 SkASSERT(!texture->texturePriv().mipMapsAreDirty());
87             }
88         }
89     }
90 
91     return true;
92 }
93 
94 #ifdef SK_DEBUG
visitProxies_debugOnly(const GrOp::VisitProxyFunc & fn) const95 void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {
96     for (const auto& resolve : fResolves) {
97         fn(resolve.fProxy.get(), GrMipMapped::kNo);
98     }
99 }
100 #endif
101