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