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