SDL alternative to glutIdleFunc()?

Hello, I’ve just started with OpenGL and at first I used glut but now I
want to use SDL instead so I’m converting my simple apps to use SDL
instead of glut. I was wondering for an alternative to glutIdleFunc()?

/ E

You don’t need anything like that, because SDL doesn’t have the nasty
habit of taking over your main loop. :slight_smile:

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Saturday 21 October 2006 00:43, Eric Lilja wrote:

Hello, I’ve just started with OpenGL and at first I used glut but
now I want to use SDL instead so I’m converting my simple apps to
use SDL instead of glut. I was wondering for an alternative to
glutIdleFunc()?

David Olofson wrote:

Hello, I’ve just started with OpenGL and at first I used glut but
now I want to use SDL instead so I’m converting my simple apps to
use SDL instead of glut. I was wondering for an alternative to
glutIdleFunc()?

You don’t need anything like that, because SDL doesn’t have the nasty
habit of taking over your main loop. :slight_smile:

Ok, but if I used the idle func to increment a variable and then
redisplaying the screen, how would I do that in sdl? A timer?> On Saturday 21 October 2006 00:43, Eric Lilja wrote:

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --’

David Olofson wrote:

Hello, I’ve just started with OpenGL and at first I used glut but
now I want to use SDL instead so I’m converting my simple apps to
use SDL instead of glut. I was wondering for an alternative to
glutIdleFunc()?

You don’t need anything like that, because SDL doesn’t have the
nasty habit of taking over your main loop. :slight_smile:

Ok, but if I used the idle func to increment a variable and then
redisplaying the screen, how would I do that in sdl? A timer?

That’s one way. (Safest way is usually to just have the callback send
an event that is handled by the main loop, to avoid synchronization
issues with shared data.)

Another way, that is more reliable and efficient in most cases, is to
keep track of time using SDL_GetTicks(), and update game logic (or
whatever you have) based on delta times between rendered frames.
There are (at least) two basic methods:

* Actually calculate state changes based on delta
  times. This can be very hard to get accurate and
  repeatable. Even if you get the maths right, you
  have the rounding errors that scale with the size
  of delta times.

* Run the game logic at a fixed frame rate, "spinning"
  it zero or more cycles per rendered frame as needed
  to maintain the intended logic frame rate. For
  smoother animation, you can interpolate display
  coordinates from the last N logic states, rather
  than just grabbing the current state. However, this
  adds some latency between the game logic and the
  display, which effectively means the game seems to
  respond slower to input. Keep the logic frame rate
  reasonably high to reduce this side effect.

Different ways of doing this have been discussed here a few times
before. Try searching the archive for “fixed rate logic” and similar.

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Saturday 21 October 2006 00:57, Eric Lilja wrote:

On Saturday 21 October 2006 00:43, Eric Lilja wrote:

Stoned koala bears drooled eucalyptus spit in awe as Eric Lilja said:

Ok, but if I used the idle func to increment a variable and then
redisplaying the screen, how would I do that in sdl? A timer?

What you need to do is write the main loop yourself since you don’t
have glut providing it. In your loop, you call event methods (I make
them virtual methods of my SDLDisplay class and let subclasses override
them), some of which are caused by the user and one is for drawing.

See the on_draw() method; it renders single frame. In there, you
increment your variable and draw stuff to the screen. Or (better yet)
follow David O’s advice on making your state update aware of elapsed
wallclock time instead of mere frame numbers.

When I was using glut, the contents of my glutIdleFunc was just
"glutPostRedisplay();" and that of course causes the draw function to
be called, making it equivalent to the code below. If you’ve got
separate & interesting stuff in your idle and draw functions, then
that’s a little different maybe.

/// call this after initialising SDL and the scene graph
void SDLDisplay::run()
{
done=false;
// done is set by the stop() method, called
// inside some event handler
while(!done){

	// deal with events
	SDL_Event event;
	while(SDL_PollEvent(&event)){
		switch(event.type){
		case SDL_ACTIVEEVENT:
			on_active(event.active);
			break;
		case SDL_KEYDOWN:
		case SDL_KEYUP:
			on_key(event.key);
			break;
		case SDL_MOUSEMOTION:
			on_mousemotion(event.motion);
			break;
		case SDL_MOUSEBUTTONDOWN:
		case SDL_MOUSEBUTTONUP:
			on_mousebutton(event.button);
			break;
		case SDL_JOYAXISMOTION:
			on_joyaxis(event.jaxis);
			break;
		case SDL_JOYBALLMOTION:
			on_joyball(event.jball);
			break;
		case SDL_JOYHATMOTION:
			on_joyhat(event.jhat);
			break;
		case SDL_JOYBUTTONDOWN:
		case SDL_JOYBUTTONUP:
			on_joybutton(event.jbutton);
			break;
		case SDL_QUIT:
			done=true;
			break;
		case SDL_SYSWMEVENT:
			on_syswm(event.syswm);
			break;
		case SDL_VIDEORESIZE:
			res.first=event.resize.w;
			res.second=event.resize.h;
			main_view->setViewport(0, res.first-1,

0, res.second-1); on_reshape(event.resize);
break;
case SDL_VIDEOEXPOSE:
on_expose(event.expose);
break;
case SDL_USEREVENT:
on_user(event.user);
break;
default:
cerr << "Bad SDL event type " <<
event.type << endl; done=true;
break;
}
}

	on_draw();

	glFinish();
	SDL_GL_SwapBuffers();
}

on_shutdown();

}

You probably want to have a function that advances time in your
program; in on_draw() you measure the elapsed time of the last frame
(perhaps SDL_GetTicks) and then call your simulation function with the
amount of time that has elapsed. Things that move, move a distance
proportional to time, etc. If you’ve got non-linear simulations, you
need to be more careful with the size and uniformity of time steps, but
simple proportional movement may be enough for you.

I use a clock class that tells me current time and time since the last
tick. I update it like this in the on_draw() method:

rep.clock.tick();
t=rep.clock.getTime();
framedt=rep.clock.getDelta();
rep.tick(framedt);

note the last line… that sends a notification of elapsed time to all
objects that have requested such notification.–
William Brodie-Tyrrell

Carpe Diem - fish of the day.

<@William_Brodie-Tyrre>
http://www.brodie-tyrrell.org/

William Brodie-Tyrrell wrote:

Stoned koala bears drooled eucalyptus spit in awe as Eric Lilja said:

Ok, but if I used the idle func to increment a variable and then
redisplaying the screen, how would I do that in sdl? A timer?

What you need to do is write the main loop yourself since you don’t
have glut providing it. In your loop, you call event methods (I make
them virtual methods of my SDLDisplay class and let subclasses override
them), some of which are caused by the user and one is for drawing.

See the on_draw() method; it renders single frame. In there, you
increment your variable and draw stuff to the screen. Or (better yet)
follow David O’s advice on making your state update aware of elapsed
wallclock time instead of mere frame numbers.

When I was using glut, the contents of my glutIdleFunc was just
"glutPostRedisplay();" and that of course causes the draw function to
be called, making it equivalent to the code below. If you’ve got
separate & interesting stuff in your idle and draw functions, then
that’s a little different maybe.

/// call this after initialising SDL and the scene graph
void SDLDisplay::run()
{
done=false;
// done is set by the stop() method, called
// inside some event handler
while(!done){

  // deal with events
  SDL_Event event;
  while(SDL_PollEvent(&event)){
  	switch(event.type){
  	case SDL_ACTIVEEVENT:
  		on_active(event.active);
  		break;
  	case SDL_KEYDOWN:
  	case SDL_KEYUP:
  		on_key(event.key);
  		break;
  	case SDL_MOUSEMOTION:
  		on_mousemotion(event.motion);
  		break;
  	case SDL_MOUSEBUTTONDOWN:
  	case SDL_MOUSEBUTTONUP:
  		on_mousebutton(event.button);
  		break;
  	case SDL_JOYAXISMOTION:
  		on_joyaxis(event.jaxis);
  		break;
  	case SDL_JOYBALLMOTION:
  		on_joyball(event.jball);
  		break;
  	case SDL_JOYHATMOTION:
  		on_joyhat(event.jhat);
  		break;
  	case SDL_JOYBUTTONDOWN:
  	case SDL_JOYBUTTONUP:
  		on_joybutton(event.jbutton);
  		break;
  	case SDL_QUIT:
  		done=true;
  		break;
  	case SDL_SYSWMEVENT:
  		on_syswm(event.syswm);
  		break;
  	case SDL_VIDEORESIZE:
  		res.first=event.resize.w;
  		res.second=event.resize.h;
  		main_view->setViewport(0, res.first-1,

0, res.second-1); on_reshape(event.resize);
break;
case SDL_VIDEOEXPOSE:
on_expose(event.expose);
break;
case SDL_USEREVENT:
on_user(event.user);
break;
default:
cerr << "Bad SDL event type " <<
event.type << endl; done=true;
break;
}
}

  on_draw();

  glFinish();
  SDL_GL_SwapBuffers();

}

on_shutdown();
}

Ok, I had a similar loop that called SDL_WaitEvent() before. When I try
your variant with two loops and the inner one calls SDL_PollEvent() my
simple program consumes 100 % CPU…

You probably want to have a function that advances time in your
program; in on_draw() you measure the elapsed time of the last frame
(perhaps SDL_GetTicks) and then call your simulation function with the
amount of time that has elapsed. Things that move, move a distance
proportional to time, etc. If you’ve got non-linear simulations, you
need to be more careful with the size and uniformity of time steps, but
simple proportional movement may be enough for you.

I use a clock class that tells me current time and time since the last
tick. I update it like this in the on_draw() method:

rep.clock.tick();
t=rep.clock.getTime();
framedt=rep.clock.getDelta();
rep.tick(framedt);

note the last line… that sends a notification of elapsed time to all
objects that have requested such notification.

/ E

Eric Lilja wrote:

Ok, I had a similar loop that called SDL_WaitEvent() before. When I try
your variant with two loops and the inner one calls SDL_PollEvent() my
simple program consumes 100 % CPU…

Changed so that the inner loop calls SDL_WaitEvent() and when it’s done
handling the event it checks if there are more in queue (using
SDL_PeepEvents and SDL_PEEKEVENT), and if there are none it breaks. Then
the rest of the outer loops runs and it redraws the screens. Seems to
work just fine without consuming an absurd amount of CPU time.

/ E

[…]

Ok, I had a similar loop that called SDL_WaitEvent() before. When I
try your variant with two loops and the inner one calls
SDL_PollEvent() my simple program consumes 100 % CPU…

That’s what happens when rendering (or rather page flipping) is not
synchronized with the display retrace. (Retrace sync, vertical
sync…)

For applications that are supposed to maintain smooth animation at all
times, there is no proper solution to this problem. The
only “correct” thing you can do is to make sure you’re using double
buffering and if possible, try to enable it. (SDL_GL_SetAttribute(
SDL_GL_SWAP_CONTROL, 1):wink:

If the user “decides” to override this by means of driver options,
there’s nothing you can do about it. You could say the user deserves
what (s)he gets, but the problem is that many drivers are installed
with retrace sync forced disabled by default. :-/

If you want to try to play nice, you can use SDL_Delay() to "throttle"
the frame rate. This can sometimes (when there are other processes
that need significant amounts of CPU time) actually result in
smoother animation, but usually it’s slightly worse than just
allowing the 100% CPU load thing to happen. (Tearing becomes less
visible as the frame rate increases, and there is no way to avoid
tearing without retrace sync.)

//David Olofson - Programmer, Composer, Open Source Advocate

.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
’-- http://www.reologica.se - Rheology instrumentation --'On Saturday 21 October 2006 17:23, Eric Lilja wrote:

Stoned koala bears drooled eucalyptus spit in awe as Eric Lilja said:

Ok, I had a similar loop that called SDL_WaitEvent() before. When I try
your variant with two loops and the inner one calls SDL_PollEvent() my
simple program consumes 100 % CPU…

David beat me to it but as he said, it’s because the program is
generating frames as fast as the video card can page flip. In my
simple demos, it runs at 500-700fps - a meaningless number but it
shows that the cycles aren’t going nowhere, they’re going to lots of
frames that you don’t see more than a few scanlines of each.

If you enable sync to vertical retrace (video card driver option), the
program will pause inside SDL_GL_SwapBuffers() and the CPU utilisation
should drop dramatically as long as the retrace wait isn’t itself a
polling loop; since it’s inside the graphics drivers it should be a
proper process yield, i.e. taken off the runnable queue until the
retrace occurs.

The inside loop that polls for events will go around only once for each
event that has been received; if no events are coming in then the inner
loop does nothing.

If you change it to wait for any SDL events before doing a redraw,
that’d be kind of bad (for a game) since nothing would happen until
user events appeared. If you’re trying to write a windowing system or
something, then I guess that’d be good.–
William Brodie-Tyrrell

Carpe Diem - fish of the day.

<@William_Brodie-Tyrre>
http://www.brodie-tyrrell.org/

You should try SDL_Framerate which is inlcuded int the SDL_Gfx lib

http://www.ferzkopp.net/joomla/content/view/19/14/

first init the SDL_FrameRate lib like this

FPSmanager FPSmanager;

//Set the frame manager to 60 Hz
SDL_initFramerate(&FPSmanager);
SDL_setFramerate(&FPSmanager,60);

and now you can use it in your main loop

while(true)
{
//Limits the game speed to 60Hz
SDL_framerateDelay(&FPSmanager);

}

2006/10/22, William Brodie-Tyrrell :>

Stoned koala bears drooled eucalyptus spit in awe as Eric Lilja said:

Ok, I had a similar loop that called SDL_WaitEvent() before. When I try
your variant with two loops and the inner one calls SDL_PollEvent() my
simple program consumes 100 % CPU…

David beat me to it but as he said, it’s because the program is
generating frames as fast as the video card can page flip. In my
simple demos, it runs at 500-700fps - a meaningless number but it
shows that the cycles aren’t going nowhere, they’re going to lots of
frames that you don’t see more than a few scanlines of each.

If you enable sync to vertical retrace (video card driver option), the
program will pause inside SDL_GL_SwapBuffers() and the CPU utilisation
should drop dramatically as long as the retrace wait isn’t itself a
polling loop; since it’s inside the graphics drivers it should be a
proper process yield, i.e. taken off the runnable queue until the
retrace occurs.

The inside loop that polls for events will go around only once for each
event that has been received; if no events are coming in then the inner
loop does nothing.

If you change it to wait for any SDL events before doing a redraw,
that’d be kind of bad (for a game) since nothing would happen until
user events appeared. If you’re trying to write a windowing system or
something, then I guess that’d be good.


William Brodie-Tyrrell

Carpe Diem - fish of the day.

http://www.brodie-tyrrell.org/

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