blob: fd13d65d236c8dd244961ca1d91de29ff2e33cb6 [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"
Brian Salomon4cfae3b2020-07-23 10:33:24 -040015#include "src/gpu/GrTexture.h"
Chris Dalton3d770272019-08-14 09:24:37 -060016
Adlai Hollerd71b7b02020-06-08 15:55:00 -040017void GrTextureResolveRenderTask::addProxy(GrDrawingManager* drawingMgr,
18 sk_sp<GrSurfaceProxy> proxyRef,
19 GrSurfaceProxy::ResolveFlags flags,
20 const GrCaps& caps) {
Adlai Holler33d569e2020-06-16 14:30:08 -040021 Resolve& resolve = fResolves.emplace_back(flags);
22 GrSurfaceProxy* proxy = proxyRef.get();
Chris Dalton16a33c62019-09-24 22:19:17 -060023
Chris Daltone2a903e2019-09-18 13:41:50 -060024 // Ensure the last render task that operated on the proxy is closed. That's where msaa and
25 // mipmaps should have been marked dirty.
Adlai Hollerd71b7b02020-06-08 15:55:00 -040026 SkASSERT(!drawingMgr->getLastRenderTask(proxy)
27 || drawingMgr->getLastRenderTask(proxy)->isClosed());
Chris Daltone2a903e2019-09-18 13:41:50 -060028 SkASSERT(GrSurfaceProxy::ResolveFlags::kNone != flags);
29
30 if (GrSurfaceProxy::ResolveFlags::kMSAA & flags) {
31 GrRenderTargetProxy* renderTargetProxy = proxy->asRenderTargetProxy();
Chris Dalton4ece96d2019-08-30 11:26:39 -060032 SkASSERT(renderTargetProxy);
33 SkASSERT(renderTargetProxy->isMSAADirty());
Adlai Holler33d569e2020-06-16 14:30:08 -040034 resolve.fMSAAResolveRect = renderTargetProxy->msaaDirtyRect();
Chris Dalton4ece96d2019-08-30 11:26:39 -060035 renderTargetProxy->markMSAAResolved();
36 }
37
Chris Daltone2a903e2019-09-18 13:41:50 -060038 if (GrSurfaceProxy::ResolveFlags::kMipMaps & flags) {
39 GrTextureProxy* textureProxy = proxy->asTextureProxy();
Brian Salomon8c82a872020-07-21 12:09:58 -040040 SkASSERT(GrMipmapped::kYes == textureProxy->mipmapped());
41 SkASSERT(textureProxy->mipmapsAreDirty());
42 textureProxy->markMipmapsClean();
Chris Dalton4ece96d2019-08-30 11:26:39 -060043 }
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.
Brian Salomon7e67dca2020-07-21 09:27:25 -040047 this->addDependency(drawingMgr, proxy, GrMipmapped::kNo,
Adlai Hollerd71b7b02020-06-08 15:55:00 -040048 GrTextureResolveManager(nullptr), caps);
Adlai Holler33d569e2020-06-16 14:30:08 -040049 this->addTarget(drawingMgr, GrSurfaceProxyView(std::move(proxyRef)));
Chris Dalton3d770272019-08-14 09:24:37 -060050}
51
52void GrTextureResolveRenderTask::gatherProxyIntervals(GrResourceAllocator* alloc) const {
Chris Daltone2a903e2019-09-18 13:41:50 -060053 // This renderTask doesn't have "normal" ops, however we still need to add intervals so
54 // fEndOfOpsTaskOpIndices will remain in sync. We create fake op#'s to capture the fact that we
55 // manipulate the resolve proxies.
56 auto fakeOp = alloc->curOp();
Adlai Holler33d569e2020-06-16 14:30:08 -040057 SkASSERT(fResolves.count() == this->numTargets());
Brian Salomon982127b2021-01-21 10:43:35 -050058 for (const sk_sp<GrSurfaceProxy>& target : fTargets) {
Adlai Holler7f7a5df2021-02-09 17:41:10 +000059 alloc->addInterval(target.get(), fakeOp, fakeOp, GrResourceAllocator::ActualUse::kYes);
Chris Daltone2a903e2019-09-18 13:41:50 -060060 }
Chris Dalton3d770272019-08-14 09:24:37 -060061 alloc->incOps();
62}
63
64bool GrTextureResolveRenderTask::onExecute(GrOpFlushState* flushState) {
Chris Daltone2a903e2019-09-18 13:41:50 -060065 // Resolve all msaa back-to-back, before regenerating mipmaps.
Adlai Holler33d569e2020-06-16 14:30:08 -040066 SkASSERT(fResolves.count() == this->numTargets());
67 for (int i = 0; i < fResolves.count(); ++i) {
68 const Resolve& resolve = fResolves[i];
Chris Daltone2a903e2019-09-18 13:41:50 -060069 if (GrSurfaceProxy::ResolveFlags::kMSAA & resolve.fFlags) {
Brian Salomon982127b2021-01-21 10:43:35 -050070 GrSurfaceProxy* proxy = this->target(i);
Chris Daltone2a903e2019-09-18 13:41:50 -060071 // peekRenderTarget might be null if there was an instantiation error.
Greg Daniel16f5c652019-10-29 11:26:01 -040072 if (GrRenderTarget* renderTarget = proxy->peekRenderTarget()) {
Jim Van Verthbb61fe32020-07-07 16:39:04 -040073 flushState->gpu()->resolveRenderTarget(renderTarget, resolve.fMSAAResolveRect);
Chris Dalton798a31d2019-09-26 19:28:32 +000074 }
Chris Dalton4ece96d2019-08-30 11:26:39 -060075 }
76 }
Chris Daltone2a903e2019-09-18 13:41:50 -060077 // Regenerate all mipmaps back-to-back.
Adlai Holler33d569e2020-06-16 14:30:08 -040078 for (int i = 0; i < fResolves.count(); ++i) {
79 const Resolve& resolve = fResolves[i];
Chris Daltone2a903e2019-09-18 13:41:50 -060080 if (GrSurfaceProxy::ResolveFlags::kMipMaps & resolve.fFlags) {
81 // peekTexture might be null if there was an instantiation error.
Brian Salomon982127b2021-01-21 10:43:35 -050082 GrTexture* texture = this->target(i)->peekTexture();
Brian Salomon4cfae3b2020-07-23 10:33:24 -040083 if (texture && texture->mipmapsAreDirty()) {
Chris Daltone2a903e2019-09-18 13:41:50 -060084 flushState->gpu()->regenerateMipMapLevels(texture);
Brian Salomon4cfae3b2020-07-23 10:33:24 -040085 SkASSERT(!texture->mipmapsAreDirty());
Chris Daltone2a903e2019-09-18 13:41:50 -060086 }
Chris Dalton4ece96d2019-08-30 11:26:39 -060087 }
Chris Dalton3d770272019-08-14 09:24:37 -060088 }
89
90 return true;
91}
Chris Daltone2a903e2019-09-18 13:41:50 -060092
93#ifdef SK_DEBUG
Adlai Holler33d569e2020-06-16 14:30:08 -040094void GrTextureResolveRenderTask::visitProxies_debugOnly(const GrOp::VisitProxyFunc& fn) const {}
Chris Daltone2a903e2019-09-18 13:41:50 -060095#endif