1 /*
2 * Copyright 2020 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/ganesh/d3d/GrD3DRenderTarget.h"
9
10 #include "include/gpu/ganesh/GrBackendSurface.h"
11 #include "include/gpu/ganesh/d3d/GrD3DTypes.h"
12 #include "src/gpu/KeyBuilder.h"
13 #include "src/gpu/ganesh/GrRenderTarget.h"
14 #include "src/gpu/ganesh/d3d/GrD3DGpu.h"
15 #include "src/gpu/ganesh/d3d/GrD3DResourceProvider.h"
16 #include "src/gpu/ganesh/d3d/GrD3DTextureResource.h"
17 #include "src/gpu/ganesh/d3d/GrD3DUtil.h"
18
19 // We're virtually derived from GrSurface (via GrRenderTarget) so its
20 // constructor must be explicitly called.
GrD3DRenderTarget(GrD3DGpu * gpu,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DTextureResourceInfo & msaaInfo,sk_sp<GrD3DResourceState> msaaState,const GrD3DDescriptorHeap::CPUHandle & colorRenderTargetView,const GrD3DDescriptorHeap::CPUHandle & resolveRenderTargetView,Wrapped,std::string_view label)21 GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
22 SkISize dimensions,
23 const GrD3DTextureResourceInfo& info,
24 sk_sp<GrD3DResourceState> state,
25 const GrD3DTextureResourceInfo& msaaInfo,
26 sk_sp<GrD3DResourceState> msaaState,
27 const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
28 const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
29 Wrapped,
30 std::string_view label)
31 : GrSurface(gpu, dimensions, info.fProtected, label)
32 , GrD3DTextureResource(info, std::move(state))
33 // for the moment we only support 1:1 color to stencil
34 , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected, label)
35 , fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState)))
36 , fColorRenderTargetView(colorRenderTargetView)
37 , fResolveRenderTargetView(resolveRenderTargetView) {
38 SkASSERT(info.fProtected == msaaInfo.fProtected);
39 SkASSERT(msaaInfo.fSampleCount > 1);
40 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
41 }
42
43 // We're virtually derived from GrSurface (via GrRenderTarget) so its
44 // constructor must be explicitly called.
GrD3DRenderTarget(GrD3DGpu * gpu,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DTextureResourceInfo & msaaInfo,sk_sp<GrD3DResourceState> msaaState,const GrD3DDescriptorHeap::CPUHandle & colorRenderTargetView,const GrD3DDescriptorHeap::CPUHandle & resolveRenderTargetView,std::string_view label)45 GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
46 SkISize dimensions,
47 const GrD3DTextureResourceInfo& info,
48 sk_sp<GrD3DResourceState> state,
49 const GrD3DTextureResourceInfo& msaaInfo,
50 sk_sp<GrD3DResourceState> msaaState,
51 const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView,
52 const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView,
53 std::string_view label)
54 : GrSurface(gpu, dimensions, info.fProtected, label)
55 , GrD3DTextureResource(info, std::move(state))
56 // for the moment we only support 1:1 color to stencil
57 , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected, label)
58 , fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState)))
59 , fColorRenderTargetView(colorRenderTargetView)
60 , fResolveRenderTargetView(resolveRenderTargetView) {
61 SkASSERT(info.fProtected == msaaInfo.fProtected);
62 SkASSERT(msaaInfo.fSampleCount > 1);
63 }
64
65 // We're virtually derived from GrSurface (via GrRenderTarget) so its
66 // constructor must be explicitly called.
GrD3DRenderTarget(GrD3DGpu * gpu,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DDescriptorHeap::CPUHandle & renderTargetView,Wrapped,std::string_view label)67 GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
68 SkISize dimensions,
69 const GrD3DTextureResourceInfo& info,
70 sk_sp<GrD3DResourceState> state,
71 const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
72 Wrapped,
73 std::string_view label)
74 : GrSurface(gpu, dimensions, info.fProtected, label)
75 , GrD3DTextureResource(info, std::move(state))
76 , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected, label)
77 , fMSAATextureResource(nullptr)
78 , fColorRenderTargetView(renderTargetView) {
79 this->registerWithCacheWrapped(GrWrapCacheable::kNo);
80 }
81
82 // We're virtually derived from GrSurface (via GrRenderTarget) so its
83 // constructor must be explicitly called.
GrD3DRenderTarget(GrD3DGpu * gpu,SkISize dimensions,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state,const GrD3DDescriptorHeap::CPUHandle & renderTargetView,std::string_view label)84 GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu,
85 SkISize dimensions,
86 const GrD3DTextureResourceInfo& info,
87 sk_sp<GrD3DResourceState> state,
88 const GrD3DDescriptorHeap::CPUHandle& renderTargetView,
89 std::string_view label)
90 : GrSurface(gpu, dimensions, info.fProtected, label)
91 , GrD3DTextureResource(info, std::move(state))
92 , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected, label)
93 , fMSAATextureResource(nullptr)
94 , fColorRenderTargetView(renderTargetView) {}
95
MakeWrappedRenderTarget(GrD3DGpu * gpu,SkISize dimensions,int sampleCnt,const GrD3DTextureResourceInfo & info,sk_sp<GrD3DResourceState> state)96 sk_sp<GrD3DRenderTarget> GrD3DRenderTarget::MakeWrappedRenderTarget(
97 GrD3DGpu* gpu, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info,
98 sk_sp<GrD3DResourceState> state) {
99 SkASSERT(info.fResource.get());
100 SkASSERT(info.fLevelCount == 1);
101 SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);
102
103 int wrappedTextureSampleCnt = static_cast<int>(info.fSampleCount);
104 if (sampleCnt != wrappedTextureSampleCnt && wrappedTextureSampleCnt != 1) {
105 return nullptr;
106 }
107
108 GrD3DDescriptorHeap::CPUHandle renderTargetView =
109 gpu->resourceProvider().createRenderTargetView(info.fResource.get());
110
111 // create msaa surface if necessary
112 GrD3DRenderTarget* d3dRT;
113 if (sampleCnt != wrappedTextureSampleCnt) {
114 GrD3DTextureResourceInfo msInfo;
115 sk_sp<GrD3DResourceState> msState;
116 // for wrapped MSAA surface we assume clear to white
117 SkColor4f clearColor = { 1, 1, 1, 1 };
118 std::tie(msInfo, msState) =
119 GrD3DTextureResource::CreateMSAA(gpu, dimensions, sampleCnt, info, clearColor);
120
121 GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView =
122 gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get());
123
124 d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), msInfo,
125 std::move(msState), msaaRenderTargetView, renderTargetView,
126 kWrapped,
127 /*label=*/"MakeWrappedRenderTargetWithMSAASurface");
128 } else {
129 d3dRT = new GrD3DRenderTarget(
130 gpu, dimensions, info, std::move(state), renderTargetView, kWrapped,
131 /*label=*/"MakeWrappedRenderTarget");
132 }
133
134 return sk_sp<GrD3DRenderTarget>(d3dRT);
135 }
136
~GrD3DRenderTarget()137 GrD3DRenderTarget::~GrD3DRenderTarget() {
138 // either release or abandon should have been called by the owner of this object.
139 SkASSERT(!fMSAATextureResource);
140 }
141
msaaTextureResource() const142 const GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() const {
143 if (this->numSamples() == 1) {
144 SkASSERT(!fMSAATextureResource);
145 return nullptr;
146 }
147 if (fMSAATextureResource) {
148 return fMSAATextureResource.get();
149 }
150 SkASSERT(!fMSAATextureResource);
151 return this;
152 }
153
msaaTextureResource()154 GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() {
155 auto* constThis = const_cast<const GrD3DRenderTarget*>(this);
156 return const_cast<GrD3DTextureResource*>(constThis->msaaTextureResource());
157 }
158
releaseInternalObjects()159 void GrD3DRenderTarget::releaseInternalObjects() {
160 GrD3DGpu* gpu = this->getD3DGpu();
161
162 if (fMSAATextureResource) {
163 fMSAATextureResource->releaseResource(gpu);
164 fMSAATextureResource.reset();
165 gpu->resourceProvider().recycleRenderTargetView(fResolveRenderTargetView);
166 }
167
168 gpu->resourceProvider().recycleRenderTargetView(fColorRenderTargetView);
169 }
170
onRelease()171 void GrD3DRenderTarget::onRelease() {
172 this->releaseInternalObjects();
173 this->releaseResource(this->getD3DGpu());
174 GrRenderTarget::onRelease();
175 }
176
onAbandon()177 void GrD3DRenderTarget::onAbandon() {
178 this->releaseInternalObjects();
179 this->releaseResource(this->getD3DGpu());
180 GrRenderTarget::onAbandon();
181 }
182
getBackendRenderTarget() const183 GrBackendRenderTarget GrD3DRenderTarget::getBackendRenderTarget() const {
184 return GrBackendRenderTarget(this->width(), this->height(), fInfo, this->grD3DResourceState());
185 }
186
getD3DGpu() const187 GrD3DGpu* GrD3DRenderTarget::getD3DGpu() const {
188 SkASSERT(!this->wasDestroyed());
189 return static_cast<GrD3DGpu*>(this->getGpu());
190 }
191
stencilDxgiFormat() const192 DXGI_FORMAT GrD3DRenderTarget::stencilDxgiFormat() const {
193 if (auto stencil = this->getStencilAttachment()) {
194 auto d3dStencil = static_cast<GrD3DAttachment*>(stencil);
195 return d3dStencil->dxgiFormat();
196 }
197 return DXGI_FORMAT_UNKNOWN;
198 }
199
genKey(skgpu::KeyBuilder * b) const200 void GrD3DRenderTarget::genKey(skgpu::KeyBuilder* b) const {
201 b->add32(this->dxgiFormat());
202 b->add32(this->numSamples());
203 b->add32(this->stencilDxgiFormat());
204 #ifdef SK_DEBUG
205 if (const GrAttachment* stencil = this->getStencilAttachment()) {
206 SkASSERT(stencil->numSamples() == this->numSamples());
207 }
208 #endif
209 b->add32(this->sampleQualityPattern());
210 }
211
onSetLabel()212 void GrD3DRenderTarget::onSetLabel() {
213 SkASSERT(this->d3dResource());
214 if (!this->getLabel().empty()) {
215 if (fMSAATextureResource) {
216 SkASSERT(fMSAATextureResource->d3dResource());
217 const std::wstring suffix = GrD3DMultiByteToWide(this->getLabel());
218 const std::wstring msaaLabel = L"_Skia_MSAA_" + suffix;
219 fMSAATextureResource->d3dResource()->SetName(msaaLabel.c_str());
220 const std::wstring resolveLabel = L"_Skia_Resolve_" + suffix;
221 this->d3dResource()->SetName(resolveLabel.c_str());
222 } else {
223 const std::wstring label = L"_Skia_" + GrD3DMultiByteToWide(this->getLabel());
224 this->d3dResource()->SetName(label.c_str());
225 }
226 }
227 }
228