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