Resizing SDL opengl window

I’m writing an opengl demo with SDL. I got this error when I try to resize my
window:

Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0xe4)!

any ideas?

Here is my source code:

//Description: Displays two rotating polygons, with one of the polygons having
//transparency (alpha = 0.6). Pressing the spacebar will switch which polygon is
//transparent.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>

#ifndef M_PI

define M_PI 3.14159265358979323846 /* pi */

#endif

SDL_Surface *screen;
bool changed = true;
static GLfloat angle = 0.0;
bool leftFirst = true;

void reshape() {
glViewport(0, 0, screen->w, screen->h);
glMatrixMode(GL_PROJECTION );
glLoadIdentity( );
float ratio = (float) screen->w / (float) screen->h;
gluPerspective(60.0, ratio, 1.0, 1024.0);
glMatrixMode(GL_MODELVIEW);
}

int init(int argc, char* argv[])
{
glEnable(GL_BLEND); // enable blending

// transparency
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glShadeModel(GL_SMOOTH);			// use smooth shading

// Clear background to black
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
reshape(); 

}

void DrawLeftPoly()
{
glColor4f(0.5f, 0.5f, 0.0f, 0.6);
glBegin(GL_QUADS);
glVertex3f(-10.0f, -10.0f, 0.0f);
glVertex3f(0.0f, -10.0f, 0.0f);
glVertex3f(0.0f, 10.0f, 0.0f);
glVertex3f(-10.0f, 10.0f, 0.0f);
glEnd();
}

void DrawRightPoly()
{
glColor4f(0.0f, 0.5f, 0.5f, 0.6);
glBegin(GL_QUADS);
glVertex3f(0.0f, -10.0f, 0.0f);
glVertex3f(10.0f, -10.0f, 0.0f);
glVertex3f(10.0f, 10.0f, 0.0f);
glVertex3f(0.0f, 10.0f, 0.0f);
glEnd();
}

void render(void)
{
changed = false;

// clear screen and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);										
glLoadIdentity();

if (angle >= 359.9f)
	angle = 0.0f;

angle += 0.1;			// increase rotation angle

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

// rotate and draw the opaque polygon
glPushMatrix();
	glRotatef(angle, 0.0f, 0.0f, 1.0f);
	if (leftFirst)
		DrawLeftPoly();
	else
		DrawRightPoly();
glPopMatrix();

// rotate and draw the transparent polygon
glPushMatrix();
	glRotatef(angle, 0.0f, 0.0f, -1.0f);
	if (leftFirst)
		DrawRightPoly();
	else
		DrawLeftPoly();
glPopMatrix();



glFlush();
SDL_GL_SwapBuffers();

}

static Uint32 callback(Uint32 interval, void *param)
{
render();
return interval;
}

int main(int argc, char* argv[]) {
///initialize SDL video and request an OpenGL window
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
return 1;
atexit(SDL_Quit);

screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL | SDL_RESIZABLE);
if (!screen)
{
  fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
  return 2;
}
SDL_WM_SetCaption("Blend Demo 1", "mydemo");
    SDL_AddTimer(10, callback, 0);

//intialize OpenGL states 
if (init(argc, argv) < 0)
	return 3;

//event loop 
bool done = false;
Uint8 *keys;
while (!done) { 
  //handle input 
  SDL_Event event; 
  while (SDL_PollEvent(&event)) {
    switch (event.type) {
      case SDL_VIDEORESIZE:
	screen = SDL_SetVideoMode(event.resize.w,
		event.resize.h, 16, SDL_OPENGL | SDL_RESIZABLE);
	reshape(); 
	if (screen)
	  changed = true;
	else
	  done = true;
        break;
			
          case SDL_QUIT:
        done = true;
	break;
     }
  }
  //handle keys 
  keys = SDL_GetKeyState(0);
  if (keys[SDLK_ESCAPE]) { 
    done = true;
  } else { 
    if (keys[SDLK_SPACE])  leftFirst = !leftFirst;
}
return 0;					

}

Will Childman wrote:

I’m writing an opengl demo with SDL. I got this error when I try to resize my
window:

Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0xe4)!

You’re calling SDL and OpenGL stuff from multiple threads (which is a
big no-no), and mayhem ensues. Either rewrite the code to not use that
timer, or use a single SDL_PushEvent in the callback and test for that
in the event loop (should be safe).

  • Gerry

And the seg-fault is probably a product of your thread (as Gerry said)
attempting to write to the context while Windows is monkeying with it.
You would need some way of ensuring that you’re locking the context
during re-size…

Regardless, though you can do all sorts of things in parallel with
GFX, there are certain things that have to happen in serial.

CKOOn Tue, 25 Jan 2005 03:11:06 +0000 (UTC), Will Childman wrote:

I’m writing an opengl demo with SDL. I got this error when I try to resize my
window:

Fatal signal: Segmentation Fault (SDL Parachute Deployed)
Xlib: unexpected async reply (sequence 0xe4)!

any ideas?

Here is my source code:

//Description: Displays two rotating polygons, with one of the polygons having
//transparency (alpha = 0.6). Pressing the spacebar will switch which polygon is
//transparent.

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL.h>

#ifndef M_PI

define M_PI 3.14159265358979323846 /* pi */

#endif

SDL_Surface *screen;
bool changed = true;
static GLfloat angle = 0.0;
bool leftFirst = true;

void reshape() {
glViewport(0, 0, screen->w, screen->h);
glMatrixMode(GL_PROJECTION );
glLoadIdentity( );
float ratio = (float) screen->w / (float) screen->h;
gluPerspective(60.0, ratio, 1.0, 1024.0);
glMatrixMode(GL_MODELVIEW);
}

int init(int argc, char* argv[])
{
glEnable(GL_BLEND); // enable blending

    // transparency
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glShadeModel(GL_SMOOTH);                        // use smooth shading

    // Clear background to black
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    reshape();

}

void DrawLeftPoly()
{
glColor4f(0.5f, 0.5f, 0.0f, 0.6);
glBegin(GL_QUADS);
glVertex3f(-10.0f, -10.0f, 0.0f);
glVertex3f(0.0f, -10.0f, 0.0f);
glVertex3f(0.0f, 10.0f, 0.0f);
glVertex3f(-10.0f, 10.0f, 0.0f);
glEnd();
}

void DrawRightPoly()
{
glColor4f(0.0f, 0.5f, 0.5f, 0.6);
glBegin(GL_QUADS);
glVertex3f(0.0f, -10.0f, 0.0f);
glVertex3f(10.0f, -10.0f, 0.0f);
glVertex3f(10.0f, 10.0f, 0.0f);
glVertex3f(0.0f, 10.0f, 0.0f);
glEnd();
}

void render(void)
{
changed = false;

    // clear screen and depth buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    if (angle >= 359.9f)
            angle = 0.0f;

    angle += 0.1;                   // increase rotation angle

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

    // rotate and draw the opaque polygon
    glPushMatrix();
            glRotatef(angle, 0.0f, 0.0f, 1.0f);
            if (leftFirst)
                    DrawLeftPoly();
            else
                    DrawRightPoly();
    glPopMatrix();

    // rotate and draw the transparent polygon
    glPushMatrix();
            glRotatef(angle, 0.0f, 0.0f, -1.0f);
            if (leftFirst)
                    DrawRightPoly();
            else
                    DrawLeftPoly();
    glPopMatrix();

    glFlush();
    SDL_GL_SwapBuffers();

}

static Uint32 callback(Uint32 interval, void *param)
{
render();
return interval;
}

int main(int argc, char* argv[]) {
///initialize SDL video and request an OpenGL window
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
return 1;
atexit(SDL_Quit);

    screen = SDL_SetVideoMode(640, 480, 16, SDL_OPENGL | SDL_RESIZABLE);
    if (!screen)
    {
      fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError());
      return 2;
    }
    SDL_WM_SetCaption("Blend Demo 1", "mydemo");
    SDL_AddTimer(10, callback, 0);

    //intialize OpenGL states
    if (init(argc, argv) < 0)
            return 3;

    //event loop
    bool done = false;
    Uint8 *keys;
    while (!done) {
      //handle input
      SDL_Event event;
      while (SDL_PollEvent(&event)) {
        switch (event.type) {
          case SDL_VIDEORESIZE:
            screen = SDL_SetVideoMode(event.resize.w,
                    event.resize.h, 16, SDL_OPENGL | SDL_RESIZABLE);
            reshape();
            if (screen)
              changed = true;
            else
              done = true;
            break;

          case SDL_QUIT:
            done = true;
            break;
         }
      }
      //handle keys
      keys = SDL_GetKeyState(0);
      if (keys[SDLK_ESCAPE]) {
        done = true;
      } else {
        if (keys[SDLK_SPACE])  leftFirst = !leftFirst;
    }
    return 0;

}


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


Casey O’Donnell
RPI STS Department - Graduate Student

http://homepage.mac.com/codonnell/
http://homepage.mac.com/codonnell/wxsync/
http://homepage.mac.com/codonnell/wxblogger/

Hi,

two comments on your code (and questions to the SDL list in general):

  switch (event.type) {
    case SDL_VIDEORESIZE:
  screen = SDL_SetVideoMode(event.resize.w,
  	event.resize.h, 16, SDL_OPENGL | SDL_RESIZABLE);
  reshape(); 

I’ve never tinkered with resizable windows, but is SDL_SetVideoMode
really necessary? From what I’ve read on this list occasionally, this
will destroy and recreate your OpenGL context, causing you to, for
example, lose all your textures.

If your application is pure OpenGL (no on-screen SDL blitting),
shouldn’t it be enough to call glViewport?

//handle keys 
keys = SDL_GetKeyState(0);
if (keys[SDLK_ESCAPE]) { 
  done = true;
} else { 
  if (keys[SDLK_SPACE])  leftFirst = !leftFirst;

I’m not sure how efficient this last part is. You’re already handling
SDL events in your event loop, why not catch keypresses there? This way,
you can also catch keys that are pressed and released between tests
(which you would currently miss if they were really, really fast). And
I’m not sure how much work goes into SDL_GetKeyState…

Also, the way you’ve set it up now, you are doing “busy waiting”, which
is generally a big no-no:
while (!done) {
if (key_pressed()) done = 1;
}
This will just keep cycling at close to 100% CPU, performing the test
way faster than a human can change the key state.

Here’s my suggestion (in pseudo-code):

while (!done) {
while (events) {
handle resize:
reshape
handle keypress:
if (space) swap_triangle()
else if (escape) done = 1
}
redraw()
if (time_passed < 10 ms) sleep (10 ms - time_passed)
}

This handles events as they appear, redraws in the main thread, and
sleeps if there’s nothing else to do.

Bye,
Benjamin