1 /*---------------------------------------------------------------------------*
2
3 Copyright (C) 2010-2011 Nintendo. All rights reserved.
4
5 These coded instructions, statements, and computer programs contain
6 proprietary information of Nintendo of America Inc. and/or Nintendo
7 Company Ltd., and are protected by Federal copyright law. They may
8 not be disclosed to third parties or copied or duplicated in any form,
9 in whole or in part, without the prior written consent of Nintendo.
10
11 *---------------------------------------------------------------------------*/
12 // ------------------------------------------------------------------
13 // DDS_10.cpp
14 // ------------------------------------------------------------------
15 #include "stdafx.h"
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <assert.h>
19 #include "ddraw.h"
20 #include "D3D10.h"
21 #include "DDS_10.h"
22 #include "DDS_Helpers.h"
23 #include "resource.h"
24
25 namespace DDSReader
26 {
27 TU_Error LoadDDS10_RGBA_32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
28 TU_Error LoadDDS10_RGBA32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
29 TU_Error LoadDDS10_RGBA_16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
30 TU_Error LoadDDS10_RGBA16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
31 TU_Error LoadDDS10_RG32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
32 TU_Error LoadDDS10_R10G10B10A2(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
33 TU_Error LoadDDS10_R11G11B10F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
34 TU_Error LoadDDS10_R8G8B8A8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
35 TU_Error LoadDDS10_R16G16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
36 TU_Error LoadDDS10_R32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
37 TU_Error LoadDDS10_R8G8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
38 TU_Error LoadDDS10_R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
39 TU_Error LoadDDS10_R8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface);
40 TU_Error LoadDDS10_FourCC(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface, u32 dwFourCC);
41
42 #define FOURCC_ATI1N MAKEFOURCC('A', 'T', 'I', '1')
43 #define FOURCC_ATI2N MAKEFOURCC('A', 'T', 'I', '2')
44
45 typedef struct
46 {
47 DXGI_FORMAT dxgiFormat;
48 D3D10_RESOURCE_DIMENSION resourceDimension;
49 UINT miscFlag; // Used for D3D10_RESOURCE_MISC_FLAG
50 UINT arraySize;
51 UINT reserved; // Currently unused
52 } DDS_HEADER_DDS10;
53
LoadDDS10(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)54 TU_Error LoadDDS10(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
55 {
56 DDS_HEADER_DDS10 HeaderDDS10;;
57 fread(&HeaderDDS10, sizeof(HeaderDDS10), 1, pFile);
58
59 TU_Error err = PE_Unknown;
60
61 switch(HeaderDDS10.dxgiFormat)
62 {
63 case DXGI_FORMAT_R32G32B32A32_FLOAT:
64 err = LoadDDS10_RGBA_32F(pFile, pDDSD, pSurface);
65 break;
66
67 case DXGI_FORMAT_R32G32B32A32_UINT:
68 case DXGI_FORMAT_R32G32B32A32_TYPELESS:
69 case DXGI_FORMAT_R32G32B32A32_SINT:
70 err = LoadDDS10_RGBA32(pFile, pDDSD, pSurface);
71 break;
72
73 case DXGI_FORMAT_R16G16B16A16_FLOAT:
74 case DXGI_FORMAT_R16G16B16A16_UINT:
75 case DXGI_FORMAT_R16G16B16A16_TYPELESS:
76 case DXGI_FORMAT_R16G16B16A16_SNORM:
77 case DXGI_FORMAT_R16G16B16A16_SINT:
78 err = LoadDDS10_RGBA16(pFile, pDDSD, pSurface);
79 break;
80
81 case DXGI_FORMAT_R32G32_TYPELESS:
82 case DXGI_FORMAT_R32G32_FLOAT:
83 case DXGI_FORMAT_R32G32_UINT:
84 case DXGI_FORMAT_R32G32_SINT:
85 err = LoadDDS10_RG32(pFile, pDDSD, pSurface);
86 break;
87
88 case DXGI_FORMAT_R10G10B10A2_TYPELESS:
89 case DXGI_FORMAT_R10G10B10A2_UNORM:
90 case DXGI_FORMAT_R10G10B10A2_UINT:
91 err = LoadDDS10_R10G10B10A2(pFile, pDDSD, pSurface);
92 break;
93
94 case DXGI_FORMAT_R11G11B10_FLOAT:
95 err = LoadDDS10_R11G11B10F(pFile, pDDSD, pSurface);
96 break;
97
98 case DXGI_FORMAT_R8G8B8A8_TYPELESS:
99 case DXGI_FORMAT_R8G8B8A8_UNORM:
100 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
101 case DXGI_FORMAT_R8G8B8A8_UINT:
102 case DXGI_FORMAT_R8G8B8A8_SNORM:
103 case DXGI_FORMAT_R8G8B8A8_SINT:
104 err = LoadDDS10_R8G8B8A8(pFile, pDDSD, pSurface);
105 break;
106
107 case DXGI_FORMAT_R16G16_TYPELESS:
108 case DXGI_FORMAT_R16G16_UNORM:
109 case DXGI_FORMAT_R16G16_UINT:
110 case DXGI_FORMAT_R16G16_SNORM:
111 case DXGI_FORMAT_R16G16_SINT:
112 err = LoadDDS10_R16G16(pFile, pDDSD, pSurface);
113 break;
114
115 case DXGI_FORMAT_R32_TYPELESS:
116 case DXGI_FORMAT_R32_UINT:
117 case DXGI_FORMAT_R32_SINT:
118 err = LoadDDS10_R32(pFile, pDDSD, pSurface);
119 break;
120
121 case DXGI_FORMAT_R8G8_TYPELESS:
122 case DXGI_FORMAT_R8G8_UNORM:
123 case DXGI_FORMAT_R8G8_UINT:
124 case DXGI_FORMAT_R8G8_SNORM:
125 case DXGI_FORMAT_R8G8_SINT:
126 err = LoadDDS10_R8G8(pFile, pDDSD, pSurface);
127 break;
128
129 case DXGI_FORMAT_R16_TYPELESS:
130 case DXGI_FORMAT_R16_FLOAT:
131 case DXGI_FORMAT_D16_UNORM:
132 case DXGI_FORMAT_R16_UNORM:
133 case DXGI_FORMAT_R16_UINT:
134 case DXGI_FORMAT_R16_SNORM:
135 case DXGI_FORMAT_R16_SINT:
136 err = LoadDDS10_R16(pFile, pDDSD, pSurface);
137 break;
138
139 case DXGI_FORMAT_R8_TYPELESS:
140 case DXGI_FORMAT_R8_UNORM:
141 case DXGI_FORMAT_R8_UINT:
142 case DXGI_FORMAT_R8_SNORM:
143 case DXGI_FORMAT_R8_SINT:
144 err = LoadDDS10_R8(pFile, pDDSD, pSurface);
145 break;
146
147 case DXGI_FORMAT_BC1_TYPELESS:
148 case DXGI_FORMAT_BC1_UNORM:
149 case DXGI_FORMAT_BC1_UNORM_SRGB:
150 err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC1);
151 break;
152
153 case DXGI_FORMAT_BC2_TYPELESS:
154 case DXGI_FORMAT_BC2_UNORM:
155 case DXGI_FORMAT_BC2_UNORM_SRGB:
156 err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC2);
157 break;
158
159 case DXGI_FORMAT_BC3_TYPELESS:
160 case DXGI_FORMAT_BC3_UNORM:
161 case DXGI_FORMAT_BC3_UNORM_SRGB:
162 err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC3);
163 break;
164
165 case DXGI_FORMAT_BC4_TYPELESS:
166 case DXGI_FORMAT_BC4_UNORM:
167 case DXGI_FORMAT_BC4_SNORM:
168 err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC4);
169 break;
170
171 case DXGI_FORMAT_BC5_TYPELESS:
172 case DXGI_FORMAT_BC5_UNORM:
173 case DXGI_FORMAT_BC5_SNORM:
174 err = LoadDDS10_FourCC(pFile, pDDSD, pSurface, FOURCC_BC5);
175 break;
176
177 default:
178 ASSERT(0);
179 }
180
181 fclose(pFile);
182
183 return err;
184 }
185
LoadDDS10_RGBA_32F(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)186 TU_Error LoadDDS10_RGBA_32F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
187 {
188 void* extra;
189 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float32, TDT_ARGB, PreLoopABGR32F, LoopABGR32F, PostLoopABGR32F);
190 }
191
LoadDDS10_RGBA32(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)192 TU_Error LoadDDS10_RGBA32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
193 {
194 void* extra;
195 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_32bit, TDT_ARGB, PreLoopABGR32F, LoopABGR32F, PostLoopABGR32F);
196 }
197
LoadDDS10_RGBA_16F(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)198 TU_Error LoadDDS10_RGBA_16F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
199 {
200 void* extra;
201 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_ARGB, PreLoopABGR16F, LoopABGR16F, PostLoopABGR16F);
202 }
203
LoadDDS10_RGBA16(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)204 TU_Error LoadDDS10_RGBA16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
205 {
206 void* extra;
207 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Float16, TDT_ARGB, PreLoopABGR16F, LoopABGR16F, PostLoopABGR16F);
208 }
209
LoadDDS10_RG32(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)210 TU_Error LoadDDS10_RG32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
211 {
212 void* extra;
213 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_32bit, TDT_XRGB, PreLoopABGR32, LoopR32G32, PreLoopABGR32);
214 }
215
LoadDDS10_R10G10B10A2(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)216 TU_Error LoadDDS10_R10G10B10A2(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
217 {
218 ChannelFormat channelFormat = CF_2101010;
219 void* pChannelFormat = &channelFormat;
220 return GenericLoadFunction(pFile, pDDSD, pSurface, pChannelFormat, channelFormat, TDT_ARGB, PreLoopDefault, LoopDefault /*LoopR10G10B10A2*/, PostLoopDefault);
221 }
222
LoadDDS10_R11G11B10F(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)223 TU_Error LoadDDS10_R11G11B10F(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
224 {
225 return PE_Unknown;
226 }
227
LoadDDS10_R8G8B8A8(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)228 TU_Error LoadDDS10_R8G8B8A8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
229 {
230 ARGB8888Struct* pARGB8888Struct = (ARGB8888Struct*)calloc(sizeof(ARGB8888Struct), 1);
231 void* extra = pARGB8888Struct;
232
233 pARGB8888Struct->nFlags |= EF_UseBitMasks;
234 pARGB8888Struct->pMemory = malloc(4 * pDDSD->dwWidth * pDDSD->dwHeight);
235 pARGB8888Struct->nRMask = 0x000000ff;
236 pARGB8888Struct->nGMask = 0x0000ff00;
237 pARGB8888Struct->nBMask = 0x00ff0000;
238 pARGB8888Struct->nRShift = 0;
239 pARGB8888Struct->nGShift = 8;
240 pARGB8888Struct->nBShift = 16;
241
242 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_ARGB, PreLoopRGB8888, LoopRGB8888, PostLoopRGB8888);
243 }
244
LoadDDS10_R16G16(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)245 TU_Error LoadDDS10_R16G16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
246 {
247 void* extra;
248 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_XRGB, PreLoopABGR16, LoopR16G16, PreLoopABGR16);
249 }
250
LoadDDS10_R8G8(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)251 TU_Error LoadDDS10_R8G8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
252 {
253 void* extra;
254 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_XRGB, PreLoopRGB8888, LoopR8G8, PreLoopRGB8888);
255 }
256
LoadDDS10_R32(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)257 TU_Error LoadDDS10_R32(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
258 {
259 void* extra;
260 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_32bit, TDT_XRGB, PreLoopABGR32, LoopR32, PostLoopABGR32);
261 }
262
LoadDDS10_R16(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)263 TU_Error LoadDDS10_R16(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
264 {
265 void* extra;
266 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_16bit, TDT_XRGB, PreLoopABGR16, LoopR16, PostLoopABGR16);
267 }
268
LoadDDS10_R8(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface)269 TU_Error LoadDDS10_R8(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface)
270 {
271 void* extra;
272 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_8bit, TDT_XRGB, PreLoopRGB8888, LoopR8, PreLoopRGB8888);
273 }
274
LoadDDS10_FourCC(FILE * pFile,DDSD2 * pDDSD,GX2Surface * pSurface,u32 dwFourCC)275 TU_Error LoadDDS10_FourCC(FILE* pFile, DDSD2* pDDSD, GX2Surface* pSurface, u32 dwFourCC)
276 {
277 void* extra;
278 return GenericLoadFunction(pFile, pDDSD, pSurface, extra, CF_Compressed, TDT_XRGB, PreLoopFourCC, LoopFourCC, PostLoopFourCC);
279 }
280
GetDXGIFormat(const GX2Surface * pSurface)281 DXGI_FORMAT GetDXGIFormat(const GX2Surface* pSurface)
282 {
283 switch (pSurface->format)
284 {
285 case GX2_SURFACE_FORMAT_T_BC1_UNORM:
286 return DXGI_FORMAT_BC1_UNORM;
287 case GX2_SURFACE_FORMAT_T_BC1_SRGB:
288 return DXGI_FORMAT_BC1_UNORM_SRGB;
289 case GX2_SURFACE_FORMAT_T_BC2_UNORM:
290 return DXGI_FORMAT_BC2_UNORM;
291 case GX2_SURFACE_FORMAT_T_BC2_SRGB:
292 return DXGI_FORMAT_BC2_UNORM_SRGB;
293 case GX2_SURFACE_FORMAT_T_BC3_UNORM:
294 return DXGI_FORMAT_BC3_UNORM;
295 case GX2_SURFACE_FORMAT_T_BC3_SRGB:
296 return DXGI_FORMAT_BC3_UNORM_SRGB;
297 case GX2_SURFACE_FORMAT_T_BC4_UNORM:
298 return DXGI_FORMAT_BC4_UNORM;
299 case GX2_SURFACE_FORMAT_T_BC4_SNORM:
300 return DXGI_FORMAT_BC4_SNORM;
301 case GX2_SURFACE_FORMAT_T_BC5_UNORM:
302 return DXGI_FORMAT_BC5_UNORM;
303 case GX2_SURFACE_FORMAT_T_BC5_SNORM:
304 return DXGI_FORMAT_BC5_SNORM;
305 case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT:
306 return DXGI_FORMAT_R11G11B10_FLOAT;
307 }
308
309 return DXGI_FORMAT_UNKNOWN;
310 }
311
SetupDDSD10(DDS_HEADER_DDS10 & HeaderDDS10,const GX2Surface * pSurface)312 bool SetupDDSD10(DDS_HEADER_DDS10& HeaderDDS10, const GX2Surface* pSurface)
313 {
314 memset(&HeaderDDS10, 0, sizeof(HeaderDDS10));
315
316 ASSERT(pSurface);
317 if(pSurface == NULL)
318 return false;
319
320 HeaderDDS10.dxgiFormat = GetDXGIFormat(pSurface);
321
322 if(pSurface->dim == GX2_SURFACE_DIM_2D)
323 {
324 HeaderDDS10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
325 HeaderDDS10.miscFlag = 0;
326 HeaderDDS10.arraySize = 1;
327 }
328 else if(pSurface->dim == GX2_SURFACE_DIM_CUBE)
329 {
330 HeaderDDS10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
331 HeaderDDS10.miscFlag = D3D10_RESOURCE_MISC_TEXTURECUBE;
332 HeaderDDS10.arraySize = 6;
333 }
334 else
335 {
336 HeaderDDS10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
337 HeaderDDS10.miscFlag = 0;
338 HeaderDDS10.arraySize = pSurface->depth;
339 }
340
341 HeaderDDS10.reserved = 0;
342
343 return true;
344 }
345
SaveDDS10(FILE * pFile,const GX2Surface * pSurface)346 TU_Error SaveDDS10(FILE* pFile, const GX2Surface* pSurface)
347 {
348 assert(pFile);
349 assert(pSurface);
350
351 DDSD2 ddsd2;
352 SetupDDSD_DDS10(ddsd2, pSurface, true);
353
354 ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
355 ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('D', 'X', '1', '0');
356
357 switch (pSurface->format)
358 {
359 case GX2_SURFACE_FORMAT_T_BC1_UNORM:
360 case GX2_SURFACE_FORMAT_T_BC1_SRGB:
361 case GX2_SURFACE_FORMAT_T_BC4_UNORM:
362 case GX2_SURFACE_FORMAT_T_BC4_SNORM:
363 ddsd2.lPitch = ddsd2.dwWidth * 2;
364 break;
365 case GX2_SURFACE_FORMAT_T_BC2_UNORM:
366 case GX2_SURFACE_FORMAT_T_BC2_SRGB:
367 case GX2_SURFACE_FORMAT_T_BC3_UNORM:
368 case GX2_SURFACE_FORMAT_T_BC3_SRGB:
369 case GX2_SURFACE_FORMAT_T_BC5_UNORM:
370 case GX2_SURFACE_FORMAT_T_BC5_SNORM:
371 ddsd2.lPitch = ddsd2.dwWidth * 4;
372 break;
373 case GX2_SURFACE_FORMAT_TC_R11_G11_B10_FLOAT:
374 ddsd2.lPitch = ddsd2.dwWidth * 4;
375 break;
376 }
377
378 // Write the data
379 fwrite(&ddsd2, sizeof(DDSD2), 1, pFile);
380
381 DDS_HEADER_DDS10 HeaderDDS10;
382 SetupDDSD10(HeaderDDS10, pSurface);
383
384 fwrite(&HeaderDDS10, sizeof(HeaderDDS10), 1, pFile);
385
386 if(pSurface->imageSize > 0)
387 fwrite(pSurface->imagePtr, GFD_ELEMENT_SIZE_32, (pSurface->imageSize + 3) / GFD_ELEMENT_SIZE_32, pFile);
388
389 if(pSurface->mipSize > 0)
390 fwrite(pSurface->mipPtr, GFD_ELEMENT_SIZE_32, (pSurface->mipSize + 3) / GFD_ELEMENT_SIZE_32, pFile);
391
392 fclose(pFile);
393
394 return PE_OK;
395 }
396 } //namespace DDSReader
397