Mercurial > sdl-ios-xcode
diff src/video/bwindow/SDL_sysvideo.cc @ 4287:0620847bf1a8 SDL-1.2
Fixed bug #798
kty@lavabit.com 2009-09-19 14:19:04 PDT
The stable release of SDL 1.2.13 for BeOS/Haiku has a bug in
BE_FindClosestFSMode that causes it to sometimes not select the best mode when
going fullscreen. There are in fact two bugs in the implementation but I will
not go into specifics because there is already a patch for it in the developer
SVN 1.3. However I am still reporting it because I believe the following code
is a better patch for the issue. The current implementation on SVN only works
if it is able to find an exact match for the requested mode. However, by
scanning from lowest-to-highest resolution instead of highest-to-lowest, one
can find the best mode at all times
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 10 Oct 2009 02:11:07 +0000 |
parents | 7a4c511c980a |
children | 46fb637777ed |
line wrap: on
line diff
--- a/src/video/bwindow/SDL_sysvideo.cc Sat Oct 10 02:03:53 2009 +0000 +++ b/src/video/bwindow/SDL_sysvideo.cc Sat Oct 10 02:11:07 2009 +0000 @@ -57,7 +57,7 @@ static void BE_FreeHWSurface(_THIS, SDL_Surface *surface); static int BE_ToggleFullScreen(_THIS, int fullscreen); -SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); +static SDL_Overlay *BE_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display); /* OpenGL functions */ #if SDL_VIDEO_OPENGL @@ -358,16 +358,25 @@ (current.timing.h_total * current.timing.v_total); modes = SDL_modelist[((bpp+7)/8)-1]; - for ( i=0; modes[i] && (modes[i]->w > width) && - (modes[i]->h > height); ++i ) { - /* still looking */ + + // find end of list (lowest-resolution mode; modes are ordered + // highest-to-lowest). + i = 0; while(modes[i]) i++; + if (!i) return false; // what? no modes at all? + + // find first mode with resolution >= requested in both dimensions + for (--i; i >= 0; --i) + { + if (modes[i]->w >= width && modes[i]->h >= height) + break; } - if ( ! modes[i] || (modes[i]->w < width) || (modes[i]->h < width) ) { - --i; /* We went too far */ - } - + + // unable to find any mode with that high a resolution! + if (i < 0) + return false; + width = modes[i]->w; - height = modes[i]->h; + height = modes[i]->h; bscreen.GetModeList(&dmodes, &nmodes); for ( i = 0; i < nmodes; ++i ) { @@ -396,88 +405,88 @@ static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen) { - int was_fullscreen; - bool needs_unlock; + // printf("SetFullScreen(%d)\n", fullscreen); BScreen bscreen; - BRect bounds; - display_mode mode; - int width, height, bpp; - - /* Set the fullscreen mode */ - was_fullscreen = SDL_Win->IsFullScreen(); - SDL_Win->SetFullScreen(fullscreen); - fullscreen = SDL_Win->IsFullScreen(); - - width = screen->w; - height = screen->h; - /* Set the appropriate video mode */ - if ( fullscreen ) { - bpp = screen->format->BitsPerPixel; - bscreen.GetMode(&mode); - if ( (bpp != ColorSpaceToBitsPerPixel(mode.space)) || - (width != mode.virtual_width) || - (height != mode.virtual_height)) { - if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) { - bscreen.SetMode(&mode); - /* This simply stops the next resize event from being - * sent to the SDL handler. - */ - SDL_Win->InhibitResize(); - } else { - fullscreen = 0; - SDL_Win->SetFullScreen(fullscreen); - } - } - } - if ( was_fullscreen && ! fullscreen ) { - bscreen.SetMode(&saved_mode); + // SetFullSscreen() does not work as expected if called in a window + // that was never shown. This is probably a bug in the Haiku Game Kit that needs + // to be investigated. + if (SDL_Win->Lock()) { + // Show our window. + SDL_Win->Show(); + } + + if (SDL_Win->IsLocked()) { + // Unlock the window if it was locked. This is needed as only the + // first call to Show() unlocks the looper. All other calls to it + // will not. + SDL_Win->Unlock(); } - if ( SDL_Win->Lock() ) { - int cx, cy; - if ( SDL_Win->Shown() ) { - needs_unlock = 1; - SDL_Win->Hide(); - } else { - needs_unlock = 0; - } - /* This resizes the window and view area, but inhibits resizing - * of the BBitmap due to the InhibitResize call above. Thus the - * bitmap (pixel data) never changes. - */ - SDL_Win->ResizeTo(width, height); - bounds = bscreen.Frame(); - /* Calculate offsets - used either to center window - * (windowed mode) or to set drawing offsets (fullscreen mode) - */ - cx = (bounds.IntegerWidth() - width)/2; - cy = (bounds.IntegerHeight() - height)/2; + int width = screen->w; + int height = screen->h; + + if (fullscreen) { + // Set resolution to the closest available one that matches the + // current SDL resolution. + display_mode mode; + bscreen.GetMode(&mode); - if ( fullscreen ) { - /* Set offset for drawing */ - SDL_Win->SetXYOffset(cx, cy); - } else { - SDL_Win->SetXYOffset(0, 0); - } - if ( ! needs_unlock || was_fullscreen ) { - /* Center the window the first time */ - SDL_Win->MoveTo(cx, cy); + int bpp = screen->format->BitsPerPixel; + if (bpp != ColorSpaceToBitsPerPixel(mode.space) || + width != mode.virtual_width || height != mode.virtual_height) { + if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) { + bscreen.SetMode(&mode); + } else { + // printf("Could not set new mode.\n"); + return(0); + } } - SDL_Win->Show(); + } else { + // Reset to the previous known resolution as we are now in window + // mode. + bscreen.SetMode(&saved_mode); + } + + // Effectivelly set/reset full screen mode. If we are already in + // full screen mode, we reset back to windowed mode first so the + // window can resize when going fullscreen. + // if (fullscreen) + // printf("Going fullscreen\n"); + // else + // printf("Going windowed\n"); + SDL_Win->SetFullScreen(fullscreen); + + // Calculate offsets for centering the window (in window mode) and for + // dentering the bitmap (in full screen mode). + BRect bounds = bscreen.Frame(); + bounds.PrintToStream(); + int32 cx = (bounds.IntegerWidth() - width)/2; + int32 cy = (bounds.IntegerHeight() - height)/2; + + // printf ("cx = %d, cy = %d\n", cx, cy); + if (!SDL_Win->IsFullScreen()) { + // printf("Doing not fullscreen stuff.\n"); + // We are not in full screen mode, so we want to change the window + // size to match the resolution in SDL. + SDL_Win->ResizeTo(width, height); - /* Unlock the window manually after the first Show() */ - if ( needs_unlock ) { - SDL_Win->Unlock(); - } + // And also center the window and reset the drawing offset. + SDL_Win->MoveTo(cx, cy); + SDL_Win->SetXYOffset(0, 0); + } else { + // printf("Doing fullscreen stuff."); + // Center the bitmap whenever we are in full screen mode. + SDL_Win->SetXYOffset(cx, cy); } - - /* Set the fullscreen flag in the screen surface */ - if ( fullscreen ) { + + // Set relevant internal SDL screen flags. + if (SDL_Win->IsFullScreen()) { screen->flags |= SDL_FULLSCREEN; } else { screen->flags &= ~SDL_FULLSCREEN; } + return(1); }