Skip to main content
GameDev.net gamedev.net
🔒 Locked 🎮 Unity

glClear() causing crash on alt+tab.

Started by ScottC Mar 9, 2006 at 2:40 PM 11 replies 4k views
Original Post
ScottC
ScottC
For some reason when I alt+tab to my desktop while in fullscreen mode, my 3d engine crashes. The line that is causing it is glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Without GL_DEPTH_BUFFER_BIT though, it does not crash. Does anybody have any idea why this is causing a crash when alt+tabbing from fullscreen? How can I fix it? Here is my OpenGL init code:

void GraphicsSystem::oglinit(){
	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );			// tell SDL that the GL drawing is going to be double buffered
	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE,   32);			// size of depth buffer
	SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 0);			// we aren't going to use the stencil buffer
	SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 0);			// this and the next three lines set the bits allocated per pixel -
	SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 0);		// - for the accumulation buffer to 0
	SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 0);
	SDL_GL_SetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, 0);
	glClearColor (0.0f, 0.0f, 0.0f, 0.5f);						// Black Background
	glClearDepth (1.0f);										// Depth Buffer Setup
	glDepthFunc  (GL_LEQUAL);									// The Type Of Depth Testing (Less Or Equal)
	glEnable     (GL_DEPTH_TEST);								// Enable Depth Testing
	glShadeModel (GL_SMOOTH);									// Select Smooth Shading
	glHint       (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Set Perspective Calculations To Most Accurate
	glEnable     (GL_TEXTURE_2D);								// Enable Texture Mapping
//	glEnable     (GL_CULL_FACE);								// Remove Back Face
	gr = ((1 + sqrt((double)5)) / 2);
}
My render code where the line that crashes it is:

void GraphicsSystem::Render(std::vector<int> scenegraph,Player* player){
	output = fopen("GLErrorLog.txt","w");
	fprintf(output,"%s\n",gluErrorString(glGetError()));	
	fclose(output);

	output = fopen("SDLErrorLog.txt","w");
	fprintf(output,"%s\n",SDL_GetError());	
	fclose(output);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// clear screen and depth buffer
	glLoadIdentity();										// reset modelview matrix
	glRotatef(player->xangle, 1.0f, 0.0f, 0.0f);
	glRotatef(player->yangle, 0.0f, 1.0f, 0.0f);
	glRotatef(player->zangle, 0.0f, 0.0f, 1.0f);
	glTranslatef(player->x,player->y,player->z);

	glColor3f(0.0f,0.6f,0.0f);
	glBegin(GL_LINES);

	for (float i = -100; i < 100;i++){
		glVertex3f(i,0,100);
		glVertex3f(i,0,-100);
	}
	for (float i = -100; i < 100;i++){
		glVertex3f(100,0,i);
		glVertex3f(-100,0,i);
	}
	glEnd();

	glBegin(GL_POINTS);
		glColor3f(1,0,0);
		glVertex3f(0,1,gr);
		glVertex3f(0,1,-gr);
		glVertex3f(0,-1,gr);
		glColor3f(0,1,0);
		glVertex3f(0,-1,-gr);
		
		glVertex3f(1,gr,0);
		glVertex3f(1,-gr,0);
		glColor3f(0,0,1);
		glVertex3f(-1,gr,0);
		glVertex3f(-1,-gr,0);

		glVertex3f(gr,0,1);
		glColor3f(1,1,1);
		glVertex3f(gr,0,-1);
		glVertex3f(-gr,0,1);
		glVertex3f(-gr,0,-1);
	glEnd();
	SDL_GL_SwapBuffers();
}
My 3D init code

void GraphicsSystem::oglinit3D(float fov,float aspect,float zNear,float zFar){
	glMatrixMode   (GL_PROJECTION);								// Select The Projection Matrix
	glLoadIdentity ();											// Reset The Projection Matrix
	gluPerspective(fov,aspect,zNear,zFar);
	glMatrixMode   (GL_MODELVIEW);								// Select The Modelview Matrix
//90,1,0.1f,100.0f
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);	// Nearest Filtered
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	// Nearest Filtered
}
and the main loop:

window::window(int width, int height,std::string WindowName){
	done = false;
	if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
	{
		fprintf( stderr, "Video initialization failed: %s\n",
			SDL_GetError( ) );
		SDL_Quit( );
	}
	atexit(SDL_Quit);
	SDL_WM_SetCaption(WindowName.c_str(), NULL);
	screen = SDL_SetVideoMode(width, height, 0, SDL_FULLSCREEN|SDL_OPENGL);
	if( !screen ) {
		fprintf(stderr, "Couldn't create a surface: %s\n",
			SDL_GetError());
		done = true;
	}
	SDL_ShowCursor(false);

	Player* player = new Player();						//Create new player
	GameTimer* timer = new GameTimer();					//Create new timer object
	GraphicsSystem* graphics = new GraphicsSystem();	//Create graphics object
	GameInput* input = new GameInput();					//Create game input object
	GameLogic* logic = new GameLogic();					//Create game logic object
	timer->Update();
	graphics->oglinit();
	graphics->oglinit3D(90,((float)width/(float)height),0.1f,100);

	std::vector<int> sg;

	while(!done)
	{	
		SDL_Event event;

		while ( SDL_PollEvent(&event) )
		{
			switch (event.type)
			{
			case SDL_QUIT:
				done = true;
				break;
			case SDL_KEYDOWN:
				if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
				break;
			}
		}
		input->Update();
		logic->UpdateGame(input->GetKeyState(),timer->GetDifference(),player,sg);
		graphics->oglinit3D(90,(float)(width/height),0.1f,100);
		graphics->Render(sg,player);
		timer->Update();
	}
	delete player;
	delete timer;
	delete graphics;
	delete input;
	delete logic;
}
(Yes I realize my scenegraph is of type int, just a placeholder.) [Edited by - ScottC on March 9, 2006 3:08:33 PM]
Boder
Boder
I think I hear your code asking for a [ source ] box. [grin]

OpenGL init code:
void GraphicsSystem::oglinit(){	SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );			// tell SDL that the GL drawing is going to be double buffered	SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE,   32);			// size of depth buffer	SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, 0);			// we aren't going to use the stencil buffer	SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 0);			// this and the next three lines set the bits allocated per pixel -	SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 0);		// - for the accumulation buffer to 0	SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 0);	SDL_GL_SetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, 0);	glClearColor (0.0f, 0.0f, 0.0f, 0.5f);						// Black Background	glClearDepth (1.0f);										// Depth Buffer Setup	glDepthFunc  (GL_LEQUAL);									// The Type Of Depth Testing (Less Or Equal)	glEnable     (GL_DEPTH_TEST);								// Enable Depth Testing	glShadeModel (GL_SMOOTH);									// Select Smooth Shading	glHint       (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// Set Perspective Calculations To Most Accurate	glEnable     (GL_TEXTURE_2D);								// Enable Texture Mapping//	glEnable     (GL_CULL_FACE);								// Remove Back Face	gr = ((1 + sqrt((double)5)) / 2);}


render code where the line that crashes it is:
void GraphicsSystem::Render(std::vector<int> scenegraph,Player* player){	output = fopen("GLErrorLog.txt","w");	fprintf(output,"%s\n",gluErrorString(glGetError()));		fclose(output);	output = fopen("SDLErrorLog.txt","w");	fprintf(output,"%s\n",SDL_GetError());		fclose(output);	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		// clear screen and depth buffer	glLoadIdentity();										// reset modelview matrix	glRotatef(player->xangle, 1.0f, 0.0f, 0.0f);	glRotatef(player->yangle, 0.0f, 1.0f, 0.0f);	glRotatef(player->zangle, 0.0f, 0.0f, 1.0f);	glTranslatef(player->x,player->y,player->z);	glColor3f(0.0f,0.6f,0.0f);	glBegin(GL_LINES);	for (float i = -100; i < 100;i++){		glVertex3f(i,0,100);		glVertex3f(i,0,-100);	}	for (float i = -100; i < 100;i++){		glVertex3f(100,0,i);		glVertex3f(-100,0,i);	}	glEnd();	glBegin(GL_POINTS);		glColor3f(1,0,0);		glVertex3f(0,1,gr);		glVertex3f(0,1,-gr);		glVertex3f(0,-1,gr);		glColor3f(0,1,0);		glVertex3f(0,-1,-gr);				glVertex3f(1,gr,0);		glVertex3f(1,-gr,0);		glColor3f(0,0,1);		glVertex3f(-1,gr,0);		glVertex3f(-1,-gr,0);		glVertex3f(gr,0,1);		glColor3f(1,1,1);		glVertex3f(gr,0,-1);		glVertex3f(-gr,0,1);		glVertex3f(-gr,0,-1);	glEnd();	SDL_GL_SwapBuffers();}


3D init code:
void GraphicsSystem::oglinit3D(float fov,float aspect,float zNear,float zFar){	glMatrixMode   (GL_PROJECTION);								// Select The Projection Matrix	glLoadIdentity ();											// Reset The Projection Matrix	gluPerspective(fov,aspect,zNear,zFar);	glMatrixMode   (GL_MODELVIEW);								// Select The Modelview Matrix//90,1,0.1f,100.0f	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);	// Nearest Filtered	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	// Nearest Filtered}


and the main loop:
window::window(int width, int height,std::string WindowName){	done = false;	if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )	{		fprintf( stderr, "Video initialization failed: %s\n",			SDL_GetError( ) );		SDL_Quit( );	}	atexit(SDL_Quit);	SDL_WM_SetCaption(WindowName.c_str(), NULL);	screen = SDL_SetVideoMode(width, height, 0, SDL_FULLSCREEN|SDL_OPENGL);	if( !screen ) {		fprintf(stderr, "Couldn't create a surface: %s\n",			SDL_GetError());		done = true;	}	SDL_ShowCursor(false);	Player* player = new Player();						//Create new player	GameTimer* timer = new GameTimer();					//Create new timer object	GraphicsSystem* graphics = new GraphicsSystem();	//Create graphics object	GameInput* input = new GameInput();					//Create game input object	GameLogic* logic = new GameLogic();					//Create game logic object	timer->Update();	graphics->oglinit();	graphics->oglinit3D(90,((float)width/(float)height),0.1f,100);	std::vector<int> sg;	while(!done)	{			SDL_Event event;		while ( SDL_PollEvent(&event) )		{			switch (event.type)			{			case SDL_QUIT:				done = true;				break;			case SDL_KEYDOWN:				if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }				break;			}		}		input->Update();		logic->UpdateGame(input->GetKeyState(),timer->GetDifference(),player,sg);		graphics->oglinit3D(90,(float)(width/height),0.1f,100);		graphics->Render(sg,player);		timer->Update();	}	delete player;	delete timer;	delete graphics;	delete input;	delete logic;}


[Edited by - Boder on March 9, 2006 5:00:29 PM]
ScottC
ScottC
Here I thought I had an answer. I used [ code ] [ /code ], seems to have worked?
CrazyCdn
CrazyCdn
I assume you're catching in your wndproc if your program is no longer active and stopping the rendering loop? I had a simular issue (didn't check where it was breaking so not sure if its the same thing...) and doing that fixed it.
"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin
ScottC
ScottC
er... I don't know the winapi all that well, i'm using SDL for my window, so no, I don't stop the rendering loop, I don't see why this wouldn't affect some people though?
Falken42
Falken42
I don't use SDL, but I'll try to take a shot at this anyway...

OpenGL doesn't care if your window is hidden (minimized), in a window, or full screen. It just renders to a context and when SwapBuffers is called, the rendered buffer is simply displayed in the window.

That being said, glClear should never crash -- even if you don't create a depth buffer, calling glClear with the GL_DEPTH_BUFFER_BIT set simply won't do anything.

My guess is either you have a bug somewhere that is overwriting memory and is causing this to happen, or there's something weird with your video drivers (a far stretch, but nonetheless possible).

I would first try a small test: minimize your code just to only a simple glClear and SwapBuffers call. Remove everything else unnecessary, such as the timer, input, and logic updates you have. Then try toggling with Alt+Tab and see if it still happens or not. Also test other OpenGL applications to make sure it's not a driver problem.

Good luck!
ScottC
ScottC
Quote:
Original post by bpoint
I don't use SDL, but I'll try to take a shot at this anyway...

OpenGL doesn't care if your window is hidden (minimized), in a window, or full screen. It just renders to a context and when SwapBuffers is called, the rendered buffer is simply displayed in the window.

That being said, glClear should never crash -- even if you don't create a depth buffer, calling glClear with the GL_DEPTH_BUFFER_BIT set simply won't do anything.

My guess is either you have a bug somewhere that is overwriting memory and is causing this to happen, or there's something weird with your video drivers (a far stretch, but nonetheless possible).

I would first try a small test: minimize your code just to only a simple glClear and SwapBuffers call. Remove everything else unnecessary, such as the timer, input, and logic updates you have. Then try toggling with Alt+Tab and see if it still happens or not. Also test other OpenGL applications to make sure it's not a driver problem.

Good luck!


I removed all other code but the clear and swapbuffers, it still crashed on alt+tab, its probably going to be a driver issue, i'll test other OpenGL+SDL apps. I've got Omega Drivers for my Radeon 9600, that may be causing issues.
Tac-Tics
Tac-Tics
Before you go off and blame your drivers, try running it through the debugger and look at the stack trace to make sure it __really__ is glClear() doing the crashing.
CrazyCdn
CrazyCdn
Also my idea was for program politeness. You're likely using over 90% of the CPU which is pointless when it's not even visible. Suspend your rendering with a simple if statement and a handling of one windows event. Make others happy ;-) Half-life 1/2, Quakes, Unreals, Doom3 all seem to do this (they all seemed to be < 10% CPU usage when I checked).

Oh, to the OP, I went and rechecked my code (dead project) and it was indeed me not initializing properly. So do what others recommend and hit that debugger :) Good luck.
"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin
ScottC
ScottC
Quote:
Original post by Mike2343
Also my idea was for program politeness. You're likely using over 90% of the CPU which is pointless when it's not even visible. Suspend your rendering with a simple if statement and a handling of one windows event. Make others happy ;-) Half-life 1/2, Quakes, Unreals, Doom3 all seem to do this (they all seemed to be < 10% CPU usage when I checked).

Oh, to the OP, I went and rechecked my code (dead project) and it was indeed me not initializing properly. So do what others recommend and hit that debugger :) Good luck.


Wouldn't I be better off just putting a check to see if the window is minimized around my entire while loop?

Edit:
I'm not sure if this is what you want me to do, but I alt+tabbed and clicked on Debug when the window came up, and it brought up MSVC++ 2003 and showed me this.

int __cdecl _lock_fhandle (        int fh        ){        ioinfo *pio = _pioinfo(fh);        /*         * Make sure the lock has been initialized.         */        if ( pio->lockinitflag == 0 ) {            _mlock( _LOCKTAB_LOCK );            __TRY                if ( pio->lockinitflag == 0 ) {                    if ( !__crtInitCritSecAndSpinCount( &(pio->lock), _CRT_SPINCOUNT )) {                        /*                         * Failed to initialize the lock, so return failure code.                         */                        return FALSE;                    }                    pio->lockinitflag++;                }            __FINALLY                _munlock( _LOCKTAB_LOCK);            __END_TRY_FINALLY        }        EnterCriticalSection( &(_pioinfo(fh)->lock) );        return TRUE;}


There was an unhandled exception with return TRUE;
It was
Unhandled exception at 0x691cdfe6 in OpenGLApp.exe: 0xC0000094: Integer division by zero.

At the bottom right of the screen (Call Stack), there was a yellow arrow pointing to:
atioglxx.dll!691cdfe6()

and a green arrow (exactly like the one that was pointing at return TRUE;) pointing at:
msvcr71.dll!_lock_fhandle(int fh=10940224) Line 453 C

Debugging the actual code brought me to this line that was right after glClear
glLoadIdentity is apparently giving me an integer division by 0?

I commented out glLoadIdentity and ran debugger again and it told me the next line (glRotatef) was integer division by 0, and I repeated that 2-3 times and it still gave me the error. Whats up with that? Same error for every one? Could I have bad drivers?

[Edited by - ScottC on March 10, 2006 12:22:31 PM]
ScottC
ScottC
FIXED
with new drivers.
CrazyCdn
CrazyCdn
Quote:
Original post by ScottC
Quote:
Original post by Mike2343
Also my idea was for program politeness. You're likely using over 90% of the CPU which is pointless when it's not even visible. Suspend your rendering with a simple if statement and a handling of one windows event. Make others happy ;-) Half-life 1/2, Quakes, Unreals, Doom3 all seem to do this (they all seemed to be < 10% CPU usage when I checked).

Oh, to the OP, I went and rechecked my code (dead project) and it was indeed me not initializing properly. So do what others recommend and hit that debugger :) Good luck.


Wouldn't I be better off just putting a check to see if the window is minimized around my entire while loop?

Edit:
I'm not sure if this is what you want me to do, but I alt+tabbed and clicked on Debug when the window came up, and it brought up MSVC++ 2003 and showed me this.

*snip*


There was an unhandled exception with return TRUE;
It was
Unhandled exception at 0x691cdfe6 in OpenGLApp.exe: 0xC0000094: Integer division by zero.

At the bottom right of the screen (Call Stack), there was a yellow arrow pointing to:
atioglxx.dll!691cdfe6()

and a green arrow (exactly like the one that was pointing at return TRUE;) pointing at:
msvcr71.dll!_lock_fhandle(int fh=10940224) Line 453 C

Debugging the actual code brought me to this line that was right after glClear
glLoadIdentity is apparently giving me an integer division by 0?

I commented out glLoadIdentity and ran debugger again and it told me the next line (glRotatef) was integer division by 0, and I repeated that 2-3 times and it still gave me the error. Whats up with that? Same error for every one? Could I have bad drivers?


Yeah, basically I check when the program is no longer active in the winproc (minimized, no longer the top window (though this could be incorrect as it may still be visible...)) and set a "isactive" variable. Which I check like you mentioned. Anyways glad you solved your issue (and posted to let us know what it was).
"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin
gumpy
gumpy
Quote:
Original post by ScottC
Here I thought I had an answer. I used [ code ] [ /code ], seems to have worked?


use the "code" tags for very small sections of code and "source" tags for larger sections to get those neat little syntax highlighted scrolling boxes.
This space for rent.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.