Commit | Line | Data |
---|---|---|
7fd59977 | 1 | /* |
2 | * Fonction | |
3 | * ~~~~~~~~ | |
4 | * Gestion des textures sous OpenGL | |
5 | * | |
6 | * | |
7 | * Notes | |
8 | * ~~~~~ | |
9 | * Les textures sont toujours initialisee avec des parametres par defaut | |
10 | * texture 1D: WRAP_S = CLAMP | |
11 | * MAG_FILTER = NEAREST | |
12 | * generation de texture automatique en OBJECT_LINEAR | |
13 | * rendu avec DECAL | |
14 | * | |
15 | * texture 2D: WRAP_S/T = REPEAT | |
16 | * MAG/MIN_FILTER = LINEAR | |
17 | * generation de texture automatique en OBJECT_LINEAR | |
18 | * rendu avec MODULATE | |
19 | * | |
20 | * texture 2D MipMap: WRAP_S/T = REPEAT | |
21 | * MAG_FILTER = LINEAR | |
22 | * MIN_FILTER = LINEAR_MIPMAP_NEAREST | |
23 | * generation de texture automatique en OBJECT_LINEAR | |
24 | * rendu avec MODULATE | |
25 | * | |
7fd59977 | 26 | * Historique des modifications |
27 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
28 | * 22-05-97: PCT ; Creation | |
29 | * 18-06-97: FMN ; Ajout entete | |
30 | * 20-06-97: PCT ; Correction bug parametres par defaut texture 1D | |
31 | * 30-06-97: PCT ; Correction bug rechargement de la texture courante | |
32 | * 04-07-97: PCT ; suppression de l'utilisation de libimage.a de SGI | |
33 | * 01-08-97: PCT ; suppression InitializeTextureBox() | |
34 | * 04-08-97: FMN,PCT ; Portage WNT | |
35 | * 05-08-97: FMN ; ajout GetTextureData... | |
36 | * 10-09-97: PCT ; ajout commentaires. GetTexture() ne doit pas | |
37 | * etre utilisee dans Cas.Cade ( le chargement est | |
38 | * fait par Graphic3d ) | |
39 | * 06-10-97: FMN ; Portage HP | |
40 | * 14-10-97: FMN ; Ajout OpenGl_Extension | |
41 | * 22-10-97: FMN ; Meilleure gestion de l'extension glXGetCurrentDisplayEXT | |
42 | * 04-11-97: FMN ; Gestion des differentes versions GLX | |
43 | * 19-11-97: FMN ; Ajout GetCurrentDisplay plus simple que glXGetCurrentDisplayEXT | |
44 | * 04-12-97: FMN ; On suppose que l'on travaille en OpenGL1.1 (cf OpenGl_Extension) | |
45 | * 17-12-97: FMN ; Probleme compilation SGI | |
46 | * 17-12-97: FMN ; Probleme sur Optimisation sur MyBindTextureEXT() | |
47 | * Le test sur la texture courante doit tenir compte du contexte. | |
48 | * 22-07-98: FGU ; Ajout fonctions TransferTexture_To_Data() et TransferData_To_Texture() | |
49 | * | |
50 | */ | |
7fd59977 | 51 | |
52 | #include <stdio.h> | |
53 | #include <stdlib.h> | |
54 | #include <string.h> | |
55 | ||
5f8b738e | 56 | #include <OpenGl_GlCore11.hxx> |
2166f0fa | 57 | #include <OpenGl_Display.hxx> |
7fd59977 | 58 | #include <OpenGl_TextureBox.hxx> |
2166f0fa | 59 | #include <OpenGl_ImageBox.hxx> |
7fd59977 | 60 | #include <OpenGl_Memory.hxx> |
161c4476 K |
61 | #include <OpenGl_ResourceCleaner.hxx> |
62 | #include <OpenGl_ResourceTexture.hxx> | |
7fd59977 | 63 | |
5f8b738e | 64 | #include <GL/glu.h> // gluBuild2DMipmaps() |
65 | ||
7fd59977 | 66 | #define GROW_TEXTURES 8 |
67 | #define GROW_TEXTURES_DATA 8 | |
68 | #define GROW_CONTEXT 8 | |
69 | ||
7fd59977 | 70 | typedef enum {TEXDATA_NONE, TEXDATA_1D, TEXDATA_2D, TEXDATA_2DMM} texDataStatus; |
71 | typedef enum {TEX_NONE, TEX_ALLOCATED} texStatus; | |
72 | ||
73 | typedef GLfloat SizeType[4]; | |
74 | ||
75 | typedef int TextureDataID; | |
76 | #define TEXTUREDATA_ERROR -1 | |
77 | ||
78 | struct texData | |
79 | { | |
80 | char imageFileName[128]; | |
81 | int imageWidth, imageHeight; | |
82 | GLubyte *image; | |
83 | texDataStatus status; | |
84 | GLint type; | |
85 | int share_count; | |
1c35b92f | 86 | DEFINE_STANDARD_ALLOC |
7fd59977 | 87 | }; |
88 | ||
89 | ||
90 | struct texDraw | |
91 | { | |
92 | TextureDataID data; | |
93 | GLuint *number; | |
94 | GLDRAWABLE *drawable; | |
95 | GLCONTEXT *context; | |
96 | char *use_bind_texture; | |
97 | int context_count; | |
98 | int context_size; | |
99 | texStatus status; | |
100 | ||
101 | GLint Gen; | |
102 | GLint Light; | |
103 | GLint Wrap; | |
104 | GLfloat Plane1[4]; | |
105 | GLfloat Plane2[4]; | |
106 | GLint Render; | |
107 | GLfloat scalex, scaley; | |
108 | GLfloat transx, transy; | |
109 | GLfloat angle; | |
110 | ||
1c35b92f | 111 | DEFINE_STANDARD_ALLOC |
7fd59977 | 112 | }; |
113 | ||
114 | ||
115 | /*----------------------------------------------------------------------*/ | |
116 | /* | |
117 | * Variables statiques | |
118 | */ | |
119 | ||
120 | static texDraw *textab = NULL; | |
121 | static int textures_count = 0; | |
122 | static int textures_size = 0; | |
123 | ||
124 | static texData *texdata = NULL; | |
125 | static int textures_data_count = 0; | |
126 | static int textures_data_size = 0; | |
127 | ||
128 | static TextureDataID current_texture_data = TEXTUREDATA_ERROR; | |
129 | static TextureID current_texture = TEXTUREBOX_ERROR; | |
130 | ||
131 | static GLfloat sgenparams[] = { 1.0 ,0.0 ,0.0 ,0.0}; | |
132 | static GLfloat tgenparams[] = { 0.0 ,1.0 ,0.0 ,0.0}; | |
133 | ||
134 | static GLenum status2type[] = { GL_NONE, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_2D }; | |
135 | ||
7fd59977 | 136 | /*----------------------------------------------------------------------*/ |
137 | /* | |
138 | * Fonctions privees | |
139 | */ | |
140 | ||
7fd59977 | 141 | /*----------------------------------------------------------------------*/ |
142 | /* | |
143 | * recherche l'existence de datas de texture par son nom | |
144 | */ | |
145 | static TextureDataID FindTextureData(char *FileName) | |
146 | { | |
147 | int i; | |
148 | ||
149 | for (i=0; i<textures_data_size; i++) | |
150 | if ( texdata[i].status!=TEXDATA_NONE && strcmp(FileName, texdata[i].imageFileName)==0 ) | |
151 | return i; | |
152 | ||
153 | return TEXTUREDATA_ERROR; | |
154 | } | |
155 | ||
156 | /*----------------------------------------------------------------------*/ | |
157 | /* | |
158 | * recherche un emplacement de data texture libre | |
159 | */ | |
160 | static TextureDataID FindFreeTextureData(void) | |
161 | { | |
162 | int i; | |
163 | ||
164 | /* ya encore de la place ? */ | |
165 | if (textures_data_count == textures_data_size) | |
166 | { | |
167 | textures_data_size += GROW_TEXTURES_DATA; | |
168 | #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530) | |
169 | texdata = (texData*)realloc(texdata, textures_data_size*sizeof(texData)); | |
170 | #else | |
171 | texdata = cmn_resizemem<texData>(texdata, textures_data_size); | |
172 | #endif | |
173 | if (texdata == NULL) return TEXTUREDATA_ERROR; | |
174 | ||
175 | for (i=textures_data_count; i<textures_data_size; i++) | |
176 | texdata[i].status = TEXDATA_NONE; | |
177 | ||
178 | /* on a deja assez perdu de temps comme ca => retourne un ID rapidement... */ | |
179 | return textures_data_count++; | |
180 | } | |
181 | ||
182 | /* recherche d'un ID libre */ | |
183 | for (i=0; i<textures_data_size; i++) | |
184 | if (texdata[i].status == TEXDATA_NONE) | |
185 | { | |
5f8b738e | 186 | textures_data_count = Max (textures_data_count, i + 1); |
7fd59977 | 187 | return i; |
188 | } | |
189 | ||
190 | return TEXTUREDATA_ERROR; | |
191 | } | |
192 | ||
193 | /*----------------------------------------------------------------------*/ | |
194 | /* | |
195 | * recherche un emplacement de texture libre | |
196 | */ | |
197 | static TextureID FindFreeTexture(void) | |
198 | { | |
199 | int i; | |
200 | ||
201 | /* ya encore de la place ? */ | |
202 | if (textures_count == textures_size) | |
203 | { | |
204 | textures_size += GROW_TEXTURES; | |
205 | #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530) | |
206 | textab = (texDraw*)realloc(textab, textures_size*sizeof(texDraw)); | |
207 | #else | |
208 | textab = cmn_resizemem<texDraw>(textab, textures_size); | |
209 | #endif | |
210 | if (textab == NULL) return TEXTUREBOX_ERROR; | |
211 | ||
212 | for (i=textures_count; i<textures_size; i++) | |
213 | textab[i].status = TEX_NONE; | |
214 | ||
215 | /* on a deja assez perdu de temps comme ca => retourne un ID rapidement... */ | |
216 | return textures_count++; | |
217 | } | |
218 | ||
219 | for (i=0; i<textures_size; i++) | |
220 | if (textab[i].status == TEX_NONE) | |
221 | { | |
5f8b738e | 222 | textures_count = Max (textures_count, i + 1); |
7fd59977 | 223 | return i; |
224 | } | |
225 | ||
226 | return TEXTUREBOX_ERROR; | |
227 | } | |
228 | ||
229 | /*----------------------------------------------------------------------*/ | |
230 | /* | |
231 | * regarde si la texture a ete definie pour le contexte courant | |
232 | */ | |
233 | static int FindTextureContext(TextureID ID) | |
234 | { | |
235 | int i; | |
236 | ||
237 | GLCONTEXT cur = GET_GL_CONTEXT(); | |
238 | for (i=0; i<textab[ID].context_count; i++) | |
239 | if (textab[ID].context[i] == cur) | |
240 | return i; | |
241 | ||
242 | return TEXTUREBOX_ERROR; | |
243 | } | |
244 | ||
245 | /*----------------------------------------------------------------------*/ | |
246 | /* | |
247 | * chargement d'une texture suivant son type | |
248 | */ | |
249 | static void LoadTexture(TextureID ID) | |
250 | { | |
251 | TextureDataID data; | |
252 | ||
253 | data = textab[ID].data; | |
254 | switch (texdata[data].status) | |
255 | { | |
256 | case TEXDATA_1D: | |
257 | glTexImage1D(GL_TEXTURE_1D, 0, 4, | |
258 | texdata[data].imageWidth, 0, | |
259 | GL_RGBA, GL_UNSIGNED_BYTE, texdata[data].image); | |
260 | break; | |
261 | ||
262 | case TEXDATA_2D: | |
263 | glTexImage2D(GL_TEXTURE_2D, 0, 4, | |
264 | texdata[data].imageWidth, texdata[data].imageHeight, 0, | |
265 | GL_RGBA, GL_UNSIGNED_BYTE, texdata[data].image); | |
266 | break; | |
267 | ||
268 | case TEXDATA_2DMM: | |
269 | gluBuild2DMipmaps(GL_TEXTURE_2D, 4, | |
270 | texdata[data].imageWidth, | |
271 | texdata[data].imageHeight, | |
272 | GL_RGBA, GL_UNSIGNED_BYTE, texdata[data].image); | |
273 | break; | |
274 | default: | |
275 | break; | |
276 | } | |
277 | } | |
278 | ||
279 | /*----------------------------------------------------------------------*/ | |
280 | /* | |
281 | * les parametres d'initialisation d'une texture | |
282 | * NE PAS METTRE DANS UNE DISPLAY LIST POUR L'INSTANT ( pb avec les matrices ) | |
283 | */ | |
284 | static void SetTextureParam(TextureID ID) | |
285 | { | |
286 | GLint cur_matrix; | |
287 | TextureDataID data; | |
288 | ||
289 | ||
290 | data = textab[ID].data; | |
291 | glGetIntegerv(GL_MATRIX_MODE, &cur_matrix); | |
292 | ||
293 | /* | |
294 | * MISE EN PLACE DE LA MATRICE DE TEXTURE | |
295 | */ | |
296 | glMatrixMode(GL_TEXTURE); | |
297 | glLoadIdentity(); | |
298 | /* if (textab[ID].Gen != GL_SPHERE_MAP) | |
299 | {*/ | |
300 | glScalef(textab[ID].scalex, textab[ID].scaley, 1.0); | |
301 | glTranslatef(-textab[ID].transx, -textab[ID].transy, 0.0); | |
302 | glRotatef(-textab[ID].angle, 0.0, 0.0, 1.0); | |
303 | /*}*/ | |
304 | ||
305 | ||
306 | /* | |
307 | * GENERATION AUTOMATIQUE DE TEXTURE | |
308 | */ | |
309 | switch (textab[ID].Gen) | |
310 | { | |
311 | case GL_OBJECT_LINEAR: | |
312 | glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | |
313 | glTexGenfv(GL_S, GL_OBJECT_PLANE, textab[ID].Plane1); | |
314 | if (texdata[data].status != TEXDATA_1D) | |
315 | { | |
316 | glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); | |
317 | glTexGenfv(GL_T, GL_OBJECT_PLANE, textab[ID].Plane2); | |
318 | } | |
319 | break; | |
320 | ||
321 | case GL_SPHERE_MAP: | |
322 | glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); | |
323 | if (texdata[data].status != TEXDATA_1D) | |
324 | glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); | |
325 | break; | |
326 | ||
327 | case GL_EYE_LINEAR: | |
328 | glMatrixMode(GL_MODELVIEW); | |
329 | glPushMatrix(); | |
330 | glLoadIdentity(); | |
331 | ||
332 | glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); | |
333 | glTexGenfv(GL_S, GL_EYE_PLANE, textab[ID].Plane1); | |
334 | ||
335 | if (texdata[data].status != TEXDATA_1D) | |
336 | { | |
337 | glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); | |
338 | glTexGenfv(GL_T, GL_EYE_PLANE, textab[ID].Plane2); | |
339 | } | |
340 | ||
341 | glPopMatrix(); | |
342 | break; | |
343 | } | |
344 | ||
345 | ||
346 | /* | |
347 | * RENDU DE LA TEXTURE AVEC LES LUMIERES | |
348 | */ | |
349 | glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textab[ID].Light); | |
350 | ||
351 | ||
352 | /* | |
353 | * LISSAGE DE LA TEXTURE | |
354 | */ | |
355 | switch (texdata[data].status) | |
356 | { | |
357 | case TEXDATA_1D: | |
358 | case TEXDATA_2D: | |
359 | glTexParameteri(texdata[data].type, GL_TEXTURE_MAG_FILTER, textab[ID].Render); | |
360 | glTexParameteri(texdata[data].type, GL_TEXTURE_MIN_FILTER, textab[ID].Render); | |
361 | break; | |
362 | ||
363 | case TEXDATA_2DMM: | |
364 | if (textab[ID].Render == GL_NEAREST) | |
365 | { | |
366 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | |
367 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); | |
368 | } | |
369 | else | |
370 | { | |
371 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
372 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); | |
373 | } | |
374 | break; | |
375 | default: | |
376 | break; | |
377 | } | |
378 | ||
379 | ||
380 | /* | |
381 | * WRAP DE LA TEXTURE | |
382 | */ | |
383 | switch (texdata[data].status) | |
384 | { | |
385 | case TEXDATA_1D: | |
386 | glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, textab[ID].Wrap); | |
387 | break; | |
388 | ||
389 | case TEXDATA_2D: | |
390 | case TEXDATA_2DMM: | |
391 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textab[ID].Wrap); | |
392 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textab[ID].Wrap); | |
393 | break; | |
394 | default: | |
395 | break; | |
396 | } | |
397 | ||
398 | glMatrixMode(cur_matrix); | |
399 | } | |
400 | ||
401 | /*----------------------------------------------------------------------*/ | |
402 | /* | |
403 | * simulation du glGenTexturesEXT pour un context | |
404 | */ | |
2166f0fa | 405 | static void MyGenTextureEXT (TextureID ID) |
7fd59977 | 406 | { |
2166f0fa SK |
407 | int Context = textab[ID].context_count; |
408 | TextureDataID data = textab[ID].data; | |
409 | ||
410 | textab[ID].context[Context] = GET_GL_CONTEXT(); | |
411 | textab[ID].drawable[Context] = GET_GLDEV_CONTEXT(); | |
412 | textab[ID].use_bind_texture[Context] = (char )GL_TRUE; | |
413 | glGenTextures (1, &textab[ID].number[Context]); | |
414 | glBindTexture (texdata[data].type, textab[ID].number[Context]); | |
415 | LoadTexture (ID); | |
416 | textab[ID].context_count++; | |
7fd59977 | 417 | } |
418 | ||
419 | /*----------------------------------------------------------------------*/ | |
420 | /* | |
421 | * simulation du glBindTextureEXT | |
422 | */ | |
2166f0fa | 423 | static void MyBindTextureEXT (TextureID ID, int Context) |
7fd59977 | 424 | { |
2166f0fa | 425 | TextureDataID data = textab[ID].data; |
c320e557 | 426 | if (texdata[data].status == TEXDATA_NONE) |
7fd59977 | 427 | return; |
428 | ||
c320e557 A |
429 | GLenum aParamName = texdata[data].status == TEXDATA_1D ? |
430 | GL_TEXTURE_BINDING_1D : GL_TEXTURE_BINDING_2D; | |
431 | ||
2166f0fa SK |
432 | GLint aCurrTex = -1; |
433 | glGetIntegerv (aParamName, &aCurrTex); | |
434 | if (textab[ID].number[Context] != aCurrTex) | |
7fd59977 | 435 | { |
2166f0fa | 436 | glBindTexture (texdata[data].type, textab[ID].number[Context]); |
7fd59977 | 437 | } |
438 | } | |
439 | ||
440 | /*----------------------------------------------------------------------*/ | |
441 | /* | |
442 | * installation de la texture pour le dernier contexte | |
443 | */ | |
444 | static int InstallTextureInContext(TextureID ID) | |
445 | { | |
446 | #ifdef PRINT | |
447 | printf("InstallTextureInContext::installation de la texture dans le context\n"); | |
448 | #endif | |
449 | ||
450 | ||
451 | /* ya encore de la place dans le tableau de context ? */ | |
452 | if (textab[ID].context_count == textab[ID].context_size) | |
453 | { | |
454 | #ifdef PRINT | |
455 | printf("InstallTextureInContext::allocation dans le context\n"); | |
456 | #endif | |
457 | textab[ID].context_size += GROW_CONTEXT; | |
458 | #if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530) | |
459 | textab[ID].number = | |
460 | (GLuint*)realloc(textab[ID].number, textab[ID].context_size*sizeof(GLuint)); | |
461 | textab[ID].context = | |
462 | (GLCONTEXT*)realloc(textab[ID].context, textab[ID].context_size*sizeof(GLCONTEXT)); | |
463 | textab[ID].drawable = | |
464 | (GLDRAWABLE*)realloc(textab[ID].drawable, textab[ID].context_size*sizeof(GLDRAWABLE)); | |
465 | textab[ID].use_bind_texture = | |
466 | (char*)realloc(textab[ID].use_bind_texture, textab[ID].context_size); | |
467 | #else | |
468 | textab[ID].number = | |
469 | cmn_resizemem<GLuint>(textab[ID].number, textab[ID].context_size); | |
470 | textab[ID].context = | |
471 | cmn_resizemem<GLCONTEXT>(textab[ID].context, textab[ID].context_size); | |
472 | textab[ID].drawable = | |
473 | cmn_resizemem<GLDRAWABLE>(textab[ID].drawable, textab[ID].context_size); | |
474 | textab[ID].use_bind_texture = | |
475 | cmn_resizemem<char>(textab[ID].use_bind_texture, textab[ID].context_size); | |
476 | #endif | |
477 | if ( (textab[ID].number == NULL) || | |
478 | (textab[ID].context == NULL) || | |
479 | (textab[ID].drawable == NULL) || | |
480 | (textab[ID].use_bind_texture == NULL) ) | |
481 | { | |
482 | /* erreur => libere tout */ | |
483 | free(textab[ID].number); | |
484 | free(textab[ID].context); | |
485 | free(textab[ID].drawable); | |
486 | free(textab[ID].use_bind_texture); | |
487 | textab[ID].context_size = 0; | |
488 | ||
489 | return TEXTUREBOX_ERROR; | |
490 | } | |
491 | } | |
492 | ||
493 | MyGenTextureEXT(ID); | |
494 | SetTextureParam(ID); | |
495 | #ifdef PRINT | |
496 | printf("InstallTextureInContext::context ok\n"); | |
497 | #endif | |
498 | return 0; | |
499 | } | |
500 | ||
501 | /*----------------------------------------------------------------------*/ | |
502 | static TextureID GetTexture(char *FileName, texDataStatus status) | |
503 | { | |
504 | TextureDataID i; | |
505 | TextureID j; | |
506 | int dummy; | |
507 | ||
508 | /* essait de trouver la texture */ | |
509 | i = FindTextureData(FileName); | |
510 | if (i == TEXTUREDATA_ERROR) | |
511 | { | |
512 | #ifdef PRINT | |
513 | printf("GetTexture::la texture %s n'existe pas => chargement\n", FileName); | |
514 | #endif | |
515 | /* creation d'une texture */ | |
516 | i = FindFreeTextureData(); | |
517 | if (i == TEXTUREDATA_ERROR) return TEXTUREBOX_ERROR; | |
518 | ||
519 | texdata[i].share_count = 0; | |
520 | strcpy(texdata[i].imageFileName, FileName); | |
521 | texdata[i].image = (GLubyte *)read_texture(FileName, | |
522 | &texdata[i].imageWidth, | |
523 | &texdata[i].imageHeight, | |
524 | &dummy); | |
525 | if (texdata[i].image == NULL) return TEXTUREBOX_ERROR; | |
526 | ||
527 | texdata[i].status = status; | |
528 | texdata[i].type = status2type[status]; | |
529 | } | |
530 | ||
531 | j = FindFreeTexture(); | |
532 | if (j != TEXTUREBOX_ERROR) | |
533 | { | |
534 | #ifdef PRINT | |
535 | printf("GetTexture::installation texture pour obj %d\n", j); | |
536 | #endif | |
537 | textab[j].context_count = 0; | |
538 | textab[j].context_size = 0; | |
539 | textab[j].number = NULL; | |
540 | textab[j].drawable = NULL; | |
541 | textab[j].context = NULL; | |
542 | textab[j].use_bind_texture = NULL; | |
543 | textab[j].data = i; | |
544 | textab[j].status = TEX_ALLOCATED; | |
545 | texdata[i].share_count++; | |
546 | ||
547 | SetTextureDefaultParams(j); | |
548 | ||
549 | #ifdef PRINT | |
550 | printf("GetTexture::texture %s(%d) texture %d count=%d\n", texdata[i].imageFileName, i, j, texdata[i].share_count); | |
551 | #endif | |
552 | } | |
553 | else | |
554 | if (texdata[i].share_count != 0) | |
555 | free(texdata[i].image); | |
556 | ||
557 | return j; | |
558 | } | |
559 | ||
560 | ||
561 | /*----------------------------------------------------------------------*/ | |
562 | static TextureID GetTextureData(char *FileName, texDataStatus status, const GLint width, const GLint height, const void *data) | |
563 | { | |
564 | TextureDataID i; | |
565 | TextureID j; | |
566 | ||
567 | /* essait de trouver la texture */ | |
568 | i = FindTextureData(FileName); | |
569 | if (i == TEXTUREDATA_ERROR) | |
570 | { | |
571 | #ifdef PRINT | |
572 | printf("GetTextureData::la texture %s n'existe pas => chargement\n", FileName); | |
573 | #endif | |
574 | /* creation d'une texture */ | |
575 | i = FindFreeTextureData(); | |
576 | if (i == TEXTUREDATA_ERROR) return TEXTUREBOX_ERROR; | |
577 | ||
578 | texdata[i].share_count = 0; | |
579 | strcpy(texdata[i].imageFileName, FileName); | |
580 | texdata[i].image = (GLubyte *)malloc(width*height*4*sizeof(GLubyte)); | |
581 | memcpy(texdata[i].image, data, (width*height*4)); | |
582 | texdata[i].imageWidth = width; | |
583 | texdata[i].imageHeight = height; | |
584 | ||
585 | if (texdata[i].image == NULL) return TEXTUREBOX_ERROR; | |
586 | ||
587 | texdata[i].status = status; | |
588 | texdata[i].type = status2type[status]; | |
589 | } | |
590 | ||
591 | j = FindFreeTexture(); | |
592 | if (j != TEXTUREBOX_ERROR) | |
593 | { | |
594 | #ifdef PRINT | |
595 | printf("GetTextureData::installation texture pour obj %d\n", j); | |
596 | #endif | |
597 | textab[j].context_count = 0; | |
598 | textab[j].context_size = 0; | |
599 | textab[j].number = NULL; | |
600 | textab[j].drawable = NULL; | |
601 | textab[j].context = NULL; | |
602 | textab[j].use_bind_texture = NULL; | |
603 | textab[j].data = i; | |
604 | textab[j].status = TEX_ALLOCATED; | |
605 | texdata[i].share_count++; | |
606 | ||
607 | SetTextureDefaultParams(j); | |
608 | ||
609 | #ifdef PRINT | |
610 | printf("GetTextureData::texture %s(%d) texture %d count=%d\n", texdata[i].imageFileName, i, j, texdata[i].share_count); | |
611 | #endif | |
612 | } | |
613 | else | |
614 | if (texdata[i].share_count != 0) | |
615 | free(texdata[i].image); | |
616 | ||
617 | return j; | |
618 | } | |
619 | ||
620 | /*----------------------------------------------------------------------*/ | |
621 | /* | |
622 | * Fonctions publiques | |
623 | */ | |
624 | ||
625 | ||
626 | /*----------------------------------------------------------------------*/ | |
627 | ||
628 | GLboolean IsTextureValid(TextureID ID) | |
629 | { | |
630 | if ((ID<0) | (ID>=textures_count)) | |
631 | return GL_FALSE; | |
632 | ||
633 | if (textab) | |
634 | return textab[ID].status == TEX_ALLOCATED; | |
635 | else | |
636 | return GL_TRUE; | |
637 | } | |
638 | ||
639 | /*----------------------------------------------------------------------*/ | |
640 | ||
641 | TextureID GetTexture1D(char *FileName) | |
642 | { | |
643 | #ifdef PRINT | |
644 | printf("GetTexture1D::loading 1d %s \n", FileName); | |
645 | #endif | |
646 | return GetTexture(FileName, TEXDATA_1D); | |
647 | } | |
648 | ||
649 | /*----------------------------------------------------------------------*/ | |
650 | ||
651 | TextureID GetTexture2D(char *FileName) | |
652 | { | |
653 | #ifdef PRINT | |
654 | printf("GetTexture2D::loading 2d %s \n", FileName); | |
655 | #endif | |
656 | return GetTexture(FileName, TEXDATA_2D); | |
657 | } | |
658 | ||
659 | /*----------------------------------------------------------------------*/ | |
660 | ||
661 | TextureID GetTexture2DMipMap(char *FileName) | |
662 | { | |
663 | #ifdef PRINT | |
664 | printf("GetTexture2DMipMap::loading 2dmm %s \n", FileName); | |
665 | #endif | |
666 | return GetTexture(FileName, TEXDATA_2DMM); | |
667 | } | |
668 | ||
669 | /*----------------------------------------------------------------------*/ | |
670 | ||
671 | TextureID GetTextureData1D(char *FileName, const GLint width, const GLint height, const void *data) | |
672 | { | |
673 | #ifdef PRINT | |
674 | printf("GetTextureData1D::loading 1d %s \n", FileName); | |
675 | #endif | |
676 | return GetTextureData(FileName, TEXDATA_1D, width, height, data); | |
677 | } | |
678 | ||
679 | /*----------------------------------------------------------------------*/ | |
680 | ||
681 | TextureID GetTextureData2D(char *FileName, const GLint width, const GLint height, const void *data) | |
682 | { | |
683 | #ifdef PRINT | |
684 | printf("GetTextureData2D::loading 2d %s \n", FileName); | |
685 | #endif | |
686 | return GetTextureData(FileName, TEXDATA_2D, width, height, data); | |
687 | } | |
688 | ||
689 | /*----------------------------------------------------------------------*/ | |
690 | ||
691 | TextureID GetTextureData2DMipMap(char *FileName, const GLint width, const GLint height, const void *data) | |
692 | { | |
693 | #ifdef PRINT | |
694 | printf("GetTextureData2DMipMap::loading 2dmm %s \n", FileName); | |
695 | #endif | |
696 | return GetTextureData(FileName, TEXDATA_2DMM, width, height, data); | |
697 | } | |
698 | ||
699 | ||
700 | /*----------------------------------------------------------------------*/ | |
701 | ||
702 | void SetCurrentTexture(TextureID ID) | |
703 | { | |
704 | int context; | |
705 | ||
706 | if (!IsTextureValid(ID)) return; | |
707 | ||
708 | context = FindTextureContext(ID); | |
709 | ||
710 | /* la texture n'existe pas dans ce contexte */ | |
711 | if (context == TEXTUREBOX_ERROR) | |
712 | { | |
713 | #ifdef PRINT | |
714 | printf("SetCurrentTexture::installation texture %d dans context\n", ID); | |
715 | #endif | |
716 | /* si on a une erreur pendant l'installation dans le context | |
717 | * alors on installe la texture sans bind */ | |
718 | if (InstallTextureInContext(ID) == TEXTUREBOX_ERROR) | |
719 | { | |
720 | LoadTexture(ID); | |
721 | SetTextureParam(ID); | |
722 | } | |
723 | } | |
724 | ||
725 | /*oui, alors on bind directement */ | |
726 | else | |
727 | { | |
728 | #ifdef PRINT | |
729 | printf("SetCurrentTexture: utilisation du bind %d\n", ID); | |
730 | #endif | |
731 | MyBindTextureEXT(ID, context); | |
732 | SetTextureParam(ID); | |
733 | } | |
734 | ||
735 | current_texture = ID; | |
736 | current_texture_data = textab[ID].data; | |
737 | } | |
738 | ||
739 | /*----------------------------------------------------------------------*/ | |
740 | ||
741 | void FreeTexture(TextureID ID) | |
742 | { | |
743 | TextureDataID data; | |
161c4476 | 744 | bool notResource = false; // if there old-style texture deletion |
7fd59977 | 745 | |
7fd59977 | 746 | GLCONTEXT cur_context; |
747 | GLDRAWABLE cur_drawable; | |
748 | int i; | |
7fd59977 | 749 | |
750 | if (!IsTextureValid(ID)) return; | |
751 | ||
752 | data = textab[ID].data; | |
753 | texdata[data].share_count--; | |
754 | if (texdata[data].share_count == 0) | |
755 | { | |
2166f0fa | 756 | // liberation des datas de la textures |
7fd59977 | 757 | free(texdata[data].image); |
758 | ||
2166f0fa SK |
759 | // liberation de la texture dans tous les contextes |
760 | cur_drawable = GET_GLDEV_CONTEXT(); | |
761 | for (i = 0; i < textab[ID].context_count; ++i) | |
7fd59977 | 762 | { |
2166f0fa SK |
763 | cur_context = 0; |
764 | bool isResource = false; | |
161c4476 | 765 | |
2166f0fa SK |
766 | if (textab[ID].use_bind_texture[i]) |
767 | { | |
768 | if( !OpenGl_ResourceCleaner::GetInstance()->AddResource(textab[ID].context[i], | |
769 | new OpenGl_ResourceTexture(textab[ID].number[i])) ) | |
7fd59977 | 770 | { |
2166f0fa SK |
771 | GL_MAKE_CURRENT((openglDisplay.IsNull() ? (Display* )NULL : (Display* )openglDisplay->GetDisplay()), |
772 | textab[ID].drawable[i], | |
773 | textab[ID].context[i]); | |
774 | ||
775 | // This check has been added to avoid exception, | |
776 | // which is raised when trying to delete textures when no rendering context is available | |
777 | cur_context = GET_GL_CONTEXT(); | |
778 | if (cur_context) | |
779 | glDeleteTextures (1, &textab[ID].number[i]); | |
780 | notResource = true; | |
781 | } | |
782 | else | |
783 | { | |
784 | isResource = true; | |
7fd59977 | 785 | } |
7fd59977 | 786 | } |
787 | ||
2166f0fa SK |
788 | if( !isResource && cur_context ) |
789 | glFinish(); | |
790 | } | |
7fd59977 | 791 | |
2166f0fa SK |
792 | if( notResource ) |
793 | GL_MAKE_CURRENT((openglDisplay.IsNull() ? (Display* )NULL : (Display* )openglDisplay->GetDisplay()), | |
794 | cur_drawable, cur_context); | |
795 | ||
796 | texdata[data].status = TEXDATA_NONE; | |
797 | if (data + 1 == textures_data_count) | |
798 | { | |
799 | --textures_data_count; | |
800 | } | |
7fd59977 | 801 | |
2166f0fa SK |
802 | free(textab[ID].context); |
803 | free(textab[ID].drawable); | |
804 | free(textab[ID].use_bind_texture); | |
805 | free(textab[ID].number); | |
7fd59977 | 806 | } |
807 | ||
808 | textab[ID].status = TEX_NONE; | |
2166f0fa SK |
809 | if (ID + 1 == textures_count) |
810 | { | |
811 | --textures_count; | |
812 | } | |
7fd59977 | 813 | |
814 | current_texture_data = TEXTUREDATA_ERROR; | |
815 | } | |
816 | ||
817 | /*----------------------------------------------------------------------*/ | |
818 | ||
819 | void EnableTexture(void) | |
820 | { | |
821 | if (!IsTextureValid(current_texture)) return; | |
822 | ||
823 | switch (texdata[current_texture_data].status) | |
824 | { | |
825 | case TEXDATA_1D: | |
826 | if (textab[current_texture].Gen != GL_NONE) | |
827 | glEnable(GL_TEXTURE_GEN_S); | |
828 | glEnable(GL_TEXTURE_1D); | |
829 | break; | |
830 | ||
831 | case TEXDATA_2D: | |
832 | case TEXDATA_2DMM: | |
833 | if (textab[current_texture].Gen != GL_NONE) | |
834 | { | |
835 | glEnable(GL_TEXTURE_GEN_S); | |
836 | glEnable(GL_TEXTURE_GEN_T); | |
837 | } | |
838 | glEnable(GL_TEXTURE_2D); | |
839 | break; | |
840 | default: | |
841 | break; | |
842 | } | |
843 | } | |
844 | ||
845 | /*----------------------------------------------------------------------*/ | |
846 | ||
847 | void DisableTexture(void) | |
848 | { | |
849 | if ( !IsTextureEnabled() ) | |
850 | return; | |
851 | if ( !IsTextureValid( current_texture ) ) | |
852 | return; | |
853 | ||
854 | switch (texdata[current_texture_data].status) | |
855 | { | |
856 | case TEXDATA_1D: | |
857 | if (textab[current_texture].Gen != GL_NONE) | |
858 | glDisable(GL_TEXTURE_GEN_S); | |
859 | glDisable(GL_TEXTURE_1D); | |
860 | break; | |
861 | ||
862 | case TEXDATA_2D: | |
863 | case TEXDATA_2DMM: | |
864 | if (textab[current_texture].Gen != GL_NONE) | |
865 | { | |
866 | glDisable(GL_TEXTURE_GEN_S); | |
867 | glDisable(GL_TEXTURE_GEN_T); | |
868 | } | |
869 | glDisable(GL_TEXTURE_2D); | |
870 | break; | |
871 | default: | |
872 | break; | |
873 | } | |
874 | } | |
875 | ||
876 | /*----------------------------------------------------------------------*/ | |
877 | ||
878 | GLboolean IsTextureEnabled(void) | |
879 | { | |
880 | GLboolean isEnabled1D= GL_FALSE, isEnabled2D= GL_FALSE; | |
881 | glGetBooleanv( GL_TEXTURE_1D, &isEnabled1D ); | |
882 | glGetBooleanv( GL_TEXTURE_2D, &isEnabled2D ); | |
883 | return isEnabled1D || isEnabled2D; | |
884 | } | |
885 | ||
886 | /*----------------------------------------------------------------------*/ | |
887 | ||
888 | void SetTextureModulate(TextureID ID) | |
889 | { | |
890 | if (!IsTextureValid(ID)) return; | |
891 | ||
892 | textab[ID].Light = GL_MODULATE; | |
893 | } | |
894 | ||
895 | /*----------------------------------------------------------------------*/ | |
896 | ||
897 | void SetTextureDecal(TextureID ID) | |
898 | { | |
899 | if (!IsTextureValid(ID)) return; | |
900 | ||
901 | textab[ID].Light = GL_DECAL; | |
902 | } | |
903 | ||
904 | /*----------------------------------------------------------------------*/ | |
905 | ||
906 | void SetTextureClamp(TextureID ID) | |
907 | { | |
908 | if (!IsTextureValid(ID)) return; | |
909 | ||
910 | textab[ID].Wrap = GL_CLAMP; | |
911 | } | |
912 | ||
913 | /*----------------------------------------------------------------------*/ | |
914 | ||
915 | void SetTextureRepeat(TextureID ID) | |
916 | { | |
917 | if (!IsTextureValid(ID)) return; | |
918 | ||
919 | textab[ID].Wrap = GL_REPEAT; | |
920 | } | |
921 | ||
922 | /*----------------------------------------------------------------------*/ | |
923 | ||
924 | /* gestion de la facon d'appliquer la texture */ | |
5f8b738e | 925 | void SetModeObject(TextureID ID, const GLfloat sparams[4], const GLfloat tparams[4]) |
7fd59977 | 926 | { |
927 | if (!IsTextureValid(ID)) return; | |
928 | ||
929 | textab[ID].Gen = GL_OBJECT_LINEAR; | |
930 | if (sparams != NULL) memcpy(textab[ID].Plane1, sparams, sizeof(sgenparams)); | |
931 | else memcpy(textab[ID].Plane1, sgenparams, sizeof(sgenparams)); | |
932 | ||
933 | if (texdata[textab[ID].data].status != TEXDATA_1D) { | |
934 | if (tparams != NULL) memcpy(textab[ID].Plane2, tparams, sizeof(tgenparams)); | |
935 | else memcpy(textab[ID].Plane2, tgenparams, sizeof(tgenparams)); | |
936 | } | |
937 | } | |
938 | ||
939 | /*----------------------------------------------------------------------*/ | |
940 | ||
941 | void SetModeSphere(TextureID ID) | |
942 | { | |
943 | if (!IsTextureValid(ID)) return; | |
944 | ||
945 | textab[ID].Gen = GL_SPHERE_MAP; | |
946 | } | |
947 | ||
948 | /*----------------------------------------------------------------------*/ | |
949 | ||
5f8b738e | 950 | void SetModeEye(TextureID ID, const GLfloat sparams[4], const GLfloat tparams[4]) |
7fd59977 | 951 | { |
952 | if (!IsTextureValid(ID)) return; | |
953 | ||
954 | textab[ID].Gen = GL_EYE_LINEAR; | |
955 | if (sparams != NULL) memcpy(textab[ID].Plane1, sparams, sizeof(sgenparams)); | |
956 | else memcpy(textab[ID].Plane1, sgenparams, sizeof(sgenparams)); | |
957 | ||
958 | if (texdata[textab[ID].data].status != TEXDATA_1D) { | |
959 | if (tparams != NULL) memcpy(textab[ID].Plane2, tparams, sizeof(tgenparams)); | |
960 | else memcpy(textab[ID].Plane2, tgenparams, sizeof(tgenparams)); | |
961 | } | |
962 | } | |
963 | ||
964 | /*----------------------------------------------------------------------*/ | |
965 | ||
966 | void SetModeManual(TextureID ID) | |
967 | { | |
968 | if (!IsTextureValid(ID)) return; | |
969 | ||
970 | textab[ID].Gen = GL_NONE; | |
971 | } | |
972 | ||
973 | /*----------------------------------------------------------------------*/ | |
974 | ||
975 | void SetRenderNearest(TextureID ID) | |
976 | { | |
977 | if (!IsTextureValid(ID)) return; | |
978 | ||
979 | textab[ID].Render = GL_NEAREST; | |
980 | } | |
981 | ||
982 | /*----------------------------------------------------------------------*/ | |
983 | ||
984 | void SetRenderLinear(TextureID ID) | |
985 | { | |
986 | if (!IsTextureValid(ID)) return; | |
987 | ||
988 | textab[ID].Render = GL_LINEAR; | |
989 | } | |
990 | ||
991 | /*----------------------------------------------------------------------*/ | |
992 | ||
993 | void SetTexturePosition(TextureID ID, | |
994 | GLfloat scalex, GLfloat scaley, | |
995 | GLfloat transx, GLfloat transy, | |
996 | GLfloat angle) | |
997 | { | |
998 | textab[ID].scalex = scalex; | |
999 | textab[ID].scaley = scaley; | |
1000 | textab[ID].transx = transx; | |
1001 | textab[ID].transy = transy; | |
1002 | textab[ID].angle = angle; | |
1003 | } | |
1004 | ||
1005 | /*----------------------------------------------------------------------*/ | |
1006 | ||
1007 | void SetTextureDefaultParams(TextureID ID) | |
1008 | { | |
1009 | if (!IsTextureValid(ID)) return; | |
1010 | ||
1011 | #ifdef PRINT | |
1012 | printf("SetTextureDefaultParams::set parm par defaut textures\n"); | |
1013 | #endif | |
1014 | ||
1015 | ||
1016 | textab[ID].scalex = 1.0; | |
1017 | textab[ID].scaley = 1.0; | |
1018 | textab[ID].transx = 0.0; | |
1019 | textab[ID].transy = 0.0; | |
1020 | textab[ID].angle = 0.0; | |
1021 | ||
1022 | textab[ID].Gen = GL_OBJECT_LINEAR; | |
1023 | textab[ID].Light = texdata[textab[ID].data].status == TEXDATA_1D ? GL_DECAL : GL_MODULATE; | |
1024 | textab[ID].Wrap = texdata[textab[ID].data].status == TEXDATA_1D ? GL_CLAMP : GL_REPEAT; | |
1025 | memcpy(textab[ID].Plane1, sgenparams, sizeof(sgenparams)); | |
1026 | memcpy(textab[ID].Plane2, tgenparams, sizeof(tgenparams)); | |
1027 | textab[ID].Render = texdata[textab[ID].data].status == TEXDATA_1D ? GL_NEAREST : GL_LINEAR; | |
1028 | } | |
1029 | ||
1030 | /*----------------------------------------------------------------------*/ | |
1031 | /* Transfere de donnee des donnees internes a la structure TransferData */ | |
1032 | void TransferTexture_To_Data(TextureID ID, TextureData *TransfDt) | |
1033 | { | |
1034 | /* affectations */ | |
1035 | strcpy(TransfDt->path, texdata[textab[ID].data].imageFileName); | |
1036 | TransfDt->gen = textab[ID].Gen; | |
1037 | TransfDt->wrap = textab[ID].Wrap; | |
1038 | TransfDt->render = textab[ID].Light; | |
1039 | TransfDt->scalex = textab[ID].scalex; | |
1040 | TransfDt->scaley = textab[ID].scaley; | |
1041 | TransfDt->transx = textab[ID].transx; | |
1042 | TransfDt->transy = textab[ID].transy; | |
1043 | TransfDt->angle = textab[ID].angle; | |
1044 | memcpy(TransfDt->plane1, textab[ID].Plane1, sizeof(SizeType)); | |
1045 | memcpy(TransfDt->plane2, textab[ID].Plane2, sizeof(SizeType)); | |
1046 | } | |
1047 | ||
1048 | /*----------------------------------------------------------------------*/ | |
1049 | /* Transfere de donnee de la structure TransferData aux donnees internes */ | |
1050 | void TransferData_To_Texture(TextureData *TransfDt, TextureID *newID) | |
1051 | { | |
1052 | TextureID ID; | |
1053 | ||
1054 | /* Affectations */ | |
1055 | FreeTexture(*newID); | |
1056 | ID = GetTexture2DMipMap(TransfDt->path); | |
1057 | ||
1058 | if(IsTextureValid(ID)) | |
1059 | { | |
1060 | /* Affectation de l id courant */ | |
1061 | *newID = ID; | |
1062 | ||
1063 | /* Donnees concernant les caracteristiques de la texture */ | |
1064 | strcpy(texdata[textab[ID].data].imageFileName, TransfDt->path); | |
1065 | textab[ID].Gen = TransfDt->gen; | |
1066 | textab[ID].Wrap = TransfDt->wrap; | |
1067 | textab[ID].Light = TransfDt->render; | |
1068 | textab[ID].scalex = TransfDt->scalex; | |
1069 | textab[ID].scaley = TransfDt->scaley; | |
1070 | textab[ID].transx = TransfDt->transx; | |
1071 | textab[ID].transy = TransfDt->transy; | |
1072 | textab[ID].angle = TransfDt->angle; | |
1073 | memcpy(textab[ID].Plane1, TransfDt->plane1, sizeof(SizeType)); | |
1074 | memcpy(textab[ID].Plane2, TransfDt->plane2, sizeof(SizeType)); | |
1075 | } | |
1076 | } |