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 --HG-- branch : SDL-1.2 extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/branches/SDL-1.2%403997
This commit is contained in:
parent
dbb19d2093
commit
259a72541e
3 changed files with 103 additions and 75 deletions
|
@ -267,6 +267,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void DispatchMessage(BMessage *msg, BHandler *target);
|
virtual void DispatchMessage(BMessage *msg, BHandler *target);
|
||||||
|
|
||||||
|
virtual void DirectConnected(direct_buffer_info *info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if SDL_VIDEO_OPENGL
|
#if SDL_VIDEO_OPENGL
|
||||||
|
|
|
@ -379,3 +379,20 @@ void SDL_BWin::DispatchMessage(BMessage *msg, BHandler *target)
|
||||||
}
|
}
|
||||||
BDirectWindow::DispatchMessage(msg, target);
|
BDirectWindow::DispatchMessage(msg, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDL_BWin::DirectConnected(direct_buffer_info *info) {
|
||||||
|
switch (info->buffer_state & B_DIRECT_MODE_MASK) {
|
||||||
|
case B_DIRECT_START:
|
||||||
|
case B_DIRECT_MODIFY:
|
||||||
|
{
|
||||||
|
int32 width = info->window_bounds.right -
|
||||||
|
info->window_bounds.left + 1;
|
||||||
|
int32 height = info->window_bounds.bottom -
|
||||||
|
info->window_bounds.top + 1;
|
||||||
|
SDL_PrivateResize(width, height);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ static void BE_UnlockHWSurface(_THIS, SDL_Surface *surface);
|
||||||
static void BE_FreeHWSurface(_THIS, SDL_Surface *surface);
|
static void BE_FreeHWSurface(_THIS, SDL_Surface *surface);
|
||||||
|
|
||||||
static int BE_ToggleFullScreen(_THIS, int fullscreen);
|
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 */
|
/* OpenGL functions */
|
||||||
#if SDL_VIDEO_OPENGL
|
#if SDL_VIDEO_OPENGL
|
||||||
|
@ -358,16 +358,25 @@ static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp,
|
||||||
(current.timing.h_total * current.timing.v_total);
|
(current.timing.h_total * current.timing.v_total);
|
||||||
|
|
||||||
modes = SDL_modelist[((bpp+7)/8)-1];
|
modes = SDL_modelist[((bpp+7)/8)-1];
|
||||||
for ( i=0; modes[i] && (modes[i]->w > width) &&
|
|
||||||
(modes[i]->h > height); ++i ) {
|
// find end of list (lowest-resolution mode; modes are ordered
|
||||||
/* still looking */
|
// 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;
|
width = modes[i]->w;
|
||||||
height = modes[i]->h;
|
height = modes[i]->h;
|
||||||
|
|
||||||
bscreen.GetModeList(&dmodes, &nmodes);
|
bscreen.GetModeList(&dmodes, &nmodes);
|
||||||
for ( i = 0; i < nmodes; ++i ) {
|
for ( i = 0; i < nmodes; ++i ) {
|
||||||
|
@ -396,88 +405,88 @@ static bool BE_FindClosestFSMode(_THIS, int width, int height, int bpp,
|
||||||
|
|
||||||
static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen)
|
static int BE_SetFullScreen(_THIS, SDL_Surface *screen, int fullscreen)
|
||||||
{
|
{
|
||||||
int was_fullscreen;
|
// printf("SetFullScreen(%d)\n", fullscreen);
|
||||||
bool needs_unlock;
|
|
||||||
BScreen bscreen;
|
BScreen bscreen;
|
||||||
BRect bounds;
|
|
||||||
display_mode mode;
|
|
||||||
int width, height, bpp;
|
|
||||||
|
|
||||||
/* Set the fullscreen mode */
|
// SetFullSscreen() does not work as expected if called in a window
|
||||||
was_fullscreen = SDL_Win->IsFullScreen();
|
// that was never shown. This is probably a bug in the Haiku Game Kit that needs
|
||||||
SDL_Win->SetFullScreen(fullscreen);
|
// to be investigated.
|
||||||
fullscreen = SDL_Win->IsFullScreen();
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
width = screen->w;
|
int width = screen->w;
|
||||||
height = screen->h;
|
int height = screen->h;
|
||||||
|
|
||||||
/* Set the appropriate video mode */
|
if (fullscreen) {
|
||||||
if ( fullscreen ) {
|
// Set resolution to the closest available one that matches the
|
||||||
bpp = screen->format->BitsPerPixel;
|
// current SDL resolution.
|
||||||
|
display_mode mode;
|
||||||
bscreen.GetMode(&mode);
|
bscreen.GetMode(&mode);
|
||||||
if ( (bpp != ColorSpaceToBitsPerPixel(mode.space)) ||
|
|
||||||
(width != mode.virtual_width) ||
|
int bpp = screen->format->BitsPerPixel;
|
||||||
(height != mode.virtual_height)) {
|
if (bpp != ColorSpaceToBitsPerPixel(mode.space) ||
|
||||||
|
width != mode.virtual_width || height != mode.virtual_height) {
|
||||||
if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) {
|
if(BE_FindClosestFSMode(_this, width, height, bpp, &mode)) {
|
||||||
bscreen.SetMode(&mode);
|
bscreen.SetMode(&mode);
|
||||||
/* This simply stops the next resize event from being
|
|
||||||
* sent to the SDL handler.
|
|
||||||
*/
|
|
||||||
SDL_Win->InhibitResize();
|
|
||||||
} else {
|
} else {
|
||||||
fullscreen = 0;
|
// printf("Could not set new mode.\n");
|
||||||
SDL_Win->SetFullScreen(fullscreen);
|
return(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Reset to the previous known resolution as we are now in window
|
||||||
|
// mode.
|
||||||
|
bscreen.SetMode(&saved_mode);
|
||||||
}
|
}
|
||||||
if ( was_fullscreen && ! fullscreen ) {
|
|
||||||
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 ( SDL_Win->Lock() ) {
|
// if (fullscreen)
|
||||||
int cx, cy;
|
// printf("Going fullscreen\n");
|
||||||
if ( SDL_Win->Shown() ) {
|
// else
|
||||||
needs_unlock = 1;
|
// printf("Going windowed\n");
|
||||||
SDL_Win->Hide();
|
SDL_Win->SetFullScreen(fullscreen);
|
||||||
} else {
|
|
||||||
needs_unlock = 0;
|
// Calculate offsets for centering the window (in window mode) and for
|
||||||
}
|
// dentering the bitmap (in full screen mode).
|
||||||
/* This resizes the window and view area, but inhibits resizing
|
BRect bounds = bscreen.Frame();
|
||||||
* of the BBitmap due to the InhibitResize call above. Thus the
|
bounds.PrintToStream();
|
||||||
* bitmap (pixel data) never changes.
|
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);
|
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;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
SDL_Win->Show();
|
|
||||||
|
|
||||||
/* Unlock the window manually after the first Show() */
|
// And also center the window and reset the drawing offset.
|
||||||
if ( needs_unlock ) {
|
SDL_Win->MoveTo(cx, cy);
|
||||||
SDL_Win->Unlock();
|
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 */
|
// Set relevant internal SDL screen flags.
|
||||||
if ( fullscreen ) {
|
if (SDL_Win->IsFullScreen()) {
|
||||||
screen->flags |= SDL_FULLSCREEN;
|
screen->flags |= SDL_FULLSCREEN;
|
||||||
} else {
|
} else {
|
||||||
screen->flags &= ~SDL_FULLSCREEN;
|
screen->flags &= ~SDL_FULLSCREEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue