Subversion Repositories gelsvn

Rev

Rev 369 | Rev 449 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 369 Rev 373
1
/*
1
/*
2
	Jonathan Dummer
2
	Jonathan Dummer
3
	2007-07-26-10.36
3
	2007-07-26-10.36
4

4

5
	Simple OpenGL Image Library
5
	Simple OpenGL Image Library
6

6

7
	Public Domain
7
	Public Domain
8
	using Sean Barret's stb_image as a base
8
	using Sean Barret's stb_image as a base
9

9

10
	Thanks to:
10
	Thanks to:
11
	* Sean Barret - for the awesome stb_image
11
	* Sean Barret - for the awesome stb_image
12
	* Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts
12
	* Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts
13
	* everybody at gamedev.net
13
	* everybody at gamedev.net
14
*/
14
*/
15
 
15
 
16
#define SOIL_CHECK_FOR_GL_ERRORS 0
16
#define SOIL_CHECK_FOR_GL_ERRORS 0
17
 
17
 
18
#ifdef WIN32
18
#ifdef WIN32
19
	#define WIN32_LEAN_AND_MEAN
19
	#define WIN32_LEAN_AND_MEAN
20
	#include <windows.h>
20
	#include <windows.h>
21
	#include <wingdi.h>
21
	#include <wingdi.h>
22
	#include <GL/gl.h>
22
	#include <GL/gl.h>
23
#elif defined(__APPLE__) || defined(__APPLE_CC__)
23
#elif defined(__APPLE__) || defined(__APPLE_CC__)
24
	/*	I can't test this Apple stuff!	*/
24
	/*	I can't test this Apple stuff!	*/
25
	#include <OpenGL/gl.h>
25
	#include <OpenGL/gl.h>
26
	#include <Carbon/Carbon.h>
26
	#include <Carbon/Carbon.h>
27
	#define APIENTRY
27
	#define APIENTRY
28
#else
28
#else
29
	#include <GL/gl.h>
29
	#include <GL/gl.h>
30
	#include <GL/glx.h>
30
	#include <GL/glx.h>
31
#endif
31
#endif
32
 
32
 
33
#include "SOIL.h"
33
#include "SOIL.h"
34
#include "stb_image_aug.h"
34
#include "stb_image_aug.h"
35
#include "image_helper.h"
35
#include "image_helper.h"
36
#include "image_DXT.h"
36
#include "image_DXT.h"
37
 
37
 
38
#include <stdlib.h>
38
#include <stdlib.h>
39
#include <string.h>
39
#include <string.h>
40
 
40
 
41
/*	error reporting	*/
41
/*	error reporting	*/
42
char *result_string_pointer = "SOIL initialized";
42
char *result_string_pointer = "SOIL initialized";
43
 
43
 
44
/*	for loading cube maps	*/
44
/*	for loading cube maps	*/
45
enum{
45
enum{
46
	SOIL_CAPABILITY_UNKNOWN = -1,
46
	SOIL_CAPABILITY_UNKNOWN = -1,
47
	SOIL_CAPABILITY_NONE = 0,
47
	SOIL_CAPABILITY_NONE = 0,
48
	SOIL_CAPABILITY_PRESENT = 1
48
	SOIL_CAPABILITY_PRESENT = 1
49
};
49
};
50
static int has_cubemap_capability = SOIL_CAPABILITY_UNKNOWN;
50
static int has_cubemap_capability = SOIL_CAPABILITY_UNKNOWN;
51
int query_cubemap_capability( void );
51
int query_cubemap_capability( void );
52
#define SOIL_TEXTURE_WRAP_R					0x8072
52
#define SOIL_TEXTURE_WRAP_R					0x8072
53
#define SOIL_CLAMP_TO_EDGE					0x812F
53
#define SOIL_CLAMP_TO_EDGE					0x812F
54
#define SOIL_NORMAL_MAP						0x8511
54
#define SOIL_NORMAL_MAP						0x8511
55
#define SOIL_REFLECTION_MAP					0x8512
55
#define SOIL_REFLECTION_MAP					0x8512
56
#define SOIL_TEXTURE_CUBE_MAP				0x8513
56
#define SOIL_TEXTURE_CUBE_MAP				0x8513
57
#define SOIL_TEXTURE_BINDING_CUBE_MAP		0x8514
57
#define SOIL_TEXTURE_BINDING_CUBE_MAP		0x8514
58
#define SOIL_TEXTURE_CUBE_MAP_POSITIVE_X	0x8515
58
#define SOIL_TEXTURE_CUBE_MAP_POSITIVE_X	0x8515
59
#define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X	0x8516
59
#define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X	0x8516
60
#define SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y	0x8517
60
#define SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y	0x8517
61
#define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y	0x8518
61
#define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y	0x8518
62
#define SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z	0x8519
62
#define SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z	0x8519
63
#define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z	0x851A
63
#define SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z	0x851A
64
#define SOIL_PROXY_TEXTURE_CUBE_MAP			0x851B
64
#define SOIL_PROXY_TEXTURE_CUBE_MAP			0x851B
65
#define SOIL_MAX_CUBE_MAP_TEXTURE_SIZE		0x851C
65
#define SOIL_MAX_CUBE_MAP_TEXTURE_SIZE		0x851C
66
/*	for non-power-of-two texture	*/
66
/*	for non-power-of-two texture	*/
67
static int has_NPOT_capability = SOIL_CAPABILITY_UNKNOWN;
67
static int has_NPOT_capability = SOIL_CAPABILITY_UNKNOWN;
68
int query_NPOT_capability( void );
68
int query_NPOT_capability( void );
69
/*	for texture rectangles	*/
69
/*	for texture rectangles	*/
70
static int has_tex_rectangle_capability = SOIL_CAPABILITY_UNKNOWN;
70
static int has_tex_rectangle_capability = SOIL_CAPABILITY_UNKNOWN;
71
int query_tex_rectangle_capability( void );
71
int query_tex_rectangle_capability( void );
72
#define SOIL_TEXTURE_RECTANGLE_ARB				0x84F5
72
#define SOIL_TEXTURE_RECTANGLE_ARB				0x84F5
73
#define SOIL_MAX_RECTANGLE_TEXTURE_SIZE_ARB		0x84F8
73
#define SOIL_MAX_RECTANGLE_TEXTURE_SIZE_ARB		0x84F8
74
/*	for using DXT compression	*/
74
/*	for using DXT compression	*/
75
static int has_DXT_capability = SOIL_CAPABILITY_UNKNOWN;
75
static int has_DXT_capability = SOIL_CAPABILITY_UNKNOWN;
76
int query_DXT_capability( void );
76
int query_DXT_capability( void );
77
#define SOIL_RGB_S3TC_DXT1		0x83F0
77
#define SOIL_RGB_S3TC_DXT1		0x83F0
78
#define SOIL_RGBA_S3TC_DXT1		0x83F1
78
#define SOIL_RGBA_S3TC_DXT1		0x83F1
79
#define SOIL_RGBA_S3TC_DXT3		0x83F2
79
#define SOIL_RGBA_S3TC_DXT3		0x83F2
80
#define SOIL_RGBA_S3TC_DXT5		0x83F3
80
#define SOIL_RGBA_S3TC_DXT5		0x83F3
81
typedef void (APIENTRY * P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data);
81
typedef void (APIENTRY * P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid * data);
82
P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC soilGlCompressedTexImage2D = NULL;
82
P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC soilGlCompressedTexImage2D = NULL;
83
unsigned int SOIL_direct_load_DDS(
83
unsigned int SOIL_direct_load_DDS(
84
		const char *filename,
84
		const char *filename,
85
		unsigned int reuse_texture_ID,
85
		unsigned int reuse_texture_ID,
86
		int flags,
86
		int flags,
87
		int loading_as_cubemap );
87
		int loading_as_cubemap );
88
unsigned int SOIL_direct_load_DDS_from_memory(
88
unsigned int SOIL_direct_load_DDS_from_memory(
89
		const unsigned char *const buffer,
89
		const unsigned char *const buffer,
90
		int buffer_length,
90
		int buffer_length,
91
		unsigned int reuse_texture_ID,
91
		unsigned int reuse_texture_ID,
92
		int flags,
92
		int flags,
93
		int loading_as_cubemap );
93
		int loading_as_cubemap );
94
/*	other functions	*/
94
/*	other functions	*/
95
unsigned int
95
unsigned int
96
	SOIL_internal_create_OGL_texture
96
	SOIL_internal_create_OGL_texture
97
	(
97
	(
98
		const unsigned char *const data,
98
		const unsigned char *const data,
99
		int width, int height, int channels,
99
		int width, int height, int channels,
100
		unsigned int reuse_texture_ID,
100
		unsigned int reuse_texture_ID,
101
		unsigned int flags,
101
		unsigned int flags,
102
		unsigned int opengl_texture_type,
102
		unsigned int opengl_texture_type,
103
		unsigned int opengl_texture_target,
103
		unsigned int opengl_texture_target,
104
		unsigned int texture_check_size_enum
104
		unsigned int texture_check_size_enum
105
	);
105
	);
106
 
106
 
107
/*	and the code magic begins here [8^)	*/
107
/*	and the code magic begins here [8^)	*/
108
unsigned int
108
unsigned int
109
	SOIL_load_OGL_texture
109
	SOIL_load_OGL_texture
110
	(
110
	(
111
		const char *filename,
111
		const char *filename,
112
		int force_channels,
112
		int force_channels,
113
		unsigned int reuse_texture_ID,
113
		unsigned int reuse_texture_ID,
114
		unsigned int flags
114
		unsigned int flags
115
	)
115
	)
116
{
116
{
117
	/*	variables	*/
117
	/*	variables	*/
118
	unsigned char* img;
118
	unsigned char* img;
119
	int width, height, channels;
119
	int width, height, channels;
120
	unsigned int tex_id;
120
	unsigned int tex_id;
121
	/*	does the user want direct uploading of the image as a DDS file?	*/
121
	/*	does the user want direct uploading of the image as a DDS file?	*/
122
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
122
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
123
	{
123
	{
124
		/*	1st try direct loading of the image as a DDS file
124
		/*	1st try direct loading of the image as a DDS file
125
			note: direct uploading will only load what is in the
125
			note: direct uploading will only load what is in the
126
			DDS file, no MIPmaps will be generated, the image will
126
			DDS file, no MIPmaps will be generated, the image will
127
			not be flipped, etc.	*/
127
			not be flipped, etc.	*/
128
		tex_id = SOIL_direct_load_DDS( filename, reuse_texture_ID, flags, 0 );
128
		tex_id = SOIL_direct_load_DDS( filename, reuse_texture_ID, flags, 0 );
129
		if( tex_id )
129
		if( tex_id )
130
		{
130
		{
131
			/*	hey, it worked!!	*/
131
			/*	hey, it worked!!	*/
132
			return tex_id;
132
			return tex_id;
133
		}
133
		}
134
	}
134
	}
135
	/*	try to load the image	*/
135
	/*	try to load the image	*/
136
	img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
136
	img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
137
	/*	channels holds the original number of channels, which may have been forced	*/
137
	/*	channels holds the original number of channels, which may have been forced	*/
138
	if( (force_channels >= 1) && (force_channels <= 4) )
138
	if( (force_channels >= 1) && (force_channels <= 4) )
139
	{
139
	{
140
		channels = force_channels;
140
		channels = force_channels;
141
	}
141
	}
142
	if( NULL == img )
142
	if( NULL == img )
143
	{
143
	{
144
		/*	image loading failed	*/
144
		/*	image loading failed	*/
145
		result_string_pointer = stbi_failure_reason();
145
		result_string_pointer = stbi_failure_reason();
146
		return 0;
146
		return 0;
147
	}
147
	}
148
	/*	OK, make it a texture!	*/
148
	/*	OK, make it a texture!	*/
149
	tex_id = SOIL_internal_create_OGL_texture(
149
	tex_id = SOIL_internal_create_OGL_texture(
150
			img, width, height, channels,
150
			img, width, height, channels,
151
			reuse_texture_ID, flags,
151
			reuse_texture_ID, flags,
152
			GL_TEXTURE_2D, GL_TEXTURE_2D,
152
			GL_TEXTURE_2D, GL_TEXTURE_2D,
153
			GL_MAX_TEXTURE_SIZE );
153
			GL_MAX_TEXTURE_SIZE );
154
	/*	and nuke the image data	*/
154
	/*	and nuke the image data	*/
155
	SOIL_free_image_data( img );
155
	SOIL_free_image_data( img );
156
	/*	and return the handle, such as it is	*/
156
	/*	and return the handle, such as it is	*/
157
	return tex_id;
157
	return tex_id;
158
}
158
}
159
 
159
 
160
unsigned int
160
unsigned int
161
	SOIL_load_OGL_HDR_texture
161
	SOIL_load_OGL_HDR_texture
162
	(
162
	(
163
		const char *filename,
163
		const char *filename,
164
		int fake_HDR_format,
164
		int fake_HDR_format,
165
		int rescale_to_max,
165
		int rescale_to_max,
166
		unsigned int reuse_texture_ID,
166
		unsigned int reuse_texture_ID,
167
		unsigned int flags
167
		unsigned int flags
168
	)
168
	)
169
{
169
{
170
	/*	variables	*/
170
	/*	variables	*/
171
	unsigned char* img;
171
	unsigned char* img;
172
	int width, height, channels;
172
	int width, height, channels;
173
	unsigned int tex_id;
173
	unsigned int tex_id;
174
	/*	no direct uploading of the image as a DDS file	*/
174
	/*	no direct uploading of the image as a DDS file	*/
175
	/* error check */
175
	/* error check */
176
	if( (fake_HDR_format != SOIL_HDR_RGBE) &&
176
	if( (fake_HDR_format != SOIL_HDR_RGBE) &&
177
		(fake_HDR_format != SOIL_HDR_RGBdivA) &&
177
		(fake_HDR_format != SOIL_HDR_RGBdivA) &&
178
		(fake_HDR_format != SOIL_HDR_RGBdivA2) )
178
		(fake_HDR_format != SOIL_HDR_RGBdivA2) )
179
	{
179
	{
180
		result_string_pointer = "Invalid fake HDR format specified";
180
		result_string_pointer = "Invalid fake HDR format specified";
181
		return 0;
181
		return 0;
182
	}
182
	}
183
	/*	try to load the image (only the HDR type) */
183
	/*	try to load the image (only the HDR type) */
184
	img = stbi_hdr_load_rgbe( filename, &width, &height, &channels, 4 );
184
	img = stbi_hdr_load_rgbe( filename, &width, &height, &channels, 4 );
185
	/*	channels holds the original number of channels, which may have been forced	*/
185
	/*	channels holds the original number of channels, which may have been forced	*/
186
	if( NULL == img )
186
	if( NULL == img )
187
	{
187
	{
188
		/*	image loading failed	*/
188
		/*	image loading failed	*/
189
		result_string_pointer = stbi_failure_reason();
189
		result_string_pointer = stbi_failure_reason();
190
		return 0;
190
		return 0;
191
	}
191
	}
192
	/* the load worked, do I need to convert it? */
192
	/* the load worked, do I need to convert it? */
193
	if( fake_HDR_format == SOIL_HDR_RGBdivA )
193
	if( fake_HDR_format == SOIL_HDR_RGBdivA )
194
	{
194
	{
195
		RGBE_to_RGBdivA( img, width, height, rescale_to_max );
195
		RGBE_to_RGBdivA( img, width, height, rescale_to_max );
196
	} else if( fake_HDR_format == SOIL_HDR_RGBdivA2 )
196
	} else if( fake_HDR_format == SOIL_HDR_RGBdivA2 )
197
	{
197
	{
198
		RGBE_to_RGBdivA2( img, width, height, rescale_to_max );
198
		RGBE_to_RGBdivA2( img, width, height, rescale_to_max );
199
	}
199
	}
200
	/*	OK, make it a texture!	*/
200
	/*	OK, make it a texture!	*/
201
	tex_id = SOIL_internal_create_OGL_texture(
201
	tex_id = SOIL_internal_create_OGL_texture(
202
			img, width, height, channels,
202
			img, width, height, channels,
203
			reuse_texture_ID, flags,
203
			reuse_texture_ID, flags,
204
			GL_TEXTURE_2D, GL_TEXTURE_2D,
204
			GL_TEXTURE_2D, GL_TEXTURE_2D,
205
			GL_MAX_TEXTURE_SIZE );
205
			GL_MAX_TEXTURE_SIZE );
206
	/*	and nuke the image data	*/
206
	/*	and nuke the image data	*/
207
	SOIL_free_image_data( img );
207
	SOIL_free_image_data( img );
208
	/*	and return the handle, such as it is	*/
208
	/*	and return the handle, such as it is	*/
209
	return tex_id;
209
	return tex_id;
210
}
210
}
211
 
211
 
212
unsigned int
212
unsigned int
213
	SOIL_load_OGL_texture_from_memory
213
	SOIL_load_OGL_texture_from_memory
214
	(
214
	(
215
		const unsigned char *const buffer,
215
		const unsigned char *const buffer,
216
		int buffer_length,
216
		int buffer_length,
217
		int force_channels,
217
		int force_channels,
218
		unsigned int reuse_texture_ID,
218
		unsigned int reuse_texture_ID,
219
		unsigned int flags
219
		unsigned int flags
220
	)
220
	)
221
{
221
{
222
	/*	variables	*/
222
	/*	variables	*/
223
	unsigned char* img;
223
	unsigned char* img;
224
	int width, height, channels;
224
	int width, height, channels;
225
	unsigned int tex_id;
225
	unsigned int tex_id;
226
	/*	does the user want direct uploading of the image as a DDS file?	*/
226
	/*	does the user want direct uploading of the image as a DDS file?	*/
227
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
227
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
228
	{
228
	{
229
		/*	1st try direct loading of the image as a DDS file
229
		/*	1st try direct loading of the image as a DDS file
230
			note: direct uploading will only load what is in the
230
			note: direct uploading will only load what is in the
231
			DDS file, no MIPmaps will be generated, the image will
231
			DDS file, no MIPmaps will be generated, the image will
232
			not be flipped, etc.	*/
232
			not be flipped, etc.	*/
233
		tex_id = SOIL_direct_load_DDS_from_memory(
233
		tex_id = SOIL_direct_load_DDS_from_memory(
234
				buffer, buffer_length,
234
				buffer, buffer_length,
235
				reuse_texture_ID, flags, 0 );
235
				reuse_texture_ID, flags, 0 );
236
		if( tex_id )
236
		if( tex_id )
237
		{
237
		{
238
			/*	hey, it worked!!	*/
238
			/*	hey, it worked!!	*/
239
			return tex_id;
239
			return tex_id;
240
		}
240
		}
241
	}
241
	}
242
	/*	try to load the image	*/
242
	/*	try to load the image	*/
243
	img = SOIL_load_image_from_memory(
243
	img = SOIL_load_image_from_memory(
244
					buffer, buffer_length,
244
					buffer, buffer_length,
245
					&width, &height, &channels,
245
					&width, &height, &channels,
246
					force_channels );
246
					force_channels );
247
	/*	channels holds the original number of channels, which may have been forced	*/
247
	/*	channels holds the original number of channels, which may have been forced	*/
248
	if( (force_channels >= 1) && (force_channels <= 4) )
248
	if( (force_channels >= 1) && (force_channels <= 4) )
249
	{
249
	{
250
		channels = force_channels;
250
		channels = force_channels;
251
	}
251
	}
252
	if( NULL == img )
252
	if( NULL == img )
253
	{
253
	{
254
		/*	image loading failed	*/
254
		/*	image loading failed	*/
255
		result_string_pointer = stbi_failure_reason();
255
		result_string_pointer = stbi_failure_reason();
256
		return 0;
256
		return 0;
257
	}
257
	}
258
	/*	OK, make it a texture!	*/
258
	/*	OK, make it a texture!	*/
259
	tex_id = SOIL_internal_create_OGL_texture(
259
	tex_id = SOIL_internal_create_OGL_texture(
260
			img, width, height, channels,
260
			img, width, height, channels,
261
			reuse_texture_ID, flags,
261
			reuse_texture_ID, flags,
262
			GL_TEXTURE_2D, GL_TEXTURE_2D,
262
			GL_TEXTURE_2D, GL_TEXTURE_2D,
263
			GL_MAX_TEXTURE_SIZE );
263
			GL_MAX_TEXTURE_SIZE );
264
	/*	and nuke the image data	*/
264
	/*	and nuke the image data	*/
265
	SOIL_free_image_data( img );
265
	SOIL_free_image_data( img );
266
	/*	and return the handle, such as it is	*/
266
	/*	and return the handle, such as it is	*/
267
	return tex_id;
267
	return tex_id;
268
}
268
}
269
 
269
 
270
unsigned int
270
unsigned int
271
	SOIL_load_OGL_cubemap
271
	SOIL_load_OGL_cubemap
272
	(
272
	(
273
		const char *x_pos_file,
273
		const char *x_pos_file,
274
		const char *x_neg_file,
274
		const char *x_neg_file,
275
		const char *y_pos_file,
275
		const char *y_pos_file,
276
		const char *y_neg_file,
276
		const char *y_neg_file,
277
		const char *z_pos_file,
277
		const char *z_pos_file,
278
		const char *z_neg_file,
278
		const char *z_neg_file,
279
		int force_channels,
279
		int force_channels,
280
		unsigned int reuse_texture_ID,
280
		unsigned int reuse_texture_ID,
281
		unsigned int flags
281
		unsigned int flags
282
	)
282
	)
283
{
283
{
284
	/*	variables	*/
284
	/*	variables	*/
285
	unsigned char* img;
285
	unsigned char* img;
286
	int width, height, channels;
286
	int width, height, channels;
287
	unsigned int tex_id;
287
	unsigned int tex_id;
288
	/*	error checking	*/
288
	/*	error checking	*/
289
	if( (x_pos_file == NULL) ||
289
	if( (x_pos_file == NULL) ||
290
		(x_neg_file == NULL) ||
290
		(x_neg_file == NULL) ||
291
		(y_pos_file == NULL) ||
291
		(y_pos_file == NULL) ||
292
		(y_neg_file == NULL) ||
292
		(y_neg_file == NULL) ||
293
		(z_pos_file == NULL) ||
293
		(z_pos_file == NULL) ||
294
		(z_neg_file == NULL) )
294
		(z_neg_file == NULL) )
295
	{
295
	{
296
		result_string_pointer = "Invalid cube map files list";
296
		result_string_pointer = "Invalid cube map files list";
297
		return 0;
297
		return 0;
298
	}
298
	}
299
	/*	capability checking	*/
299
	/*	capability checking	*/
300
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
300
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
301
	{
301
	{
302
		result_string_pointer = "No cube map capability present";
302
		result_string_pointer = "No cube map capability present";
303
		return 0;
303
		return 0;
304
	}
304
	}
305
	/*	1st face: try to load the image	*/
305
	/*	1st face: try to load the image	*/
306
	img = SOIL_load_image( x_pos_file, &width, &height, &channels, force_channels );
306
	img = SOIL_load_image( x_pos_file, &width, &height, &channels, force_channels );
307
	/*	channels holds the original number of channels, which may have been forced	*/
307
	/*	channels holds the original number of channels, which may have been forced	*/
308
	if( (force_channels >= 1) && (force_channels <= 4) )
308
	if( (force_channels >= 1) && (force_channels <= 4) )
309
	{
309
	{
310
		channels = force_channels;
310
		channels = force_channels;
311
	}
311
	}
312
	if( NULL == img )
312
	if( NULL == img )
313
	{
313
	{
314
		/*	image loading failed	*/
314
		/*	image loading failed	*/
315
		result_string_pointer = stbi_failure_reason();
315
		result_string_pointer = stbi_failure_reason();
316
		return 0;
316
		return 0;
317
	}
317
	}
318
	/*	upload the texture, and create a texture ID if necessary	*/
318
	/*	upload the texture, and create a texture ID if necessary	*/
319
	tex_id = SOIL_internal_create_OGL_texture(
319
	tex_id = SOIL_internal_create_OGL_texture(
320
			img, width, height, channels,
320
			img, width, height, channels,
321
			reuse_texture_ID, flags,
321
			reuse_texture_ID, flags,
322
			SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_X,
322
			SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_X,
323
			SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
323
			SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
324
	/*	and nuke the image data	*/
324
	/*	and nuke the image data	*/
325
	SOIL_free_image_data( img );
325
	SOIL_free_image_data( img );
326
	/*	continue?	*/
326
	/*	continue?	*/
327
	if( tex_id != 0 )
327
	if( tex_id != 0 )
328
	{
328
	{
329
		/*	1st face: try to load the image	*/
329
		/*	1st face: try to load the image	*/
330
		img = SOIL_load_image( x_neg_file, &width, &height, &channels, force_channels );
330
		img = SOIL_load_image( x_neg_file, &width, &height, &channels, force_channels );
331
		/*	channels holds the original number of channels, which may have been forced	*/
331
		/*	channels holds the original number of channels, which may have been forced	*/
332
		if( (force_channels >= 1) && (force_channels <= 4) )
332
		if( (force_channels >= 1) && (force_channels <= 4) )
333
		{
333
		{
334
			channels = force_channels;
334
			channels = force_channels;
335
		}
335
		}
336
		if( NULL == img )
336
		if( NULL == img )
337
		{
337
		{
338
			/*	image loading failed	*/
338
			/*	image loading failed	*/
339
			result_string_pointer = stbi_failure_reason();
339
			result_string_pointer = stbi_failure_reason();
340
			return 0;
340
			return 0;
341
		}
341
		}
342
		/*	upload the texture, but reuse the assigned texture ID	*/
342
		/*	upload the texture, but reuse the assigned texture ID	*/
343
		tex_id = SOIL_internal_create_OGL_texture(
343
		tex_id = SOIL_internal_create_OGL_texture(
344
				img, width, height, channels,
344
				img, width, height, channels,
345
				tex_id, flags,
345
				tex_id, flags,
346
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X,
346
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X,
347
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
347
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
348
		/*	and nuke the image data	*/
348
		/*	and nuke the image data	*/
349
		SOIL_free_image_data( img );
349
		SOIL_free_image_data( img );
350
	}
350
	}
351
	/*	continue?	*/
351
	/*	continue?	*/
352
	if( tex_id != 0 )
352
	if( tex_id != 0 )
353
	{
353
	{
354
		/*	1st face: try to load the image	*/
354
		/*	1st face: try to load the image	*/
355
		img = SOIL_load_image( y_pos_file, &width, &height, &channels, force_channels );
355
		img = SOIL_load_image( y_pos_file, &width, &height, &channels, force_channels );
356
		/*	channels holds the original number of channels, which may have been forced	*/
356
		/*	channels holds the original number of channels, which may have been forced	*/
357
		if( (force_channels >= 1) && (force_channels <= 4) )
357
		if( (force_channels >= 1) && (force_channels <= 4) )
358
		{
358
		{
359
			channels = force_channels;
359
			channels = force_channels;
360
		}
360
		}
361
		if( NULL == img )
361
		if( NULL == img )
362
		{
362
		{
363
			/*	image loading failed	*/
363
			/*	image loading failed	*/
364
			result_string_pointer = stbi_failure_reason();
364
			result_string_pointer = stbi_failure_reason();
365
			return 0;
365
			return 0;
366
		}
366
		}
367
		/*	upload the texture, but reuse the assigned texture ID	*/
367
		/*	upload the texture, but reuse the assigned texture ID	*/
368
		tex_id = SOIL_internal_create_OGL_texture(
368
		tex_id = SOIL_internal_create_OGL_texture(
369
				img, width, height, channels,
369
				img, width, height, channels,
370
				tex_id, flags,
370
				tex_id, flags,
371
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y,
371
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y,
372
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
372
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
373
		/*	and nuke the image data	*/
373
		/*	and nuke the image data	*/
374
		SOIL_free_image_data( img );
374
		SOIL_free_image_data( img );
375
	}
375
	}
376
	/*	continue?	*/
376
	/*	continue?	*/
377
	if( tex_id != 0 )
377
	if( tex_id != 0 )
378
	{
378
	{
379
		/*	1st face: try to load the image	*/
379
		/*	1st face: try to load the image	*/
380
		img = SOIL_load_image( y_neg_file, &width, &height, &channels, force_channels );
380
		img = SOIL_load_image( y_neg_file, &width, &height, &channels, force_channels );
381
		/*	channels holds the original number of channels, which may have been forced	*/
381
		/*	channels holds the original number of channels, which may have been forced	*/
382
		if( (force_channels >= 1) && (force_channels <= 4) )
382
		if( (force_channels >= 1) && (force_channels <= 4) )
383
		{
383
		{
384
			channels = force_channels;
384
			channels = force_channels;
385
		}
385
		}
386
		if( NULL == img )
386
		if( NULL == img )
387
		{
387
		{
388
			/*	image loading failed	*/
388
			/*	image loading failed	*/
389
			result_string_pointer = stbi_failure_reason();
389
			result_string_pointer = stbi_failure_reason();
390
			return 0;
390
			return 0;
391
		}
391
		}
392
		/*	upload the texture, but reuse the assigned texture ID	*/
392
		/*	upload the texture, but reuse the assigned texture ID	*/
393
		tex_id = SOIL_internal_create_OGL_texture(
393
		tex_id = SOIL_internal_create_OGL_texture(
394
				img, width, height, channels,
394
				img, width, height, channels,
395
				tex_id, flags,
395
				tex_id, flags,
396
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
396
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
397
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
397
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
398
		/*	and nuke the image data	*/
398
		/*	and nuke the image data	*/
399
		SOIL_free_image_data( img );
399
		SOIL_free_image_data( img );
400
	}
400
	}
401
	/*	continue?	*/
401
	/*	continue?	*/
402
	if( tex_id != 0 )
402
	if( tex_id != 0 )
403
	{
403
	{
404
		/*	1st face: try to load the image	*/
404
		/*	1st face: try to load the image	*/
405
		img = SOIL_load_image( z_pos_file, &width, &height, &channels, force_channels );
405
		img = SOIL_load_image( z_pos_file, &width, &height, &channels, force_channels );
406
		/*	channels holds the original number of channels, which may have been forced	*/
406
		/*	channels holds the original number of channels, which may have been forced	*/
407
		if( (force_channels >= 1) && (force_channels <= 4) )
407
		if( (force_channels >= 1) && (force_channels <= 4) )
408
		{
408
		{
409
			channels = force_channels;
409
			channels = force_channels;
410
		}
410
		}
411
		if( NULL == img )
411
		if( NULL == img )
412
		{
412
		{
413
			/*	image loading failed	*/
413
			/*	image loading failed	*/
414
			result_string_pointer = stbi_failure_reason();
414
			result_string_pointer = stbi_failure_reason();
415
			return 0;
415
			return 0;
416
		}
416
		}
417
		/*	upload the texture, but reuse the assigned texture ID	*/
417
		/*	upload the texture, but reuse the assigned texture ID	*/
418
		tex_id = SOIL_internal_create_OGL_texture(
418
		tex_id = SOIL_internal_create_OGL_texture(
419
				img, width, height, channels,
419
				img, width, height, channels,
420
				tex_id, flags,
420
				tex_id, flags,
421
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z,
421
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z,
422
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
422
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
423
		/*	and nuke the image data	*/
423
		/*	and nuke the image data	*/
424
		SOIL_free_image_data( img );
424
		SOIL_free_image_data( img );
425
	}
425
	}
426
	/*	continue?	*/
426
	/*	continue?	*/
427
	if( tex_id != 0 )
427
	if( tex_id != 0 )
428
	{
428
	{
429
		/*	1st face: try to load the image	*/
429
		/*	1st face: try to load the image	*/
430
		img = SOIL_load_image( z_neg_file, &width, &height, &channels, force_channels );
430
		img = SOIL_load_image( z_neg_file, &width, &height, &channels, force_channels );
431
		/*	channels holds the original number of channels, which may have been forced	*/
431
		/*	channels holds the original number of channels, which may have been forced	*/
432
		if( (force_channels >= 1) && (force_channels <= 4) )
432
		if( (force_channels >= 1) && (force_channels <= 4) )
433
		{
433
		{
434
			channels = force_channels;
434
			channels = force_channels;
435
		}
435
		}
436
		if( NULL == img )
436
		if( NULL == img )
437
		{
437
		{
438
			/*	image loading failed	*/
438
			/*	image loading failed	*/
439
			result_string_pointer = stbi_failure_reason();
439
			result_string_pointer = stbi_failure_reason();
440
			return 0;
440
			return 0;
441
		}
441
		}
442
		/*	upload the texture, but reuse the assigned texture ID	*/
442
		/*	upload the texture, but reuse the assigned texture ID	*/
443
		tex_id = SOIL_internal_create_OGL_texture(
443
		tex_id = SOIL_internal_create_OGL_texture(
444
				img, width, height, channels,
444
				img, width, height, channels,
445
				tex_id, flags,
445
				tex_id, flags,
446
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
446
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
447
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
447
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
448
		/*	and nuke the image data	*/
448
		/*	and nuke the image data	*/
449
		SOIL_free_image_data( img );
449
		SOIL_free_image_data( img );
450
	}
450
	}
451
	/*	and return the handle, such as it is	*/
451
	/*	and return the handle, such as it is	*/
452
	return tex_id;
452
	return tex_id;
453
}
453
}
454
 
454
 
455
unsigned int
455
unsigned int
456
	SOIL_load_OGL_cubemap_from_memory
456
	SOIL_load_OGL_cubemap_from_memory
457
	(
457
	(
458
		const unsigned char *const x_pos_buffer,
458
		const unsigned char *const x_pos_buffer,
459
		int x_pos_buffer_length,
459
		int x_pos_buffer_length,
460
		const unsigned char *const x_neg_buffer,
460
		const unsigned char *const x_neg_buffer,
461
		int x_neg_buffer_length,
461
		int x_neg_buffer_length,
462
		const unsigned char *const y_pos_buffer,
462
		const unsigned char *const y_pos_buffer,
463
		int y_pos_buffer_length,
463
		int y_pos_buffer_length,
464
		const unsigned char *const y_neg_buffer,
464
		const unsigned char *const y_neg_buffer,
465
		int y_neg_buffer_length,
465
		int y_neg_buffer_length,
466
		const unsigned char *const z_pos_buffer,
466
		const unsigned char *const z_pos_buffer,
467
		int z_pos_buffer_length,
467
		int z_pos_buffer_length,
468
		const unsigned char *const z_neg_buffer,
468
		const unsigned char *const z_neg_buffer,
469
		int z_neg_buffer_length,
469
		int z_neg_buffer_length,
470
		int force_channels,
470
		int force_channels,
471
		unsigned int reuse_texture_ID,
471
		unsigned int reuse_texture_ID,
472
		unsigned int flags
472
		unsigned int flags
473
	)
473
	)
474
{
474
{
475
	/*	variables	*/
475
	/*	variables	*/
476
	unsigned char* img;
476
	unsigned char* img;
477
	int width, height, channels;
477
	int width, height, channels;
478
	unsigned int tex_id;
478
	unsigned int tex_id;
479
	/*	error checking	*/
479
	/*	error checking	*/
480
	if( (x_pos_buffer == NULL) ||
480
	if( (x_pos_buffer == NULL) ||
481
		(x_neg_buffer == NULL) ||
481
		(x_neg_buffer == NULL) ||
482
		(y_pos_buffer == NULL) ||
482
		(y_pos_buffer == NULL) ||
483
		(y_neg_buffer == NULL) ||
483
		(y_neg_buffer == NULL) ||
484
		(z_pos_buffer == NULL) ||
484
		(z_pos_buffer == NULL) ||
485
		(z_neg_buffer == NULL) )
485
		(z_neg_buffer == NULL) )
486
	{
486
	{
487
		result_string_pointer = "Invalid cube map buffers list";
487
		result_string_pointer = "Invalid cube map buffers list";
488
		return 0;
488
		return 0;
489
	}
489
	}
490
	/*	capability checking	*/
490
	/*	capability checking	*/
491
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
491
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
492
	{
492
	{
493
		result_string_pointer = "No cube map capability present";
493
		result_string_pointer = "No cube map capability present";
494
		return 0;
494
		return 0;
495
	}
495
	}
496
	/*	1st face: try to load the image	*/
496
	/*	1st face: try to load the image	*/
497
	img = SOIL_load_image_from_memory(
497
	img = SOIL_load_image_from_memory(
498
			x_pos_buffer, x_pos_buffer_length,
498
			x_pos_buffer, x_pos_buffer_length,
499
			&width, &height, &channels, force_channels );
499
			&width, &height, &channels, force_channels );
500
	/*	channels holds the original number of channels, which may have been forced	*/
500
	/*	channels holds the original number of channels, which may have been forced	*/
501
	if( (force_channels >= 1) && (force_channels <= 4) )
501
	if( (force_channels >= 1) && (force_channels <= 4) )
502
	{
502
	{
503
		channels = force_channels;
503
		channels = force_channels;
504
	}
504
	}
505
	if( NULL == img )
505
	if( NULL == img )
506
	{
506
	{
507
		/*	image loading failed	*/
507
		/*	image loading failed	*/
508
		result_string_pointer = stbi_failure_reason();
508
		result_string_pointer = stbi_failure_reason();
509
		return 0;
509
		return 0;
510
	}
510
	}
511
	/*	upload the texture, and create a texture ID if necessary	*/
511
	/*	upload the texture, and create a texture ID if necessary	*/
512
	tex_id = SOIL_internal_create_OGL_texture(
512
	tex_id = SOIL_internal_create_OGL_texture(
513
			img, width, height, channels,
513
			img, width, height, channels,
514
			reuse_texture_ID, flags,
514
			reuse_texture_ID, flags,
515
			SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_X,
515
			SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_X,
516
			SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
516
			SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
517
	/*	and nuke the image data	*/
517
	/*	and nuke the image data	*/
518
	SOIL_free_image_data( img );
518
	SOIL_free_image_data( img );
519
	/*	continue?	*/
519
	/*	continue?	*/
520
	if( tex_id != 0 )
520
	if( tex_id != 0 )
521
	{
521
	{
522
		/*	1st face: try to load the image	*/
522
		/*	1st face: try to load the image	*/
523
		img = SOIL_load_image_from_memory(
523
		img = SOIL_load_image_from_memory(
524
				x_neg_buffer, x_neg_buffer_length,
524
				x_neg_buffer, x_neg_buffer_length,
525
				&width, &height, &channels, force_channels );
525
				&width, &height, &channels, force_channels );
526
		/*	channels holds the original number of channels, which may have been forced	*/
526
		/*	channels holds the original number of channels, which may have been forced	*/
527
		if( (force_channels >= 1) && (force_channels <= 4) )
527
		if( (force_channels >= 1) && (force_channels <= 4) )
528
		{
528
		{
529
			channels = force_channels;
529
			channels = force_channels;
530
		}
530
		}
531
		if( NULL == img )
531
		if( NULL == img )
532
		{
532
		{
533
			/*	image loading failed	*/
533
			/*	image loading failed	*/
534
			result_string_pointer = stbi_failure_reason();
534
			result_string_pointer = stbi_failure_reason();
535
			return 0;
535
			return 0;
536
		}
536
		}
537
		/*	upload the texture, but reuse the assigned texture ID	*/
537
		/*	upload the texture, but reuse the assigned texture ID	*/
538
		tex_id = SOIL_internal_create_OGL_texture(
538
		tex_id = SOIL_internal_create_OGL_texture(
539
				img, width, height, channels,
539
				img, width, height, channels,
540
				tex_id, flags,
540
				tex_id, flags,
541
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X,
541
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X,
542
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
542
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
543
		/*	and nuke the image data	*/
543
		/*	and nuke the image data	*/
544
		SOIL_free_image_data( img );
544
		SOIL_free_image_data( img );
545
	}
545
	}
546
	/*	continue?	*/
546
	/*	continue?	*/
547
	if( tex_id != 0 )
547
	if( tex_id != 0 )
548
	{
548
	{
549
		/*	1st face: try to load the image	*/
549
		/*	1st face: try to load the image	*/
550
		img = SOIL_load_image_from_memory(
550
		img = SOIL_load_image_from_memory(
551
				y_pos_buffer, y_pos_buffer_length,
551
				y_pos_buffer, y_pos_buffer_length,
552
				&width, &height, &channels, force_channels );
552
				&width, &height, &channels, force_channels );
553
		/*	channels holds the original number of channels, which may have been forced	*/
553
		/*	channels holds the original number of channels, which may have been forced	*/
554
		if( (force_channels >= 1) && (force_channels <= 4) )
554
		if( (force_channels >= 1) && (force_channels <= 4) )
555
		{
555
		{
556
			channels = force_channels;
556
			channels = force_channels;
557
		}
557
		}
558
		if( NULL == img )
558
		if( NULL == img )
559
		{
559
		{
560
			/*	image loading failed	*/
560
			/*	image loading failed	*/
561
			result_string_pointer = stbi_failure_reason();
561
			result_string_pointer = stbi_failure_reason();
562
			return 0;
562
			return 0;
563
		}
563
		}
564
		/*	upload the texture, but reuse the assigned texture ID	*/
564
		/*	upload the texture, but reuse the assigned texture ID	*/
565
		tex_id = SOIL_internal_create_OGL_texture(
565
		tex_id = SOIL_internal_create_OGL_texture(
566
				img, width, height, channels,
566
				img, width, height, channels,
567
				tex_id, flags,
567
				tex_id, flags,
568
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y,
568
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y,
569
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
569
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
570
		/*	and nuke the image data	*/
570
		/*	and nuke the image data	*/
571
		SOIL_free_image_data( img );
571
		SOIL_free_image_data( img );
572
	}
572
	}
573
	/*	continue?	*/
573
	/*	continue?	*/
574
	if( tex_id != 0 )
574
	if( tex_id != 0 )
575
	{
575
	{
576
		/*	1st face: try to load the image	*/
576
		/*	1st face: try to load the image	*/
577
		img = SOIL_load_image_from_memory(
577
		img = SOIL_load_image_from_memory(
578
				y_neg_buffer, y_neg_buffer_length,
578
				y_neg_buffer, y_neg_buffer_length,
579
				&width, &height, &channels, force_channels );
579
				&width, &height, &channels, force_channels );
580
		/*	channels holds the original number of channels, which may have been forced	*/
580
		/*	channels holds the original number of channels, which may have been forced	*/
581
		if( (force_channels >= 1) && (force_channels <= 4) )
581
		if( (force_channels >= 1) && (force_channels <= 4) )
582
		{
582
		{
583
			channels = force_channels;
583
			channels = force_channels;
584
		}
584
		}
585
		if( NULL == img )
585
		if( NULL == img )
586
		{
586
		{
587
			/*	image loading failed	*/
587
			/*	image loading failed	*/
588
			result_string_pointer = stbi_failure_reason();
588
			result_string_pointer = stbi_failure_reason();
589
			return 0;
589
			return 0;
590
		}
590
		}
591
		/*	upload the texture, but reuse the assigned texture ID	*/
591
		/*	upload the texture, but reuse the assigned texture ID	*/
592
		tex_id = SOIL_internal_create_OGL_texture(
592
		tex_id = SOIL_internal_create_OGL_texture(
593
				img, width, height, channels,
593
				img, width, height, channels,
594
				tex_id, flags,
594
				tex_id, flags,
595
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
595
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
596
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
596
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
597
		/*	and nuke the image data	*/
597
		/*	and nuke the image data	*/
598
		SOIL_free_image_data( img );
598
		SOIL_free_image_data( img );
599
	}
599
	}
600
	/*	continue?	*/
600
	/*	continue?	*/
601
	if( tex_id != 0 )
601
	if( tex_id != 0 )
602
	{
602
	{
603
		/*	1st face: try to load the image	*/
603
		/*	1st face: try to load the image	*/
604
		img = SOIL_load_image_from_memory(
604
		img = SOIL_load_image_from_memory(
605
				z_pos_buffer, z_pos_buffer_length,
605
				z_pos_buffer, z_pos_buffer_length,
606
				&width, &height, &channels, force_channels );
606
				&width, &height, &channels, force_channels );
607
		/*	channels holds the original number of channels, which may have been forced	*/
607
		/*	channels holds the original number of channels, which may have been forced	*/
608
		if( (force_channels >= 1) && (force_channels <= 4) )
608
		if( (force_channels >= 1) && (force_channels <= 4) )
609
		{
609
		{
610
			channels = force_channels;
610
			channels = force_channels;
611
		}
611
		}
612
		if( NULL == img )
612
		if( NULL == img )
613
		{
613
		{
614
			/*	image loading failed	*/
614
			/*	image loading failed	*/
615
			result_string_pointer = stbi_failure_reason();
615
			result_string_pointer = stbi_failure_reason();
616
			return 0;
616
			return 0;
617
		}
617
		}
618
		/*	upload the texture, but reuse the assigned texture ID	*/
618
		/*	upload the texture, but reuse the assigned texture ID	*/
619
		tex_id = SOIL_internal_create_OGL_texture(
619
		tex_id = SOIL_internal_create_OGL_texture(
620
				img, width, height, channels,
620
				img, width, height, channels,
621
				tex_id, flags,
621
				tex_id, flags,
622
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z,
622
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z,
623
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
623
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
624
		/*	and nuke the image data	*/
624
		/*	and nuke the image data	*/
625
		SOIL_free_image_data( img );
625
		SOIL_free_image_data( img );
626
	}
626
	}
627
	/*	continue?	*/
627
	/*	continue?	*/
628
	if( tex_id != 0 )
628
	if( tex_id != 0 )
629
	{
629
	{
630
		/*	1st face: try to load the image	*/
630
		/*	1st face: try to load the image	*/
631
		img = SOIL_load_image_from_memory(
631
		img = SOIL_load_image_from_memory(
632
				z_neg_buffer, z_neg_buffer_length,
632
				z_neg_buffer, z_neg_buffer_length,
633
				&width, &height, &channels, force_channels );
633
				&width, &height, &channels, force_channels );
634
		/*	channels holds the original number of channels, which may have been forced	*/
634
		/*	channels holds the original number of channels, which may have been forced	*/
635
		if( (force_channels >= 1) && (force_channels <= 4) )
635
		if( (force_channels >= 1) && (force_channels <= 4) )
636
		{
636
		{
637
			channels = force_channels;
637
			channels = force_channels;
638
		}
638
		}
639
		if( NULL == img )
639
		if( NULL == img )
640
		{
640
		{
641
			/*	image loading failed	*/
641
			/*	image loading failed	*/
642
			result_string_pointer = stbi_failure_reason();
642
			result_string_pointer = stbi_failure_reason();
643
			return 0;
643
			return 0;
644
		}
644
		}
645
		/*	upload the texture, but reuse the assigned texture ID	*/
645
		/*	upload the texture, but reuse the assigned texture ID	*/
646
		tex_id = SOIL_internal_create_OGL_texture(
646
		tex_id = SOIL_internal_create_OGL_texture(
647
				img, width, height, channels,
647
				img, width, height, channels,
648
				tex_id, flags,
648
				tex_id, flags,
649
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
649
				SOIL_TEXTURE_CUBE_MAP, SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
650
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
650
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
651
		/*	and nuke the image data	*/
651
		/*	and nuke the image data	*/
652
		SOIL_free_image_data( img );
652
		SOIL_free_image_data( img );
653
	}
653
	}
654
	/*	and return the handle, such as it is	*/
654
	/*	and return the handle, such as it is	*/
655
	return tex_id;
655
	return tex_id;
656
}
656
}
657
 
657
 
658
unsigned int
658
unsigned int
659
	SOIL_load_OGL_single_cubemap
659
	SOIL_load_OGL_single_cubemap
660
	(
660
	(
661
		const char *filename,
661
		const char *filename,
662
		const char face_order[6],
662
		const char face_order[6],
663
		int force_channels,
663
		int force_channels,
664
		unsigned int reuse_texture_ID,
664
		unsigned int reuse_texture_ID,
665
		unsigned int flags
665
		unsigned int flags
666
	)
666
	)
667
{
667
{
668
	/*	variables	*/
668
	/*	variables	*/
669
	unsigned char* img;
669
	unsigned char* img;
670
	int width, height, channels, i;
670
	int width, height, channels, i;
671
	unsigned int tex_id = 0;
671
	unsigned int tex_id = 0;
672
	/*	error checking	*/
672
	/*	error checking	*/
673
	if( filename == NULL )
673
	if( filename == NULL )
674
	{
674
	{
675
		result_string_pointer = "Invalid single cube map file name";
675
		result_string_pointer = "Invalid single cube map file name";
676
		return 0;
676
		return 0;
677
	}
677
	}
678
	/*	does the user want direct uploading of the image as a DDS file?	*/
678
	/*	does the user want direct uploading of the image as a DDS file?	*/
679
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
679
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
680
	{
680
	{
681
		/*	1st try direct loading of the image as a DDS file
681
		/*	1st try direct loading of the image as a DDS file
682
			note: direct uploading will only load what is in the
682
			note: direct uploading will only load what is in the
683
			DDS file, no MIPmaps will be generated, the image will
683
			DDS file, no MIPmaps will be generated, the image will
684
			not be flipped, etc.	*/
684
			not be flipped, etc.	*/
685
		tex_id = SOIL_direct_load_DDS( filename, reuse_texture_ID, flags, 1 );
685
		tex_id = SOIL_direct_load_DDS( filename, reuse_texture_ID, flags, 1 );
686
		if( tex_id )
686
		if( tex_id )
687
		{
687
		{
688
			/*	hey, it worked!!	*/
688
			/*	hey, it worked!!	*/
689
			return tex_id;
689
			return tex_id;
690
		}
690
		}
691
	}
691
	}
692
	/*	face order checking	*/
692
	/*	face order checking	*/
693
	for( i = 0; i < 6; ++i )
693
	for( i = 0; i < 6; ++i )
694
	{
694
	{
695
		if( (face_order[i] != 'N') &&
695
		if( (face_order[i] != 'N') &&
696
			(face_order[i] != 'S') &&
696
			(face_order[i] != 'S') &&
697
			(face_order[i] != 'W') &&
697
			(face_order[i] != 'W') &&
698
			(face_order[i] != 'E') &&
698
			(face_order[i] != 'E') &&
699
			(face_order[i] != 'U') &&
699
			(face_order[i] != 'U') &&
700
			(face_order[i] != 'D') )
700
			(face_order[i] != 'D') )
701
		{
701
		{
702
			result_string_pointer = "Invalid single cube map face order";
702
			result_string_pointer = "Invalid single cube map face order";
703
			return 0;
703
			return 0;
704
		};
704
		};
705
	}
705
	}
706
	/*	capability checking	*/
706
	/*	capability checking	*/
707
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
707
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
708
	{
708
	{
709
		result_string_pointer = "No cube map capability present";
709
		result_string_pointer = "No cube map capability present";
710
		return 0;
710
		return 0;
711
	}
711
	}
712
	/*	1st off, try to load the full image	*/
712
	/*	1st off, try to load the full image	*/
713
	img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
713
	img = SOIL_load_image( filename, &width, &height, &channels, force_channels );
714
	/*	channels holds the original number of channels, which may have been forced	*/
714
	/*	channels holds the original number of channels, which may have been forced	*/
715
	if( (force_channels >= 1) && (force_channels <= 4) )
715
	if( (force_channels >= 1) && (force_channels <= 4) )
716
	{
716
	{
717
		channels = force_channels;
717
		channels = force_channels;
718
	}
718
	}
719
	if( NULL == img )
719
	if( NULL == img )
720
	{
720
	{
721
		/*	image loading failed	*/
721
		/*	image loading failed	*/
722
		result_string_pointer = stbi_failure_reason();
722
		result_string_pointer = stbi_failure_reason();
723
		return 0;
723
		return 0;
724
	}
724
	}
725
	/*	now, does this image have the right dimensions?	*/
725
	/*	now, does this image have the right dimensions?	*/
726
	if( (width != 6*height) &&
726
	if( (width != 6*height) &&
727
		(6*width != height) )
727
		(6*width != height) )
728
	{
728
	{
729
		SOIL_free_image_data( img );
729
		SOIL_free_image_data( img );
730
		result_string_pointer = "Single cubemap image must have a 6:1 ratio";
730
		result_string_pointer = "Single cubemap image must have a 6:1 ratio";
731
		return 0;
731
		return 0;
732
	}
732
	}
733
	/*	try the image split and create	*/
733
	/*	try the image split and create	*/
734
	tex_id = SOIL_create_OGL_single_cubemap(
734
	tex_id = SOIL_create_OGL_single_cubemap(
735
			img, width, height, channels,
735
			img, width, height, channels,
736
			face_order, reuse_texture_ID, flags
736
			face_order, reuse_texture_ID, flags
737
			);
737
			);
738
	/*	nuke the temporary image data and return the texture handle	*/
738
	/*	nuke the temporary image data and return the texture handle	*/
739
	SOIL_free_image_data( img );
739
	SOIL_free_image_data( img );
740
	return tex_id;
740
	return tex_id;
741
}
741
}
742
 
742
 
743
unsigned int
743
unsigned int
744
	SOIL_load_OGL_single_cubemap_from_memory
744
	SOIL_load_OGL_single_cubemap_from_memory
745
	(
745
	(
746
		const unsigned char *const buffer,
746
		const unsigned char *const buffer,
747
		int buffer_length,
747
		int buffer_length,
748
		const char face_order[6],
748
		const char face_order[6],
749
		int force_channels,
749
		int force_channels,
750
		unsigned int reuse_texture_ID,
750
		unsigned int reuse_texture_ID,
751
		unsigned int flags
751
		unsigned int flags
752
	)
752
	)
753
{
753
{
754
	/*	variables	*/
754
	/*	variables	*/
755
	unsigned char* img;
755
	unsigned char* img;
756
	int width, height, channels, i;
756
	int width, height, channels, i;
757
	unsigned int tex_id = 0;
757
	unsigned int tex_id = 0;
758
	/*	error checking	*/
758
	/*	error checking	*/
759
	if( buffer == NULL )
759
	if( buffer == NULL )
760
	{
760
	{
761
		result_string_pointer = "Invalid single cube map buffer";
761
		result_string_pointer = "Invalid single cube map buffer";
762
		return 0;
762
		return 0;
763
	}
763
	}
764
	/*	does the user want direct uploading of the image as a DDS file?	*/
764
	/*	does the user want direct uploading of the image as a DDS file?	*/
765
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
765
	if( flags & SOIL_FLAG_DDS_LOAD_DIRECT )
766
	{
766
	{
767
		/*	1st try direct loading of the image as a DDS file
767
		/*	1st try direct loading of the image as a DDS file
768
			note: direct uploading will only load what is in the
768
			note: direct uploading will only load what is in the
769
			DDS file, no MIPmaps will be generated, the image will
769
			DDS file, no MIPmaps will be generated, the image will
770
			not be flipped, etc.	*/
770
			not be flipped, etc.	*/
771
		tex_id = SOIL_direct_load_DDS_from_memory(
771
		tex_id = SOIL_direct_load_DDS_from_memory(
772
				buffer, buffer_length,
772
				buffer, buffer_length,
773
				reuse_texture_ID, flags, 1 );
773
				reuse_texture_ID, flags, 1 );
774
		if( tex_id )
774
		if( tex_id )
775
		{
775
		{
776
			/*	hey, it worked!!	*/
776
			/*	hey, it worked!!	*/
777
			return tex_id;
777
			return tex_id;
778
		}
778
		}
779
	}
779
	}
780
	/*	face order checking	*/
780
	/*	face order checking	*/
781
	for( i = 0; i < 6; ++i )
781
	for( i = 0; i < 6; ++i )
782
	{
782
	{
783
		if( (face_order[i] != 'N') &&
783
		if( (face_order[i] != 'N') &&
784
			(face_order[i] != 'S') &&
784
			(face_order[i] != 'S') &&
785
			(face_order[i] != 'W') &&
785
			(face_order[i] != 'W') &&
786
			(face_order[i] != 'E') &&
786
			(face_order[i] != 'E') &&
787
			(face_order[i] != 'U') &&
787
			(face_order[i] != 'U') &&
788
			(face_order[i] != 'D') )
788
			(face_order[i] != 'D') )
789
		{
789
		{
790
			result_string_pointer = "Invalid single cube map face order";
790
			result_string_pointer = "Invalid single cube map face order";
791
			return 0;
791
			return 0;
792
		};
792
		};
793
	}
793
	}
794
	/*	capability checking	*/
794
	/*	capability checking	*/
795
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
795
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
796
	{
796
	{
797
		result_string_pointer = "No cube map capability present";
797
		result_string_pointer = "No cube map capability present";
798
		return 0;
798
		return 0;
799
	}
799
	}
800
	/*	1st off, try to load the full image	*/
800
	/*	1st off, try to load the full image	*/
801
	img = SOIL_load_image_from_memory(
801
	img = SOIL_load_image_from_memory(
802
			buffer, buffer_length,
802
			buffer, buffer_length,
803
			&width, &height, &channels,
803
			&width, &height, &channels,
804
			force_channels );
804
			force_channels );
805
	/*	channels holds the original number of channels, which may have been forced	*/
805
	/*	channels holds the original number of channels, which may have been forced	*/
806
	if( (force_channels >= 1) && (force_channels <= 4) )
806
	if( (force_channels >= 1) && (force_channels <= 4) )
807
	{
807
	{
808
		channels = force_channels;
808
		channels = force_channels;
809
	}
809
	}
810
	if( NULL == img )
810
	if( NULL == img )
811
	{
811
	{
812
		/*	image loading failed	*/
812
		/*	image loading failed	*/
813
		result_string_pointer = stbi_failure_reason();
813
		result_string_pointer = stbi_failure_reason();
814
		return 0;
814
		return 0;
815
	}
815
	}
816
	/*	now, does this image have the right dimensions?	*/
816
	/*	now, does this image have the right dimensions?	*/
817
	if( (width != 6*height) &&
817
	if( (width != 6*height) &&
818
		(6*width != height) )
818
		(6*width != height) )
819
	{
819
	{
820
		SOIL_free_image_data( img );
820
		SOIL_free_image_data( img );
821
		result_string_pointer = "Single cubemap image must have a 6:1 ratio";
821
		result_string_pointer = "Single cubemap image must have a 6:1 ratio";
822
		return 0;
822
		return 0;
823
	}
823
	}
824
	/*	try the image split and create	*/
824
	/*	try the image split and create	*/
825
	tex_id = SOIL_create_OGL_single_cubemap(
825
	tex_id = SOIL_create_OGL_single_cubemap(
826
			img, width, height, channels,
826
			img, width, height, channels,
827
			face_order, reuse_texture_ID, flags
827
			face_order, reuse_texture_ID, flags
828
			);
828
			);
829
	/*	nuke the temporary image data and return the texture handle	*/
829
	/*	nuke the temporary image data and return the texture handle	*/
830
	SOIL_free_image_data( img );
830
	SOIL_free_image_data( img );
831
	return tex_id;
831
	return tex_id;
832
}
832
}
833
 
833
 
834
unsigned int
834
unsigned int
835
	SOIL_create_OGL_single_cubemap
835
	SOIL_create_OGL_single_cubemap
836
	(
836
	(
837
		const unsigned char *const data,
837
		const unsigned char *const data,
838
		int width, int height, int channels,
838
		int width, int height, int channels,
839
		const char face_order[6],
839
		const char face_order[6],
840
		unsigned int reuse_texture_ID,
840
		unsigned int reuse_texture_ID,
841
		unsigned int flags
841
		unsigned int flags
842
	)
842
	)
843
{
843
{
844
	/*	variables	*/
844
	/*	variables	*/
845
	unsigned char* sub_img;
845
	unsigned char* sub_img;
846
	int dw, dh, sz, i;
846
	int dw, dh, sz, i;
847
	unsigned int tex_id;
847
	unsigned int tex_id;
848
	/*	error checking	*/
848
	/*	error checking	*/
849
	if( data == NULL )
849
	if( data == NULL )
850
	{
850
	{
851
		result_string_pointer = "Invalid single cube map image data";
851
		result_string_pointer = "Invalid single cube map image data";
852
		return 0;
852
		return 0;
853
	}
853
	}
854
	/*	face order checking	*/
854
	/*	face order checking	*/
855
	for( i = 0; i < 6; ++i )
855
	for( i = 0; i < 6; ++i )
856
	{
856
	{
857
		if( (face_order[i] != 'N') &&
857
		if( (face_order[i] != 'N') &&
858
			(face_order[i] != 'S') &&
858
			(face_order[i] != 'S') &&
859
			(face_order[i] != 'W') &&
859
			(face_order[i] != 'W') &&
860
			(face_order[i] != 'E') &&
860
			(face_order[i] != 'E') &&
861
			(face_order[i] != 'U') &&
861
			(face_order[i] != 'U') &&
862
			(face_order[i] != 'D') )
862
			(face_order[i] != 'D') )
863
		{
863
		{
864
			result_string_pointer = "Invalid single cube map face order";
864
			result_string_pointer = "Invalid single cube map face order";
865
			return 0;
865
			return 0;
866
		};
866
		};
867
	}
867
	}
868
	/*	capability checking	*/
868
	/*	capability checking	*/
869
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
869
	if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
870
	{
870
	{
871
		result_string_pointer = "No cube map capability present";
871
		result_string_pointer = "No cube map capability present";
872
		return 0;
872
		return 0;
873
	}
873
	}
874
	/*	now, does this image have the right dimensions?	*/
874
	/*	now, does this image have the right dimensions?	*/
875
	if( (width != 6*height) &&
875
	if( (width != 6*height) &&
876
		(6*width != height) )
876
		(6*width != height) )
877
	{
877
	{
878
		result_string_pointer = "Single cubemap image must have a 6:1 ratio";
878
		result_string_pointer = "Single cubemap image must have a 6:1 ratio";
879
		return 0;
879
		return 0;
880
	}
880
	}
881
	/*	which way am I stepping?	*/
881
	/*	which way am I stepping?	*/
882
	if( width > height )
882
	if( width > height )
883
	{
883
	{
884
		dw = height;
884
		dw = height;
885
		dh = 0;
885
		dh = 0;
886
	} else
886
	} else
887
	{
887
	{
888
		dw = 0;
888
		dw = 0;
889
		dh = width;
889
		dh = width;
890
	}
890
	}
891
	sz = dw+dh;
891
	sz = dw+dh;
892
	sub_img = (unsigned char *)malloc( sz*sz*channels );
892
	sub_img = (unsigned char *)malloc( sz*sz*channels );
893
	/*	do the splitting and uploading	*/
893
	/*	do the splitting and uploading	*/
894
	tex_id = reuse_texture_ID;
894
	tex_id = reuse_texture_ID;
895
	for( i = 0; i < 6; ++i )
895
	for( i = 0; i < 6; ++i )
896
	{
896
	{
897
		int x, y, idx = 0;
897
		int x, y, idx = 0;
898
		unsigned int cubemap_target = 0;
898
		unsigned int cubemap_target = 0;
899
		/*	copy in the sub-image	*/
899
		/*	copy in the sub-image	*/
900
		for( y = i*dh; y < i*dh+sz; ++y )
900
		for( y = i*dh; y < i*dh+sz; ++y )
901
		{
901
		{
902
			for( x = i*dw*channels; x < (i*dw+sz)*channels; ++x )
902
			for( x = i*dw*channels; x < (i*dw+sz)*channels; ++x )
903
			{
903
			{
904
				sub_img[idx++] = data[y*width*channels+x];
904
				sub_img[idx++] = data[y*width*channels+x];
905
			}
905
			}
906
		}
906
		}
907
		/*	what is my texture target?
907
		/*	what is my texture target?
908
			remember, this coordinate system is
908
			remember, this coordinate system is
909
			LHS if viewed from inside the cube!	*/
909
			LHS if viewed from inside the cube!	*/
910
		switch( face_order[i] )
910
		switch( face_order[i] )
911
		{
911
		{
912
		case 'N':
912
		case 'N':
913
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z;
913
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_Z;
914
			break;
914
			break;
915
		case 'S':
915
		case 'S':
916
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
916
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
917
			break;
917
			break;
918
		case 'W':
918
		case 'W':
919
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X;
919
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_X;
920
			break;
920
			break;
921
		case 'E':
921
		case 'E':
922
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_X;
922
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_X;
923
			break;
923
			break;
924
		case 'U':
924
		case 'U':
925
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y;
925
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_POSITIVE_Y;
926
			break;
926
			break;
927
		case 'D':
927
		case 'D':
928
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
928
			cubemap_target = SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Y;
929
			break;
929
			break;
930
		}
930
		}
931
		/*	upload it as a texture	*/
931
		/*	upload it as a texture	*/
932
		tex_id = SOIL_internal_create_OGL_texture(
932
		tex_id = SOIL_internal_create_OGL_texture(
933
				sub_img, sz, sz, channels,
933
				sub_img, sz, sz, channels,
934
				tex_id, flags,
934
				tex_id, flags,
935
				SOIL_TEXTURE_CUBE_MAP,
935
				SOIL_TEXTURE_CUBE_MAP,
936
				cubemap_target,
936
				cubemap_target,
937
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
937
				SOIL_MAX_CUBE_MAP_TEXTURE_SIZE );
938
	}
938
	}
939
	/*	and nuke the image and sub-image data	*/
939
	/*	and nuke the image and sub-image data	*/
940
	SOIL_free_image_data( sub_img );
940
	SOIL_free_image_data( sub_img );
941
	/*	and return the handle, such as it is	*/
941
	/*	and return the handle, such as it is	*/
942
	return tex_id;
942
	return tex_id;
943
}
943
}
944
 
944
 
945
unsigned int
945
unsigned int
946
	SOIL_create_OGL_texture
946
	SOIL_create_OGL_texture
947
	(
947
	(
948
		const unsigned char *const data,
948
		const unsigned char *const data,
949
		int width, int height, int channels,
949
		int width, int height, int channels,
950
		unsigned int reuse_texture_ID,
950
		unsigned int reuse_texture_ID,
951
		unsigned int flags
951
		unsigned int flags
952
	)
952
	)
953
{
953
{
954
	/*	wrapper function for 2D textures	*/
954
	/*	wrapper function for 2D textures	*/
955
	return SOIL_internal_create_OGL_texture(
955
	return SOIL_internal_create_OGL_texture(
956
				data, width, height, channels,
956
				data, width, height, channels,
957
				reuse_texture_ID, flags,
957
				reuse_texture_ID, flags,
958
				GL_TEXTURE_2D, GL_TEXTURE_2D,
958
				GL_TEXTURE_2D, GL_TEXTURE_2D,
959
				GL_MAX_TEXTURE_SIZE );
959
				GL_MAX_TEXTURE_SIZE );
960
}
960
}
961
 
961
 
962
#if SOIL_CHECK_FOR_GL_ERRORS
962
#if SOIL_CHECK_FOR_GL_ERRORS
963
void check_for_GL_errors( const char *calling_location )
963
void check_for_GL_errors( const char *calling_location )
964
{
964
{
965
	/*	check for errors	*/
965
	/*	check for errors	*/
966
	GLenum err_code = glGetError();
966
	GLenum err_code = glGetError();
967
	while( GL_NO_ERROR != err_code )
967
	while( GL_NO_ERROR != err_code )
968
	{
968
	{
969
		printf( "OpenGL Error @ %s: %i", calling_location, err_code );
969
		printf( "OpenGL Error @ %s: %i", calling_location, err_code );
970
		err_code = glGetError();
970
		err_code = glGetError();
971
	}
971
	}
972
}
972
}
973
#else
973
#else
974
void check_for_GL_errors( const char *calling_location )
974
void check_for_GL_errors( const char *calling_location )
975
{
975
{
976
	/*	no check for errors	*/
976
	/*	no check for errors	*/
977
}
977
}
978
#endif
978
#endif
979
 
979
 
980
unsigned int
980
unsigned int
981
	SOIL_internal_create_OGL_texture
981
	SOIL_internal_create_OGL_texture
982
	(
982
	(
983
		const unsigned char *const data,
983
		const unsigned char *const data,
984
		int width, int height, int channels,
984
		int width, int height, int channels,
985
		unsigned int reuse_texture_ID,
985
		unsigned int reuse_texture_ID,
986
		unsigned int flags,
986
		unsigned int flags,
987
		unsigned int opengl_texture_type,
987
		unsigned int opengl_texture_type,
988
		unsigned int opengl_texture_target,
988
		unsigned int opengl_texture_target,
989
		unsigned int texture_check_size_enum
989
		unsigned int texture_check_size_enum
990
	)
990
	)
991
{
991
{
992
	/*	variables	*/
992
	/*	variables	*/
993
	unsigned char* img;
993
	unsigned char* img;
994
	unsigned int tex_id;
994
	unsigned int tex_id;
995
	unsigned int internal_texture_format = 0, original_texture_format = 0;
995
	unsigned int internal_texture_format = 0, original_texture_format = 0;
996
	int DXT_mode = SOIL_CAPABILITY_UNKNOWN;
996
	int DXT_mode = SOIL_CAPABILITY_UNKNOWN;
997
	int max_supported_size;
997
	int max_supported_size;
998
	/*	If the user wants to use the texture rectangle I kill a few flags	*/
998
	/*	If the user wants to use the texture rectangle I kill a few flags	*/
999
	if( flags & SOIL_FLAG_TEXTURE_RECTANGLE )
999
	if( flags & SOIL_FLAG_TEXTURE_RECTANGLE )
1000
	{
1000
	{
1001
		/*	well, the user asked for it, can we do that?	*/
1001
		/*	well, the user asked for it, can we do that?	*/
1002
		if( query_tex_rectangle_capability() == SOIL_CAPABILITY_PRESENT )
1002
		if( query_tex_rectangle_capability() == SOIL_CAPABILITY_PRESENT )
1003
		{
1003
		{
1004
			/*	only allow this if the user in _NOT_ trying to do a cubemap!	*/
1004
			/*	only allow this if the user in _NOT_ trying to do a cubemap!	*/
1005
			if( opengl_texture_type == GL_TEXTURE_2D )
1005
			if( opengl_texture_type == GL_TEXTURE_2D )
1006
			{
1006
			{
1007
				/*	clean out the flags that cannot be used with texture rectangles	*/
1007
				/*	clean out the flags that cannot be used with texture rectangles	*/
1008
				flags &= ~(
1008
				flags &= ~(
1009
						SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS |
1009
						SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS |
1010
						SOIL_FLAG_TEXTURE_REPEATS
1010
						SOIL_FLAG_TEXTURE_REPEATS
1011
					);
1011
					);
1012
				/*	and change my target	*/
1012
				/*	and change my target	*/
1013
				opengl_texture_target = SOIL_TEXTURE_RECTANGLE_ARB;
1013
				opengl_texture_target = SOIL_TEXTURE_RECTANGLE_ARB;
1014
				opengl_texture_type = SOIL_TEXTURE_RECTANGLE_ARB;
1014
				opengl_texture_type = SOIL_TEXTURE_RECTANGLE_ARB;
1015
			} else
1015
			} else
1016
			{
1016
			{
1017
				/*	not allowed for any other uses (yes, I'm looking at you, cubemaps!)	*/
1017
				/*	not allowed for any other uses (yes, I'm looking at you, cubemaps!)	*/
1018
				flags &= ~SOIL_FLAG_TEXTURE_RECTANGLE;
1018
				flags &= ~SOIL_FLAG_TEXTURE_RECTANGLE;
1019
			}
1019
			}
1020
 
1020
 
1021
		} else
1021
		} else
1022
		{
1022
		{
1023
			/*	can't do it, and that is a breakable offense (uv coords use pixels instead of [0,1]!)	*/
1023
			/*	can't do it, and that is a breakable offense (uv coords use pixels instead of [0,1]!)	*/
1024
			result_string_pointer = "Texture Rectangle extension unsupported";
1024
			result_string_pointer = "Texture Rectangle extension unsupported";
1025
			return 0;
1025
			return 0;
1026
		}
1026
		}
1027
	}
1027
	}
1028
	/*	create a copy the image data	*/
1028
	/*	create a copy the image data	*/
1029
	img = (unsigned char*)malloc( width*height*channels );
1029
	img = (unsigned char*)malloc( width*height*channels );
1030
	memcpy( img, data, width*height*channels );
1030
	memcpy( img, data, width*height*channels );
1031
	/*	does the user want me to invert the image?	*/
1031
	/*	does the user want me to invert the image?	*/
1032
	if( flags & SOIL_FLAG_INVERT_Y )
1032
	if( flags & SOIL_FLAG_INVERT_Y )
1033
	{
1033
	{
1034
		int i, j;
1034
		int i, j;
1035
		for( j = 0; j*2 < height; ++j )
1035
		for( j = 0; j*2 < height; ++j )
1036
		{
1036
		{
1037
			int index1 = j * width * channels;
1037
			int index1 = j * width * channels;
1038
			int index2 = (height - 1 - j) * width * channels;
1038
			int index2 = (height - 1 - j) * width * channels;
1039
			for( i = width * channels; i > 0; --i )
1039
			for( i = width * channels; i > 0; --i )
1040
			{
1040
			{
1041
				unsigned char temp = img[index1];
1041
				unsigned char temp = img[index1];
1042
				img[index1] = img[index2];
1042
				img[index1] = img[index2];
1043
				img[index2] = temp;
1043
				img[index2] = temp;
1044
				++index1;
1044
				++index1;
1045
				++index2;
1045
				++index2;
1046
			}
1046
			}
1047
		}
1047
		}
1048
	}
1048
	}
1049
	/*	does the user want me to scale the colors into the NTSC safe RGB range?	*/
1049
	/*	does the user want me to scale the colors into the NTSC safe RGB range?	*/
1050
	if( flags & SOIL_FLAG_NTSC_SAFE_RGB )
1050
	if( flags & SOIL_FLAG_NTSC_SAFE_RGB )
1051
	{
1051
	{
1052
		scale_image_RGB_to_NTSC_safe( img, width, height, channels );
1052
		scale_image_RGB_to_NTSC_safe( img, width, height, channels );
1053
	}
1053
	}
1054
	/*	does the user want me to convert from straight to pre-multiplied alpha?
1054
	/*	does the user want me to convert from straight to pre-multiplied alpha?
1055
		(and do we even _have_ alpha?)	*/
1055
		(and do we even _have_ alpha?)	*/
1056
	if( flags & SOIL_FLAG_MULTIPLY_ALPHA )
1056
	if( flags & SOIL_FLAG_MULTIPLY_ALPHA )
1057
	{
1057
	{
1058
		int i;
1058
		int i;
1059
		switch( channels )
1059
		switch( channels )
1060
		{
1060
		{
1061
		case 2:
1061
		case 2:
1062
			for( i = 0; i < 2*width*height; i += 2 )
1062
			for( i = 0; i < 2*width*height; i += 2 )
1063
			{
1063
			{
1064
				img[i] = (img[i] * img[i+1] + 128) >> 8;
1064
				img[i] = (img[i] * img[i+1] + 128) >> 8;
1065
			}
1065
			}
1066
			break;
1066
			break;
1067
		case 4:
1067
		case 4:
1068
			for( i = 0; i < 4*width*height; i += 4 )
1068
			for( i = 0; i < 4*width*height; i += 4 )
1069
			{
1069
			{
1070
				img[i+0] = (img[i+0] * img[i+3] + 128) >> 8;
1070
				img[i+0] = (img[i+0] * img[i+3] + 128) >> 8;
1071
				img[i+1] = (img[i+1] * img[i+3] + 128) >> 8;
1071
				img[i+1] = (img[i+1] * img[i+3] + 128) >> 8;
1072
				img[i+2] = (img[i+2] * img[i+3] + 128) >> 8;
1072
				img[i+2] = (img[i+2] * img[i+3] + 128) >> 8;
1073
			}
1073
			}
1074
			break;
1074
			break;
1075
		default:
1075
		default:
1076
			/*	no other number of channels contains alpha data	*/
1076
			/*	no other number of channels contains alpha data	*/
1077
			break;
1077
			break;
1078
		}
1078
		}
1079
	}
1079
	}
1080
	/*	if the user can't support NPOT textures, make sure we force the POT option	*/
1080
	/*	if the user can't support NPOT textures, make sure we force the POT option	*/
1081
	if( (query_NPOT_capability() == SOIL_CAPABILITY_NONE) &&
1081
	if( (query_NPOT_capability() == SOIL_CAPABILITY_NONE) &&
1082
		!(flags & SOIL_FLAG_TEXTURE_RECTANGLE) )
1082
		!(flags & SOIL_FLAG_TEXTURE_RECTANGLE) )
1083
	{
1083
	{
1084
		/*	add in the POT flag */
1084
		/*	add in the POT flag */
1085
		flags |= SOIL_FLAG_POWER_OF_TWO;
1085
		flags |= SOIL_FLAG_POWER_OF_TWO;
1086
	}
1086
	}
1087
	/*	how large of a texture can this OpenGL implementation handle?	*/
1087
	/*	how large of a texture can this OpenGL implementation handle?	*/
1088
	/*	texture_check_size_enum will be GL_MAX_TEXTURE_SIZE or SOIL_MAX_CUBE_MAP_TEXTURE_SIZE	*/
1088
	/*	texture_check_size_enum will be GL_MAX_TEXTURE_SIZE or SOIL_MAX_CUBE_MAP_TEXTURE_SIZE	*/
1089
	glGetIntegerv( texture_check_size_enum, &max_supported_size );
1089
	glGetIntegerv( texture_check_size_enum, &max_supported_size );
1090
	/*	do I need to make it a power of 2?	*/
1090
	/*	do I need to make it a power of 2?	*/
1091
	if(
1091
	if(
1092
		(flags & SOIL_FLAG_POWER_OF_TWO) ||	/*	user asked for it	*/
1092
		(flags & SOIL_FLAG_POWER_OF_TWO) ||	/*	user asked for it	*/
1093
		(flags & SOIL_FLAG_MIPMAPS) ||		/*	need it for the MIP-maps	*/
1093
		(flags & SOIL_FLAG_MIPMAPS) ||		/*	need it for the MIP-maps	*/
1094
		(width > max_supported_size) ||		/*	it's too big, (make sure it's	*/
1094
		(width > max_supported_size) ||		/*	it's too big, (make sure it's	*/
1095
		(height > max_supported_size) )		/*	2^n for later down-sampling)	*/
1095
		(height > max_supported_size) )		/*	2^n for later down-sampling)	*/
1096
	{
1096
	{
1097
		int new_width = 1;
1097
		int new_width = 1;
1098
		int new_height = 1;
1098
		int new_height = 1;
1099
		while( new_width < width )
1099
		while( new_width < width )
1100
		{
1100
		{
1101
			new_width *= 2;
1101
			new_width *= 2;
1102
		}
1102
		}
1103
		while( new_height < height )
1103
		while( new_height < height )
1104
		{
1104
		{
1105
			new_height *= 2;
1105
			new_height *= 2;
1106
		}
1106
		}
1107
		/*	still?	*/
1107
		/*	still?	*/
1108
		if( (new_width != width) || (new_height != height) )
1108
		if( (new_width != width) || (new_height != height) )
1109
		{
1109
		{
1110
			/*	yep, resize	*/
1110
			/*	yep, resize	*/
1111
			unsigned char *resampled = (unsigned char*)malloc( channels*new_width*new_height );
1111
			unsigned char *resampled = (unsigned char*)malloc( channels*new_width*new_height );
1112
			up_scale_image(
1112
			up_scale_image(
1113
					img, width, height, channels,
1113
					img, width, height, channels,
1114
					resampled, new_width, new_height );
1114
					resampled, new_width, new_height );
1115
			/*	OJO	this is for debug only!	*/
1115
			/*	OJO	this is for debug only!	*/
1116
			/*
1116
			/*
1117
			SOIL_save_image( "\\showme.bmp", SOIL_SAVE_TYPE_BMP,
1117
			SOIL_save_image( "\\showme.bmp", SOIL_SAVE_TYPE_BMP,
1118
							new_width, new_height, channels,
1118
							new_width, new_height, channels,
1119
							resampled );
1119
							resampled );
1120
			*/
1120
			*/
1121
			/*	nuke the old guy, then point it at the new guy	*/
1121
			/*	nuke the old guy, then point it at the new guy	*/
1122
			SOIL_free_image_data( img );
1122
			SOIL_free_image_data( img );
1123
			img = resampled;
1123
			img = resampled;
1124
			width = new_width;
1124
			width = new_width;
1125
			height = new_height;
1125
			height = new_height;
1126
		}
1126
		}
1127
	}
1127
	}
1128
	/*	now, if it is too large...	*/
1128
	/*	now, if it is too large...	*/
1129
	if( (width > max_supported_size) || (height > max_supported_size) )
1129
	if( (width > max_supported_size) || (height > max_supported_size) )
1130
	{
1130
	{
1131
		/*	I've already made it a power of two, so simply use the MIPmapping
1131
		/*	I've already made it a power of two, so simply use the MIPmapping
1132
			code to reduce its size to the allowable maximum.	*/
1132
			code to reduce its size to the allowable maximum.	*/
1133
		unsigned char *resampled;
1133
		unsigned char *resampled;
1134
		int reduce_block_x = 1, reduce_block_y = 1;
1134
		int reduce_block_x = 1, reduce_block_y = 1;
1135
		int new_width, new_height;
1135
		int new_width, new_height;
1136
		if( width > max_supported_size )
1136
		if( width > max_supported_size )
1137
		{
1137
		{
1138
			reduce_block_x = width / max_supported_size;
1138
			reduce_block_x = width / max_supported_size;
1139
		}
1139
		}
1140
		if( height > max_supported_size )
1140
		if( height > max_supported_size )
1141
		{
1141
		{
1142
			reduce_block_y = height / max_supported_size;
1142
			reduce_block_y = height / max_supported_size;
1143
		}
1143
		}
1144
		new_width = width / reduce_block_x;
1144
		new_width = width / reduce_block_x;
1145
		new_height = height / reduce_block_y;
1145
		new_height = height / reduce_block_y;
1146
		resampled = (unsigned char*)malloc( channels*new_width*new_height );
1146
		resampled = (unsigned char*)malloc( channels*new_width*new_height );
1147
		/*	perform the actual reduction	*/
1147
		/*	perform the actual reduction	*/
1148
		mipmap_image(	img, width, height, channels,
1148
		mipmap_image(	img, width, height, channels,
1149
						resampled, reduce_block_x, reduce_block_y );
1149
						resampled, reduce_block_x, reduce_block_y );
1150
		/*	nuke the old guy, then point it at the new guy	*/
1150
		/*	nuke the old guy, then point it at the new guy	*/
1151
		SOIL_free_image_data( img );
1151
		SOIL_free_image_data( img );
1152
		img = resampled;
1152
		img = resampled;
1153
		width = new_width;
1153
		width = new_width;
1154
		height = new_height;
1154
		height = new_height;
1155
	}
1155
	}
1156
	/*	does the user want us to use YCoCg color space?	*/
1156
	/*	does the user want us to use YCoCg color space?	*/
1157
	if( flags & SOIL_FLAG_CoCg_Y )
1157
	if( flags & SOIL_FLAG_CoCg_Y )
1158
	{
1158
	{
1159
		/*	this will only work with RGB and RGBA images */
1159
		/*	this will only work with RGB and RGBA images */
1160
		convert_RGB_to_YCoCg( img, width, height, channels );
1160
		convert_RGB_to_YCoCg( img, width, height, channels );
1161
		/*
1161
		/*
1162
		save_image_as_DDS( "CoCg_Y.dds", width, height, channels, img );
1162
		save_image_as_DDS( "CoCg_Y.dds", width, height, channels, img );
1163
		*/
1163
		*/
1164
	}
1164
	}
1165
	/*	create the OpenGL texture ID handle
1165
	/*	create the OpenGL texture ID handle
1166
    	(note: allowing a forced texture ID lets me reload a texture)	*/
1166
    	(note: allowing a forced texture ID lets me reload a texture)	*/
1167
    tex_id = reuse_texture_ID;
1167
    tex_id = reuse_texture_ID;
1168
    if( tex_id == 0 )
1168
    if( tex_id == 0 )
1169
    {
1169
    {
1170
		glGenTextures( 1, &tex_id );
1170
		glGenTextures( 1, &tex_id );
1171
    }
1171
    }
1172
	check_for_GL_errors( "glGenTextures" );
1172
	check_for_GL_errors( "glGenTextures" );
1173
	/* Note: sometimes glGenTextures fails (usually no OpenGL context)	*/
1173
	/* Note: sometimes glGenTextures fails (usually no OpenGL context)	*/
1174
	if( tex_id )
1174
	if( tex_id )
1175
	{
1175
	{
1176
		/*	and what type am I using as the internal texture format?	*/
1176
		/*	and what type am I using as the internal texture format?	*/
1177
		switch( channels )
1177
		switch( channels )
1178
		{
1178
		{
1179
		case 1:
1179
		case 1:
1180
			original_texture_format = GL_LUMINANCE;
1180
			original_texture_format = GL_LUMINANCE;
1181
			break;
1181
			break;
1182
		case 2:
1182
		case 2:
1183
			original_texture_format = GL_LUMINANCE_ALPHA;
1183
			original_texture_format = GL_LUMINANCE_ALPHA;
1184
			break;
1184
			break;
1185
		case 3:
1185
		case 3:
1186
			original_texture_format = GL_RGB;
1186
			original_texture_format = GL_RGB;
1187
			break;
1187
			break;
1188
		case 4:
1188
		case 4:
1189
			original_texture_format = GL_RGBA;
1189
			original_texture_format = GL_RGBA;
1190
			break;
1190
			break;
1191
		}
1191
		}
1192
		internal_texture_format = original_texture_format;
1192
		internal_texture_format = original_texture_format;
1193
		/*	does the user want me to, and can I, save as DXT?	*/
1193
		/*	does the user want me to, and can I, save as DXT?	*/
1194
		if( flags & SOIL_FLAG_COMPRESS_TO_DXT )
1194
		if( flags & SOIL_FLAG_COMPRESS_TO_DXT )
1195
		{
1195
		{
1196
			DXT_mode = query_DXT_capability();
1196
			DXT_mode = query_DXT_capability();
1197
			if( DXT_mode == SOIL_CAPABILITY_PRESENT )
1197
			if( DXT_mode == SOIL_CAPABILITY_PRESENT )
1198
			{
1198
			{
1199
				/*	I can use DXT, whether I compress it or OpenGL does	*/
1199
				/*	I can use DXT, whether I compress it or OpenGL does	*/
1200
				if( (channels & 1) == 1 )
1200
				if( (channels & 1) == 1 )
1201
				{
1201
				{
1202
					/*	1 or 3 channels = DXT1	*/
1202
					/*	1 or 3 channels = DXT1	*/
1203
					internal_texture_format = SOIL_RGB_S3TC_DXT1;
1203
					internal_texture_format = SOIL_RGB_S3TC_DXT1;
1204
				} else
1204
				} else
1205
				{
1205
				{
1206
					/*	2 or 4 channels = DXT5	*/
1206
					/*	2 or 4 channels = DXT5	*/
1207
					internal_texture_format = SOIL_RGBA_S3TC_DXT5;
1207
					internal_texture_format = SOIL_RGBA_S3TC_DXT5;
1208
				}
1208
				}
1209
			}
1209
			}
1210
		}
1210
		}
1211
		/*  bind an OpenGL texture ID	*/
1211
		/*  bind an OpenGL texture ID	*/
1212
		glBindTexture( opengl_texture_type, tex_id );
1212
		glBindTexture( opengl_texture_type, tex_id );
1213
		check_for_GL_errors( "glBindTexture" );
1213
		check_for_GL_errors( "glBindTexture" );
1214
		/*  upload the main image	*/
1214
		/*  upload the main image	*/
1215
		if( DXT_mode == SOIL_CAPABILITY_PRESENT )
1215
		if( DXT_mode == SOIL_CAPABILITY_PRESENT )
1216
		{
1216
		{
1217
			/*	user wants me to do the DXT conversion!	*/
1217
			/*	user wants me to do the DXT conversion!	*/
1218
			int DDS_size;
1218
			int DDS_size;
1219
			unsigned char *DDS_data = NULL;
1219
			unsigned char *DDS_data = NULL;
1220
			if( (channels & 1) == 1 )
1220
			if( (channels & 1) == 1 )
1221
			{
1221
			{
1222
				/*	RGB, use DXT1	*/
1222
				/*	RGB, use DXT1	*/
1223
				DDS_data = convert_image_to_DXT1( img, width, height, channels, &DDS_size );
1223
				DDS_data = convert_image_to_DXT1( img, width, height, channels, &DDS_size );
1224
			} else
1224
			} else
1225
			{
1225
			{
1226
				/*	RGBA, use DXT5	*/
1226
				/*	RGBA, use DXT5	*/
1227
				DDS_data = convert_image_to_DXT5( img, width, height, channels, &DDS_size );
1227
				DDS_data = convert_image_to_DXT5( img, width, height, channels, &DDS_size );
1228
			}
1228
			}
1229
			if( DDS_data )
1229
			if( DDS_data )
1230
			{
1230
			{
1231
				soilGlCompressedTexImage2D(
1231
				soilGlCompressedTexImage2D(
1232
					opengl_texture_target, 0,
1232
					opengl_texture_target, 0,
1233
					internal_texture_format, width, height, 0,
1233
					internal_texture_format, width, height, 0,
1234
					DDS_size, DDS_data );
1234
					DDS_size, DDS_data );
1235
				check_for_GL_errors( "glCompressedTexImage2D" );
1235
				check_for_GL_errors( "glCompressedTexImage2D" );
1236
				SOIL_free_image_data( DDS_data );
1236
				SOIL_free_image_data( DDS_data );
1237
				/*	printf( "Internal DXT compressor\n" );	*/
1237
				/*	printf( "Internal DXT compressor\n" );	*/
1238
			} else
1238
			} else
1239
			{
1239
			{
1240
				/*	my compression failed, try the OpenGL driver's version	*/
1240
				/*	my compression failed, try the OpenGL driver's version	*/
1241
				glTexImage2D(
1241
				glTexImage2D(
1242
					opengl_texture_target, 0,
1242
					opengl_texture_target, 0,
1243
					internal_texture_format, width, height, 0,
1243
					internal_texture_format, width, height, 0,
1244
					original_texture_format, GL_UNSIGNED_BYTE, img );
1244
					original_texture_format, GL_UNSIGNED_BYTE, img );
1245
				check_for_GL_errors( "glTexImage2D" );
1245
				check_for_GL_errors( "glTexImage2D" );
1246
				/*	printf( "OpenGL DXT compressor\n" );	*/
1246
				/*	printf( "OpenGL DXT compressor\n" );	*/
1247
			}
1247
			}
1248
		} else
1248
		} else
1249
		{
1249
		{
1250
			/*	user want OpenGL to do all the work!	*/
1250
			/*	user want OpenGL to do all the work!	*/
1251
			glTexImage2D(
1251
			glTexImage2D(
1252
				opengl_texture_target, 0,
1252
				opengl_texture_target, 0,
1253
				internal_texture_format, width, height, 0,
1253
				internal_texture_format, width, height, 0,
1254
				original_texture_format, GL_UNSIGNED_BYTE, img );
1254
				original_texture_format, GL_UNSIGNED_BYTE, img );
1255
			check_for_GL_errors( "glTexImage2D" );
1255
			check_for_GL_errors( "glTexImage2D" );
1256
			/*printf( "OpenGL DXT compressor\n" );	*/
1256
			/*printf( "OpenGL DXT compressor\n" );	*/
1257
		}
1257
		}
1258
		/*	are any MIPmaps desired?	*/
1258
		/*	are any MIPmaps desired?	*/
1259
		if( flags & SOIL_FLAG_MIPMAPS )
1259
		if( flags & SOIL_FLAG_MIPMAPS )
1260
		{
1260
		{
1261
			int MIPlevel = 1;
1261
			int MIPlevel = 1;
1262
			int MIPwidth = (width+1) / 2;
1262
			int MIPwidth = (width+1) / 2;
1263
			int MIPheight = (height+1) / 2;
1263
			int MIPheight = (height+1) / 2;
1264
			unsigned char *resampled = (unsigned char*)malloc( channels*MIPwidth*MIPheight );
1264
			unsigned char *resampled = (unsigned char*)malloc( channels*MIPwidth*MIPheight );
1265
			while( ((1<<MIPlevel) <= width) || ((1<<MIPlevel) <= height) )
1265
			while( ((1<<MIPlevel) <= width) || ((1<<MIPlevel) <= height) )
1266
			{
1266
			{
1267
				/*	do this MIPmap level	*/
1267
				/*	do this MIPmap level	*/
1268
				mipmap_image(
1268
				mipmap_image(
1269
						img, width, height, channels,
1269
						img, width, height, channels,
1270
						resampled,
1270
						resampled,
1271
						(1 << MIPlevel), (1 << MIPlevel) );
1271
						(1 << MIPlevel), (1 << MIPlevel) );
1272
				/*  upload the MIPmaps	*/
1272
				/*  upload the MIPmaps	*/
1273
				if( DXT_mode == SOIL_CAPABILITY_PRESENT )
1273
				if( DXT_mode == SOIL_CAPABILITY_PRESENT )
1274
				{
1274
				{
1275
					/*	user wants me to do the DXT conversion!	*/
1275
					/*	user wants me to do the DXT conversion!	*/
1276
					int DDS_size;
1276
					int DDS_size;
1277
					unsigned char *DDS_data = NULL;
1277
					unsigned char *DDS_data = NULL;
1278
					if( (channels & 1) == 1 )
1278
					if( (channels & 1) == 1 )
1279
					{
1279
					{
1280
						/*	RGB, use DXT1	*/
1280
						/*	RGB, use DXT1	*/
1281
						DDS_data = convert_image_to_DXT1(
1281
						DDS_data = convert_image_to_DXT1(
1282
								resampled, MIPwidth, MIPheight, channels, &DDS_size );
1282
								resampled, MIPwidth, MIPheight, channels, &DDS_size );
1283
					} else
1283
					} else
1284
					{
1284
					{
1285
						/*	RGBA, use DXT5	*/
1285
						/*	RGBA, use DXT5	*/
1286
						DDS_data = convert_image_to_DXT5(
1286
						DDS_data = convert_image_to_DXT5(
1287
								resampled, MIPwidth, MIPheight, channels, &DDS_size );
1287
								resampled, MIPwidth, MIPheight, channels, &DDS_size );
1288
					}
1288
					}
1289
					if( DDS_data )
1289
					if( DDS_data )
1290
					{
1290
					{
1291
						soilGlCompressedTexImage2D(
1291
						soilGlCompressedTexImage2D(
1292
							opengl_texture_target, MIPlevel,
1292
							opengl_texture_target, MIPlevel,
1293
							internal_texture_format, MIPwidth, MIPheight, 0,
1293
							internal_texture_format, MIPwidth, MIPheight, 0,
1294
							DDS_size, DDS_data );
1294
							DDS_size, DDS_data );
1295
						check_for_GL_errors( "glCompressedTexImage2D" );
1295
						check_for_GL_errors( "glCompressedTexImage2D" );
1296
						SOIL_free_image_data( DDS_data );
1296
						SOIL_free_image_data( DDS_data );
1297
					} else
1297
					} else
1298
					{
1298
					{
1299
						/*	my compression failed, try the OpenGL driver's version	*/
1299
						/*	my compression failed, try the OpenGL driver's version	*/
1300
						glTexImage2D(
1300
						glTexImage2D(
1301
							opengl_texture_target, MIPlevel,
1301
							opengl_texture_target, MIPlevel,
1302
							internal_texture_format, MIPwidth, MIPheight, 0,
1302
							internal_texture_format, MIPwidth, MIPheight, 0,
1303
							original_texture_format, GL_UNSIGNED_BYTE, resampled );
1303
							original_texture_format, GL_UNSIGNED_BYTE, resampled );
1304
						check_for_GL_errors( "glTexImage2D" );
1304
						check_for_GL_errors( "glTexImage2D" );
1305
					}
1305
					}
1306
				} else
1306
				} else
1307
				{
1307
				{
1308
					/*	user want OpenGL to do all the work!	*/
1308
					/*	user want OpenGL to do all the work!	*/
1309
					glTexImage2D(
1309
					glTexImage2D(
1310
						opengl_texture_target, MIPlevel,
1310
						opengl_texture_target, MIPlevel,
1311
						internal_texture_format, MIPwidth, MIPheight, 0,
1311
						internal_texture_format, MIPwidth, MIPheight, 0,
1312
						original_texture_format, GL_UNSIGNED_BYTE, resampled );
1312
						original_texture_format, GL_UNSIGNED_BYTE, resampled );
1313
					check_for_GL_errors( "glTexImage2D" );
1313
					check_for_GL_errors( "glTexImage2D" );
1314
				}
1314
				}
1315
				/*	prep for the next level	*/
1315
				/*	prep for the next level	*/
1316
				++MIPlevel;
1316
				++MIPlevel;
1317
				MIPwidth = (MIPwidth + 1) / 2;
1317
				MIPwidth = (MIPwidth + 1) / 2;
1318
				MIPheight = (MIPheight + 1) / 2;
1318
				MIPheight = (MIPheight + 1) / 2;
1319
			}
1319
			}
1320
			SOIL_free_image_data( resampled );
1320
			SOIL_free_image_data( resampled );
1321
			/*	instruct OpenGL to use the MIPmaps	*/
1321
			/*	instruct OpenGL to use the MIPmaps	*/
1322
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1322
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1323
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1323
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1324
			check_for_GL_errors( "GL_TEXTURE_MIN/MAG_FILTER" );
1324
			check_for_GL_errors( "GL_TEXTURE_MIN/MAG_FILTER" );
1325
		} else
1325
		} else
1326
		{
1326
		{
1327
			/*	instruct OpenGL _NOT_ to use the MIPmaps	*/
1327
			/*	instruct OpenGL _NOT_ to use the MIPmaps	*/
1328
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1328
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1329
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1329
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1330
			check_for_GL_errors( "GL_TEXTURE_MIN/MAG_FILTER" );
1330
			check_for_GL_errors( "GL_TEXTURE_MIN/MAG_FILTER" );
1331
		}
1331
		}
1332
		/*	does the user want clamping, or wrapping?	*/
1332
		/*	does the user want clamping, or wrapping?	*/
1333
		if( flags & SOIL_FLAG_TEXTURE_REPEATS )
1333
		if( flags & SOIL_FLAG_TEXTURE_REPEATS )
1334
		{
1334
		{
1335
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT );
1335
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT );
1336
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT );
1336
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT );
1337
			if( opengl_texture_type == SOIL_TEXTURE_CUBE_MAP )
1337
			if( opengl_texture_type == SOIL_TEXTURE_CUBE_MAP )
1338
			{
1338
			{
1339
				/*	SOIL_TEXTURE_WRAP_R is invalid if cubemaps aren't supported	*/
1339
				/*	SOIL_TEXTURE_WRAP_R is invalid if cubemaps aren't supported	*/
1340
				glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, GL_REPEAT );
1340
				glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, GL_REPEAT );
1341
			}
1341
			}
1342
			check_for_GL_errors( "GL_TEXTURE_WRAP_*" );
1342
			check_for_GL_errors( "GL_TEXTURE_WRAP_*" );
1343
		} else
1343
		} else
1344
		{
1344
		{
1345
			/*	unsigned int clamp_mode = SOIL_CLAMP_TO_EDGE;	*/
1345
			/*	unsigned int clamp_mode = SOIL_CLAMP_TO_EDGE;	*/
1346
			unsigned int clamp_mode = GL_CLAMP;
1346
			unsigned int clamp_mode = GL_CLAMP;
1347
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, clamp_mode );
1347
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, clamp_mode );
1348
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, clamp_mode );
1348
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, clamp_mode );
1349
			if( opengl_texture_type == SOIL_TEXTURE_CUBE_MAP )
1349
			if( opengl_texture_type == SOIL_TEXTURE_CUBE_MAP )
1350
			{
1350
			{
1351
				/*	SOIL_TEXTURE_WRAP_R is invalid if cubemaps aren't supported	*/
1351
				/*	SOIL_TEXTURE_WRAP_R is invalid if cubemaps aren't supported	*/
1352
				glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, clamp_mode );
1352
				glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, clamp_mode );
1353
			}
1353
			}
1354
			check_for_GL_errors( "GL_TEXTURE_WRAP_*" );
1354
			check_for_GL_errors( "GL_TEXTURE_WRAP_*" );
1355
		}
1355
		}
1356
		/*	done	*/
1356
		/*	done	*/
1357
		result_string_pointer = "Image loaded as an OpenGL texture";
1357
		result_string_pointer = "Image loaded as an OpenGL texture";
1358
	} else
1358
	} else
1359
	{
1359
	{
1360
		/*	failed	*/
1360
		/*	failed	*/
1361
		result_string_pointer = "Failed to generate an OpenGL texture name; missing OpenGL context?";
1361
		result_string_pointer = "Failed to generate an OpenGL texture name; missing OpenGL context?";
1362
	}
1362
	}
1363
	SOIL_free_image_data( img );
1363
	SOIL_free_image_data( img );
1364
	return tex_id;
1364
	return tex_id;
1365
}
1365
}
1366
 
1366
 
1367
int
1367
int
1368
	SOIL_save_screenshot
1368
	SOIL_save_screenshot
1369
	(
1369
	(
1370
		const char *filename,
1370
		const char *filename,
1371
		int image_type,
1371
		int image_type,
1372
		int x, int y,
1372
		int x, int y,
1373
		int width, int height
1373
		int width, int height
1374
	)
1374
	)
1375
{
1375
{
1376
	unsigned char *pixel_data;
1376
	unsigned char *pixel_data;
1377
	int i, j;
1377
	int i, j;
1378
	int save_result;
1378
	int save_result;
1379
 
1379
 
1380
	/*	error checks	*/
1380
	/*	error checks	*/
1381
	if( (width < 1) || (height < 1) )
1381
	if( (width < 1) || (height < 1) )
1382
	{
1382
	{
1383
		result_string_pointer = "Invalid screenshot dimensions";
1383
		result_string_pointer = "Invalid screenshot dimensions";
1384
		return 0;
1384
		return 0;
1385
	}
1385
	}
1386
	if( (x < 0) || (y < 0) )
1386
	if( (x < 0) || (y < 0) )
1387
	{
1387
	{
1388
		result_string_pointer = "Invalid screenshot location";
1388
		result_string_pointer = "Invalid screenshot location";
1389
		return 0;
1389
		return 0;
1390
	}
1390
	}
1391
	if( filename == NULL )
1391
	if( filename == NULL )
1392
	{
1392
	{
1393
		result_string_pointer = "Invalid screenshot filename";
1393
		result_string_pointer = "Invalid screenshot filename";
1394
		return 0;
1394
		return 0;
1395
	}
1395
	}
1396
 
1396
 
1397
    /*  Get the data from OpenGL	*/
1397
    /*  Get the data from OpenGL	*/
1398
    pixel_data = (unsigned char*)malloc( 3*width*height );
1398
    pixel_data = (unsigned char*)malloc( 3*width*height );
1399
    glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixel_data);
1399
    glReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixel_data);
1400
 
1400
 
1401
    /*	invert the image	*/
1401
    /*	invert the image	*/
1402
    for( j = 0; j*2 < height; ++j )
1402
    for( j = 0; j*2 < height; ++j )
1403
	{
1403
	{
1404
		int index1 = j * width * 3;
1404
		int index1 = j * width * 3;
1405
		int index2 = (height - 1 - j) * width * 3;
1405
		int index2 = (height - 1 - j) * width * 3;
1406
		for( i = width * 3; i > 0; --i )
1406
		for( i = width * 3; i > 0; --i )
1407
		{
1407
		{
1408
			unsigned char temp = pixel_data[index1];
1408
			unsigned char temp = pixel_data[index1];
1409
			pixel_data[index1] = pixel_data[index2];
1409
			pixel_data[index1] = pixel_data[index2];
1410
			pixel_data[index2] = temp;
1410
			pixel_data[index2] = temp;
1411
			++index1;
1411
			++index1;
1412
			++index2;
1412
			++index2;
1413
		}
1413
		}
1414
	}
1414
	}
1415
 
1415
 
1416
    /*	save the image	*/
1416
    /*	save the image	*/
1417
    save_result = SOIL_save_image( filename, image_type, width, height, 3, pixel_data);
1417
    save_result = SOIL_save_image( filename, image_type, width, height, 3, pixel_data);
1418
 
1418
 
1419
    /*  And free the memory	*/
1419
    /*  And free the memory	*/
1420
    SOIL_free_image_data( pixel_data );
1420
    SOIL_free_image_data( pixel_data );
1421
	return save_result;
1421
	return save_result;
1422
}
1422
}
1423
 
1423
 
1424
unsigned char*
1424
unsigned char*
1425
	SOIL_load_image
1425
	SOIL_load_image
1426
	(
1426
	(
1427
		const char *filename,
1427
		const char *filename,
1428
		int *width, int *height, int *channels,
1428
		int *width, int *height, int *channels,
1429
		int force_channels
1429
		int force_channels
1430
	)
1430
	)
1431
{
1431
{
1432
	unsigned char *result = stbi_load( filename,
1432
	unsigned char *result = stbi_load( filename,
1433
			width, height, channels, force_channels );
1433
			width, height, channels, force_channels );
1434
	if( result == NULL )
1434
	if( result == NULL )
1435
	{
1435
	{
1436
		result_string_pointer = stbi_failure_reason();
1436
		result_string_pointer = stbi_failure_reason();
1437
	} else
1437
	} else
1438
	{
1438
	{
1439
		result_string_pointer = "Image loaded";
1439
		result_string_pointer = "Image loaded";
1440
	}
1440
	}
1441
	return result;
1441
	return result;
1442
}
1442
}
1443
 
1443
 
1444
unsigned char*
1444
unsigned char*
1445
	SOIL_load_image_from_memory
1445
	SOIL_load_image_from_memory
1446
	(
1446
	(
1447
		const unsigned char *const buffer,
1447
		const unsigned char *const buffer,
1448
		int buffer_length,
1448
		int buffer_length,
1449
		int *width, int *height, int *channels,
1449
		int *width, int *height, int *channels,
1450
		int force_channels
1450
		int force_channels
1451
	)
1451
	)
1452
{
1452
{
1453
	unsigned char *result = stbi_load_from_memory(
1453
	unsigned char *result = stbi_load_from_memory(
1454
				buffer, buffer_length,
1454
				buffer, buffer_length,
1455
				width, height, channels,
1455
				width, height, channels,
1456
				force_channels );
1456
				force_channels );
1457
	if( result == NULL )
1457
	if( result == NULL )
1458
	{
1458
	{
1459
		result_string_pointer = stbi_failure_reason();
1459
		result_string_pointer = stbi_failure_reason();
1460
	} else
1460
	} else
1461
	{
1461
	{
1462
		result_string_pointer = "Image loaded from memory";
1462
		result_string_pointer = "Image loaded from memory";
1463
	}
1463
	}
1464
	return result;
1464
	return result;
1465
}
1465
}
1466
 
1466
 
1467
int
1467
int
1468
	SOIL_save_image
1468
	SOIL_save_image
1469
	(
1469
	(
1470
		const char *filename,
1470
		const char *filename,
1471
		int image_type,
1471
		int image_type,
1472
		int width, int height, int channels,
1472
		int width, int height, int channels,
1473
		const unsigned char *const data
1473
		const unsigned char *const data
1474
	)
1474
	)
1475
{
1475
{
1476
	int save_result;
1476
	int save_result;
1477
 
1477
 
1478
	/*	error check	*/
1478
	/*	error check	*/
1479
	if( (width < 1) || (height < 1) ||
1479
	if( (width < 1) || (height < 1) ||
1480
		(channels < 1) || (channels > 4) ||
1480
		(channels < 1) || (channels > 4) ||
1481
		(data == NULL) ||
1481
		(data == NULL) ||
1482
		(filename == NULL) )
1482
		(filename == NULL) )
1483
	{
1483
	{
1484
		return 0;
1484
		return 0;
1485
	}
1485
	}
1486
	if( image_type == SOIL_SAVE_TYPE_BMP )
1486
	if( image_type == SOIL_SAVE_TYPE_BMP )
1487
	{
1487
	{
1488
		save_result = stbi_write_bmp( filename,
1488
		save_result = stbi_write_bmp( filename,
1489
				width, height, channels, (void*)data );
1489
				width, height, channels, (void*)data );
1490
	} else
1490
	} else
1491
	if( image_type == SOIL_SAVE_TYPE_TGA )
1491
	if( image_type == SOIL_SAVE_TYPE_TGA )
1492
	{
1492
	{
1493
		save_result = stbi_write_tga( filename,
1493
		save_result = stbi_write_tga( filename,
1494
				width, height, channels, (void*)data );
1494
				width, height, channels, (void*)data );
1495
	} else
1495
	} else
1496
	if( image_type == SOIL_SAVE_TYPE_DDS )
1496
	if( image_type == SOIL_SAVE_TYPE_DDS )
1497
	{
1497
	{
1498
		save_result = save_image_as_DDS( filename,
1498
		save_result = save_image_as_DDS( filename,
1499
				width, height, channels, (const unsigned char *const)data );
1499
				width, height, channels, (const unsigned char *const)data );
1500
	} else
1500
	} else
1501
	{
1501
	{
1502
		save_result = 0;
1502
		save_result = 0;
1503
	}
1503
	}
1504
	if( save_result == 0 )
1504
	if( save_result == 0 )
1505
	{
1505
	{
1506
		result_string_pointer = "Saving the image failed";
1506
		result_string_pointer = "Saving the image failed";
1507
	} else
1507
	} else
1508
	{
1508
	{
1509
		result_string_pointer = "Image saved";
1509
		result_string_pointer = "Image saved";
1510
	}
1510
	}
1511
	return save_result;
1511
	return save_result;
1512
}
1512
}
1513
 
1513
 
1514
void
1514
void
1515
	SOIL_free_image_data
1515
	SOIL_free_image_data
1516
	(
1516
	(
1517
		unsigned char *img_data
1517
		unsigned char *img_data
1518
	)
1518
	)
1519
{
1519
{
1520
	free( (void*)img_data );
1520
	free( (void*)img_data );
1521
}
1521
}
1522
 
1522
 
1523
const char*
1523
const char*
1524
	SOIL_last_result
1524
	SOIL_last_result
1525
	(
1525
	(
1526
		void
1526
		void
1527
	)
1527
	)
1528
{
1528
{
1529
	return result_string_pointer;
1529
	return result_string_pointer;
1530
}
1530
}
1531
 
1531
 
1532
unsigned int SOIL_direct_load_DDS_from_memory(
1532
unsigned int SOIL_direct_load_DDS_from_memory(
1533
		const unsigned char *const buffer,
1533
		const unsigned char *const buffer,
1534
		int buffer_length,
1534
		int buffer_length,
1535
		unsigned int reuse_texture_ID,
1535
		unsigned int reuse_texture_ID,
1536
		int flags,
1536
		int flags,
1537
		int loading_as_cubemap )
1537
		int loading_as_cubemap )
1538
{
1538
{
1539
	/*	variables	*/
1539
	/*	variables	*/
1540
	DDS_header header;
1540
	DDS_header header;
1541
	unsigned int buffer_index = 0;
1541
	unsigned int buffer_index = 0;
1542
	unsigned int tex_ID = 0;
1542
	unsigned int tex_ID = 0;
1543
	/*	file reading variables	*/
1543
	/*	file reading variables	*/
1544
	unsigned int S3TC_type = 0;
1544
	unsigned int S3TC_type = 0;
1545
	unsigned char *DDS_data;
1545
	unsigned char *DDS_data;
1546
	unsigned int DDS_main_size;
1546
	unsigned int DDS_main_size;
1547
	unsigned int DDS_full_size;
1547
	unsigned int DDS_full_size;
1548
	unsigned int width, height;
1548
	unsigned int width, height;
1549
	int mipmaps, cubemap, uncompressed, block_size = 16;
1549
	int mipmaps, cubemap, uncompressed, block_size = 16;
1550
	unsigned int flag;
1550
	unsigned int flag;
1551
	unsigned int cf_target, ogl_target_start, ogl_target_end;
1551
	unsigned int cf_target, ogl_target_start, ogl_target_end;
1552
	unsigned int opengl_texture_type;
1552
	unsigned int opengl_texture_type;
1553
	int i;
1553
	int i;
1554
	/*	1st off, does the filename even exist?	*/
1554
	/*	1st off, does the filename even exist?	*/
1555
	if( NULL == buffer )
1555
	if( NULL == buffer )
1556
	{
1556
	{
1557
		/*	we can't do it!	*/
1557
		/*	we can't do it!	*/
1558
		result_string_pointer = "NULL buffer";
1558
		result_string_pointer = "NULL buffer";
1559
		return 0;
1559
		return 0;
1560
	}
1560
	}
1561
	if( buffer_length < sizeof( DDS_header ) )
1561
	if( buffer_length < sizeof( DDS_header ) )
1562
	{
1562
	{
1563
		/*	we can't do it!	*/
1563
		/*	we can't do it!	*/
1564
		result_string_pointer = "DDS file was too small to contain the DDS header";
1564
		result_string_pointer = "DDS file was too small to contain the DDS header";
1565
		return 0;
1565
		return 0;
1566
	}
1566
	}
1567
	/*	try reading in the header	*/
1567
	/*	try reading in the header	*/
1568
	memcpy ( (void*)(&header), (const void *)buffer, sizeof( DDS_header ) );
1568
	memcpy ( (void*)(&header), (const void *)buffer, sizeof( DDS_header ) );
1569
	buffer_index = sizeof( DDS_header );
1569
	buffer_index = sizeof( DDS_header );
1570
	/*	guilty until proven innocent	*/
1570
	/*	guilty until proven innocent	*/
1571
	result_string_pointer = "Failed to read a known DDS header";
1571
	result_string_pointer = "Failed to read a known DDS header";
1572
	/*	validate the header (warning, "goto"'s ahead, shield your eyes!!)	*/
1572
	/*	validate the header (warning, "goto"'s ahead, shield your eyes!!)	*/
1573
	flag = ('D'<<0)|('D'<<8)|('S'<<16)|(' '<<24);
1573
	flag = ('D'<<0)|('D'<<8)|('S'<<16)|(' '<<24);
1574
	if( header.dwMagic != flag ) {goto quick_exit;}
1574
	if( header.dwMagic != flag ) {goto quick_exit;}
1575
	if( header.dwSize != 124 ) {goto quick_exit;}
1575
	if( header.dwSize != 124 ) {goto quick_exit;}
1576
	/*	I need all of these	*/
1576
	/*	I need all of these	*/
1577
	flag = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1577
	flag = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1578
	if( (header.dwFlags & flag) != flag ) {goto quick_exit;}
1578
	if( (header.dwFlags & flag) != flag ) {goto quick_exit;}
1579
	/*	According to the MSDN spec, the dwFlags should contain
1579
	/*	According to the MSDN spec, the dwFlags should contain
1580
		DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
1580
		DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
1581
		uncompressed.  Some DDS writers do not conform to the
1581
		uncompressed.  Some DDS writers do not conform to the
1582
		spec, so I need to make my reader more tolerant	*/
1582
		spec, so I need to make my reader more tolerant	*/
1583
	/*	I need one of these	*/
1583
	/*	I need one of these	*/
1584
	flag = DDPF_FOURCC | DDPF_RGB;
1584
	flag = DDPF_FOURCC | DDPF_RGB;
1585
	if( (header.sPixelFormat.dwFlags & flag) == 0 ) {goto quick_exit;}
1585
	if( (header.sPixelFormat.dwFlags & flag) == 0 ) {goto quick_exit;}
1586
	if( header.sPixelFormat.dwSize != 32 ) {goto quick_exit;}
1586
	if( header.sPixelFormat.dwSize != 32 ) {goto quick_exit;}
1587
	if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) {goto quick_exit;}
1587
	if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) {goto quick_exit;}
1588
	/*	make sure it is a type we can upload	*/
1588
	/*	make sure it is a type we can upload	*/
1589
	if( (header.sPixelFormat.dwFlags & DDPF_FOURCC) &&
1589
	if( (header.sPixelFormat.dwFlags & DDPF_FOURCC) &&
1590
		!(
1590
		!(
1591
		(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) ||
1591
		(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))) ||
1592
		(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('3'<<24))) ||
1592
		(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('3'<<24))) ||
1593
		(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('5'<<24)))
1593
		(header.sPixelFormat.dwFourCC == (('D'<<0)|('X'<<8)|('T'<<16)|('5'<<24)))
1594
		) )
1594
		) )
1595
	{
1595
	{
1596
		goto quick_exit;
1596
		goto quick_exit;
1597
	}
1597
	}
1598
	/*	OK, validated the header, let's load the image data	*/
1598
	/*	OK, validated the header, let's load the image data	*/
1599
	result_string_pointer = "DDS header loaded and validated";
1599
	result_string_pointer = "DDS header loaded and validated";
1600
	width = header.dwWidth;
1600
	width = header.dwWidth;
1601
	height = header.dwHeight;
1601
	height = header.dwHeight;
1602
	uncompressed = 1 - (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
1602
	uncompressed = 1 - (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
1603
	cubemap = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
1603
	cubemap = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
1604
	if( uncompressed )
1604
	if( uncompressed )
1605
	{
1605
	{
1606
		S3TC_type = GL_RGB;
1606
		S3TC_type = GL_RGB;
1607
		block_size = 3;
1607
		block_size = 3;
1608
		if( header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS )
1608
		if( header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS )
1609
		{
1609
		{
1610
			S3TC_type = GL_RGBA;
1610
			S3TC_type = GL_RGBA;
1611
			block_size = 4;
1611
			block_size = 4;
1612
		}
1612
		}
1613
		DDS_main_size = width * height * block_size;
1613
		DDS_main_size = width * height * block_size;
1614
	} else
1614
	} else
1615
	{
1615
	{
1616
		/*	can we even handle direct uploading to OpenGL DXT compressed images?	*/
1616
		/*	can we even handle direct uploading to OpenGL DXT compressed images?	*/
1617
		if( query_DXT_capability() != SOIL_CAPABILITY_PRESENT )
1617
		if( query_DXT_capability() != SOIL_CAPABILITY_PRESENT )
1618
		{
1618
		{
1619
			/*	we can't do it!	*/
1619
			/*	we can't do it!	*/
1620
			result_string_pointer = "Direct upload of S3TC images not supported by the OpenGL driver";
1620
			result_string_pointer = "Direct upload of S3TC images not supported by the OpenGL driver";
1621
			return 0;
1621
			return 0;
1622
		}
1622
		}
1623
		/*	well, we know it is DXT1/3/5, because we checked above	*/
1623
		/*	well, we know it is DXT1/3/5, because we checked above	*/
1624
		switch( (header.sPixelFormat.dwFourCC >> 24) - '0' )
1624
		switch( (header.sPixelFormat.dwFourCC >> 24) - '0' )
1625
		{
1625
		{
1626
		case 1:
1626
		case 1:
1627
			S3TC_type = SOIL_RGBA_S3TC_DXT1;
1627
			S3TC_type = SOIL_RGBA_S3TC_DXT1;
1628
			block_size = 8;
1628
			block_size = 8;
1629
			break;
1629
			break;
1630
		case 3:
1630
		case 3:
1631
			S3TC_type = SOIL_RGBA_S3TC_DXT3;
1631
			S3TC_type = SOIL_RGBA_S3TC_DXT3;
1632
			block_size = 16;
1632
			block_size = 16;
1633
			break;
1633
			break;
1634
		case 5:
1634
		case 5:
1635
			S3TC_type = SOIL_RGBA_S3TC_DXT5;
1635
			S3TC_type = SOIL_RGBA_S3TC_DXT5;
1636
			block_size = 16;
1636
			block_size = 16;
1637
			break;
1637
			break;
1638
		}
1638
		}
1639
		DDS_main_size = ((width+3)>>2)*((height+3)>>2)*block_size;
1639
		DDS_main_size = ((width+3)>>2)*((height+3)>>2)*block_size;
1640
	}
1640
	}
1641
	if( cubemap )
1641
	if( cubemap )
1642
	{
1642
	{
1643
		/* does the user want a cubemap?	*/
1643
		/* does the user want a cubemap?	*/
1644
		if( !loading_as_cubemap )
1644
		if( !loading_as_cubemap )
1645
		{
1645
		{
1646
			/*	we can't do it!	*/
1646
			/*	we can't do it!	*/
1647
			result_string_pointer = "DDS image was a cubemap";
1647
			result_string_pointer = "DDS image was a cubemap";
1648
			return 0;
1648
			return 0;
1649
		}
1649
		}
1650
		/*	can we even handle cubemaps with the OpenGL driver?	*/
1650
		/*	can we even handle cubemaps with the OpenGL driver?	*/
1651
		if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
1651
		if( query_cubemap_capability() != SOIL_CAPABILITY_PRESENT )
1652
		{
1652
		{
1653
			/*	we can't do it!	*/
1653
			/*	we can't do it!	*/
1654
			result_string_pointer = "Direct upload of cubemap images not supported by the OpenGL driver";
1654
			result_string_pointer = "Direct upload of cubemap images not supported by the OpenGL driver";
1655
			return 0;
1655
			return 0;
1656
		}
1656
		}
1657
		ogl_target_start = SOIL_TEXTURE_CUBE_MAP_POSITIVE_X;
1657
		ogl_target_start = SOIL_TEXTURE_CUBE_MAP_POSITIVE_X;
1658
		ogl_target_end =   SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1658
		ogl_target_end =   SOIL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1659
		opengl_texture_type = SOIL_TEXTURE_CUBE_MAP;
1659
		opengl_texture_type = SOIL_TEXTURE_CUBE_MAP;
1660
	} else
1660
	} else
1661
	{
1661
	{
1662
		/* does the user want a non-cubemap?	*/
1662
		/* does the user want a non-cubemap?	*/
1663
		if( loading_as_cubemap )
1663
		if( loading_as_cubemap )
1664
		{
1664
		{
1665
			/*	we can't do it!	*/
1665
			/*	we can't do it!	*/
1666
			result_string_pointer = "DDS image was not a cubemap";
1666
			result_string_pointer = "DDS image was not a cubemap";
1667
			return 0;
1667
			return 0;
1668
		}
1668
		}
1669
		ogl_target_start = GL_TEXTURE_2D;
1669
		ogl_target_start = GL_TEXTURE_2D;
1670
		ogl_target_end =   GL_TEXTURE_2D;
1670
		ogl_target_end =   GL_TEXTURE_2D;
1671
		opengl_texture_type = GL_TEXTURE_2D;
1671
		opengl_texture_type = GL_TEXTURE_2D;
1672
	}
1672
	}
1673
	if( (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1) )
1673
	if( (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1) )
1674
	{
1674
	{
1675
		int shift_offset;
1675
		int shift_offset;
1676
		mipmaps = header.dwMipMapCount - 1;
1676
		mipmaps = header.dwMipMapCount - 1;
1677
		DDS_full_size = DDS_main_size;
1677
		DDS_full_size = DDS_main_size;
1678
		if( uncompressed )
1678
		if( uncompressed )
1679
		{
1679
		{
1680
			/*	uncompressed DDS, simple MIPmap size calculation	*/
1680
			/*	uncompressed DDS, simple MIPmap size calculation	*/
1681
			shift_offset = 0;
1681
			shift_offset = 0;
1682
		} else
1682
		} else
1683
		{
1683
		{
1684
			/*	compressed DDS, MIPmap size calculation is block based	*/
1684
			/*	compressed DDS, MIPmap size calculation is block based	*/
1685
			shift_offset = 2;
1685
			shift_offset = 2;
1686
		}
1686
		}
1687
		for( i = 1; i <= mipmaps; ++ i )
1687
		for( i = 1; i <= mipmaps; ++ i )
1688
		{
1688
		{
1689
			int w, h;
1689
			int w, h;
1690
			w = width >> (shift_offset + i);
1690
			w = width >> (shift_offset + i);
1691
			h = height >> (shift_offset + i);
1691
			h = height >> (shift_offset + i);
1692
			if( w < 1 )
1692
			if( w < 1 )
1693
			{
1693
			{
1694
				w = 1;
1694
				w = 1;
1695
			}
1695
			}
1696
			if( h < 1 )
1696
			if( h < 1 )
1697
			{
1697
			{
1698
				h = 1;
1698
				h = 1;
1699
			}
1699
			}
1700
			DDS_full_size += w*h*block_size;
1700
			DDS_full_size += w*h*block_size;
1701
		}
1701
		}
1702
	} else
1702
	} else
1703
	{
1703
	{
1704
		mipmaps = 0;
1704
		mipmaps = 0;
1705
		DDS_full_size = DDS_main_size;
1705
		DDS_full_size = DDS_main_size;
1706
	}
1706
	}
1707
	DDS_data = (unsigned char*)malloc( DDS_full_size );
1707
	DDS_data = (unsigned char*)malloc( DDS_full_size );
1708
	/*	got the image data RAM, create or use an existing OpenGL texture handle	*/
1708
	/*	got the image data RAM, create or use an existing OpenGL texture handle	*/
1709
	tex_ID = reuse_texture_ID;
1709
	tex_ID = reuse_texture_ID;
1710
	if( tex_ID == 0 )
1710
	if( tex_ID == 0 )
1711
	{
1711
	{
1712
		glGenTextures( 1, &tex_ID );
1712
		glGenTextures( 1, &tex_ID );
1713
	}
1713
	}
1714
	/*  bind an OpenGL texture ID	*/
1714
	/*  bind an OpenGL texture ID	*/
1715
	glBindTexture( opengl_texture_type, tex_ID );
1715
	glBindTexture( opengl_texture_type, tex_ID );
1716
	/*	do this for each face of the cubemap!	*/
1716
	/*	do this for each face of the cubemap!	*/
1717
	for( cf_target = ogl_target_start; cf_target <= ogl_target_end; ++cf_target )
1717
	for( cf_target = ogl_target_start; cf_target <= ogl_target_end; ++cf_target )
1718
	{
1718
	{
1719
		if( buffer_index + DDS_full_size <= buffer_length )
1719
		if( buffer_index + DDS_full_size <= (unsigned int)buffer_length )
1720
		{
1720
		{
1721
			unsigned int byte_offset = DDS_main_size;
1721
			unsigned int byte_offset = DDS_main_size;
1722
			memcpy( (void*)DDS_data, (const void*)(&buffer[buffer_index]), DDS_full_size );
1722
			memcpy( (void*)DDS_data, (const void*)(&buffer[buffer_index]), DDS_full_size );
1723
			buffer_index += DDS_full_size;
1723
			buffer_index += DDS_full_size;
1724
			/*	upload the main chunk	*/
1724
			/*	upload the main chunk	*/
1725
			if( uncompressed )
1725
			if( uncompressed )
1726
			{
1726
			{
1727
				/*	and remember, DXT uncompressed uses BGR(A),
1727
				/*	and remember, DXT uncompressed uses BGR(A),
1728
					so swap to RGB(A) for ALL MIPmap levels	*/
1728
					so swap to RGB(A) for ALL MIPmap levels	*/
1729
				for( i = 0; i < DDS_full_size; i += block_size )
1729
				for( i = 0; i < (int)DDS_full_size; i += block_size )
1730
				{
1730
				{
1731
					unsigned char temp = DDS_data[i];
1731
					unsigned char temp = DDS_data[i];
1732
					DDS_data[i] = DDS_data[i+2];
1732
					DDS_data[i] = DDS_data[i+2];
1733
					DDS_data[i+2] = temp;
1733
					DDS_data[i+2] = temp;
1734
				}
1734
				}
1735
				glTexImage2D(
1735
				glTexImage2D(
1736
					cf_target, 0,
1736
					cf_target, 0,
1737
					S3TC_type, width, height, 0,
1737
					S3TC_type, width, height, 0,
1738
					S3TC_type, GL_UNSIGNED_BYTE, DDS_data );
1738
					S3TC_type, GL_UNSIGNED_BYTE, DDS_data );
1739
			} else
1739
			} else
1740
			{
1740
			{
1741
				soilGlCompressedTexImage2D(
1741
				soilGlCompressedTexImage2D(
1742
					cf_target, 0,
1742
					cf_target, 0,
1743
					S3TC_type, width, height, 0,
1743
					S3TC_type, width, height, 0,
1744
					DDS_main_size, DDS_data );
1744
					DDS_main_size, DDS_data );
1745
			}
1745
			}
1746
			/*	upload the mipmaps, if we have them	*/
1746
			/*	upload the mipmaps, if we have them	*/
1747
			for( i = 1; i <= mipmaps; ++i )
1747
			for( i = 1; i <= mipmaps; ++i )
1748
			{
1748
			{
1749
				int w, h, mip_size;
1749
				int w, h, mip_size;
1750
				w = width >> i;
1750
				w = width >> i;
1751
				h = height >> i;
1751
				h = height >> i;
1752
				if( w < 1 )
1752
				if( w < 1 )
1753
				{
1753
				{
1754
					w = 1;
1754
					w = 1;
1755
				}
1755
				}
1756
				if( h < 1 )
1756
				if( h < 1 )
1757
				{
1757
				{
1758
					h = 1;
1758
					h = 1;
1759
				}
1759
				}
1760
				/*	upload this mipmap	*/
1760
				/*	upload this mipmap	*/
1761
				if( uncompressed )
1761
				if( uncompressed )
1762
				{
1762
				{
1763
					mip_size = w*h*block_size;
1763
					mip_size = w*h*block_size;
1764
					glTexImage2D(
1764
					glTexImage2D(
1765
						cf_target, i,
1765
						cf_target, i,
1766
						S3TC_type, w, h, 0,
1766
						S3TC_type, w, h, 0,
1767
						S3TC_type, GL_UNSIGNED_BYTE, &DDS_data[byte_offset] );
1767
						S3TC_type, GL_UNSIGNED_BYTE, &DDS_data[byte_offset] );
1768
				} else
1768
				} else
1769
				{
1769
				{
1770
					mip_size = ((w+3)/4)*((h+3)/4)*block_size;
1770
					mip_size = ((w+3)/4)*((h+3)/4)*block_size;
1771
					soilGlCompressedTexImage2D(
1771
					soilGlCompressedTexImage2D(
1772
						cf_target, i,
1772
						cf_target, i,
1773
						S3TC_type, w, h, 0,
1773
						S3TC_type, w, h, 0,
1774
						mip_size, &DDS_data[byte_offset] );
1774
						mip_size, &DDS_data[byte_offset] );
1775
				}
1775
				}
1776
				/*	and move to the next mipmap	*/
1776
				/*	and move to the next mipmap	*/
1777
				byte_offset += mip_size;
1777
				byte_offset += mip_size;
1778
			}
1778
			}
1779
			/*	it worked!	*/
1779
			/*	it worked!	*/
1780
			result_string_pointer = "DDS file loaded";
1780
			result_string_pointer = "DDS file loaded";
1781
		} else
1781
		} else
1782
		{
1782
		{
1783
			glDeleteTextures( 1, & tex_ID );
1783
			glDeleteTextures( 1, & tex_ID );
1784
			tex_ID = 0;
1784
			tex_ID = 0;
1785
			cf_target = ogl_target_end + 1;
1785
			cf_target = ogl_target_end + 1;
1786
			result_string_pointer = "DDS file was too small for expected image data";
1786
			result_string_pointer = "DDS file was too small for expected image data";
1787
		}
1787
		}
1788
	}/* end reading each face */
1788
	}/* end reading each face */
1789
	SOIL_free_image_data( DDS_data );
1789
	SOIL_free_image_data( DDS_data );
1790
	if( tex_ID )
1790
	if( tex_ID )
1791
	{
1791
	{
1792
		/*	did I have MIPmaps?	*/
1792
		/*	did I have MIPmaps?	*/
1793
		if( mipmaps > 0 )
1793
		if( mipmaps > 0 )
1794
		{
1794
		{
1795
			/*	instruct OpenGL to use the MIPmaps	*/
1795
			/*	instruct OpenGL to use the MIPmaps	*/
1796
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1796
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1797
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1797
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
1798
		} else
1798
		} else
1799
		{
1799
		{
1800
			/*	instruct OpenGL _NOT_ to use the MIPmaps	*/
1800
			/*	instruct OpenGL _NOT_ to use the MIPmaps	*/
1801
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1801
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1802
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1802
			glTexParameteri( opengl_texture_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1803
		}
1803
		}
1804
		/*	does the user want clamping, or wrapping?	*/
1804
		/*	does the user want clamping, or wrapping?	*/
1805
		if( flags & SOIL_FLAG_TEXTURE_REPEATS )
1805
		if( flags & SOIL_FLAG_TEXTURE_REPEATS )
1806
		{
1806
		{
1807
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT );
1807
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, GL_REPEAT );
1808
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT );
1808
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, GL_REPEAT );
1809
			glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, GL_REPEAT );
1809
			glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, GL_REPEAT );
1810
		} else
1810
		} else
1811
		{
1811
		{
1812
			/*	unsigned int clamp_mode = SOIL_CLAMP_TO_EDGE;	*/
1812
			/*	unsigned int clamp_mode = SOIL_CLAMP_TO_EDGE;	*/
1813
			unsigned int clamp_mode = GL_CLAMP;
1813
			unsigned int clamp_mode = GL_CLAMP;
1814
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, clamp_mode );
1814
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_S, clamp_mode );
1815
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, clamp_mode );
1815
			glTexParameteri( opengl_texture_type, GL_TEXTURE_WRAP_T, clamp_mode );
1816
			glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, clamp_mode );
1816
			glTexParameteri( opengl_texture_type, SOIL_TEXTURE_WRAP_R, clamp_mode );
1817
		}
1817
		}
1818
	}
1818
	}
1819
 
1819
 
1820
quick_exit:
1820
quick_exit:
1821
	/*	report success or failure	*/
1821
	/*	report success or failure	*/
1822
	return tex_ID;
1822
	return tex_ID;
1823
}
1823
}
1824
 
1824
 
1825
unsigned int SOIL_direct_load_DDS(
1825
unsigned int SOIL_direct_load_DDS(
1826
		const char *filename,
1826
		const char *filename,
1827
		unsigned int reuse_texture_ID,
1827
		unsigned int reuse_texture_ID,
1828
		int flags,
1828
		int flags,
1829
		int loading_as_cubemap )
1829
		int loading_as_cubemap )
1830
{
1830
{
1831
	FILE *f;
1831
	FILE *f;
1832
	unsigned char *buffer;
1832
	unsigned char *buffer;
1833
	size_t buffer_length, bytes_read;
1833
	size_t buffer_length, bytes_read;
1834
	unsigned int tex_ID = 0;
1834
	unsigned int tex_ID = 0;
1835
	/*	error checks	*/
1835
	/*	error checks	*/
1836
	if( NULL == filename )
1836
	if( NULL == filename )
1837
	{
1837
	{
1838
		result_string_pointer = "NULL filename";
1838
		result_string_pointer = "NULL filename";
1839
		return 0;
1839
		return 0;
1840
	}
1840
	}
1841
	f = fopen( filename, "rb" );
1841
	f = fopen( filename, "rb" );
1842
	if( NULL == f )
1842
	if( NULL == f )
1843
	{
1843
	{
1844
		/*	the file doesn't seem to exist (or be open-able)	*/
1844
		/*	the file doesn't seem to exist (or be open-able)	*/
1845
		result_string_pointer = "Can not find DDS file";
1845
		result_string_pointer = "Can not find DDS file";
1846
		return 0;
1846
		return 0;
1847
	}
1847
	}
1848
	fseek( f, 0, SEEK_END );
1848
	fseek( f, 0, SEEK_END );
1849
	buffer_length = ftell( f );
1849
	buffer_length = ftell( f );
1850
	fseek( f, 0, SEEK_SET );
1850
	fseek( f, 0, SEEK_SET );
1851
	buffer = (unsigned char *) malloc( buffer_length );
1851
	buffer = (unsigned char *) malloc( buffer_length );
1852
	if( NULL == buffer )
1852
	if( NULL == buffer )
1853
	{
1853
	{
1854
		result_string_pointer = "malloc failed";
1854
		result_string_pointer = "malloc failed";
1855
		fclose( f );
1855
		fclose( f );
1856
		return 0;
1856
		return 0;
1857
	}
1857
	}
1858
	bytes_read = fread( (void*)buffer, 1, buffer_length, f );
1858
	bytes_read = fread( (void*)buffer, 1, buffer_length, f );
1859
	fclose( f );
1859
	fclose( f );
1860
	if( bytes_read < buffer_length )
1860
	if( bytes_read < buffer_length )
1861
	{
1861
	{
1862
		/*	huh?	*/
1862
		/*	huh?	*/
1863
		buffer_length = bytes_read;
1863
		buffer_length = bytes_read;
1864
	}
1864
	}
1865
	/*	now try to do the loading	*/
1865
	/*	now try to do the loading	*/
1866
	tex_ID = SOIL_direct_load_DDS_from_memory(
1866
	tex_ID = SOIL_direct_load_DDS_from_memory(
1867
		(const unsigned char *const)buffer, buffer_length,
1867
		(const unsigned char *const)buffer, buffer_length,
1868
		reuse_texture_ID, flags, loading_as_cubemap );
1868
		reuse_texture_ID, flags, loading_as_cubemap );
1869
	SOIL_free_image_data( buffer );
1869
	SOIL_free_image_data( buffer );
1870
	return tex_ID;
1870
	return tex_ID;
1871
}
1871
}
1872
 
1872
 
1873
int query_NPOT_capability( void )
1873
int query_NPOT_capability( void )
1874
{
1874
{
1875
	/*	check for the capability	*/
1875
	/*	check for the capability	*/
1876
	if( has_NPOT_capability == SOIL_CAPABILITY_UNKNOWN )
1876
	if( has_NPOT_capability == SOIL_CAPABILITY_UNKNOWN )
1877
	{
1877
	{
1878
		/*	we haven't yet checked for the capability, do so	*/
1878
		/*	we haven't yet checked for the capability, do so	*/
1879
		if(
1879
		if(
1880
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1880
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1881
				"GL_ARB_texture_non_power_of_two" ) )
1881
				"GL_ARB_texture_non_power_of_two" ) )
1882
			)
1882
			)
1883
		{
1883
		{
1884
			/*	not there, flag the failure	*/
1884
			/*	not there, flag the failure	*/
1885
			has_NPOT_capability = SOIL_CAPABILITY_NONE;
1885
			has_NPOT_capability = SOIL_CAPABILITY_NONE;
1886
		} else
1886
		} else
1887
		{
1887
		{
1888
			/*	it's there!	*/
1888
			/*	it's there!	*/
1889
			has_NPOT_capability = SOIL_CAPABILITY_PRESENT;
1889
			has_NPOT_capability = SOIL_CAPABILITY_PRESENT;
1890
		}
1890
		}
1891
	}
1891
	}
1892
	/*	let the user know if we can do non-power-of-two textures or not	*/
1892
	/*	let the user know if we can do non-power-of-two textures or not	*/
1893
	return has_NPOT_capability;
1893
	return has_NPOT_capability;
1894
}
1894
}
1895
 
1895
 
1896
int query_tex_rectangle_capability( void )
1896
int query_tex_rectangle_capability( void )
1897
{
1897
{
1898
	/*	check for the capability	*/
1898
	/*	check for the capability	*/
1899
	if( has_tex_rectangle_capability == SOIL_CAPABILITY_UNKNOWN )
1899
	if( has_tex_rectangle_capability == SOIL_CAPABILITY_UNKNOWN )
1900
	{
1900
	{
1901
		/*	we haven't yet checked for the capability, do so	*/
1901
		/*	we haven't yet checked for the capability, do so	*/
1902
		if(
1902
		if(
1903
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1903
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1904
				"GL_ARB_texture_rectangle" ) )
1904
				"GL_ARB_texture_rectangle" ) )
1905
		&&
1905
		&&
1906
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1906
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1907
				"GL_EXT_texture_rectangle" ) )
1907
				"GL_EXT_texture_rectangle" ) )
1908
		&&
1908
		&&
1909
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1909
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1910
				"GL_NV_texture_rectangle" ) )
1910
				"GL_NV_texture_rectangle" ) )
1911
			)
1911
			)
1912
		{
1912
		{
1913
			/*	not there, flag the failure	*/
1913
			/*	not there, flag the failure	*/
1914
			has_tex_rectangle_capability = SOIL_CAPABILITY_NONE;
1914
			has_tex_rectangle_capability = SOIL_CAPABILITY_NONE;
1915
		} else
1915
		} else
1916
		{
1916
		{
1917
			/*	it's there!	*/
1917
			/*	it's there!	*/
1918
			has_tex_rectangle_capability = SOIL_CAPABILITY_PRESENT;
1918
			has_tex_rectangle_capability = SOIL_CAPABILITY_PRESENT;
1919
		}
1919
		}
1920
	}
1920
	}
1921
	/*	let the user know if we can do texture rectangles or not	*/
1921
	/*	let the user know if we can do texture rectangles or not	*/
1922
	return has_tex_rectangle_capability;
1922
	return has_tex_rectangle_capability;
1923
}
1923
}
1924
 
1924
 
1925
int query_cubemap_capability( void )
1925
int query_cubemap_capability( void )
1926
{
1926
{
1927
	/*	check for the capability	*/
1927
	/*	check for the capability	*/
1928
	if( has_cubemap_capability == SOIL_CAPABILITY_UNKNOWN )
1928
	if( has_cubemap_capability == SOIL_CAPABILITY_UNKNOWN )
1929
	{
1929
	{
1930
		/*	we haven't yet checked for the capability, do so	*/
1930
		/*	we haven't yet checked for the capability, do so	*/
1931
		if(
1931
		if(
1932
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1932
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1933
				"GL_ARB_texture_cube_map" ) )
1933
				"GL_ARB_texture_cube_map" ) )
1934
		&&
1934
		&&
1935
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1935
			(NULL == strstr( (char const*)glGetString( GL_EXTENSIONS ),
1936
				"GL_EXT_texture_cube_map" ) )
1936
				"GL_EXT_texture_cube_map" ) )
1937
			)
1937
			)
1938
		{
1938
		{
1939
			/*	not there, flag the failure	*/
1939
			/*	not there, flag the failure	*/
1940
			has_cubemap_capability = SOIL_CAPABILITY_NONE;
1940
			has_cubemap_capability = SOIL_CAPABILITY_NONE;
1941
		} else
1941
		} else
1942
		{
1942
		{
1943
			/*	it's there!	*/
1943
			/*	it's there!	*/
1944
			has_cubemap_capability = SOIL_CAPABILITY_PRESENT;
1944
			has_cubemap_capability = SOIL_CAPABILITY_PRESENT;
1945
		}
1945
		}
1946
	}
1946
	}
1947
	/*	let the user know if we can do cubemaps or not	*/
1947
	/*	let the user know if we can do cubemaps or not	*/
1948
	return has_cubemap_capability;
1948
	return has_cubemap_capability;
1949
}
1949
}
1950
 
1950
 
1951
int query_DXT_capability( void )
1951
int query_DXT_capability( void )
1952
{
1952
{
1953
	/*	check for the capability	*/
1953
	/*	check for the capability	*/
1954
	if( has_DXT_capability == SOIL_CAPABILITY_UNKNOWN )
1954
	if( has_DXT_capability == SOIL_CAPABILITY_UNKNOWN )
1955
	{
1955
	{
1956
		/*	we haven't yet checked for the capability, do so	*/
1956
		/*	we haven't yet checked for the capability, do so	*/
1957
		if( NULL == strstr(
1957
		if( NULL == strstr(
1958
				(char const*)glGetString( GL_EXTENSIONS ),
1958
				(char const*)glGetString( GL_EXTENSIONS ),
1959
				"GL_EXT_texture_compression_s3tc" ) )
1959
				"GL_EXT_texture_compression_s3tc" ) )
1960
		{
1960
		{
1961
			/*	not there, flag the failure	*/
1961
			/*	not there, flag the failure	*/
1962
			has_DXT_capability = SOIL_CAPABILITY_NONE;
1962
			has_DXT_capability = SOIL_CAPABILITY_NONE;
1963
		} else
1963
		} else
1964
		{
1964
		{
1965
			/*	and find the address of the extension function	*/
1965
			/*	and find the address of the extension function	*/
1966
			P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC ext_addr = NULL;
1966
			P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC ext_addr = NULL;
1967
			#ifdef WIN32
1967
			#ifdef WIN32
1968
				ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
1968
				ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
1969
						wglGetProcAddress
1969
						wglGetProcAddress
1970
						(
1970
						(
1971
							"glCompressedTexImage2DARB"
1971
							"glCompressedTexImage2DARB"
1972
						);
1972
						);
1973
			#elif defined(__APPLE__) || defined(__APPLE_CC__)
1973
			#elif defined(__APPLE__) || defined(__APPLE_CC__)
1974
				/*	I can't test this Apple stuff!	*/
1974
				/*	I can't test this Apple stuff!	*/
1975
				CFBundleRef bundle;
1975
				CFBundleRef bundle;
1976
				CFURLRef bundleURL =
1976
				CFURLRef bundleURL =
1977
					CFURLCreateWithFileSystemPath(
1977
					CFURLCreateWithFileSystemPath(
1978
						kCFAllocatorDefault,
1978
						kCFAllocatorDefault,
1979
						CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1979
						CFSTR("/System/Library/Frameworks/OpenGL.framework"),
1980
						kCFURLPOSIXPathStyle,
1980
						kCFURLPOSIXPathStyle,
1981
						true );
1981
						true );
1982
				CFStringRef extensionName =
1982
				CFStringRef extensionName =
1983
					CFStringCreateWithCString(
1983
					CFStringCreateWithCString(
1984
						kCFAllocatorDefault,
1984
						kCFAllocatorDefault,
1985
						"glCompressedTexImage2DARB",
1985
						"glCompressedTexImage2DARB",
1986
						kCFStringEncodingASCII );
1986
						kCFStringEncodingASCII );
1987
				bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
1987
				bundle = CFBundleCreate( kCFAllocatorDefault, bundleURL );
1988
				assert( bundle != NULL );
1988
				assert( bundle != NULL );
1989
				ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
1989
				ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
1990
						CFBundleGetFunctionPointerForName
1990
						CFBundleGetFunctionPointerForName
1991
						(
1991
						(
1992
							bundle, extensionName
1992
							bundle, extensionName
1993
						);
1993
						);
1994
				CFRelease( bundleURL );
1994
				CFRelease( bundleURL );
1995
				CFRelease( extensionName );
1995
				CFRelease( extensionName );
1996
				CFRelease( bundle );
1996
				CFRelease( bundle );
1997
			#else
1997
			#else
1998
				ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
1998
				ext_addr = (P_SOIL_GLCOMPRESSEDTEXIMAGE2DPROC)
1999
						glXGetProcAddressARB
1999
						glXGetProcAddressARB
2000
						(
2000
						(
2001
							(const GLubyte *)"glCompressedTexImage2DARB"
2001
							(const GLubyte *)"glCompressedTexImage2DARB"
2002
						);
2002
						);
2003
			#endif
2003
			#endif
2004
			/*	Flag it so no checks needed later	*/
2004
			/*	Flag it so no checks needed later	*/
2005
			if( NULL == ext_addr )
2005
			if( NULL == ext_addr )
2006
			{
2006
			{
2007
				/*	hmm, not good!!  This should not happen, but does on my
2007
				/*	hmm, not good!!  This should not happen, but does on my
2008
					laptop's VIA chipset.  The GL_EXT_texture_compression_s3tc
2008
					laptop's VIA chipset.  The GL_EXT_texture_compression_s3tc
2009
					spec requires that ARB_texture_compression be present too.
2009
					spec requires that ARB_texture_compression be present too.
2010
					this means I can upload and have the OpenGL drive do the
2010
					this means I can upload and have the OpenGL drive do the
2011
					conversion, but I can't use my own routines or load DDS files
2011
					conversion, but I can't use my own routines or load DDS files
2012
					from disk and upload them directly [8^(	*/
2012
					from disk and upload them directly [8^(	*/
2013
				has_DXT_capability = SOIL_CAPABILITY_NONE;
2013
				has_DXT_capability = SOIL_CAPABILITY_NONE;
2014
			} else
2014
			} else
2015
			{
2015
			{
2016
				/*	all's well!	*/
2016
				/*	all's well!	*/
2017
				soilGlCompressedTexImage2D = ext_addr;
2017
				soilGlCompressedTexImage2D = ext_addr;
2018
				has_DXT_capability = SOIL_CAPABILITY_PRESENT;
2018
				has_DXT_capability = SOIL_CAPABILITY_PRESENT;
2019
			}
2019
			}
2020
		}
2020
		}
2021
	}
2021
	}
2022
	/*	let the user know if we can do DXT or not	*/
2022
	/*	let the user know if we can do DXT or not	*/
2023
	return has_DXT_capability;
2023
	return has_DXT_capability;
2024
}
2024
}
2025
 
2025