]> git.cworth.org Git - apitrace/blob - retrace/dxgistate.cpp
d3dretrace: Dump D3D10 depth stencil surfaces as float.
[apitrace] / retrace / dxgistate.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013 VMware, Inc.
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include <assert.h>
28
29 #include <iostream>
30
31 #include "image.hpp"
32
33 #include "dxgistate.hpp"
34
35 #ifdef __MINGW32__
36 #define nullptr NULL
37 #endif
38 #include "DirectXTex.h"
39
40
41 namespace d3dstate {
42
43
44 static DXGI_FORMAT
45 ChooseConversionFormat(DXGI_FORMAT Format, unsigned &numChannels, image::ChannelType &channelType)
46 {
47     numChannels = 4;
48     channelType = image::TYPE_UNORM8;
49
50     switch (Format) {
51
52     // Float
53     case DXGI_FORMAT_R32G32B32A32_FLOAT:
54     case DXGI_FORMAT_R32G32B32_FLOAT:
55     case DXGI_FORMAT_R16G16B16A16_FLOAT:
56     case DXGI_FORMAT_R32G32_FLOAT:
57     case DXGI_FORMAT_R11G11B10_FLOAT:
58     case DXGI_FORMAT_R16G16_FLOAT:
59     case DXGI_FORMAT_R32_FLOAT:
60     case DXGI_FORMAT_R16_FLOAT:
61     case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
62     case DXGI_FORMAT_BC6H_UF16:
63     case DXGI_FORMAT_BC6H_SF16:
64         channelType = image::TYPE_FLOAT;
65         return DXGI_FORMAT_R32G32B32A32_FLOAT;
66
67     // Unsigned normalized
68     case DXGI_FORMAT_R16G16B16A16_UNORM:
69     case DXGI_FORMAT_R10G10B10A2_UNORM:
70     case DXGI_FORMAT_R8G8B8A8_UNORM:
71     case DXGI_FORMAT_R16G16_UNORM:
72     case DXGI_FORMAT_R8G8_UNORM:
73     case DXGI_FORMAT_R16_UNORM:
74     case DXGI_FORMAT_R8_UNORM:
75     case DXGI_FORMAT_A8_UNORM:
76     case DXGI_FORMAT_R1_UNORM:
77     case DXGI_FORMAT_R8G8_B8G8_UNORM:
78     case DXGI_FORMAT_G8R8_G8B8_UNORM:
79     case DXGI_FORMAT_BC1_UNORM:
80     case DXGI_FORMAT_BC2_UNORM:
81     case DXGI_FORMAT_BC3_UNORM:
82     case DXGI_FORMAT_BC4_UNORM:
83     case DXGI_FORMAT_BC5_UNORM:
84     case DXGI_FORMAT_B5G6R5_UNORM:
85     case DXGI_FORMAT_B5G5R5A1_UNORM:
86     case DXGI_FORMAT_B8G8R8A8_UNORM:
87     case DXGI_FORMAT_B8G8R8X8_UNORM:
88     case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
89     case DXGI_FORMAT_BC7_UNORM:
90         return DXGI_FORMAT_R8G8B8A8_UNORM;
91
92     // SRGB
93     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
94     case DXGI_FORMAT_BC1_UNORM_SRGB:
95     case DXGI_FORMAT_BC2_UNORM_SRGB:
96     case DXGI_FORMAT_BC3_UNORM_SRGB:
97     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
98     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
99     case DXGI_FORMAT_BC7_UNORM_SRGB:
100         return DXGI_FORMAT_R8G8B8A8_UNORM;
101
102     // Signed normalized
103     case DXGI_FORMAT_R16G16B16A16_SNORM:
104     case DXGI_FORMAT_R8G8B8A8_SNORM:
105     case DXGI_FORMAT_R16G16_SNORM:
106     case DXGI_FORMAT_R8G8_SNORM:
107     case DXGI_FORMAT_R16_SNORM:
108     case DXGI_FORMAT_R8_SNORM:
109     case DXGI_FORMAT_BC4_SNORM:
110     case DXGI_FORMAT_BC5_SNORM:
111         return DXGI_FORMAT_R8G8B8A8_SNORM;
112
113     // Unsigned
114     case DXGI_FORMAT_R32G32B32A32_UINT:
115     case DXGI_FORMAT_R32G32B32_UINT:
116     case DXGI_FORMAT_R16G16B16A16_UINT:
117     case DXGI_FORMAT_R32G32_UINT:
118     case DXGI_FORMAT_R10G10B10A2_UINT:
119     case DXGI_FORMAT_R8G8B8A8_UINT:
120     case DXGI_FORMAT_R16G16_UINT:
121     case DXGI_FORMAT_R32_UINT:
122     case DXGI_FORMAT_R8G8_UINT:
123     case DXGI_FORMAT_R16_UINT:
124     case DXGI_FORMAT_R8_UINT:
125         return DXGI_FORMAT_R8G8B8A8_UINT;
126
127     // Signed
128     case DXGI_FORMAT_R32G32B32A32_SINT:
129     case DXGI_FORMAT_R32G32B32_SINT:
130     case DXGI_FORMAT_R16G16B16A16_SINT:
131     case DXGI_FORMAT_R32G32_SINT:
132     case DXGI_FORMAT_R8G8B8A8_SINT:
133     case DXGI_FORMAT_R16G16_SINT:
134     case DXGI_FORMAT_R32_SINT:
135     case DXGI_FORMAT_R8G8_SINT:
136     case DXGI_FORMAT_R16_SINT:
137     case DXGI_FORMAT_R8_SINT:
138         return DXGI_FORMAT_R8G8B8A8_SINT;
139
140     // Depth
141     case DXGI_FORMAT_D32_FLOAT:
142     case DXGI_FORMAT_D24_UNORM_S8_UINT:
143     case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
144     case DXGI_FORMAT_D16_UNORM:
145         numChannels = 1;
146         channelType = image::TYPE_FLOAT;
147         return DXGI_FORMAT_D32_FLOAT;
148
149     // Typeless
150     case DXGI_FORMAT_UNKNOWN:
151     case DXGI_FORMAT_R32G32B32A32_TYPELESS:
152     case DXGI_FORMAT_R32G32B32_TYPELESS:
153     case DXGI_FORMAT_R16G16B16A16_TYPELESS:
154     case DXGI_FORMAT_R32G32_TYPELESS:
155     case DXGI_FORMAT_R32G8X24_TYPELESS:
156     case DXGI_FORMAT_R10G10B10A2_TYPELESS:
157     case DXGI_FORMAT_R8G8B8A8_TYPELESS:
158     case DXGI_FORMAT_R16G16_TYPELESS:
159     case DXGI_FORMAT_R32_TYPELESS:
160     case DXGI_FORMAT_R8G8_TYPELESS:
161     case DXGI_FORMAT_R16_TYPELESS:
162     case DXGI_FORMAT_R8_TYPELESS:
163     case DXGI_FORMAT_BC1_TYPELESS:
164     case DXGI_FORMAT_BC2_TYPELESS:
165     case DXGI_FORMAT_BC3_TYPELESS:
166     case DXGI_FORMAT_BC4_TYPELESS:
167     case DXGI_FORMAT_BC5_TYPELESS:
168     case DXGI_FORMAT_B8G8R8A8_TYPELESS:
169     case DXGI_FORMAT_B8G8R8X8_TYPELESS:
170     case DXGI_FORMAT_BC6H_TYPELESS:
171     case DXGI_FORMAT_BC7_TYPELESS:
172     case DXGI_FORMAT_R24G8_TYPELESS:
173     case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
174     case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
175     case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
176     case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
177         return DXGI_FORMAT_UNKNOWN;
178
179     default:
180         return DXGI_FORMAT_R8G8B8A8_UNORM;
181     }
182 }
183
184
185 /**
186  * Convert between DXGI formats.
187  *
188  */
189 HRESULT
190 ConvertFormat(DXGI_FORMAT SrcFormat,
191               void *SrcData,
192               UINT SrcPitch,
193               DXGI_FORMAT DstFormat,
194               void *DstData,
195               UINT DstPitch,
196               UINT Width, UINT Height)
197 {
198     HRESULT hr;
199
200     DirectX::Image SrcImage;
201     DirectX::Image DstImage;
202
203     SrcImage.width = Width;
204     SrcImage.height = Height;
205     SrcImage.format = SrcFormat;
206     SrcImage.rowPitch = SrcPitch;
207     SrcImage.slicePitch = Height * SrcPitch;
208     SrcImage.pixels = (uint8_t*)SrcData;
209
210     DstImage.width = Width;
211     DstImage.height = Height;
212     DstImage.format = DstFormat;
213     DstImage.rowPitch = DstPitch;
214     DstImage.slicePitch = Height * DstPitch;
215     DstImage.pixels = (uint8_t*)DstData;
216
217     DirectX::Rect rect(0, 0, Width, Height);
218
219     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
220     assert(SUCCEEDED(hr));
221     if (FAILED(hr)) {
222         return hr;
223     }
224
225     if (SrcFormat != DstFormat) {
226         DirectX::ScratchImage ScratchImage;
227         ScratchImage.Initialize2D(DstFormat, Width, Height, 1, 1);
228
229         if (DirectX::IsCompressed(SrcFormat)) {
230             hr = DirectX::Decompress(SrcImage, DstFormat, ScratchImage);
231         } else {
232             hr = DirectX::Convert(SrcImage, DstFormat, DirectX::TEX_FILTER_DEFAULT, 0.0f, ScratchImage);
233         }
234
235         if (SUCCEEDED(hr)) {
236             hr = CopyRectangle(*ScratchImage.GetImage(0, 0, 0), rect, DstImage, DirectX::TEX_FILTER_DEFAULT, 0, 0);
237         }
238     } else {
239         hr = CopyRectangle(SrcImage, rect, DstImage, DirectX::TEX_FILTER_DEFAULT, 0, 0);
240     }
241
242     return hr;
243 }
244
245
246 image::Image *
247 ConvertImage(DXGI_FORMAT SrcFormat,
248              void *SrcData,
249              UINT SrcPitch,
250              UINT Width, UINT Height)
251 {
252     unsigned numChannels;
253     image::ChannelType channelType;
254
255     DXGI_FORMAT DstFormat = ChooseConversionFormat(SrcFormat, numChannels, channelType);
256     if (DstFormat == DXGI_FORMAT_UNKNOWN) {
257         return NULL;
258     }
259
260     image::Image *image = new image::Image(Width, Height, numChannels, false, channelType);
261     if (!image) {
262         return NULL;
263     }
264     assert(image->stride() > 0);
265
266     HRESULT hr;
267     hr = ConvertFormat(SrcFormat,
268                        SrcData, SrcPitch,
269                        DstFormat,
270                        image->start(), image->stride(),
271                        Width, Height);
272     if (FAILED(hr)) {
273         std::cerr << "warning: failed to convert from format " << SrcFormat << " to format " << DstFormat << "\n";
274         delete image;
275         image = NULL;
276     }
277
278     return image;
279 }
280
281 } /* namespace d3dstate */