Bug: SetVideoMode Resize Crash

Hi all,

I think I stumbled across what would appear to be a pretty big bug in the
Windows/DX implementation of SDL_SetVideoMode last night. I’m a relative
newbie here, so please pardon me if this already a known bug and let me know
any existing workarounds. I searched the list archive but didn’t find a
reference to this exact problem.

The problem, in short, is this: If you create a window, call SetVideoMode
again to resize it, then call SetVideoMode with the FULLSCREEN flag enabled
(and a new resolution), it is possible that you will get a memory access
violation during that final SetVideoMode.

The error occurs most frequently when you are switching to very low
resolution (320x200) fullscreen modes. It will occur in the higher
resolutions too, just not as often. Also, it only seems to occur if you’ve
written something to the windowed surfaces before the final failing
SetVideoMode call.

The problem occurs in the 1.2.1 distribution, as well as the latest CVS
release. I am using the DX8.0a SDK/runtimes. I’m using a W2k Pro on an IBM
Thinkpad 600e (NeoMagic video - no acceleration) with the latest available
video drivers.

I threw together a small program (below) to demonstrate the bug in its
simplest form. It produces the following output under Visual C++:

Pass 1…
Setting 640x400 window… Resizing window… Going fullscreen 320x200
First-chance exception in vidtest.exe (MSVCRTD.DLL): 0xC0000005: Access
Violation.

If you take out the resize section of code, it seems to run without error
every time.

I wish I could step through the code and find the exact failing line, but it
occurs after the SetVideoMode function has gotten DirectX to go
FULLSCREEN|POSTAL on me. I tried using higher resolutions on the final
SetVideoMode call, since I can still get Visual Studio to the foreground and
step through the code that way, but oddly the bug never almost never occurs
if the last SetVideoMode is 800x600 or greater (and I challenge anyone to
use VS in 320x200 rez).

Thanks in advance for any help/suggestions!
Jesse Litton

#include <sdl.h>
#include <windows.h> // for OutputDebugString

int main(int argc, char *argv[])
{
SDL_Surface screen;
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr,
“Couldn’t initialize SDL: %s\n”, SDL_GetError());
return (1);
}
atexit(SDL_Quit); /
Clean up on exit */

char msg[64];
for(int x = 0; x < 3; x++)
{
sprintf(msg, “Pass %i…\n”, x+1);
OutputDebugString(msg);

OutputDebugString("Setting 640x400 window… ");
screen = SDL_SetVideoMode(640, 400, 16,
SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE);
SDL_LockSurface(screen);
UINT32 buffer = (UINT32)screen->pixels;
buffer = 0xFF; // Error only seems to occur if you write to the
surface
SDL_UnlockSurface(screen);

OutputDebugString("Resizing window… ");
screen = SDL_SetVideoMode(640, 333, 16,
SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE);
SDL_LockSurface(screen);
buffer = (UINT32)screen->pixels;
buffer = 0xFF;
SDL_UnlockSurface(screen);
SDL_Delay(1500);

OutputDebugString(“Going fullscreen 320x200\n”);
screen = SDL_SetVideoMode(320, 200, 16,
SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN);
if(!screen) {
OutputDebugString(“Screen NULL!\n”);
break;
}
}
return(0);
}