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