0023022: This is desirable to access OpenGl extensions and core API (1.2+) in one...
[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 * 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 */
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55
56 #include <OpenGl_GlCore11.hxx>
57 #include <OpenGl_Display.hxx>
58 #include <OpenGl_TextureBox.hxx>
59 #include <OpenGl_ImageBox.hxx>
60 #include <OpenGl_Memory.hxx>
61 #include <OpenGl_ResourceCleaner.hxx>
62 #include <OpenGl_ResourceTexture.hxx>
63
64 #include <GL/glu.h> // gluBuild2DMipmaps()
65
66 #define GROW_TEXTURES 8
67 #define GROW_TEXTURES_DATA 8
68 #define GROW_CONTEXT 8
69
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;
86   DEFINE_STANDARD_ALLOC
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
111   DEFINE_STANDARD_ALLOC
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
136 /*----------------------------------------------------------------------*/
137 /*
138 * Fonctions privees
139 */
140
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     {
186       textures_data_count = Max (textures_data_count, i + 1);
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     {
222       textures_count = Max (textures_count, i + 1);
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 */
405 static void MyGenTextureEXT (TextureID ID)
406 {
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++;
417 }
418
419 /*----------------------------------------------------------------------*/
420 /*
421 * simulation du glBindTextureEXT
422 */
423 static void MyBindTextureEXT (TextureID ID, int Context)
424 {
425   TextureDataID data = textab[ID].data;
426   if (texdata[data].status == TEXDATA_NONE)
427     return;
428
429   GLenum aParamName = texdata[data].status == TEXDATA_1D ? 
430         GL_TEXTURE_BINDING_1D : GL_TEXTURE_BINDING_2D;
431
432   GLint aCurrTex = -1;
433   glGetIntegerv (aParamName, &aCurrTex);
434   if (textab[ID].number[Context] != aCurrTex)
435   {
436     glBindTexture (texdata[data].type, textab[ID].number[Context]);
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;
744   bool notResource = false; // if there old-style texture deletion
745
746   GLCONTEXT cur_context;
747   GLDRAWABLE cur_drawable;
748   int i;
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   {      
756     // liberation des datas de la textures
757     free(texdata[data].image);
758
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)
762     {
763       cur_context = 0;
764       bool isResource = false; 
765
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])) )
770         {
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;
785         }
786       }
787
788       if( !isResource && cur_context )
789         glFinish();
790     }
791
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     }
801
802     free(textab[ID].context);
803     free(textab[ID].drawable);
804     free(textab[ID].use_bind_texture);
805     free(textab[ID].number);
806   }
807
808   textab[ID].status = TEX_NONE;
809   if (ID + 1 == textures_count)
810   {
811     --textures_count;
812   }
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 */
925 void SetModeObject(TextureID ID, const GLfloat sparams[4], const GLfloat tparams[4])
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
950 void SetModeEye(TextureID ID, const GLfloat sparams[4], const GLfloat tparams[4])
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 }