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 :
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;
}
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
...
Texture * maTexture = listeLecture.at(j);
maTexture->load();
refreshDisplay();
...
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à.

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 :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
...
Texture * maTexture = listeLecture.at(j);
maTexture->startThread();
...
La fonction "startThread()" comporte juste une ligne et lance une fonction "actionThread()" :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
pthread_create(&thread, NULL, &actionThread, NULL);
Enfin, cette fonction "actionThread()" comporte les 2 lignes déjà citées :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
load();
refreshDisplay();
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.

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);