Subversion Repositories gelsvn

Rev

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

Rev 449 Rev 555
1
/*
1
/*
2
	Jonathan Dummer
2
	Jonathan Dummer
3
	2007-07-26-10.36
3
	2007-07-26-10.36
4

4

5
	Simple OpenGL Image Library
5
	Simple OpenGL Image Library
6

6

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

9

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