1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
21 * Gestion des textures sous OpenGL
26 * Les textures sont toujours initialisee avec des parametres par defaut
27 * texture 1D: WRAP_S = CLAMP
28 * MAG_FILTER = NEAREST
29 * generation de texture automatique en OBJECT_LINEAR
32 * texture 2D: WRAP_S/T = REPEAT
33 * MAG/MIN_FILTER = LINEAR
34 * generation de texture automatique en OBJECT_LINEAR
37 * texture 2D MipMap: WRAP_S/T = REPEAT
39 * MIN_FILTER = LINEAR_MIPMAP_NEAREST
40 * generation de texture automatique en OBJECT_LINEAR
43 * Historique des modifications
44 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45 * 22-05-97: PCT ; Creation
46 * 18-06-97: FMN ; Ajout entete
47 * 20-06-97: PCT ; Correction bug parametres par defaut texture 1D
48 * 30-06-97: PCT ; Correction bug rechargement de la texture courante
49 * 04-07-97: PCT ; suppression de l'utilisation de libimage.a de SGI
50 * 01-08-97: PCT ; suppression InitializeTextureBox()
51 * 04-08-97: FMN,PCT ; Portage WNT
52 * 05-08-97: FMN ; ajout GetTextureData...
53 * 10-09-97: PCT ; ajout commentaires. GetTexture() ne doit pas
54 * etre utilisee dans Cas.Cade ( le chargement est
55 * fait par Graphic3d )
56 * 06-10-97: FMN ; Portage HP
57 * 14-10-97: FMN ; Ajout OpenGl_Extension
58 * 22-10-97: FMN ; Meilleure gestion de l'extension glXGetCurrentDisplayEXT
59 * 04-11-97: FMN ; Gestion des differentes versions GLX
60 * 19-11-97: FMN ; Ajout GetCurrentDisplay plus simple que glXGetCurrentDisplayEXT
61 * 04-12-97: FMN ; On suppose que l'on travaille en OpenGL1.1 (cf OpenGl_Extension)
62 * 17-12-97: FMN ; Probleme compilation SGI
63 * 17-12-97: FMN ; Probleme sur Optimisation sur MyBindTextureEXT()
64 * Le test sur la texture courante doit tenir compte du contexte.
65 * 22-07-98: FGU ; Ajout fonctions TransferTexture_To_Data() et TransferData_To_Texture()
73 #include <OpenGl_GlCore11.hxx>
74 #include <OpenGl_Display.hxx>
75 #include <OpenGl_TextureBox.hxx>
76 #include <OpenGl_ResourceTexture.hxx>
77 #include <OpenGl_Context.hxx>
79 #include <GL/glu.h> // gluBuild2DMipmaps()
81 #include <NCollection_Vector.hxx>
83 typedef enum {TEXDATA_NONE, TEXDATA_1D, TEXDATA_2D, TEXDATA_2DMM} texDataStatus;
84 typedef enum {TEX_NONE, TEX_ALLOCATED} texStatus;
86 typedef GLfloat SizeType[4];
88 typedef int TextureDataID;
89 #define TEXTUREDATA_ERROR -1
93 char imageFileName[128];
94 int imageWidth, imageHeight;
112 NCollection_Vector<contextData> contextdata;
121 GLfloat scalex, scaley;
122 GLfloat transx, transy;
125 DEFINE_STANDARD_ALLOC
129 /*----------------------------------------------------------------------*/
131 * Variables statiques
134 static NCollection_Vector<texDraw> textab;
136 static NCollection_Vector<texData> texdata;
138 static TextureDataID current_texture_data = TEXTUREDATA_ERROR;
139 static TextureID current_texture = TEXTUREBOX_ERROR;
141 static GLfloat sgenparams[] = { 1.0 ,0.0 ,0.0 ,0.0};
142 static GLfloat tgenparams[] = { 0.0 ,1.0 ,0.0 ,0.0};
144 static GLenum status2type[] = { GL_NONE, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_2D };
146 /*----------------------------------------------------------------------*/
151 /*----------------------------------------------------------------------*/
153 * recherche l'existence de datas de texture par son nom
155 static TextureDataID FindTextureData(char *FileName)
157 for (int i = 0; i < texdata.Length(); i++)
159 if ( texdata(i).status != TEXDATA_NONE && strcmp(FileName, texdata(i).imageFileName) == 0 )
165 return TEXTUREDATA_ERROR;
168 /*----------------------------------------------------------------------*/
170 * recherche un emplacement de data texture libre
172 static TextureDataID FindFreeTextureData(void)
174 for (int i = 0; i < texdata.Length(); i++)
176 if (texdata(i).status == TEXDATA_NONE)
183 texdata.Append(aTexData);
184 return texdata.Length() - 1;
187 /*----------------------------------------------------------------------*/
189 * recherche un emplacement de texture libre
191 static TextureID FindFreeTexture(void)
193 for (int i = 0; i < textab.Length(); i++)
195 if (textab(i).status == TEX_NONE)
202 textab.Append(aTexDraw);
203 return textab.Length() - 1;
206 /*----------------------------------------------------------------------*/
208 * regarde si la texture a ete definie pour le contexte courant
210 static int FindTextureContext(TextureID ID)
214 GLCONTEXT cur = GET_GL_CONTEXT();
215 for (i=0; i<textab(ID).contextdata.Length(); i++)
216 if (textab(ID).contextdata(i).context == cur)
219 return TEXTUREBOX_ERROR;
222 /*----------------------------------------------------------------------*/
224 * chargement d'une texture suivant son type
226 static void LoadTexture(TextureID ID)
230 data = textab(ID).data;
231 switch (texdata(data).status)
234 glTexImage1D(GL_TEXTURE_1D, 0, 4,
235 texdata(data).imageWidth, 0,
236 GL_RGBA, GL_UNSIGNED_BYTE, texdata(data).image);
240 glTexImage2D(GL_TEXTURE_2D, 0, 4,
241 texdata(data).imageWidth, texdata(data).imageHeight, 0,
242 GL_RGBA, GL_UNSIGNED_BYTE, texdata(data).image);
246 gluBuild2DMipmaps(GL_TEXTURE_2D, 4,
247 texdata(data).imageWidth,
248 texdata(data).imageHeight,
249 GL_RGBA, GL_UNSIGNED_BYTE, texdata(data).image);
256 /*----------------------------------------------------------------------*/
258 * les parametres d'initialisation d'une texture
259 * NE PAS METTRE DANS UNE DISPLAY LIST POUR L'INSTANT ( pb avec les matrices )
261 static void SetTextureParam(TextureID ID)
267 data = textab(ID).data;
268 glGetIntegerv(GL_MATRIX_MODE, &cur_matrix);
271 * MISE EN PLACE DE LA MATRICE DE TEXTURE
273 glMatrixMode(GL_TEXTURE);
275 /* if (textab(ID).Gen != GL_SPHERE_MAP)
277 glScalef(textab(ID).scalex, textab(ID).scaley, 1.0);
278 glTranslatef(-textab(ID).transx, -textab(ID).transy, 0.0);
279 glRotatef(-textab(ID).angle, 0.0, 0.0, 1.0);
284 * GENERATION AUTOMATIQUE DE TEXTURE
286 switch (textab(ID).Gen)
288 case GL_OBJECT_LINEAR:
289 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
290 glTexGenfv(GL_S, GL_OBJECT_PLANE, textab(ID).Plane1);
291 if (texdata(data).status != TEXDATA_1D)
293 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
294 glTexGenfv(GL_T, GL_OBJECT_PLANE, textab(ID).Plane2);
299 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
300 if (texdata(data).status != TEXDATA_1D)
301 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
305 glMatrixMode(GL_MODELVIEW);
309 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
310 glTexGenfv(GL_S, GL_EYE_PLANE, textab(ID).Plane1);
312 if (texdata(data).status != TEXDATA_1D)
314 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
315 glTexGenfv(GL_T, GL_EYE_PLANE, textab(ID).Plane2);
324 * RENDU DE LA TEXTURE AVEC LES LUMIERES
326 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, textab(ID).Light);
330 * LISSAGE DE LA TEXTURE
332 switch (texdata(data).status)
336 glTexParameteri(texdata(data).type, GL_TEXTURE_MAG_FILTER, textab(ID).Render);
337 glTexParameteri(texdata(data).type, GL_TEXTURE_MIN_FILTER, textab(ID).Render);
341 if (textab(ID).Render == GL_NEAREST)
343 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
344 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
360 switch (texdata(data).status)
363 glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, textab(ID).Wrap);
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, textab(ID).Wrap);
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, textab(ID).Wrap);
375 glMatrixMode(cur_matrix);
378 /*----------------------------------------------------------------------*/
380 * simulation du glGenTexturesEXT pour un context
382 static void MyGenTextureEXT (TextureID ID)
384 TextureDataID data = textab(ID).data;
385 contextData aContextData;
387 aContextData.context = GET_GL_CONTEXT();
388 aContextData.drawable = GET_GLDEV_CONTEXT();
389 glGenTextures (1, &aContextData.number);
390 textab(ID).contextdata.Append(aContextData);
391 glBindTexture (texdata(data).type, aContextData.number);
395 /*----------------------------------------------------------------------*/
397 * simulation du glBindTextureEXT
399 static void MyBindTextureEXT (TextureID ID, int Context)
401 TextureDataID data = textab(ID).data;
402 if (texdata(data).status == TEXDATA_NONE)
405 GLenum aParamName = texdata(data).status == TEXDATA_1D ?
406 GL_TEXTURE_BINDING_1D : GL_TEXTURE_BINDING_2D;
409 glGetIntegerv (aParamName, &aCurrTex);
410 if (textab(ID).contextdata(Context).number != aCurrTex)
412 glBindTexture (texdata(data).type, textab(ID).contextdata(Context).number);
416 /*----------------------------------------------------------------------*/
418 * installation de la texture pour le dernier contexte
420 static int InstallTextureInContext(TextureID ID)
423 printf("InstallTextureInContext::installation de la texture dans le context\n");
428 printf("InstallTextureInContext::context ok\n");
433 /*----------------------------------------------------------------------*/
434 static TextureID GetTextureData(char *FileName, texDataStatus status, const GLint width, const GLint height, const void *data)
439 /* essait de trouver la texture */
440 i = FindTextureData(FileName);
441 if (i == TEXTUREDATA_ERROR)
444 printf("GetTextureData::la texture %s n'existe pas => chargement\n", FileName);
446 /* creation d'une texture */
447 i = FindFreeTextureData();
448 if (i == TEXTUREDATA_ERROR) return TEXTUREBOX_ERROR;
450 texdata(i).share_count = 0;
451 strcpy(texdata(i).imageFileName, FileName);
452 texdata(i).image = new GLubyte[width*height*4];
453 memcpy(texdata(i).image, data, (width*height*4));
454 texdata(i).imageWidth = width;
455 texdata(i).imageHeight = height;
457 if (texdata(i).image == NULL) return TEXTUREBOX_ERROR;
459 texdata(i).status = status;
460 texdata(i).type = status2type[status];
463 j = FindFreeTexture();
464 if (j != TEXTUREBOX_ERROR)
467 printf("GetTextureData::installation texture pour obj %d\n", j);
469 textab(j).contextdata.Clear();
471 textab(j).status = TEX_ALLOCATED;
472 texdata(i).share_count++;
474 SetTextureDefaultParams(j);
477 printf("GetTextureData::texture %s(%d) texture %d count=%d\n", texdata(i).imageFileName, i, j, texdata(i).share_count);
481 if (texdata(i).share_count != 0)
482 delete [] texdata(i).image;
487 /*----------------------------------------------------------------------*/
489 * Fonctions publiques
493 /*----------------------------------------------------------------------*/
495 GLboolean IsTextureValid(TextureID ID)
497 if ( (ID < 0) || (ID >= textab.Length()) )
500 if (textab.Length() > 0)
502 return textab(ID).status == TEX_ALLOCATED;
510 /*----------------------------------------------------------------------*/
512 TextureID GetTextureData1D(char *FileName, const GLint width, const GLint height, const void *data)
515 printf("GetTextureData1D::loading 1d %s \n", FileName);
517 return GetTextureData(FileName, TEXDATA_1D, width, height, data);
520 /*----------------------------------------------------------------------*/
522 TextureID GetTextureData2D(char *FileName, const GLint width, const GLint height, const void *data)
525 printf("GetTextureData2D::loading 2d %s \n", FileName);
527 return GetTextureData(FileName, TEXDATA_2D, width, height, data);
530 /*----------------------------------------------------------------------*/
532 TextureID GetTextureData2DMipMap(char *FileName, const GLint width, const GLint height, const void *data)
535 printf("GetTextureData2DMipMap::loading 2dmm %s \n", FileName);
537 return GetTextureData(FileName, TEXDATA_2DMM, width, height, data);
541 /*----------------------------------------------------------------------*/
543 void SetCurrentTexture(TextureID ID)
547 if (!IsTextureValid(ID)) return;
549 context = FindTextureContext(ID);
551 /* la texture n'existe pas dans ce contexte */
552 if (context == TEXTUREBOX_ERROR)
555 printf("SetCurrentTexture::installation texture %d dans context\n", ID);
557 /* si on a une erreur pendant l'installation dans le context
558 * alors on installe la texture sans bind */
559 if (InstallTextureInContext(ID) == TEXTUREBOX_ERROR)
566 /*oui, alors on bind directement */
570 printf("SetCurrentTexture: utilisation du bind %d\n", ID);
572 MyBindTextureEXT(ID, context);
576 current_texture = ID;
577 current_texture_data = textab(ID).data;
580 /*----------------------------------------------------------------------*/
582 void FreeTexture (const Handle(OpenGl_Context)& theContext,
585 if (!IsTextureValid (ID))
590 TextureDataID data = textab(ID).data;
591 texdata(data).share_count--;
592 if (texdata(data).share_count == 0)
594 // release texture data
595 delete [] texdata(data).image;
597 // liberation de la texture dans tous les contextes
598 for (int i = 0; i < textab(ID).contextdata.Length(); ++i)
600 Handle(OpenGl_ResourceTexture) aResource = new OpenGl_ResourceTexture (textab(ID).contextdata(i).number);
602 if (!theContext.IsNull())
604 theContext->DelayedRelease (aResource);
608 texdata(data).status = TEXDATA_NONE;
610 textab(ID).contextdata.Clear();
613 textab(ID).status = TEX_NONE;
615 current_texture_data = TEXTUREDATA_ERROR;
618 /*----------------------------------------------------------------------*/
620 void EnableTexture(void)
622 if (!IsTextureValid(current_texture)) return;
624 switch (texdata(current_texture_data).status)
627 if (textab(current_texture).Gen != GL_NONE)
628 glEnable(GL_TEXTURE_GEN_S);
629 glEnable(GL_TEXTURE_1D);
634 if (textab(current_texture).Gen != GL_NONE)
636 glEnable(GL_TEXTURE_GEN_S);
637 glEnable(GL_TEXTURE_GEN_T);
639 glEnable(GL_TEXTURE_2D);
646 /*----------------------------------------------------------------------*/
648 void DisableTexture(void)
650 if ( !IsTextureEnabled() )
652 if ( !IsTextureValid( current_texture ) )
655 switch (texdata(current_texture_data).status)
658 if (textab(current_texture).Gen != GL_NONE)
659 glDisable(GL_TEXTURE_GEN_S);
660 glDisable(GL_TEXTURE_1D);
665 if (textab(current_texture).Gen != GL_NONE)
667 glDisable(GL_TEXTURE_GEN_S);
668 glDisable(GL_TEXTURE_GEN_T);
670 glDisable(GL_TEXTURE_2D);
677 /*----------------------------------------------------------------------*/
679 GLboolean IsTextureEnabled(void)
681 GLboolean isEnabled1D= GL_FALSE, isEnabled2D= GL_FALSE;
682 glGetBooleanv( GL_TEXTURE_1D, &isEnabled1D );
683 glGetBooleanv( GL_TEXTURE_2D, &isEnabled2D );
684 return isEnabled1D || isEnabled2D;
687 /*----------------------------------------------------------------------*/
689 void SetTextureModulate(TextureID ID)
691 if (!IsTextureValid(ID)) return;
693 textab(ID).Light = GL_MODULATE;
696 /*----------------------------------------------------------------------*/
698 void SetTextureDecal(TextureID ID)
700 if (!IsTextureValid(ID)) return;
702 textab(ID).Light = GL_DECAL;
705 /*----------------------------------------------------------------------*/
707 void SetTextureClamp(TextureID ID)
709 if (!IsTextureValid(ID)) return;
711 textab(ID).Wrap = GL_CLAMP;
714 /*----------------------------------------------------------------------*/
716 void SetTextureRepeat(TextureID ID)
718 if (!IsTextureValid(ID)) return;
720 textab(ID).Wrap = GL_REPEAT;
723 /*----------------------------------------------------------------------*/
725 /* gestion de la facon d'appliquer la texture */
726 void SetModeObject(TextureID ID, const GLfloat sparams[4], const GLfloat tparams[4])
728 if (!IsTextureValid(ID)) return;
730 textab(ID).Gen = GL_OBJECT_LINEAR;
731 if (sparams != NULL) memcpy(textab(ID).Plane1, sparams, sizeof(sgenparams));
732 else memcpy(textab(ID).Plane1, sgenparams, sizeof(sgenparams));
734 if (texdata(textab(ID).data).status != TEXDATA_1D) {
735 if (tparams != NULL) memcpy(textab(ID).Plane2, tparams, sizeof(tgenparams));
736 else memcpy(textab(ID).Plane2, tgenparams, sizeof(tgenparams));
740 /*----------------------------------------------------------------------*/
742 void SetModeSphere(TextureID ID)
744 if (!IsTextureValid(ID)) return;
746 textab(ID).Gen = GL_SPHERE_MAP;
749 /*----------------------------------------------------------------------*/
751 void SetModeEye(TextureID ID, const GLfloat sparams[4], const GLfloat tparams[4])
753 if (!IsTextureValid(ID)) return;
755 textab(ID).Gen = GL_EYE_LINEAR;
756 if (sparams != NULL) memcpy(textab(ID).Plane1, sparams, sizeof(sgenparams));
757 else memcpy(textab(ID).Plane1, sgenparams, sizeof(sgenparams));
759 if (texdata(textab(ID).data).status != TEXDATA_1D) {
760 if (tparams != NULL) memcpy(textab(ID).Plane2, tparams, sizeof(tgenparams));
761 else memcpy(textab(ID).Plane2, tgenparams, sizeof(tgenparams));
765 /*----------------------------------------------------------------------*/
767 void SetModeManual(TextureID ID)
769 if (!IsTextureValid(ID)) return;
771 textab(ID).Gen = GL_NONE;
774 /*----------------------------------------------------------------------*/
776 void SetRenderNearest(TextureID ID)
778 if (!IsTextureValid(ID)) return;
780 textab(ID).Render = GL_NEAREST;
783 /*----------------------------------------------------------------------*/
785 void SetRenderLinear(TextureID ID)
787 if (!IsTextureValid(ID)) return;
789 textab(ID).Render = GL_LINEAR;
792 /*----------------------------------------------------------------------*/
794 void SetTexturePosition(TextureID ID,
795 GLfloat scalex, GLfloat scaley,
796 GLfloat transx, GLfloat transy,
799 textab(ID).scalex = scalex;
800 textab(ID).scaley = scaley;
801 textab(ID).transx = transx;
802 textab(ID).transy = transy;
803 textab(ID).angle = angle;
806 /*----------------------------------------------------------------------*/
808 void SetTextureDefaultParams(TextureID ID)
810 if (!IsTextureValid(ID)) return;
813 printf("SetTextureDefaultParams::set parm par defaut textures\n");
817 textab(ID).scalex = 1.0;
818 textab(ID).scaley = 1.0;
819 textab(ID).transx = 0.0;
820 textab(ID).transy = 0.0;
821 textab(ID).angle = 0.0;
823 textab(ID).Gen = GL_OBJECT_LINEAR;
824 textab(ID).Light = texdata(textab(ID).data).status == TEXDATA_1D ? GL_DECAL : GL_MODULATE;
825 textab(ID).Wrap = texdata(textab(ID).data).status == TEXDATA_1D ? GL_CLAMP : GL_REPEAT;
826 memcpy(textab(ID).Plane1, sgenparams, sizeof(sgenparams));
827 memcpy(textab(ID).Plane2, tgenparams, sizeof(tgenparams));
828 textab(ID).Render = texdata(textab(ID).data).status == TEXDATA_1D ? GL_NEAREST : GL_LINEAR;
831 /*----------------------------------------------------------------------*/
832 /* Transfere de donnee des donnees internes a la structure TransferData */
833 void TransferTexture_To_Data(TextureID ID, TextureData *TransfDt)
836 strcpy(TransfDt->path, texdata(textab(ID).data).imageFileName);
837 TransfDt->gen = textab(ID).Gen;
838 TransfDt->wrap = textab(ID).Wrap;
839 TransfDt->render = textab(ID).Light;
840 TransfDt->scalex = textab(ID).scalex;
841 TransfDt->scaley = textab(ID).scaley;
842 TransfDt->transx = textab(ID).transx;
843 TransfDt->transy = textab(ID).transy;
844 TransfDt->angle = textab(ID).angle;
845 memcpy(TransfDt->plane1, textab(ID).Plane1, sizeof(SizeType));
846 memcpy(TransfDt->plane2, textab(ID).Plane2, sizeof(SizeType));