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