Sign in to follow this  
Beren77

SDL Fullscreen speed problems Win32

Recommended Posts

Hi, in a game I am developing, I use SDL_SetVideoMode(1024, 768, 32, SDL_DOUBLEBUF | SDL_FULLSCREEN)); to set the video mode. (And I also tried various combinations of SDL_HWSURFACE/SW_SURFACE, SDL_HWACCEL, SDL_ANYFORMAT, etc.) The problem is that the game runs smoothly in windowed mode (at around 50 FPS) which drop down to _7_ FPS in full screen. The game itself is "simply" blitting 2d tiles on a surface, using SDL_BlitSurface. Scrolling is involved and it works like a breeze in windowed mode, as I said... I googled and found that this seems to be a problem in Windows only, namely the renderer appears to be DirectX 5 which might not be supported by MS which causes it to be so slow. So, I am supposed to set the renderer to the Windows GDI which supposedly is going to make it faster (sounds bad enough to me, but if it works...). First problem: How do I set the video mode? The function SDL_setenv does not appear to be in the SDL or SDLmain.dll. (I am using SDL 1.2.9 btw -- could upgrading to 1.2.11 help?). However, I found the information stated above here in a _pascal_ forum. I am using Visual C++ (.Net 2003). I tried setting a regular environment variable under Windows using setenv("SDL_VIDEODRIVER=windib"); which had no effect at all (and I called it, before I called SDL_Init. The call to SDL_Init is SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_TIMER | SDL_INIT_AUDIO). Anything wrong here?). Any ideas what could be wrong? Thanks for your help! Beren

Share this post


Link to post
Share on other sites
I don't remember how to change the rendering engine, but no, you don't want GDI anyway. DirectX 5 is old, but it's not "unsupported" in the technical sense. It works just fine for this sort of application. The problem is probably that you're not converting the loaded images to the display format. I believe the function in question is SDL_DisplayFormat. Windows handles things differently in fullscreen and you're probably finding that it's converting each surface from software to hardware or vice versa with each individual blit.

Share this post


Link to post
Share on other sites
Thanks for the reply. But I do use DisplayFormat for every surface I use. If I hadn't, I'd have a frame rate around 11-16 in windowed mode.

Removing the SDL_DOUBLEBUF in the video init call solved the problem: Now I do have 50 frames in fullscreen as well. I don't really understand it, but since I do not see any side-effects (i.e. flicker), I'll stick to the "solution" for now. Does anyone have a clue as to why I can't use double buffering when in full screen? Is DirectX already double buffering everything I send to the pipeline?

Thanks!

Share this post


Link to post
Share on other sites
No, there's definitely something else broken there. Are you doing some alpha blending? If you are, then that runs very slowly with hardware surfaces. Windowed mode tends to force SDL/DirectDraw back down to software surfaces which is why you may see faster results in the windowed case.

Share this post


Link to post
Share on other sites
Yes, I am doing some alpha blending. I changed all surfaces from HW to SW but I cannot see any change. Whenever I enable double buffering, the frame rate in fullscreen mode goes way down.

I'd send in code examples, but I'm not sure what I could show you: Apart from the initialization and blitting, I don't do anything fancy:


if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0) {
fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
atexit(deInit);

SDL_SetVideoMode(getWidth(), getHeight(), getBits(), SDL_SWSURFACE /*| SDL_FULLSCREEN*/));

...

SDL_Surface *temp = IMG_Load("tilesAlpha.png");
SDL_PixelFormat dd;
dd.Aloss = 0;
dd.alpha = 255;
dd.Amask = 0x000000FF;
dd.Ashift = 0;
dd.BitsPerPixel = 32;
dd.Bloss = 0;
dd.Bmask = 0xFF00;
dd.Bshift = 8;
dd.BytesPerPixel = 4;
dd.colorkey = 0;
dd.Gloss = 0;
dd.Gmask = 0xFF0000;
dd.Gshift = 16;
dd.Rloss = 0;
dd.Rmask = 0xFF000000;
dd.Rshift = 24;
dd.palette = getScreen() -> format -> palette;

transparentTileSurface = SDL_ConvertSurface(temp, &dd, SDL_SWSURFACE);
SDL_FreeSurface(temp);

...

SDL_Rect sourceRect;
SDL_Rect destRect;
sourceRect.w = destRect.w = TILESIZE;
sourceRect.h = destRect.h = TILESIZE;
sourceRect.x = 0;
sourceRect.y = TILESIZE * tile;
destRect.x = x;
destRect.y = y;
SDL_BlitSurface(transparentTileSurface()
&sourceRect,
getScreen(),
&destRect);




Anything looks odd?

Thanks.

Share this post


Link to post
Share on other sites
We had that exact same problem when I was making Q'Bicles. I managed to figure out using a profiler that the game was spending an absurd amount of time (~100ms/frame) in WaitForSingleObject in, of all places, the DirectInput code. As I barely know DX at all, I fixed the symptom by upgrading the DirectInput code in SDL from whatever version it was using (3, iirc) to version 8. The FPS went "way" up to about 20 fps (which was still something like half the windowed mode frame rate but it was closer).

I would actually be really interested if this really was was the same problem we had.

Share this post


Link to post
Share on other sites
The DirectInput problem sounds interesting. I will look into that. Thanks! When you say you "upgraded the DirectInput code in SDL", do you mean that you recompiled the SDL sources with DirectInput in its latest version? Or is there a way to externally hook the DI code without recompiling SDL?

Share this post


Link to post
Share on other sites
SDL will try obtain a hardware surface for SDL_DOUBLEBUF. As such alpha blending and SDL's double buffering will be extremely slow. Note that using SDL_SWSURFACE will not affect this as SDL_SWSURFACE is actually 0 and will be overridden by any other format value you OR with it.

For a really interesting read about SDL and hardware surfaces ( and 2 other interesting SDL related articles ), take a look at Bob Pendelton's articles here.

Also, your surface conversion code seems a bit verbose when you could simply use SDL_DisplayFormatAlpha(). [smile]

Share this post


Link to post
Share on other sites
I just upgraded to SDL 1.2.11 and SDL_Image 1.2.5.
What happens is that I now get _the exact same framerate_ for windowed and fullscreen mode, even if I enable SDL_DOUBLEBUF.

BUT: I have upgraded SDL on my home computer and I honestly don't know if the problem existed here in the first place. So, now I will also upgrade to the latest SDL version on my development machine and I will keep you posted if that solved the problem.

@rip-off: Thanks for the link to the articles -- and the hint to my verbose conversion function oooops -- they are proving to be helpful already.

Share this post


Link to post
Share on other sites
Quote:
Original post by Beren77
Updating to SDL 1.2.11 solved the problem for me. Why? I don't have a clue...


I believe that SDL has changed the default backend on win32 from directX to GDI in recent versions. I don't think you'll get hardware surfaces in GDI so its back to software versus hardware surface performance.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this