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