Problem with a multithreaded GL app

Started by
1 comment, last by Gothmog 18 years, 5 months ago
I have a problem with a very simple multithreaded openGL program. I wanted to write a simple app which would create mutiple windows, each with OpenGL. But when I run it, only one (sometimes two) window initializes properly. Every time SetPixelFormat() returns FALSE, and i get a 'The specified resource type cannot be found in the image file' system error message. Here's the full source:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>

#pragma comment(lib,"gdi32.lib")
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")

DWORD WINAPI GL_Thread(LPVOID);
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam);

void ErrorMsg()
{
	LPVOID lpMsgBuf;
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
				  FORMAT_MESSAGE_FROM_SYSTEM|
				  FORMAT_MESSAGE_IGNORE_INSERTS,
				  NULL,
				  GetLastError(),
				  MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
				  (LPTSTR)&lpMsgBuf,
				  0,
				  NULL);

	MessageBox(NULL,(LPCTSTR)lpMsgBuf,0,MB_ICONINFORMATION);

	LocalFree( lpMsgBuf );
}

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int)
{
	WNDCLASS wc=
	{
		CS_OWNDC,
		WndProc,
		0,0,
		hInst,
		NULL,
		NULL,
		(HBRUSH)NULL,
		NULL,
		"GL_TestWndClass"
	};

	RegisterClass(&wc);

	DWORD threadIds[3];
	HANDLE threads[3]=
	{
		CreateThread(NULL,0,GL_Thread,(LPVOID)hInst,0,&threadIds[0]),
		CreateThread(NULL,0,GL_Thread,(LPVOID)hInst,0,&threadIds[1]),
		CreateThread(NULL,0,GL_Thread,(LPVOID)hInst,0,&threadIds[2])
	};

	WaitForMultipleObjects(3,threads,TRUE,INFINITE);

	UnregisterClass("GL_TestWndClass",hInst);

	return 0;
}

DWORD WINAPI GL_Thread(LPVOID param)
{
	HINSTANCE hInst=(HINSTANCE)param;

	HWND hwnd=CreateWindow("GL_TestWndClass",
						   "GL_Test window",
						   WS_VISIBLE|WS_POPUP|WS_SYSMENU|WS_CAPTION,
						   CW_USEDEFAULT,CW_USEDEFAULT,
						   256,256,
						   NULL,
						   NULL,
						   hInst,
						   NULL);

	if(!hwnd)
	{
		MessageBox(NULL,"Could not create the window",0,MB_ICONERROR);
		ErrorMsg();
		return 1;
	}

	HDC dc=GetDC(hwnd);
	if(!dc)
	{
		MessageBox(NULL,"DC is invalid",0,MB_ICONERROR);
		ErrorMsg();
		return 2;
	}

	PIXELFORMATDESCRIPTOR pfd=
	{
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA,
		32,
		0,0,0,0,0,0,0,0,
		0,0,0,0,0,
		16,
		0,
		0,
		0,0,0,0,0
	};

	int iFormat=ChoosePixelFormat(dc,&pfd);
	if(!iFormat)
	{
		MessageBox(NULL,"Could not choose pixel format",0,MB_ICONERROR);
		ErrorMsg();
		return 3;
	}

	if(!SetPixelFormat(dc,iFormat,&pfd))
	{
		MessageBox(NULL,"Could not set pixel format",0,MB_ICONERROR);
		ErrorMsg();
		return 4;
	}

	HGLRC rc=wglCreateContext(dc);
	if(!rc)
	{
		MessageBox(NULL,"Could not create the rendering context",0,MB_ICONERROR);
		ErrorMsg();
		return 5;
	}

	if(!wglMakeCurrent(dc,rc))
	{
		MessageBox(NULL,"Could not make the rendering context current",0,MB_ICONERROR);
		ErrorMsg();
		return 6;
	}

	MSG msg;
	bool bRun=true;

	GLUquadricObj *quad=gluNewQuadric();
	gluQuadricNormals(quad,GLU_SMOOTH);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
	gluPerspective(90.0f,1.0f,1.0f,100.0f);
        glMatrixMode(GL_MODELVIEW);

	glTranslatef(0.0f,0.0f,-15.0f);

	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHTING);
	glDisable(GL_CULL_FACE);

	while(bRun)
	{
		while(PeekMessage(&msg,hwnd,0,0,PM_REMOVE))
		{
			if(msg.message==WM_QUIT)
				bRun=false;
			else
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}

		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
		
		glRotatef(0.1f,1.0f,1.0f,1.0f);
		gluCylinder(quad,5,5,10,20,5);

		glFlush();
		SwapBuffers(dc);
	}

	gluDeleteQuadric(quad);

	wglMakeCurrent(NULL,NULL);
	wglDeleteContext(rc);

	return (DWORD)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	switch(msg)
	{
	case WM_CLOSE:
		PostQuitMessage(0);
		break;

	default:
		return DefWindowProc(hwnd,msg,wparam,lparam);
	}

	return 0;
}


Anybody has an idea what's happening? Thanks in advance. [Edited by - Gothmog on November 6, 2005 2:00:41 AM]
Advertisement
Perhaps this is your problem

SetPixelFormat description from msdn
Quote:
If hdc references a window, calling the SetPixelFormat function also changes the pixel format of the window. Setting the pixel format of a window more than once can lead to significant complications for the Window Manager and for multithread applications, so it is not allowed. An application can only set the pixel format of a window one time. Once a window's pixel format is set, it cannot be changed.
"Pfft, Facts! Facts can be used to prove anything!" -- Homer J. Simpson
Ok, but I set the format for a single window only once. So this isn't the problem.

This topic is closed to new replies.

Advertisement