1 // ==============================================================
2 //	This file is part of Glest Shared Library (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Marti�o Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #include "texture_gl.h"
13 
14 #include <stdexcept>
15 
16 #include "opengl.h"
17 #include "leak_dumper.h"
18 
19 using namespace std;
20 
21 namespace Shared{ namespace Graphics{ namespace Gl{
22 
23 using namespace Platform;
24 
toWrapModeGl(Texture::WrapMode wrapMode)25 GLint toWrapModeGl(Texture::WrapMode wrapMode){
26 	switch(wrapMode){
27 	case Texture::wmClamp:
28 		return GL_CLAMP;
29 	case Texture::wmRepeat:
30 		return GL_REPEAT;
31 	case Texture::wmClampToEdge:
32 		return GL_CLAMP_TO_EDGE;
33 	default:
34 		assert(false);
35 		return GL_CLAMP;
36 	}
37 }
38 
toFormatGl(Texture::Format format,int components)39 GLint toFormatGl(Texture::Format format, int components){
40 	switch(format){
41 	case Texture::fAuto:
42 		switch(components){
43 		case 1:
44 			return GL_LUMINANCE;
45 		case 3:
46 			return GL_RGB;
47 		case 4:
48 			return GL_RGBA;
49 		default:
50 			assert(false);
51 			return GL_RGBA;
52 		}
53 		break;
54 	case Texture::fLuminance:
55 		return GL_LUMINANCE;
56 	case Texture::fAlpha:
57 		return GL_ALPHA;
58 	case Texture::fRgb:
59 		return GL_RGB;
60 	case Texture::fRgba:
61 		return GL_RGBA;
62 	default:
63 		assert(false);
64 		return GL_RGB;
65 	}
66 }
67 
toInternalFormatGl(Texture::Format format,int components)68 GLint toInternalFormatGl(Texture::Format format, int components){
69 	switch(format){
70 	case Texture::fAuto:
71 		switch(components){
72 		case 1:
73 			return GL_LUMINANCE8;
74 		case 3:
75 			return GL_RGB8;
76 		case 4:
77 			return GL_RGBA8;
78 		default:
79 			assert(false);
80 			return GL_RGBA8;
81 		}
82 		break;
83 	case Texture::fLuminance:
84 		return GL_LUMINANCE8;
85 	case Texture::fAlpha:
86 		return GL_ALPHA8;
87 	case Texture::fRgb:
88 		return GL_RGB8;
89 	case Texture::fRgba:
90 		return GL_RGBA8;
91 	default:
92 		assert(false);
93 		return GL_RGB8;
94 	}
95 }
96 
97 // =====================================================
98 //	class Texture1DGl
99 // =====================================================
100 
init(Filter filter,int maxAnisotropy)101 void Texture1DGl::init(Filter filter, int maxAnisotropy){
102 	assertGl();
103 
104 	if(!inited){
105 
106 		//params
107 		GLint wrap= toWrapModeGl(wrapMode);
108 		GLint glFormat= toFormatGl(format, pixmap.getComponents());
109 		GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
110 
111 		//pixel init var
112 		const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
113 
114 		//gen texture
115 		glGenTextures(1, &handle);
116 		glBindTexture(GL_TEXTURE_1D, handle);
117 
118 		//wrap params
119 		glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, wrap);
120 
121 		//maxAnisotropy
122 		if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
123 			glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
124 		}
125 
126 		if(mipmap){
127 			GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
128 
129 			//build mipmaps
130 			glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, glFilter);
131 			glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
132 
133 			int error= gluBuild1DMipmaps(
134 				GL_TEXTURE_1D, glInternalFormat, pixmap.getW(),
135 				glFormat, GL_UNSIGNED_BYTE, pixels);
136 
137 			if(error!=0){
138 				throw runtime_error("Error building texture 1D mipmaps");
139 			}
140 		}
141 		else{
142 			//build single texture
143 			glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
144 			glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
145 
146 			glTexImage1D(
147 				GL_TEXTURE_1D, 0, glInternalFormat, pixmap.getW(),
148 				0, glFormat, GL_UNSIGNED_BYTE, pixels);
149 
150 			GLint error= glGetError();
151 			if(error!=GL_NO_ERROR){
152 				throw runtime_error("Error creating texture 1D");
153 			}
154 		}
155 		inited= true;
156 	}
157 
158 	assertGl();
159 }
160 
end()161 void Texture1DGl::end(){
162 	if(inited){
163 		assertGl();
164 		glDeleteTextures(1, &handle);
165 		assertGl();
166 	}
167 }
168 
169 // =====================================================
170 //	class Texture2DGl
171 // =====================================================
172 
init(Filter filter,int maxAnisotropy)173 void Texture2DGl::init(Filter filter, int maxAnisotropy){
174 	assertGl();
175 
176 	if(!inited){
177 
178 		//params
179 		GLint wrap= toWrapModeGl(wrapMode);
180 		GLint glFormat= toFormatGl(format, pixmap.getComponents());
181 		GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
182 
183 		//pixel init var
184 		const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
185 
186 		//gen texture
187 		glGenTextures(1, &handle);
188 		glBindTexture(GL_TEXTURE_2D, handle);
189 
190 		//wrap params
191 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
192 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
193 
194 		//maxAnisotropy
195 		if(isGlExtensionSupported("GL_EXT_texture_filter_anisotropic")){
196 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnisotropy);
197 		}
198 
199 		if(mipmap){
200 			GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
201 
202 			//build mipmaps
203 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFilter);
204 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
205 
206 			int error= gluBuild2DMipmaps(
207 				GL_TEXTURE_2D, glInternalFormat,
208 				pixmap.getW(), pixmap.getH(),
209 				glFormat, GL_UNSIGNED_BYTE, pixels);
210 
211 			if(error!=0){
212 				throw runtime_error("Error building texture 2D mipmaps");
213 			}
214 		}
215 		else{
216 			//build single texture
217 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
218 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
219 
220 			glTexImage2D(
221 				GL_TEXTURE_2D, 0, glInternalFormat,
222 				pixmap.getW(), pixmap.getH(),
223 				0, glFormat, GL_UNSIGNED_BYTE, pixels);
224 
225 			GLint error= glGetError();
226 			if(error!=GL_NO_ERROR){
227 				throw runtime_error("Error creating texture 2D");
228 			}
229 		}
230 		inited= true;
231 	}
232 
233 	assertGl();
234 }
235 
end()236 void Texture2DGl::end(){
237 	if(inited){
238 		assertGl();
239 		glDeleteTextures(1, &handle);
240 		assertGl();
241 	}
242 }
243 
244 // =====================================================
245 //	class Texture3DGl
246 // =====================================================
247 
init(Filter filter,int maxAnisotropy)248 void Texture3DGl::init(Filter filter, int maxAnisotropy){
249 	assertGl();
250 
251 	if(!inited){
252 
253 		//params
254 		GLint wrap= toWrapModeGl(wrapMode);
255 		GLint glFormat= toFormatGl(format, pixmap.getComponents());
256 		GLint glInternalFormat= toInternalFormatGl(format, pixmap.getComponents());
257 
258 		//pixel init var
259 		const uint8* pixels= pixmapInit? pixmap.getPixels(): NULL;
260 
261 		//gen texture
262 		glGenTextures(1, &handle);
263 		glBindTexture(GL_TEXTURE_3D, handle);
264 
265 		//wrap params
266 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap);
267 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap);
268 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap);
269 
270 		//build single texture
271 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
272 		glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
273 
274 		glTexImage3D(
275 			GL_TEXTURE_3D, 0, glInternalFormat,
276 			pixmap.getW(), pixmap.getH(), pixmap.getD(),
277 			0, glFormat, GL_UNSIGNED_BYTE, pixels);
278 
279 		GLint error= glGetError();
280 		if(error!=GL_NO_ERROR){
281 			throw runtime_error("Error creating texture 3D");
282 		}
283 		inited= true;
284 	}
285 
286 	assertGl();
287 }
288 
end()289 void Texture3DGl::end(){
290 	if(inited){
291 		assertGl();
292 		glDeleteTextures(1, &handle);
293 		assertGl();
294 	}
295 }
296 
297 // =====================================================
298 //	class TextureCubeGl
299 // =====================================================
300 
init(Filter filter,int maxAnisotropy)301 void TextureCubeGl::init(Filter filter, int maxAnisotropy){
302 	assertGl();
303 
304 	if(!inited){
305 
306 		//gen texture
307 		glGenTextures(1, &handle);
308 		glBindTexture(GL_TEXTURE_CUBE_MAP, handle);
309 
310 		//wrap
311 		GLint wrap= toWrapModeGl(wrapMode);
312 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrap);
313 		glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrap);
314 
315 		//filter
316 		if(mipmap){
317 			GLuint glFilter= filter==fTrilinear? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST;
318 			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, glFilter);
319 			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
320 		}
321 		else{
322 			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
323 			glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
324 		}
325 
326 		for(int i=0; i<6; ++i){
327 			//params
328 			const Pixmap2D *currentPixmap= pixmap.getFace(i);
329 
330 			GLint glFormat= toFormatGl(format, currentPixmap->getComponents());
331 			GLint glInternalFormat= toInternalFormatGl(format, currentPixmap->getComponents());
332 
333 			//pixel init var
334 			const uint8* pixels= pixmapInit? currentPixmap->getPixels(): NULL;
335 			GLenum target= GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
336 
337 			if(mipmap){
338 				int error= gluBuild2DMipmaps(
339 					target, glInternalFormat,
340 					currentPixmap->getW(), currentPixmap->getH(),
341 					glFormat, GL_UNSIGNED_BYTE, pixels);
342 
343 				if(error!=0){
344 					throw runtime_error("Error building texture cube mipmaps");
345 				}
346 			}
347 			else{
348 				glTexImage2D(
349 					target, 0, glInternalFormat,
350 					currentPixmap->getW(), currentPixmap->getH(),
351 					0, glFormat, GL_UNSIGNED_BYTE, pixels);
352 			}
353 
354 			if(glGetError()!=GL_NO_ERROR){
355 				throw runtime_error("Error creating texture cube");
356 			}
357 		}
358 		inited= true;
359 
360 	}
361 
362 	assertGl();
363 }
364 
end()365 void TextureCubeGl::end(){
366 	if(inited){
367 		assertGl();
368 		glDeleteTextures(1, &handle);
369 		assertGl();
370 	}
371 }
372 
373 }}}//end namespace
374