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