1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
|
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <inttypes.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h> // Your local header file
#ifdef USE_OSMESA
#include <GL/osmesa.h>
#endif
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC l_glCompressedTexImage2DARB;
#define MAKEFOURCC(ch0, ch1, ch2, ch3) \
((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \
((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
typedef enum _D3DFORMAT {
D3DFMT_DXT1 = MAKEFOURCC('D', 'X', 'T', '1'),
D3DFMT_DXT2 = MAKEFOURCC('D', 'X', 'T', '2'),
D3DFMT_DXT3 = MAKEFOURCC('D', 'X', 'T', '3'),
D3DFMT_DXT4 = MAKEFOURCC('D', 'X', 'T', '4'),
D3DFMT_DXT5 = MAKEFOURCC('D', 'X', 'T', '5'),
} D3DFORMAT;
typedef struct _DDCOLORKEY
{
uint32_t dwColorSpaceLowValue;/* low boundary of color space that is to
* be treated as Color Key, inclusive
*/
uint32_t dwColorSpaceHighValue;/* high boundary of color space that is
* to be treated as Color Key, inclusive
*/
} DDCOLORKEY,*LPDDCOLORKEY;
typedef struct _DDPIXELFORMAT {
uint32_t dwSize; /* 0: size of structure */
uint32_t dwFlags; /* 4: pixel format flags */
uint32_t dwFourCC; /* 8: (FOURCC code) */
union {
uint32_t dwRGBBitCount; /* C: how many bits per pixel */
uint32_t dwYUVBitCount; /* C: how many bits per pixel */
uint32_t dwZBufferBitDepth; /* C: how many bits for z buffers */
uint32_t dwAlphaBitDepth; /* C: how many bits for alpha channels*/
uint32_t dwLuminanceBitCount;
uint32_t dwBumpBitCount;
} DUMMYUNIONNAME1;
union {
uint32_t dwRBitMask; /* 10: mask for red bit*/
uint32_t dwYBitMask; /* 10: mask for Y bits*/
uint32_t dwStencilBitDepth;
uint32_t dwLuminanceBitMask;
uint32_t dwBumpDuBitMask;
} DUMMYUNIONNAME2;
union {
uint32_t dwGBitMask; /* 14: mask for green bits*/
uint32_t dwUBitMask; /* 14: mask for U bits*/
uint32_t dwZBitMask;
uint32_t dwBumpDvBitMask;
} DUMMYUNIONNAME3;
union {
uint32_t dwBBitMask; /* 18: mask for blue bits*/
uint32_t dwVBitMask; /* 18: mask for V bits*/
uint32_t dwStencilBitMask;
uint32_t dwBumpLuminanceBitMask;
} DUMMYUNIONNAME4;
union {
uint32_t dwRGBAlphaBitMask; /* 1C: mask for alpha channel */
uint32_t dwYUVAlphaBitMask; /* 1C: mask for alpha channel */
uint32_t dwLuminanceAlphaBitMask;
uint32_t dwRGBZBitMask; /* 1C: mask for Z channel */
uint32_t dwYUVZBitMask; /* 1C: mask for Z channel */
} DUMMYUNIONNAME5;
/* 20: next structure */
} DDPIXELFORMAT,*LPDDPIXELFORMAT;
typedef struct _DDSCAPS2 {
uint32_t dwCaps; /* capabilities of surface wanted */
uint32_t dwCaps2; /* additional capabilities */
uint32_t dwCaps3; /* reserved capabilities */
uint32_t dwCaps4; /* more reserved capabilities */
} DDSCAPS2,*LPDDSCAPS2;
typedef struct _DDSURFACEDESC2
{
uint32_t dwSize; /* 0: size of the DDSURFACEDESC2 structure*/
uint32_t dwFlags; /* 4: determines what fields are valid*/
uint32_t dwHeight; /* 8: height of surface to be created*/
uint32_t dwWidth; /* C: width of input surface*/
union {
uint32_t lPitch; /*10: distance to start of next line (return value only)*/
uint32_t dwLinearSize; /*10: formless late-allocated optimized surface size */
} x;
uint32_t dwBackBufferCount;/* 14: number of back buffers requested*/
union {
uint32_t dwMipMapCount;/* 18:number of mip-map levels requested*/
uint32_t dwRefreshRate;/* 18:refresh rate (used when display mode is described)*/
uint32_t dwSrcVBHandle;/* 18:source used in VB::Optimize */
} y;
uint32_t dwAlphaBitDepth;/* 1C:depth of alpha buffer requested*/
uint32_t dwReserved; /* 20:reserved*/
void * lpSurface; /* 24:pointer to the associated surface memory*/
union {
DDCOLORKEY ddckCKDestOverlay; /* 28: CK for dest overlay use*/
uint32_t dwEmptyFaceColor; /* 28: color for empty cubemap faces */
} z;
DDCOLORKEY ddckCKDestBlt; /* 30: CK for destination blt use*/
DDCOLORKEY ddckCKSrcOverlay;/* 38: CK for source overlay use*/
DDCOLORKEY ddckCKSrcBlt; /* 40: CK for source blt use*/
union {
DDPIXELFORMAT ddpfPixelFormat;/* 48: pixel format description of the surface*/
uint32_t dwFVF; /* 48: vertex format description of vertex buffers */
} t;
DDSCAPS2 ddsCaps; /* 68: DDraw surface caps */
uint32_t dwTextureStage; /* 78: stage in multitexture cascade */
} DDSURFACEDESC2,*LPDDSURFACEDESC2;
typedef struct
{
GLsizei width;
GLsizei height;
GLint components;
GLenum format;
int numMipMaps;
GLubyte *pixels;
} DDS_IMAGE_DATA;
DDS_IMAGE_DATA* loadDDSTextureFile( const char *filename )
{
DDS_IMAGE_DATA *pDDSImageData;
DDSURFACEDESC2 ddsd;
char filecode[4];
FILE *pFile;
int factor;
int bufferSize;
// Open the file
pFile = fopen( filename, "rb" );
if( pFile == NULL )
{
char str[255];
sprintf( str, "loadDDSTextureFile couldn't find, or failed to load \"%s\"", filename );
// MessageBox( NULL, str, "ERROR", MB_OK|MB_ICONEXCLAMATION );
return NULL;
}
// Verify the file is a true .dds file
fread( filecode, 1, 4, pFile );
if( strncmp( filecode, "DDS ", 4 ) != 0 )
{
char str[255];
sprintf( str, "The file \"%s\" doesn't appear to be a valid .dds file!", filename );
// MessageBox( NULL, str, "ERROR", MB_OK|MB_ICONEXCLAMATION );
fclose( pFile );
return NULL;
}
// Get the surface descriptor
fread( &ddsd, sizeof(ddsd), 1, pFile );
pDDSImageData = (DDS_IMAGE_DATA*) malloc(sizeof(DDS_IMAGE_DATA));
memset( pDDSImageData, 0, sizeof(DDS_IMAGE_DATA) );
//
// This .dds loader supports the loading of compressed formats DXT1, DXT3
// and DXT5.
//
switch( ddsd.t.ddpfPixelFormat.dwFourCC )
{
case D3DFMT_DXT1:
// DXT1's compression ratio is 8:1
pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
factor = 2;
break;
case D3DFMT_DXT3:
// DXT3's compression ratio is 4:1
pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
factor = 4;
break;
case D3DFMT_DXT5:
// DXT5's compression ratio is 4:1
pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
factor = 4;
break;
default: {
char str[255];
sprintf( str, "The file \"%s\" doesn't appear to be compressed "
"using DXT1, DXT3, or DXT5!", filename );
// MessageBox( NULL, str, "ERROR", MB_OK|MB_ICONEXCLAMATION );
return NULL;
}
}
//
// How big will the buffer need to be to load all of the pixel data
// including mip-maps?
//
if( ddsd.x.dwLinearSize == 0 )
{
// MessageBox( NULL, "dwLinearSize is 0!","ERROR",
// MB_OK|MB_ICONEXCLAMATION);
return NULL;
}
if( ddsd.y.dwMipMapCount > 1 )
bufferSize = ddsd.x.dwLinearSize * factor;
else
bufferSize = ddsd.x.dwLinearSize;
pDDSImageData->pixels = (unsigned char*)malloc(bufferSize * sizeof(unsigned char));
fread( pDDSImageData->pixels, 1, bufferSize, pFile );
// Close the file
fclose( pFile );
pDDSImageData->width = ddsd.dwWidth;
pDDSImageData->height = ddsd.dwHeight;
pDDSImageData->numMipMaps = ddsd.y.dwMipMapCount;
if( ddsd.t.ddpfPixelFormat.dwFourCC == D3DFMT_DXT1 )
pDDSImageData->components = 3;
else
pDDSImageData->components = 4;
return pDDSImageData;
}
void destroyDDS( DDS_IMAGE_DATA *pDDSImageData )
{
if( pDDSImageData != NULL )
{
if( pDDSImageData->pixels != NULL )
free( pDDSImageData->pixels );
free( pDDSImageData );
}
}
int loadCompressedTexture( DDS_IMAGE_DATA *pDDSImageData )
{
int g_compressedTextureID;
if( pDDSImageData != NULL )
{
int nHeight = pDDSImageData->height;
int nWidth = pDDSImageData->width;
int nNumMipMaps = pDDSImageData->numMipMaps;
int nBlockSize;
if( pDDSImageData->format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
nBlockSize = 8;
else
nBlockSize = 16;
glGenTextures( 1, &g_compressedTextureID );
glBindTexture( GL_TEXTURE_2D, g_compressedTextureID );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
int nSize;
int nOffset = 0;
int i;
// Load the mip-map levels
for( i = 0; i < nNumMipMaps; ++i )
{
if( nWidth == 0 ) nWidth = 1;
if( nHeight == 0 ) nHeight = 1;
nSize = ((nWidth+3)/4) * ((nHeight+3)/4) * nBlockSize;
l_glCompressedTexImage2DARB( GL_TEXTURE_2D,
i,
pDDSImageData->format,
nWidth,
nHeight,
0,
nSize,
pDDSImageData->pixels + nOffset );
nOffset += nSize;
// Half the image size for the next mip-map level...
nWidth = (nWidth / 2);
nHeight = (nHeight / 2);
}
}
return g_compressedTextureID;
}
int ddsInit() {
char *ext = (char*)glGetString( GL_EXTENSIONS );
if( strstr( ext, "ARB_texture_compression" ) == NULL )
{
// MessageBox(NULL,"ARB_texture_compression extension was not found",
// "ERROR",MB_OK|MB_ICONEXCLAMATION);
return -1;
}
else
{
#ifdef USE_OSMESA
l_glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)OSMesaGetProcAddress("glCompressedTexImage2DARB");
#else
l_glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)glxGetProcAddress("glCompressedTexImage2DARB");
#endif
if( !l_glCompressedTexImage2DARB )
{
// MessageBox(NULL,"One or more ARB_texture_compression functions were not found",
// "ERROR",MB_OK|MB_ICONEXCLAMATION);
return -2;
}
}
return 0;
}
|