]> git.cworth.org Git - apitrace/blob - retrace/dxgistate.cpp
d3dretrace: Dump DXGI_FORMAT_R32G32B32A32_FLOAT images in floating point.
[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, image::ChannelType &channelType)
46 {
47     channelType = image::TYPE_UNORM8;
48
49     switch (Format) {
50
51     // Float
52     case DXGI_FORMAT_R32G32B32A32_FLOAT:
53     case DXGI_FORMAT_R32G32B32_FLOAT:
54     case DXGI_FORMAT_R16G16B16A16_FLOAT:
55     case DXGI_FORMAT_R32G32_FLOAT:
56     case DXGI_FORMAT_R11G11B10_FLOAT:
57     case DXGI_FORMAT_R16G16_FLOAT:
58     case DXGI_FORMAT_R32_FLOAT:
59     case DXGI_FORMAT_R16_FLOAT:
60     case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
61     case DXGI_FORMAT_BC6H_UF16:
62     case DXGI_FORMAT_BC6H_SF16:
63         channelType = image::TYPE_FLOAT;
64         return DXGI_FORMAT_R32G32B32A32_FLOAT;
65
66     // Unsigned normalized
67     case DXGI_FORMAT_R16G16B16A16_UNORM:
68     case DXGI_FORMAT_R10G10B10A2_UNORM:
69     case DXGI_FORMAT_R8G8B8A8_UNORM:
70     case DXGI_FORMAT_R16G16_UNORM:
71     case DXGI_FORMAT_R8G8_UNORM:
72     case DXGI_FORMAT_R16_UNORM:
73     case DXGI_FORMAT_R8_UNORM:
74     case DXGI_FORMAT_A8_UNORM:
75     case DXGI_FORMAT_R1_UNORM:
76     case DXGI_FORMAT_R8G8_B8G8_UNORM:
77     case DXGI_FORMAT_G8R8_G8B8_UNORM:
78     case DXGI_FORMAT_BC1_UNORM:
79     case DXGI_FORMAT_BC2_UNORM:
80     case DXGI_FORMAT_BC3_UNORM:
81     case DXGI_FORMAT_BC4_UNORM:
82     case DXGI_FORMAT_BC5_UNORM:
83     case DXGI_FORMAT_B5G6R5_UNORM:
84     case DXGI_FORMAT_B5G5R5A1_UNORM:
85     case DXGI_FORMAT_B8G8R8A8_UNORM:
86     case DXGI_FORMAT_B8G8R8X8_UNORM:
87     case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
88     case DXGI_FORMAT_BC7_UNORM:
89         return DXGI_FORMAT_R8G8B8A8_UNORM;
90
91     // SRGB
92     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
93     case DXGI_FORMAT_BC1_UNORM_SRGB:
94     case DXGI_FORMAT_BC2_UNORM_SRGB:
95     case DXGI_FORMAT_BC3_UNORM_SRGB:
96     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
97     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
98     case DXGI_FORMAT_BC7_UNORM_SRGB:
99         return DXGI_FORMAT_R8G8B8A8_UNORM;
100
101     // Signed normalized
102     case DXGI_FORMAT_R16G16B16A16_SNORM:
103     case DXGI_FORMAT_R8G8B8A8_SNORM:
104     case DXGI_FORMAT_R16G16_SNORM:
105     case DXGI_FORMAT_R8G8_SNORM:
106     case DXGI_FORMAT_R16_SNORM:
107     case DXGI_FORMAT_R8_SNORM:
108     case DXGI_FORMAT_BC4_SNORM:
109     case DXGI_FORMAT_BC5_SNORM:
110         return DXGI_FORMAT_R8G8B8A8_SNORM;
111
112     // Unsigned
113     case DXGI_FORMAT_R32G32B32A32_UINT:
114     case DXGI_FORMAT_R32G32B32_UINT:
115     case DXGI_FORMAT_R16G16B16A16_UINT:
116     case DXGI_FORMAT_R32G32_UINT:
117     case DXGI_FORMAT_R10G10B10A2_UINT:
118     case DXGI_FORMAT_R8G8B8A8_UINT:
119     case DXGI_FORMAT_R16G16_UINT:
120     case DXGI_FORMAT_R32_UINT:
121     case DXGI_FORMAT_R8G8_UINT:
122     case DXGI_FORMAT_R16_UINT:
123     case DXGI_FORMAT_R8_UINT:
124         return DXGI_FORMAT_R8G8B8A8_UINT;
125
126     // Signed
127     case DXGI_FORMAT_R32G32B32A32_SINT:
128     case DXGI_FORMAT_R32G32B32_SINT:
129     case DXGI_FORMAT_R16G16B16A16_SINT:
130     case DXGI_FORMAT_R32G32_SINT:
131     case DXGI_FORMAT_R8G8B8A8_SINT:
132     case DXGI_FORMAT_R16G16_SINT:
133     case DXGI_FORMAT_R32_SINT:
134     case DXGI_FORMAT_R8G8_SINT:
135     case DXGI_FORMAT_R16_SINT:
136     case DXGI_FORMAT_R8_SINT:
137         return DXGI_FORMAT_R8G8B8A8_SINT;
138
139     // Depth
140     case DXGI_FORMAT_D32_FLOAT:
141     case DXGI_FORMAT_D24_UNORM_S8_UINT:
142     case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
143     case DXGI_FORMAT_D16_UNORM:
144         return DXGI_FORMAT_R8G8B8A8_UNORM;
145
146     // Typeless
147     case DXGI_FORMAT_UNKNOWN:
148     case DXGI_FORMAT_R32G32B32A32_TYPELESS:
149     case DXGI_FORMAT_R32G32B32_TYPELESS:
150     case DXGI_FORMAT_R16G16B16A16_TYPELESS:
151     case DXGI_FORMAT_R32G32_TYPELESS:
152     case DXGI_FORMAT_R32G8X24_TYPELESS:
153     case DXGI_FORMAT_R10G10B10A2_TYPELESS:
154     case DXGI_FORMAT_R8G8B8A8_TYPELESS:
155     case DXGI_FORMAT_R16G16_TYPELESS:
156     case DXGI_FORMAT_R32_TYPELESS:
157     case DXGI_FORMAT_R8G8_TYPELESS:
158     case DXGI_FORMAT_R16_TYPELESS:
159     case DXGI_FORMAT_R8_TYPELESS:
160     case DXGI_FORMAT_BC1_TYPELESS:
161     case DXGI_FORMAT_BC2_TYPELESS:
162     case DXGI_FORMAT_BC3_TYPELESS:
163     case DXGI_FORMAT_BC4_TYPELESS:
164     case DXGI_FORMAT_BC5_TYPELESS:
165     case DXGI_FORMAT_B8G8R8A8_TYPELESS:
166     case DXGI_FORMAT_B8G8R8X8_TYPELESS:
167     case DXGI_FORMAT_BC6H_TYPELESS:
168     case DXGI_FORMAT_BC7_TYPELESS:
169     case DXGI_FORMAT_R24G8_TYPELESS:
170     case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
171     case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
172     case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
173     case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
174         return DXGI_FORMAT_UNKNOWN;
175
176     default:
177         return DXGI_FORMAT_R8G8B8A8_UNORM;
178     }
179 }
180
181
182 /**
183  * Convert between DXGI formats.
184  *
185  */
186 HRESULT
187 ConvertFormat(DXGI_FORMAT SrcFormat,
188               void *SrcData,
189               UINT SrcPitch,
190               DXGI_FORMAT DstFormat,
191               void *DstData,
192               UINT DstPitch,
193               UINT Width, UINT Height)
194 {
195     HRESULT hr;
196
197     DirectX::Image SrcImage;
198     DirectX::Image DstImage;
199
200     SrcImage.width = Width;
201     SrcImage.height = Height;
202     SrcImage.format = SrcFormat;
203     SrcImage.rowPitch = SrcPitch;
204     SrcImage.slicePitch = Height * SrcPitch;
205     SrcImage.pixels = (uint8_t*)SrcData;
206
207     DstImage.width = Width;
208     DstImage.height = Height;
209     DstImage.format = DstFormat;
210     DstImage.rowPitch = DstPitch;
211     DstImage.slicePitch = Height * DstPitch;
212     DstImage.pixels = (uint8_t*)DstData;
213
214     DirectX::Rect rect(0, 0, Width, Height);
215
216     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
217     assert(SUCCEEDED(hr));
218     if (FAILED(hr)) {
219         return hr;
220     }
221
222     if (SrcFormat != DstFormat) {
223         DirectX::ScratchImage ScratchImage;
224         ScratchImage.Initialize2D(DstFormat, Width, Height, 1, 1);
225
226         if (DirectX::IsCompressed(SrcFormat)) {
227             hr = DirectX::Decompress(SrcImage, DstFormat, ScratchImage);
228         } else {
229             hr = DirectX::Convert(SrcImage, DstFormat, DirectX::TEX_FILTER_DEFAULT, 0.0f, ScratchImage);
230         }
231
232         if (SUCCEEDED(hr)) {
233             hr = CopyRectangle(*ScratchImage.GetImage(0, 0, 0), rect, DstImage, DirectX::TEX_FILTER_DEFAULT, 0, 0);
234         }
235     } else {
236         hr = CopyRectangle(SrcImage, rect, DstImage, DirectX::TEX_FILTER_DEFAULT, 0, 0);
237     }
238
239     return hr;
240 }
241
242
243 image::Image *
244 ConvertImage(DXGI_FORMAT SrcFormat,
245              void *SrcData,
246              UINT SrcPitch,
247              UINT Width, UINT Height)
248 {
249     image::ChannelType channelType;
250
251     DXGI_FORMAT DstFormat = ChooseConversionFormat(SrcFormat, channelType);
252     if (DstFormat == DXGI_FORMAT_UNKNOWN) {
253         return NULL;
254     }
255
256     image::Image *image = new image::Image(Width, Height, 4, false, channelType);
257     if (!image) {
258         return NULL;
259     }
260     assert(image->stride() > 0);
261
262     HRESULT hr;
263     hr = ConvertFormat(SrcFormat,
264                        SrcData, SrcPitch,
265                        DstFormat,
266                        image->start(), image->stride(),
267                        Width, Height);
268     if (FAILED(hr)) {
269         std::cerr << "warning: failed to convert from format " << SrcFormat << " to format " << DstFormat << "\n";
270         delete image;
271         image = NULL;
272     }
273
274     return image;
275 }
276
277 } /* namespace d3dstate */