1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 2015 James Canete
5
6 This file is part of Quake III Arena source code.
7
8 Quake III Arena source code is free software; you can redistribute it
9 and/or modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
12
13 Quake III Arena source code is distributed in the hope that it will be
14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Quake III Arena source code; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 ===========================================================================
22 */
23
24 #include "tr_local.h"
25
26 typedef unsigned int ui32_t;
27
28 typedef struct ddsHeader_s
29 {
30 ui32_t headerSize;
31 ui32_t flags;
32 ui32_t height;
33 ui32_t width;
34 ui32_t pitchOrFirstMipSize;
35 ui32_t volumeDepth;
36 ui32_t numMips;
37 ui32_t reserved1[11];
38 ui32_t always_0x00000020;
39 ui32_t pixelFormatFlags;
40 ui32_t fourCC;
41 ui32_t rgbBitCount;
42 ui32_t rBitMask;
43 ui32_t gBitMask;
44 ui32_t bBitMask;
45 ui32_t aBitMask;
46 ui32_t caps;
47 ui32_t caps2;
48 ui32_t caps3;
49 ui32_t caps4;
50 ui32_t reserved2;
51 }
52 ddsHeader_t;
53
54 // flags:
55 #define _DDSFLAGS_REQUIRED 0x001007
56 #define _DDSFLAGS_PITCH 0x8
57 #define _DDSFLAGS_MIPMAPCOUNT 0x20000
58 #define _DDSFLAGS_FIRSTMIPSIZE 0x80000
59 #define _DDSFLAGS_VOLUMEDEPTH 0x800000
60
61 // pixelFormatFlags:
62 #define DDSPF_ALPHAPIXELS 0x1
63 #define DDSPF_ALPHA 0x2
64 #define DDSPF_FOURCC 0x4
65 #define DDSPF_RGB 0x40
66 #define DDSPF_YUV 0x200
67 #define DDSPF_LUMINANCE 0x20000
68
69 // caps:
70 #define DDSCAPS_COMPLEX 0x8
71 #define DDSCAPS_MIPMAP 0x400000
72 #define DDSCAPS_REQUIRED 0x1000
73
74 // caps2:
75 #define DDSCAPS2_CUBEMAP 0xFE00
76 #define DDSCAPS2_VOLUME 0x200000
77
78 typedef struct ddsHeaderDxt10_s
79 {
80 ui32_t dxgiFormat;
81 ui32_t dimensions;
82 ui32_t miscFlags;
83 ui32_t arraySize;
84 ui32_t miscFlags2;
85 }
86 ddsHeaderDxt10_t;
87
88 // dxgiFormat
89 // from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
90 typedef enum DXGI_FORMAT {
91 DXGI_FORMAT_UNKNOWN = 0,
92 DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
93 DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
94 DXGI_FORMAT_R32G32B32A32_UINT = 3,
95 DXGI_FORMAT_R32G32B32A32_SINT = 4,
96 DXGI_FORMAT_R32G32B32_TYPELESS = 5,
97 DXGI_FORMAT_R32G32B32_FLOAT = 6,
98 DXGI_FORMAT_R32G32B32_UINT = 7,
99 DXGI_FORMAT_R32G32B32_SINT = 8,
100 DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
101 DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
102 DXGI_FORMAT_R16G16B16A16_UNORM = 11,
103 DXGI_FORMAT_R16G16B16A16_UINT = 12,
104 DXGI_FORMAT_R16G16B16A16_SNORM = 13,
105 DXGI_FORMAT_R16G16B16A16_SINT = 14,
106 DXGI_FORMAT_R32G32_TYPELESS = 15,
107 DXGI_FORMAT_R32G32_FLOAT = 16,
108 DXGI_FORMAT_R32G32_UINT = 17,
109 DXGI_FORMAT_R32G32_SINT = 18,
110 DXGI_FORMAT_R32G8X24_TYPELESS = 19,
111 DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
112 DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
113 DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
114 DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
115 DXGI_FORMAT_R10G10B10A2_UNORM = 24,
116 DXGI_FORMAT_R10G10B10A2_UINT = 25,
117 DXGI_FORMAT_R11G11B10_FLOAT = 26,
118 DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
119 DXGI_FORMAT_R8G8B8A8_UNORM = 28,
120 DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
121 DXGI_FORMAT_R8G8B8A8_UINT = 30,
122 DXGI_FORMAT_R8G8B8A8_SNORM = 31,
123 DXGI_FORMAT_R8G8B8A8_SINT = 32,
124 DXGI_FORMAT_R16G16_TYPELESS = 33,
125 DXGI_FORMAT_R16G16_FLOAT = 34,
126 DXGI_FORMAT_R16G16_UNORM = 35,
127 DXGI_FORMAT_R16G16_UINT = 36,
128 DXGI_FORMAT_R16G16_SNORM = 37,
129 DXGI_FORMAT_R16G16_SINT = 38,
130 DXGI_FORMAT_R32_TYPELESS = 39,
131 DXGI_FORMAT_D32_FLOAT = 40,
132 DXGI_FORMAT_R32_FLOAT = 41,
133 DXGI_FORMAT_R32_UINT = 42,
134 DXGI_FORMAT_R32_SINT = 43,
135 DXGI_FORMAT_R24G8_TYPELESS = 44,
136 DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
137 DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
138 DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
139 DXGI_FORMAT_R8G8_TYPELESS = 48,
140 DXGI_FORMAT_R8G8_UNORM = 49,
141 DXGI_FORMAT_R8G8_UINT = 50,
142 DXGI_FORMAT_R8G8_SNORM = 51,
143 DXGI_FORMAT_R8G8_SINT = 52,
144 DXGI_FORMAT_R16_TYPELESS = 53,
145 DXGI_FORMAT_R16_FLOAT = 54,
146 DXGI_FORMAT_D16_UNORM = 55,
147 DXGI_FORMAT_R16_UNORM = 56,
148 DXGI_FORMAT_R16_UINT = 57,
149 DXGI_FORMAT_R16_SNORM = 58,
150 DXGI_FORMAT_R16_SINT = 59,
151 DXGI_FORMAT_R8_TYPELESS = 60,
152 DXGI_FORMAT_R8_UNORM = 61,
153 DXGI_FORMAT_R8_UINT = 62,
154 DXGI_FORMAT_R8_SNORM = 63,
155 DXGI_FORMAT_R8_SINT = 64,
156 DXGI_FORMAT_A8_UNORM = 65,
157 DXGI_FORMAT_R1_UNORM = 66,
158 DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
159 DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
160 DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
161 DXGI_FORMAT_BC1_TYPELESS = 70,
162 DXGI_FORMAT_BC1_UNORM = 71,
163 DXGI_FORMAT_BC1_UNORM_SRGB = 72,
164 DXGI_FORMAT_BC2_TYPELESS = 73,
165 DXGI_FORMAT_BC2_UNORM = 74,
166 DXGI_FORMAT_BC2_UNORM_SRGB = 75,
167 DXGI_FORMAT_BC3_TYPELESS = 76,
168 DXGI_FORMAT_BC3_UNORM = 77,
169 DXGI_FORMAT_BC3_UNORM_SRGB = 78,
170 DXGI_FORMAT_BC4_TYPELESS = 79,
171 DXGI_FORMAT_BC4_UNORM = 80,
172 DXGI_FORMAT_BC4_SNORM = 81,
173 DXGI_FORMAT_BC5_TYPELESS = 82,
174 DXGI_FORMAT_BC5_UNORM = 83,
175 DXGI_FORMAT_BC5_SNORM = 84,
176 DXGI_FORMAT_B5G6R5_UNORM = 85,
177 DXGI_FORMAT_B5G5R5A1_UNORM = 86,
178 DXGI_FORMAT_B8G8R8A8_UNORM = 87,
179 DXGI_FORMAT_B8G8R8X8_UNORM = 88,
180 DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
181 DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
182 DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
183 DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
184 DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
185 DXGI_FORMAT_BC6H_TYPELESS = 94,
186 DXGI_FORMAT_BC6H_UF16 = 95,
187 DXGI_FORMAT_BC6H_SF16 = 96,
188 DXGI_FORMAT_BC7_TYPELESS = 97,
189 DXGI_FORMAT_BC7_UNORM = 98,
190 DXGI_FORMAT_BC7_UNORM_SRGB = 99,
191 DXGI_FORMAT_AYUV = 100,
192 DXGI_FORMAT_Y410 = 101,
193 DXGI_FORMAT_Y416 = 102,
194 DXGI_FORMAT_NV12 = 103,
195 DXGI_FORMAT_P010 = 104,
196 DXGI_FORMAT_P016 = 105,
197 DXGI_FORMAT_420_OPAQUE = 106,
198 DXGI_FORMAT_YUY2 = 107,
199 DXGI_FORMAT_Y210 = 108,
200 DXGI_FORMAT_Y216 = 109,
201 DXGI_FORMAT_NV11 = 110,
202 DXGI_FORMAT_AI44 = 111,
203 DXGI_FORMAT_IA44 = 112,
204 DXGI_FORMAT_P8 = 113,
205 DXGI_FORMAT_A8P8 = 114,
206 DXGI_FORMAT_B4G4R4A4_UNORM = 115,
207 DXGI_FORMAT_FORCE_UINT = 0xffffffffUL
208 } DXGI_FORMAT;
209
210 #define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \
211 (((ui32_t)((x)[1])) << 8 ) | \
212 (((ui32_t)((x)[2])) << 16) | \
213 (((ui32_t)((x)[3])) << 24) )
214
215
R_LoadDDS(const char * filename,byte ** pic,int * width,int * height,GLenum * picFormat,int * numMips)216 void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
217 {
218 union {
219 byte *b;
220 void *v;
221 } buffer;
222 int len;
223 ddsHeader_t *ddsHeader = NULL;
224 ddsHeaderDxt10_t *ddsHeaderDxt10 = NULL;
225 byte *data;
226
227 if (!picFormat)
228 {
229 ri.Printf(PRINT_ERROR, "R_LoadDDS() called without picFormat parameter!");
230 return;
231 }
232
233 if (width)
234 *width = 0;
235 if (height)
236 *height = 0;
237 if (picFormat)
238 *picFormat = GL_RGBA8;
239 if (numMips)
240 *numMips = 1;
241
242 *pic = NULL;
243
244 //
245 // load the file
246 //
247 len = ri.FS_ReadFile( ( char * ) filename, &buffer.v);
248 if (!buffer.b || len < 0) {
249 return;
250 }
251
252 //
253 // reject files that are too small to hold even a header
254 //
255 if (len < 4 + sizeof(*ddsHeader))
256 {
257 ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", filename);
258 ri.FS_FreeFile(buffer.v);
259 return;
260 }
261
262 //
263 // reject files that don't start with "DDS "
264 //
265 if (*((ui32_t *)(buffer.b)) != EncodeFourCC("DDS "))
266 {
267 ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", filename);
268 ri.FS_FreeFile(buffer.v);
269 return;
270 }
271
272 //
273 // parse header and dx10 header if available
274 //
275 ddsHeader = (ddsHeader_t *)(buffer.b + 4);
276 if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10"))
277 {
278 if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10))
279 {
280 ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", filename);
281 ri.FS_FreeFile(buffer.v);
282 return;
283 }
284
285 ddsHeaderDxt10 = (ddsHeaderDxt10_t *)(buffer.b + 4 + sizeof(ddsHeader_t));
286 data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
287 len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
288 }
289 else
290 {
291 data = buffer.b + 4 + sizeof(*ddsHeader);
292 len -= 4 + sizeof(*ddsHeader);
293 }
294
295 if (width)
296 *width = ddsHeader->width;
297 if (height)
298 *height = ddsHeader->height;
299
300 if (numMips)
301 {
302 if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT)
303 *numMips = ddsHeader->numMips;
304 else
305 *numMips = 1;
306 }
307
308 // FIXME: handle cube map
309 //if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
310
311 //
312 // Convert DXGI format/FourCC into OpenGL format
313 //
314 if (ddsHeaderDxt10)
315 {
316 switch (ddsHeaderDxt10->dxgiFormat)
317 {
318 case DXGI_FORMAT_BC1_TYPELESS:
319 case DXGI_FORMAT_BC1_UNORM:
320 // FIXME: check for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
321 *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
322 break;
323
324 case DXGI_FORMAT_BC1_UNORM_SRGB:
325 // FIXME: check for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
326 *picFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
327 break;
328
329 case DXGI_FORMAT_BC2_TYPELESS:
330 case DXGI_FORMAT_BC2_UNORM:
331 *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
332 break;
333
334 case DXGI_FORMAT_BC2_UNORM_SRGB:
335 *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
336 break;
337
338 case DXGI_FORMAT_BC3_TYPELESS:
339 case DXGI_FORMAT_BC3_UNORM:
340 *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
341 break;
342
343 case DXGI_FORMAT_BC3_UNORM_SRGB:
344 *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
345 break;
346
347 case DXGI_FORMAT_BC4_TYPELESS:
348 case DXGI_FORMAT_BC4_UNORM:
349 *picFormat = GL_COMPRESSED_RED_RGTC1;
350 break;
351
352 case DXGI_FORMAT_BC4_SNORM:
353 *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
354 break;
355
356 case DXGI_FORMAT_BC5_TYPELESS:
357 case DXGI_FORMAT_BC5_UNORM:
358 *picFormat = GL_COMPRESSED_RG_RGTC2;
359 break;
360
361 case DXGI_FORMAT_BC5_SNORM:
362 *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
363 break;
364
365 case DXGI_FORMAT_BC6H_TYPELESS:
366 case DXGI_FORMAT_BC6H_UF16:
367 *picFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
368 break;
369
370 case DXGI_FORMAT_BC6H_SF16:
371 *picFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
372 break;
373
374 case DXGI_FORMAT_BC7_TYPELESS:
375 case DXGI_FORMAT_BC7_UNORM:
376 *picFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
377 break;
378
379 case DXGI_FORMAT_BC7_UNORM_SRGB:
380 *picFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
381 break;
382
383 case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
384 *picFormat = GL_SRGB8_ALPHA8_EXT;
385 break;
386
387 case DXGI_FORMAT_R8G8B8A8_UNORM:
388 case DXGI_FORMAT_R8G8B8A8_SNORM:
389 *picFormat = GL_RGBA8;
390 break;
391
392 default:
393 ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", filename, ddsHeaderDxt10->dxgiFormat);
394 ri.FS_FreeFile(buffer.v);
395 return;
396 break;
397 }
398 }
399 else
400 {
401 if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC)
402 {
403 if (ddsHeader->fourCC == EncodeFourCC("DXT1"))
404 *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
405 else if (ddsHeader->fourCC == EncodeFourCC("DXT2"))
406 *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
407 else if (ddsHeader->fourCC == EncodeFourCC("DXT3"))
408 *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
409 else if (ddsHeader->fourCC == EncodeFourCC("DXT4"))
410 *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
411 else if (ddsHeader->fourCC == EncodeFourCC("DXT5"))
412 *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
413 else if (ddsHeader->fourCC == EncodeFourCC("ATI1"))
414 *picFormat = GL_COMPRESSED_RED_RGTC1;
415 else if (ddsHeader->fourCC == EncodeFourCC("BC4U"))
416 *picFormat = GL_COMPRESSED_RED_RGTC1;
417 else if (ddsHeader->fourCC == EncodeFourCC("BC4S"))
418 *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
419 else if (ddsHeader->fourCC == EncodeFourCC("ATI2"))
420 *picFormat = GL_COMPRESSED_RG_RGTC2;
421 else if (ddsHeader->fourCC == EncodeFourCC("BC5U"))
422 *picFormat = GL_COMPRESSED_RG_RGTC2;
423 else if (ddsHeader->fourCC == EncodeFourCC("BC5S"))
424 *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
425 else
426 {
427 ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", filename);
428 ri.FS_FreeFile(buffer.v);
429 return;
430 }
431 }
432 else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS)
433 && ddsHeader->rgbBitCount == 32
434 && ddsHeader->rBitMask == 0x000000ff
435 && ddsHeader->gBitMask == 0x0000ff00
436 && ddsHeader->bBitMask == 0x00ff0000
437 && ddsHeader->aBitMask == 0xff000000)
438 {
439 *picFormat = GL_RGBA8;
440 }
441 else
442 {
443 ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", filename);
444 ri.FS_FreeFile(buffer.v);
445 return;
446 }
447 }
448
449 *pic = ri.Z_Malloc(len);
450 Com_Memcpy(*pic, data, len);
451
452 ri.FS_FreeFile(buffer.v);
453 }
454
R_SaveDDS(const char * filename,byte * pic,int width,int height,int depth)455 void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth)
456 {
457 byte *data;
458 ddsHeader_t *ddsHeader;
459 int picSize, size;
460
461 if (!depth)
462 depth = 1;
463
464 picSize = width * height * depth * 4;
465 size = 4 + sizeof(*ddsHeader) + picSize;
466 data = ri.Z_Malloc(size);
467
468 data[0] = 'D';
469 data[1] = 'D';
470 data[2] = 'S';
471 data[3] = ' ';
472
473 ddsHeader = (ddsHeader_t *)(data + 4);
474 memset(ddsHeader, 0, sizeof(ddsHeader_t));
475
476 ddsHeader->headerSize = 0x7c;
477 ddsHeader->flags = _DDSFLAGS_REQUIRED;
478 ddsHeader->height = height;
479 ddsHeader->width = width;
480 ddsHeader->always_0x00000020 = 0x00000020;
481 ddsHeader->caps = DDSCAPS_COMPLEX | DDSCAPS_REQUIRED;
482
483 if (depth == 6)
484 ddsHeader->caps2 = DDSCAPS2_CUBEMAP;
485
486 ddsHeader->pixelFormatFlags = DDSPF_RGB | DDSPF_ALPHAPIXELS;
487 ddsHeader->rgbBitCount = 32;
488 ddsHeader->rBitMask = 0x000000ff;
489 ddsHeader->gBitMask = 0x0000ff00;
490 ddsHeader->bBitMask = 0x00ff0000;
491 ddsHeader->aBitMask = 0xff000000;
492
493 Com_Memcpy(data + 4 + sizeof(*ddsHeader), pic, picSize);
494
495 ri.FS_WriteFile(filename, data, size);
496
497 ri.Free(data);
498 }
499