blob: 8a59caf3cbe742fec17710775b8831995269d4c8 [file] [log] [blame]
Chris Dalton3d770272019-08-14 09:24:37 -06001/*
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"
Chris Dalton4ece96d2019-08-30 11:26:39 -060013#include "src/gpu/GrRenderTarget.h"
Chris Dalton3d770272019-08-14 09:24:37 -060014#include "src/gpu/GrResourceAllocator.h"
15#include "src/gpu/GrTexturePriv.h"
16
Chris Daltone2a903e2019-09-18 13:41:50 -060017GrTextureResolveRenderTask::~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
24void GrTextureResolveRenderTask::addProxy(
25 sk_sp<GrSurfaceProxy> proxy, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
26 // Ensure the last render task that operated on the proxy is closed. That's where msaa and
27 // mipmaps should have been marked dirty.
28 SkASSERT(!proxy->getLastRenderTask() || proxy->getLastRenderTask()->isClosed());
29 SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
30
31 if (GrSurfaceProxy::ResolveFlags::kMSAA & flags) {
32 GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
Chris Dalton4ece96d2019-08-30 11:26:39 -060033 SkASSERT(renderTargetProxy);
34 SkASSERT(renderTargetProxy->isMSAADirty());
35 renderTargetProxy->markMSAAResolved();
36 }
37
Chris Daltone2a903e2019-09-18 13:41:50 -060038 if (GrSurfaceProxy::ResolveFlags::kMipMaps & flags) {
39 GrTextureProxy* textureProxy = proxy->asTextureProxy();
Chris Dalton4ece96d2019-08-30 11:26:39 -060040 SkASSERT(GrMipMapped::kYes == textureProxy->mipMapped());
41 SkASSERT(textureProxy->mipMapsAreDirty());
42 textureProxy->markMipMapsClean();
43 }
44
Chris Daltone2a903e2019-09-18 13:41:50 -060045 // Add the proxy as a dependency: We will read the existing contents of this texture while
Chris Dalton3d770272019-08-14 09:24:37 -060046 // generating mipmap levels and/or resolving MSAA.
Chris Daltone2a903e2019-09-18 13:41:50 -060047 this->addDependency(proxy.get(), GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
48 proxy->setLastRenderTask(this);
Chris Dalton3d770272019-08-14 09:24:37 -060049
Chris Daltone2a903e2019-09-18 13:41:50 -060050 fResolves.emplace_back(std::move(proxy), flags);
Chris Dalton3d770272019-08-14 09:24:37 -060051}
52
53void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
Chris Daltone2a903e2019-09-18 13:41:50 -060054 // This renderTask doesn't have "normal" ops, however we still need to add intervals so
55 // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
56 // manipulate the resolve proxies.
57 auto fakeOp = alloc->curOp();
58 for (const auto& resolve : fResolves) {
59 alloc->addInterval(resolve.fProxy.get(), fakeOp, fakeOp,
60 GrResourceAllocator::ActualUse::kYes);
61 }
Chris Dalton3d770272019-08-14 09:24:37 -060062 alloc->incOps();
63}
64
65bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
Chris Daltone2a903e2019-09-18 13:41:50 -060066 // Resolve all msaa back-to-back, before regenerating mipmaps.
67 for (const auto& resolve : fResolves) {
68 if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
69 // peekRenderTarget might be null if there was an instantiation error.
70 GrRenderTarget* renderTarget = resolve.fProxy->peekRenderTarget();
71 if (renderTarget && renderTarget->needsResolve()) {
72 flushState->gpu()->resolveRenderTarget(renderTarget);
73 }
Chris Dalton4ece96d2019-08-30 11:26:39 -060074 }
75 }
Chris Daltone2a903e2019-09-18 13:41:50 -060076 // Regenerate all mipmaps back-to-back.
77 for (const auto& resolve : fResolves) {
78 if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
79 // peekTexture might be null if there was an instantiation error.
80 GrTexture* texture = resolve.fProxy->peekTexture();
81 if (texture && texture->texturePriv().mipMapsAreDirty()) {
82 flushState->gpu()->regenerateMipMapLevels(texture);
83 }
Chris Dalton4ece96d2019-08-30 11:26:39 -060084 }
Chris Dalton3d770272019-08-14 09:24:37 -060085 }
86
87 return true;
88}
Chris Daltone2a903e2019-09-18 13:41:50 -060089
90#ifdef SK_DEBUG
91void GrTextureResolveRenderTask::visitProxies_debugOnly(const VisitSurfaceProxyFunc& fn) const {
92 for (const auto& resolve : fResolves) {
93 fn(resolve.fProxy.get(), GrMipMapped::kNo);
94 }
95}
96#endif