1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DRenderTarget.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h"
11cb93a386Sopenharmony_ci#include "include/gpu/d3d/GrD3DTypes.h"
12cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h"
13cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DGpu.h"
14cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DResourceProvider.h"
15cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DTextureResource.h"
16cb93a386Sopenharmony_ci#include "src/gpu/d3d/GrD3DUtil.h"
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_ci// We're virtually derived from GrSurface (via GrRenderTarget) so its
19cb93a386Sopenharmony_ci// constructor must be explicitly called.
20cb93a386Sopenharmony_ciGrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
21cb93a386Sopenharmony_ci                                     SkISize dimensions,
22cb93a386Sopenharmony_ci                                     const GrD3DTextureResourceInfo& info,
23cb93a386Sopenharmony_ci                                     sk_sp<GrD3DResourceState> state,
24cb93a386Sopenharmony_ci                                     const GrD3DTextureResourceInfo& msaaInfo,
25cb93a386Sopenharmony_ci                                     sk_sp<GrD3DResourceState> msaaState,
26cb93a386Sopenharmony_ci                                     const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
27cb93a386Sopenharmony_ci                                     const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
28cb93a386Sopenharmony_ci                                     Wrapped)
29cb93a386Sopenharmony_ci        : GrSurface(gpu, dimensions, info.fProtected)
30cb93a386Sopenharmony_ci        , GrD3DTextureResource(info, std::move(state))
31cb93a386Sopenharmony_ci        // for the moment we only support 1:1 color to stencil
32cb93a386Sopenharmony_ci        , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected)
33cb93a386Sopenharmony_ci        , fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState)))
34cb93a386Sopenharmony_ci        , fColorRenderTargetView(colorRenderTargetView)
35cb93a386Sopenharmony_ci        , fResolveRenderTargetView(resolveRenderTargetView) {
36cb93a386Sopenharmony_ci    SkASSERT(info.fProtected == msaaInfo.fProtected);
37cb93a386Sopenharmony_ci    SkASSERT(msaaInfo.fSampleCount > 1);
38cb93a386Sopenharmony_ci    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
39cb93a386Sopenharmony_ci}
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci// We're virtually derived from GrSurface (via GrRenderTarget) so its
42cb93a386Sopenharmony_ci// constructor must be explicitly called.
43cb93a386Sopenharmony_ciGrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
44cb93a386Sopenharmony_ci                                     SkISize dimensions,
45cb93a386Sopenharmony_ci                                     const GrD3DTextureResourceInfo& info,
46cb93a386Sopenharmony_ci                                     sk_sp<GrD3DResourceState> state,
47cb93a386Sopenharmony_ci                                     const GrD3DTextureResourceInfo& msaaInfo,
48cb93a386Sopenharmony_ci                                     sk_sp<GrD3DResourceState> msaaState,
49cb93a386Sopenharmony_ci                                     const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
50cb93a386Sopenharmony_ci                                     const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView)
51cb93a386Sopenharmony_ci        : GrSurface(gpu, dimensions, info.fProtected)
52cb93a386Sopenharmony_ci        , GrD3DTextureResource(info, std::move(state))
53cb93a386Sopenharmony_ci        // for the moment we only support 1:1 color to stencil
54cb93a386Sopenharmony_ci        , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected)
55cb93a386Sopenharmony_ci        , fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState)))
56cb93a386Sopenharmony_ci        , fColorRenderTargetView(colorRenderTargetView)
57cb93a386Sopenharmony_ci        , fResolveRenderTargetView(resolveRenderTargetView) {
58cb93a386Sopenharmony_ci    SkASSERT(info.fProtected == msaaInfo.fProtected);
59cb93a386Sopenharmony_ci    SkASSERT(msaaInfo.fSampleCount > 1);
60cb93a386Sopenharmony_ci}
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci// We're virtually derived from GrSurface (via GrRenderTarget) so its
63cb93a386Sopenharmony_ci// constructor must be explicitly called.
64cb93a386Sopenharmony_ciGrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
65cb93a386Sopenharmony_ci                                     SkISize dimensions,
66cb93a386Sopenharmony_ci                                     const GrD3DTextureResourceInfo& info,
67cb93a386Sopenharmony_ci                                     sk_sp<GrD3DResourceState> state,
68cb93a386Sopenharmony_ci                                     const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
69cb93a386Sopenharmony_ci                                     Wrapped)
70cb93a386Sopenharmony_ci        : GrSurface(gpu, dimensions, info.fProtected)
71cb93a386Sopenharmony_ci        , GrD3DTextureResource(info, std::move(state))
72cb93a386Sopenharmony_ci        , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected)
73cb93a386Sopenharmony_ci        , fMSAATextureResource(nullptr)
74cb93a386Sopenharmony_ci        , fColorRenderTargetView(renderTargetView) {
75cb93a386Sopenharmony_ci    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
76cb93a386Sopenharmony_ci}
77cb93a386Sopenharmony_ci
78cb93a386Sopenharmony_ci// We're virtually derived from GrSurface (via GrRenderTarget) so its
79cb93a386Sopenharmony_ci// constructor must be explicitly called.
80cb93a386Sopenharmony_ciGrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
81cb93a386Sopenharmony_ci                                     SkISize dimensions,
82cb93a386Sopenharmony_ci                                     const GrD3DTextureResourceInfo& info,
83cb93a386Sopenharmony_ci                                     sk_sp<GrD3DResourceState> state,
84cb93a386Sopenharmony_ci                                     const GrD3DDescriptorHeap::CPUHandle& renderTargetView)
85cb93a386Sopenharmony_ci        : GrSurface(gpu, dimensions, info.fProtected)
86cb93a386Sopenharmony_ci        , GrD3DTextureResource(info, std::move(state))
87cb93a386Sopenharmony_ci        , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected)
88cb93a386Sopenharmony_ci        , fMSAATextureResource(nullptr)
89cb93a386Sopenharmony_ci        , fColorRenderTargetView(renderTargetView) {}
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_cisk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget(
92cb93a386Sopenharmony_ci            GrD3DGpu* gpu, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info,
93cb93a386Sopenharmony_ci            sk_sp<GrD3DResourceState> state) {
94cb93a386Sopenharmony_ci    SkASSERT(info.fResource.get());
95cb93a386Sopenharmony_ci    SkASSERT(info.fLevelCount == 1);
96cb93a386Sopenharmony_ci    SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    int wrappedTextureSampleCnt = static_cast<int>(info.fSampleCount);
99cb93a386Sopenharmony_ci    if (sampleCnt != wrappedTextureSampleCnt && wrappedTextureSampleCnt != 1) {
100cb93a386Sopenharmony_ci        return nullptr;
101cb93a386Sopenharmony_ci    }
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    GrD3DDescriptorHeap::CPUHandle renderTargetView =
104cb93a386Sopenharmony_ci            gpu->resourceProvider().createRenderTargetView(info.fResource.get());
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    // create msaa surface if necessary
107cb93a386Sopenharmony_ci    GrD3DRenderTarget* d3dRT;
108cb93a386Sopenharmony_ci    if (sampleCnt != wrappedTextureSampleCnt) {
109cb93a386Sopenharmony_ci        GrD3DTextureResourceInfo msInfo;
110cb93a386Sopenharmony_ci        sk_sp<GrD3DResourceState> msState;
111cb93a386Sopenharmony_ci        // for wrapped MSAA surface we assume clear to white
112cb93a386Sopenharmony_ci        SkColor4f clearColor = { 1, 1, 1, 1 };
113cb93a386Sopenharmony_ci        std::tie(msInfo, msState) =
114cb93a386Sopenharmony_ci                GrD3DTextureResource::CreateMSAA(gpu, dimensions, sampleCnt, info, clearColor);
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci        GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView =
117cb93a386Sopenharmony_ci                gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_ci        d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), msInfo,
120cb93a386Sopenharmony_ci                                      std::move(msState), msaaRenderTargetView, renderTargetView,
121cb93a386Sopenharmony_ci                                      kWrapped);
122cb93a386Sopenharmony_ci    } else {
123cb93a386Sopenharmony_ci        d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), renderTargetView,
124cb93a386Sopenharmony_ci                                      kWrapped);
125cb93a386Sopenharmony_ci    }
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci    return sk_sp<GrD3DRenderTarget>(d3dRT);
128cb93a386Sopenharmony_ci}
129cb93a386Sopenharmony_ci
130cb93a386Sopenharmony_ciGrD3DRenderTarget::~GrD3DRenderTarget() {
131cb93a386Sopenharmony_ci    // either release or abandon should have been called by the owner of this object.
132cb93a386Sopenharmony_ci    SkASSERT(!fMSAATextureResource);
133cb93a386Sopenharmony_ci}
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ciconst GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() const {
136cb93a386Sopenharmony_ci    if (this->numSamples() == 1) {
137cb93a386Sopenharmony_ci        SkASSERT(!fMSAATextureResource);
138cb93a386Sopenharmony_ci        return nullptr;
139cb93a386Sopenharmony_ci    }
140cb93a386Sopenharmony_ci    if (fMSAATextureResource) {
141cb93a386Sopenharmony_ci        return fMSAATextureResource.get();
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci    SkASSERT(!fMSAATextureResource);
144cb93a386Sopenharmony_ci    return this;
145cb93a386Sopenharmony_ci}
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ciGrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() {
148cb93a386Sopenharmony_ci    auto* constThis = const_cast<const GrD3DRenderTarget*>(this);
149cb93a386Sopenharmony_ci    return const_cast<GrD3DTextureResource*>(constThis->msaaTextureResource());
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_civoid GrD3DRenderTarget::releaseInternalObjects() {
153cb93a386Sopenharmony_ci    GrD3DGpu* gpu = this->getD3DGpu();
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci    if (fMSAATextureResource) {
156cb93a386Sopenharmony_ci        fMSAATextureResource->releaseResource(gpu);
157cb93a386Sopenharmony_ci        fMSAATextureResource.reset();
158cb93a386Sopenharmony_ci        gpu->resourceProvider().recycleRenderTargetView(fResolveRenderTargetView);
159cb93a386Sopenharmony_ci    }
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci    gpu->resourceProvider().recycleRenderTargetView(fColorRenderTargetView);
162cb93a386Sopenharmony_ci}
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_civoid GrD3DRenderTarget::onRelease() {
165cb93a386Sopenharmony_ci    this->releaseInternalObjects();
166cb93a386Sopenharmony_ci    this->releaseResource(this->getD3DGpu());
167cb93a386Sopenharmony_ci    GrRenderTarget::onRelease();
168cb93a386Sopenharmony_ci}
169cb93a386Sopenharmony_ci
170cb93a386Sopenharmony_civoid GrD3DRenderTarget::onAbandon() {
171cb93a386Sopenharmony_ci    this->releaseInternalObjects();
172cb93a386Sopenharmony_ci    this->releaseResource(this->getD3DGpu());
173cb93a386Sopenharmony_ci    GrRenderTarget::onAbandon();
174cb93a386Sopenharmony_ci}
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ciGrBackendRenderTarget GrD3DRenderTarget::getBackendRenderTarget() const {
177cb93a386Sopenharmony_ci    return GrBackendRenderTarget(this->width(), this->height(), fInfo, this->grD3DResourceState());
178cb93a386Sopenharmony_ci}
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ciGrD3DGpu* GrD3DRenderTarget::getD3DGpu() const {
181cb93a386Sopenharmony_ci    SkASSERT(!this->wasDestroyed());
182cb93a386Sopenharmony_ci    return static_cast<GrD3DGpu*>(this->getGpu());
183cb93a386Sopenharmony_ci}
184cb93a386Sopenharmony_ci
185cb93a386Sopenharmony_ciDXGI_FORMAT GrD3DRenderTarget::stencilDxgiFormat() const {
186cb93a386Sopenharmony_ci    if (auto stencil = this->getStencilAttachment()) {
187cb93a386Sopenharmony_ci        auto d3dStencil = static_cast<GrD3DAttachment*>(stencil);
188cb93a386Sopenharmony_ci        return d3dStencil->dxgiFormat();
189cb93a386Sopenharmony_ci    }
190cb93a386Sopenharmony_ci    return DXGI_FORMAT_UNKNOWN;
191cb93a386Sopenharmony_ci}
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_civoid GrD3DRenderTarget::genKey(GrProcessorKeyBuilder* b) const {
194cb93a386Sopenharmony_ci    b->add32(this->dxgiFormat());
195cb93a386Sopenharmony_ci    b->add32(this->numSamples());
196cb93a386Sopenharmony_ci    b->add32(this->stencilDxgiFormat());
197cb93a386Sopenharmony_ci#ifdef SK_DEBUG
198cb93a386Sopenharmony_ci    if (const GrAttachment* stencil = this->getStencilAttachment()) {
199cb93a386Sopenharmony_ci        SkASSERT(stencil->numSamples() == this->numSamples());
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci#endif
202cb93a386Sopenharmony_ci    b->add32(this->sampleQualityPattern());
203cb93a386Sopenharmony_ci}
204