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