SDL Video updates:

- Properly handle migration from "screenmodes" and "windowmodes" to "screen"
- Fix has_mode() logic to really test for actual mode availability. i.e.
  no longer start in large screen mode if user specified a max size.
This commit is contained in:
gbeauche 2006-05-09 21:41:02 +00:00
parent 484469962b
commit 5019174a22

View File

@ -286,69 +286,21 @@ static vector<monitor_desc *> VideoMonitors;
// Find Apple mode matching best specified dimensions
static int find_apple_resolution(int xsize, int ysize)
{
int apple_id;
if (xsize < 800)
apple_id = APPLE_640x480;
else if (xsize < 1024)
apple_id = APPLE_800x600;
else if (xsize < 1152)
apple_id = APPLE_1024x768;
else if (xsize < 1280) {
if (ysize < 900)
apple_id = APPLE_1152x768;
else
apple_id = APPLE_1152x900;
}
else if (xsize < 1600)
apple_id = APPLE_1280x1024;
else
apple_id = APPLE_1600x1200;
return apple_id;
}
// Set parameters to specified Apple mode
static void set_apple_resolution(int apple_id, int &xsize, int &ysize)
{
switch (apple_id) {
case APPLE_640x480:
xsize = 640;
ysize = 480;
break;
case APPLE_800x600:
xsize = 800;
ysize = 600;
break;
case APPLE_1024x768:
xsize = 1024;
ysize = 768;
break;
case APPLE_1152x768:
xsize = 1152;
ysize = 768;
break;
case APPLE_1152x900:
xsize = 1152;
ysize = 900;
break;
case APPLE_1280x1024:
xsize = 1280;
ysize = 1024;
break;
case APPLE_1600x1200:
xsize = 1600;
ysize = 1200;
break;
default:
abort();
}
}
// Match Apple mode matching best specified dimensions
static int match_apple_resolution(int &xsize, int &ysize)
{
int apple_id = find_apple_resolution(xsize, ysize);
set_apple_resolution(apple_id, xsize, ysize);
return apple_id;
if (xsize == 640 && ysize == 480)
return APPLE_640x480;
if (xsize == 800 && ysize == 600)
return APPLE_800x600;
if (xsize == 1024 && ysize == 768)
return APPLE_1024x768;
if (xsize == 1152 && ysize == 768)
return APPLE_1152x768;
if (xsize == 1152 && ysize == 900)
return APPLE_1152x900;
if (xsize == 1280 && ysize == 1024)
return APPLE_1280x1024;
if (xsize == 1600 && ysize == 1200)
return APPLE_1600x1200;
return APPLE_CUSTOM;
}
// Display error alert
@ -455,69 +407,74 @@ static int sdl_depth_of_video_depth(int video_depth)
return (video_depth <= VIDEO_DEPTH_8BIT) ? 8 : mac_depth_of_video_depth(video_depth);
}
// Get screen dimensions
static void sdl_display_dimensions(int &width, int &height)
{
static int max_width, max_height;
if (max_width == 0 && max_height == 0) {
max_width = 640 ; max_height = 480;
SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
if (modes && modes != (SDL_Rect **)-1) {
// It turns out that on some implementations, and contrary to the documentation,
// the returned list is not sorted from largest to smallest (e.g. Windows)
for (int i = 0; modes[i] != NULL; i++) {
const int w = modes[i]->w;
const int h = modes[i]->h;
if (w > max_width && h > max_height) {
max_width = w;
max_height = h;
}
}
}
}
width = max_width;
height = max_height;
}
static inline int sdl_display_width(void)
{
int width, height;
sdl_display_dimensions(width, height);
return width;
}
static inline int sdl_display_height(void)
{
int width, height;
sdl_display_dimensions(width, height);
return height;
}
// Check wether specified mode is available
static bool has_mode(int type, int width, int height)
static bool has_mode(int type, int width, int height, int depth)
{
#ifdef SHEEPSHAVER
// Filter out Classic resolutiosn
// Filter out Classic resolutions
if (width == 512 && height == 384)
return false;
// "screen" prefs items always succeeds
if (PrefsFindString("screen"))
return true;
// Read window & screen modes prefs
static uint32 window_modes = 0;
static uint32 screen_modes = 0;
if (window_modes == 0 || screen_modes == 0) {
window_modes = PrefsFindInt32("windowmodes");
screen_modes = PrefsFindInt32("screenmodes");
if (window_modes == 0 || screen_modes == 0)
window_modes |= 3; // Allow at least 640x480 and 800x600 window modes
}
int test_modes;
switch (type) {
case DISPLAY_WINDOW:
test_modes = window_modes;
break;
case DISPLAY_SCREEN:
test_modes = screen_modes;
break;
default:
test_modes = 0;
break;
}
int apple_mask;
switch (find_apple_resolution(width, height)) {
case APPLE_640x480: apple_mask = 0x01; break;
case APPLE_800x600: apple_mask = 0x02; break;
case APPLE_1024x768: apple_mask = 0x04; break;
case APPLE_1152x768: apple_mask = 0x40; break;
case APPLE_1152x900: apple_mask = 0x08; break;
case APPLE_1280x1024: apple_mask = 0x10; break;
case APPLE_1600x1200: apple_mask = 0x20; break;
default: apple_mask = 0x00; break;
}
return (test_modes & apple_mask);
#endif
return true;
// Filter out out-of-bounds resolutions
if (width > sdl_display_width() || height > sdl_display_height())
return false;
// Rely on SDL capabilities
return SDL_VideoModeOK(width, height,
sdl_depth_of_video_depth(depth),
SDL_HWSURFACE | (type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0));
}
// Add mode to list of supported modes
static void add_mode(int type, int width, int height, int resolution_id, int bytes_per_row, int depth)
{
// Filter out unsupported modes
if (!has_mode(type, width, height))
if (!has_mode(type, width, height, depth))
return;
// Fill in VideoMode entry
VIDEO_MODE mode;
#ifdef SHEEPSHAVER
// Recalculate dimensions to fit Apple modes
resolution_id = match_apple_resolution(width, height);
resolution_id = find_apple_resolution(width, height);
mode.viType = type;
#endif
VIDEO_MODE_X = width;
@ -528,19 +485,6 @@ static void add_mode(int type, int width, int height, int resolution_id, int byt
VideoModes.push_back(mode);
}
// Add standard list of windowed modes for given color depth
static void add_window_modes(int depth)
{
video_depth vdepth = (video_depth)depth;
add_mode(DISPLAY_WINDOW, 512, 384, 0x80, TrivialBytesPerRow(512, vdepth), depth);
add_mode(DISPLAY_WINDOW, 640, 480, 0x81, TrivialBytesPerRow(640, vdepth), depth);
add_mode(DISPLAY_WINDOW, 800, 600, 0x82, TrivialBytesPerRow(800, vdepth), depth);
add_mode(DISPLAY_WINDOW, 1024, 768, 0x83, TrivialBytesPerRow(1024, vdepth), depth);
add_mode(DISPLAY_WINDOW, 1152, 870, 0x84, TrivialBytesPerRow(1152, vdepth), depth);
add_mode(DISPLAY_WINDOW, 1280, 1024, 0x85, TrivialBytesPerRow(1280, vdepth), depth);
add_mode(DISPLAY_WINDOW, 1600, 1200, 0x86, TrivialBytesPerRow(1600, vdepth), depth);
}
// Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac)
static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool native_byte_order)
{
@ -584,6 +528,55 @@ static SDL_GrabMode set_grab_mode(SDL_GrabMode mode)
return (vi && vi->wm_available ? SDL_WM_GrabInput(mode) : SDL_GRAB_OFF);
}
// Migrate preferences items (XXX to be handled in MigratePrefs())
static void migrate_screen_prefs(void)
{
#ifdef SHEEPSHAVER
// Look-up priorities are: "screen", "screenmodes", "windowmodes".
if (PrefsFindString("screen"))
return;
uint32 window_modes = PrefsFindInt32("windowmodes");
uint32 screen_modes = PrefsFindInt32("screenmodes");
int width = 0, height = 0;
if (screen_modes) {
static const struct {
int id;
int width;
int height;
}
modes[] = {
{ 1, 640, 480 },
{ 2, 800, 600 },
{ 4, 1024, 768 },
{ 64, 1152, 768 },
{ 8, 1152, 900 },
{ 16, 1280, 1024 },
{ 32, 1600, 1200 },
{ 0, }
};
for (int i = 0; modes[i].id != 0; i++) {
if (screen_modes & modes[i].id) {
if (width < modes[i].width && height < modes[i].height) {
width = modes[i].width;
height = modes[i].height;
}
}
}
} else {
if (window_modes & 1)
width = 640, height = 480;
if (window_modes & 2)
width = 800, height = 600;
}
if (width && height) {
char str[32];
sprintf(str, "%s/%d/%d", screen_modes ? "dga" : "win", width, height);
PrefsReplaceString("screen", str);
}
#endif
}
/*
* Display "driver" classes
@ -1123,6 +1116,7 @@ bool VideoInit(bool classic)
mouse_wheel_lines = PrefsFindInt32("mousewheellines");
// Get screen mode from preferences
migrate_screen_prefs();
const char *mode_str = NULL;
if (classic_mode)
mode_str = "win/512/342";
@ -1146,28 +1140,14 @@ bool VideoInit(bool classic)
else if (sscanf(mode_str, "dga/%d/%d", &default_width, &default_height) == 2)
display_type = DISPLAY_SCREEN;
}
int max_width = 640, max_height = 480;
SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
if (modes && modes != (SDL_Rect **)-1) {
// It turns out that on some implementations, and contrary to the documentation,
// the returned list is not sorted from largest to smallest (e.g. Windows)
for (int i = 0; modes[i] != NULL; i++) {
const int w = modes[i]->w;
const int h = modes[i]->h;
if (w > max_width && h > max_height) {
max_width = w;
max_height = h;
}
}
if (default_width > max_width)
default_width = max_width;
if (default_height > max_height)
default_height = max_height;
}
if (default_width <= 0)
default_width = max_width;
default_width = sdl_display_width();
else if (default_width > sdl_display_width())
default_width = sdl_display_width();
if (default_height <= 0)
default_height = max_height;
default_height = sdl_display_height();
else if (default_height > sdl_display_height())
default_height = sdl_display_height();
// Mac screen depth follows X depth
screen_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
@ -1187,47 +1167,51 @@ bool VideoInit(bool classic)
break;
}
// Initialize list of video modes to try
struct {
int w;
int h;
int resolution_id;
}
video_modes[] = {
{ -1, -1, 0x80 },
{ 512, 384, 0x80 },
{ 640, 480, 0x81 },
{ 800, 600, 0x82 },
{ 1024, 768, 0x83 },
{ 1152, 870, 0x84 },
{ 1280, 1024, 0x85 },
{ 1600, 1200, 0x86 },
{ 0, }
};
video_modes[0].w = default_width;
video_modes[0].h = default_height;
// Construct list of supported modes
if (display_type == DISPLAY_WINDOW) {
if (classic)
add_mode(display_type, 512, 342, 0x80, 64, VIDEO_DEPTH_1BIT);
else {
for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) {
int bpp = sdl_depth_of_video_depth(d);
if (SDL_VideoModeOK(max_width, max_height, bpp, SDL_HWSURFACE))
add_window_modes(video_depth(d));
for (int i = 0; video_modes[i].w != 0; i++) {
const int w = video_modes[i].w;
const int h = video_modes[i].h;
if (i > 0 && (w >= default_width || h >= default_height))
continue;
for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++)
add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
}
}
} else if (display_type == DISPLAY_SCREEN) {
struct {
int w;
int h;
int resolution_id;
}
video_modes[] = {
{ -1, -1, 0x80 },
{ 640, 480, 0x81 },
{ 800, 600, 0x82 },
{ 1024, 768, 0x83 },
{ 1152, 870, 0x84 },
{ 1280, 1024, 0x85 },
{ 1600, 1200, 0x86 },
{ 0, }
};
video_modes[0].w = default_width;
video_modes[0].h = default_height;
for (int i = 0; video_modes[i].w != 0; i++) {
const int w = video_modes[i].w;
const int h = video_modes[i].h;
if (i > 0 && (w >= default_width || h >= default_height))
continue;
if (w == 512 && h == 384)
continue;
#ifdef ENABLE_VOSF
for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) {
int bpp = sdl_depth_of_video_depth(d);
if (SDL_VideoModeOK(w, h, bpp, SDL_HWSURFACE | SDL_FULLSCREEN))
add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
}
for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++)
add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
#else
add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)default_depth), default_depth);
#endif