Bonjour tout le monde, :]
J'ai un petit souci avec la fonction gluBuild2DMipmaps (OpenGL) en environnement multi-thread. Je m'explique : ...
J'ai créé une classe Texture comportant une méthode publique "load()". Cette fonction charge un fichier image et le transforme en texture OpenGL. Voici son code :
J'appelle cette méthode de la façon la plus simple qui soit, à savoir que dans ma fonction main() j'ai ça :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 int Texture::load() { // Loading the image file SDL_Surface * surfaceImage = IMG_Load("/home/test/image_file.png"); if (surfaceImage == NULL) { return ERROR; } // Mask Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif // Format SDL_PixelFormat format = *(surfaceImage->format); format.BitsPerPixel = 32; format.BytesPerPixel = 4; format.Rmask = rmask; format.Gmask = gmask; format.Bmask = bmask; format.Amask = amask; SDL_Surface * surfaceGL = SDL_ConvertSurface(surfaceImage, &format, SDL_SWSURFACE); // Flipping the surface SDL_Surface * flipedSurfaceGL = SDL_CreateRGBSurface(SDL_SWSURFACE, surfaceGL->w, surfaceGL->h, surfaceGL->format->BitsPerPixel, surfaceGL->format->Rmask, surfaceGL->format->Gmask, surfaceGL->format->Bmask, surfaceGL->format->Amask); SDL_LockSurface(surfaceGL); SDL_LockSurface(flipedSurfaceGL); int pitch = surfaceGL->pitch; for (int i = 0; i < surfaceGL->h; i++) { memcpy(&((unsigned char* )flipedSurfaceGL->pixels)[i*pitch], &((unsigned char* )surfaceGL->pixels)[(surfaceGL->h - 1 - i)*pitch], pitch); } SDL_UnlockSurface(flipedSurfaceGL); SDL_UnlockSurface(surfaceGL); // Building the texture glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glBindTexture(GL_TEXTURE_2D, textureId); gluBuild2DMipmaps(GL_TEXTURE_2D, 4, flipedSurfaceGL->w, flipedSurfaceGL->h, GL_RGBA,GL_UNSIGNED_BYTE, flipedSurfaceGL->pixels); // Anti-aliasing glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); SDL_FreeSurface(flipedSurfaceGL); SDL_FreeSurface(surfaceGL); SDL_FreeSurface(surfaceImage); return OK; }
La fonction "refreshDisplay()" ne sert ici qu'à mettre à jour mon VBO. Elle n'est pas l'objet de ce topique car, a priori, elle fonctionne bien et le problème ne se situe pas là.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 ... Texture * maTexture = listeLecture.at(j); maTexture->load(); refreshDisplay(); ...
D'ailleurs tout ce que j'ai donné jusque là fonctionne à merveille. Avec ce code j'arrive à afficher en texture le fichier image indiqué dans la méthode "load()".
Le problème vient du fait que je veux appeler cette fonction dans un autre thread que le principal. J'ai donc fait le choix d'utiliser la bibliothèque pthread pour cela.
Concrètement j'ai transformé mon code d'appel en ceci :
La fonction "startThread()" comporte juste une ligne et lance une fonction "actionThread()" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 ... Texture * maTexture = listeLecture.at(j); maTexture->startThread(); ...
Enfin, cette fonction "actionThread()" comporte les 2 lignes déjà citées :
Code : Sélectionner tout - Visualiser dans une fenêtre à part pthread_create(&thread, NULL, &actionThread, NULL);
Et c'est là que le bât blesse! En effet : le thread se lance bien, le programme rentre dans la fonction "load()", arrive jusqu'à la fonction "gluBuild2DMipmaps()" et ... plante! J'ai un magnifique seg fault en plein dans cette fonction. Je ne sais pas d'où il vient et je sollicite votre aide pour en déterminer la cause.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 load(); refreshDisplay();
S'il s'agit d'une incompatibilité entre OpenGL et pthread quelqu'un en connaitrait-il l'explication ? Je sais qu'OpenGL est une machine à états, néanmoins je ne pense pas avoir modifié l'ordre des appels. D'autant que je bloque (avec un sémaphore) le thread principal en attendant que le nouveau thread se termine...
Merci et bon week-end.
PS : Au cas où cela servirait : j'ai initialisé SDL et OpenGL dans mon thread principal avec le code suivant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 // Init SDL if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) == -1) { return ERROR; } SDL_SetVideoMode(1600, 600, 16, SDL_ANYFORMAT | SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_OPENGL); glewInit(); glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST);
Partager