blob: 80ef7e99f6bdae93c664bf797db132b6df3f3694 [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.
Greg Daniel16f5c652019-10-29 11:26:01 -040020 resolve.fProxyView.proxy()->setLastRenderTask(nullptr);
Chris Daltone2a903e2019-09-18 13:41:50 -060021 }
22}
23
24void GrTextureResolveRenderTask::addProxy(
Greg Daniel16f5c652019-10-29 11:26:01 -040025 GrSurfaceProxyView proxyView, GrSurfaceProxy::ResolveFlags flags, const GrCaps& caps) {
26 fResolves.emplace_back(std::move(proxyView), flags);
27 GrSurfaceProxy* proxy = fResolves.back().fProxyView.proxy();
Chris Dalton16a33c62019-09-24 22:19:17 -060028
Chris Daltone2a903e2019-09-18 13:41:50 -060029 // 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();
Chris Dalton4ece96d2019-08-30 11:26:39 -060036 SkASSERT(renderTargetProxy);
37 SkASSERT(renderTargetProxy->isMSAADirty());
Chris Dalton16a33c62019-09-24 22:19:17 -060038 fResolves.back().fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
Chris Dalton4ece96d2019-08-30 11:26:39 -060039 renderTargetProxy->markMSAAResolved();
40 }
41
Chris Daltone2a903e2019-09-18 13:41:50 -060042 if (GrSurfaceProxy::ResolveFlags::kMipMaps & flags) {
43 GrTextureProxy* textureProxy = proxy->asTextureProxy();
Chris Dalton4ece96d2019-08-30 11:26:39 -060044 SkASSERT(GrMipMapped::kYes == textureProxy->mipMapped());
45 SkASSERT(textureProxy->mipMapsAreDirty());
46 textureProxy->markMipMapsClean();
47 }
48
Chris Daltone2a903e2019-09-18 13:41:50 -060049 // Add the proxy as a dependency: We will read the existing contents of this texture while
Chris Dalton3d770272019-08-14 09:24:37 -060050 // generating mipmap levels and/or resolving MSAA.
Chris Dalton16a33c62019-09-24 22:19:17 -060051 this->addDependency(proxy, GrMipMapped::kNo, GrTextureResolveManager(nullptr), caps);
Chris Daltone2a903e2019-09-18 13:41:50 -060052 proxy->setLastRenderTask(this);
Chris Dalton3d770272019-08-14 09:24:37 -060053}
54
55void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
Chris Daltone2a903e2019-09-18 13:41:50 -060056 // 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) {
Greg Daniel16f5c652019-10-29 11:26:01 -040061 alloc->addInterval(resolve.fProxyView.proxy(), fakeOp, fakeOp,
Chris Daltone2a903e2019-09-18 13:41:50 -060062 GrResourceAllocator::ActualUse::kYes);
63 }
Chris Dalton3d770272019-08-14 09:24:37 -060064 alloc->incOps();
65}
66
67bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
Chris Daltone2a903e2019-09-18 13:41:50 -060068 // Resolve all msaa back-to-back, before regenerating mipmaps.
69 for (const auto& resolve : fResolves) {
70 if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
Greg Daniel16f5c652019-10-29 11:26:01 -040071 GrSurfaceProxy* proxy = resolve.fProxyView.proxy();
Chris Daltone2a903e2019-09-18 13:41:50 -060072 // peekRenderTarget might be null if there was an instantiation error.
Greg Daniel16f5c652019-10-29 11:26:01 -040073 if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
Chris Dalton798a31d2019-09-26 19:28:32 +000074 flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect,
Greg Daniel16f5c652019-10-29 11:26:01 -040075 resolve.fProxyView.origin(),
Chris Dalton798a31d2019-09-26 19:28:32 +000076 GrGpu::ForExternalIO::kNo);
Chris Dalton798a31d2019-09-26 19:28:32 +000077 }
Chris Dalton4ece96d2019-08-30 11:26:39 -060078 }
79 }
Chris Daltone2a903e2019-09-18 13:41:50 -060080 // Regenerate all mipmaps back-to-back.
81 for (const auto& resolve : fResolves) {
82 if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
83 // peekTexture might be null if there was an instantiation error.
Greg Daniel16f5c652019-10-29 11:26:01 -040084 GrTexture* texture = resolve.fProxyView.proxy()->peekTexture();
Chris Daltone2a903e2019-09-18 13:41:50 -060085 if (texture && texture->texturePriv().mipMapsAreDirty()) {
86 flushState->gpu()->regenerateMipMapLevels(texture);
Chris Dalton16a33c62019-09-24 22:19:17 -060087 SkASSERT(!texture->texturePriv().mipMapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -060088 }
Chris Dalton4ece96d2019-08-30 11:26:39 -060089 }
Chris Dalton3d770272019-08-14 09:24:37 -060090 }
91
92 return true;
93}
Chris Daltone2a903e2019-09-18 13:41:50 -060094
95#ifdef SK_DEBUG
Michael Ludwigfcdd0612019-11-25 08:34:31 -050096void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {
Chris Daltone2a903e2019-09-18 13:41:50 -060097 for (const auto& resolve : fResolves) {
Greg Daniel16f5c652019-10-29 11:26:01 -040098 fn(resolve.fProxyView.proxy(), GrMipMapped::kNo);
Chris Daltone2a903e2019-09-18 13:41:50 -060099 }
100}
101#endif