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