Subversion Repositories gelsvn

Rev

Rev 628 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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