--- BasiliskII/src/SDL/video_sdl.cpp 2004/06/24 15:25:57 1.4 +++ BasiliskII/src/SDL/video_sdl.cpp 2004/06/29 21:50:22 1.10 @@ -35,6 +35,9 @@ * - Events processing is bound to the general emulation thread as SDL requires * to PumpEvents() within the same thread as the one that called SetVideoMode(). * Besides, there can't seem to be a way to call SetVideoMode() from a child thread. + * - Refresh performance is still slow. Use SDL_CreateRGBSurface()? + * - Backport hw cursor acceleration to Basilisk II? + * - Move generic Native QuickDraw acceleration routines to gfxaccel.cpp */ #include "sysdeps.h" @@ -96,7 +99,7 @@ static volatile bool redraw_thread_cance static SDL_Thread *redraw_thread = NULL; // Redraw thread #ifdef ENABLE_VOSF -static bool use_vosf = true; // Flag: VOSF enabled +static bool use_vosf = false; // Flag: VOSF enabled #else static const bool use_vosf = false; // VOSF not possible #endif @@ -114,6 +117,8 @@ static int keycode_table[256]; // X // SDL variables static int screen_depth; // Depth of current screen +static SDL_Cursor *sdl_cursor; // Copy of Mac cursor +static volatile bool cursor_changed = false; // Flag: cursor changed, redraw_func must update the cursor static SDL_Color sdl_palette[256]; // Color palette to be used as CLUT and gamma table static bool sdl_palette_changed = false; // Flag: Palette changed, redraw thread must set new colors static const int sdl_eventmask = SDL_MOUSEBUTTONDOWNMASK | SDL_MOUSEBUTTONUPMASK | SDL_MOUSEMOTIONMASK | SDL_KEYUPMASK | SDL_KEYDOWNMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK; @@ -255,6 +260,12 @@ static void ErrorAlert(int error) { ErrorAlert(GetString(error)); } + +// Display warning alert +static void WarningAlert(int warning) +{ + WarningAlert(GetString(warning)); +} #endif @@ -342,15 +353,58 @@ static int sdl_depth_of_video_depth(int return depth; } -// 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) +// Check wether specified mode is available +static bool has_mode(int type, int width, int height) { - VIDEO_MODE mode; + // FIXME: no fullscreen support yet + if (type == DISPLAY_SCREEN) + return false; + #ifdef SHEEPSHAVER - // Don't add 512x384 modes + // Filter out Classic resolutiosn if (width == 512 && height == 384) + return false; + + // Read window 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 + } + + if (type == DISPLAY_WINDOW) { + int apple_mask, apple_id = find_apple_resolution(width, height); + switch (apple_id) { + 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 (window_modes & apple_mask); + } +#else + return true; +#endif + return false; +} + +// 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)) return; + // Fill in VideoMode entry + VIDEO_MODE mode; +#ifdef SHEEPSHAVER // Recalculate dimensions to fit Apple modes resolution_id = match_apple_resolution(width, height); mode.viType = type; @@ -359,7 +413,7 @@ static void add_mode(int type, int width VIDEO_MODE_Y = height; VIDEO_MODE_RESOLUTION = resolution_id; VIDEO_MODE_ROW_BYTES = bytes_per_row; - VIDEO_MODE_DEPTH = depth; + VIDEO_MODE_DEPTH = (video_depth)depth; VideoModes.push_back(mode); } @@ -533,7 +587,7 @@ void driver_base::update_palette(void) { const VIDEO_MODE &mode = monitor.get_current_mode(); - if (VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) + if ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT) SDL_SetPalette(s, SDL_PHYSPAL, sdl_palette, 0, 256); } @@ -564,7 +618,7 @@ driver_window::driver_window(SDL_monitor ADBSetRelMouseMode(mouse_grabbed); // Create surface - int depth = (VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT ? 8 : screen_depth); + int depth = ((int)VIDEO_MODE_DEPTH <= VIDEO_DEPTH_8BIT ? 8 : screen_depth); if ((s = SDL_SetVideoMode(width, height, depth, SDL_HWSURFACE)) == NULL) return; @@ -576,20 +630,45 @@ driver_window::driver_window(SDL_monitor the_buffer = (uint8 *)vm_acquire(the_buffer_size); the_buffer_copy = (uint8 *)malloc(the_buffer_size); D(bug("the_buffer = %p, the_buffer_copy = %p, the_host_buffer = %p\n", the_buffer, the_buffer_copy, the_host_buffer)); + + // Check whether we can initialize the VOSF subsystem and it's profitable + if (!video_vosf_init(m)) { + WarningAlert(STR_VOSF_INIT_ERR); + use_vosf = false; + } + else if (!video_vosf_profitable()) { + video_vosf_exit(); + printf("VOSF acceleration is not profitable on this platform, disabling it\n"); + use_vosf = false; + } + if (!use_vosf) { + free(the_buffer_copy); + vm_release(the_buffer, the_buffer_size); + the_host_buffer = NULL; + } +#endif + if (!use_vosf) { + // Allocate memory for frame buffer + the_buffer_size = (aligned_height + 2) * s->pitch; + the_buffer_copy = (uint8 *)calloc(1, the_buffer_size); + the_buffer = (uint8 *)calloc(1, the_buffer_size); + D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); + } + +#ifdef SHEEPSHAVER + // Create cursor + if ((sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, 0, 0)) != NULL) { + SDL_SetCursor(sdl_cursor); + cursor_changed = false; + } #else - // Allocate memory for frame buffer - the_buffer_size = (aligned_height + 2) * s->pitch; - the_buffer_copy = (uint8 *)calloc(1, the_buffer_size); - the_buffer = (uint8 *)calloc(1, the_buffer_size); - D(bug("the_buffer = %p, the_buffer_copy = %p\n", the_buffer, the_buffer_copy)); + // Hide cursor + SDL_ShowCursor(0); #endif // Set window name/class set_window_name(STR_WINDOW_TITLE); - // Hide cursor - SDL_ShowCursor(0); - // Init blitting routines SDL_PixelFormat *f = s->format; VisualFormat visualFormat; @@ -708,8 +787,8 @@ static void keycode_init(void) if (video_driver_found) { // Skip aliases - static const char alias_str[] = "alias"; - if (strncmp(line, alias_str, sizeof(alias_str) - 1) == 0) + static const char sdl_str[] = "sdl"; + if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0) continue; // Read keycode @@ -720,9 +799,9 @@ static void keycode_init(void) break; } else { // Search for SDL video driver string - static const char alias_sdl_str[] = "alias SDL"; - if (strncmp(line, alias_sdl_str, sizeof(alias_sdl_str) - 1) == 0) { - char *p = line + sizeof(alias_sdl_str); + static const char sdl_str[] = "sdl"; + if (strncmp(line, sdl_str, sizeof(sdl_str) - 1) == 0) { + char *p = line + sizeof(sdl_str); if (strstr(video_driver, p) == video_driver) video_driver_found = true; } @@ -748,6 +827,10 @@ bool SDL_monitor_desc::video_open(void) { D(bug("video_open()\n")); const VIDEO_MODE &mode = get_current_mode(); +#if DEBUG + D(bug("Current video mode:\n")); + D(bug(" %dx%d (ID %02x), %d bpp\n", VIDEO_MODE_X, VIDEO_MODE_Y, VIDEO_MODE_RESOLUTION, 1 << (VIDEO_MODE_DEPTH & 0x0f))); +#endif // Create display driver object of requested type switch (display_type) { @@ -763,16 +846,6 @@ bool SDL_monitor_desc::video_open(void) return false; } -#ifdef ENABLE_VOSF - if (use_vosf) { - // Initialize the VOSF system - if (!video_vosf_init(*this)) { - ErrorAlert(STR_VOSF_INIT_ERR); - return false; - } - } -#endif - // Initialize VideoRefresh function VideoRefreshInit(); @@ -820,11 +893,13 @@ bool VideoInit(bool classic) mouse_wheel_lines = PrefsFindInt32("mousewheellines"); // Get screen mode from preferences - const char *mode_str; + const char *mode_str = NULL; +#ifndef SHEEPSHAVER if (classic_mode) mode_str = "win/512/342"; else mode_str = PrefsFindString("screen"); +#endif // Determine display type and default dimensions int default_width, default_height; @@ -842,12 +917,14 @@ bool VideoInit(bool classic) display_type = DISPLAY_WINDOW; } int max_width = 640, max_height = 480; - if (display_type == DISPLAY_SCREEN) { - SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); - if (modes && modes != (SDL_Rect **)-1) { - max_width = modes[0]->w; - max_height = modes[0]->h; - } + SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE); + if (modes && modes != (SDL_Rect **)-1) { + max_width = modes[0]->w; + max_height = modes[0]->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; @@ -914,12 +991,14 @@ bool VideoInit(bool classic) } #ifdef SHEEPSHAVER - for (int i = 0; i < VideoModes.size(); ++i) + for (int i = 0; i < VideoModes.size(); i++) VModes[i] = VideoModes[i]; - - const VIDEO_MODE & mode = VideoModes[cur_mode]; - D(bug("Current video mode\n")); - D(bug(" %dx%d (ID %02x), %d bpp\n", VIDEO_MODE_X, VIDEO_MODE_Y, VIDEO_MODE_RESOLUTION, 1 << (VIDEO_MODE_DEPTH - 0x80))); + VideoInfo *p = &VModes[VideoModes.size()]; + p->viType = DIS_INVALID; // End marker + p->viRowBytes = 0; + p->viXsize = p->viYsize = 0; + p->viAppleMode = 0; + p->viAppleID = 0; #endif #if DEBUG @@ -1068,7 +1147,7 @@ void SDL_monitor_desc::set_palette(uint8 const VIDEO_MODE &mode = get_current_mode(); // FIXME: how can we handle the gamma ramp? - if (VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT) + if ((int)VIDEO_MODE_DEPTH > VIDEO_DEPTH_8BIT) return; LOCK_PALETTE; @@ -1093,11 +1172,13 @@ void SDL_monitor_desc::set_palette(uint8 } #ifdef ENABLE_VOSF - // We have to redraw everything because the interpretation of pixel values changed - LOCK_VOSF; - PFLAG_SET_ALL; - UNLOCK_VOSF; - memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); + if (use_vosf) { + // We have to redraw everything because the interpretation of pixel values changed + LOCK_VOSF; + PFLAG_SET_ALL; + UNLOCK_VOSF; + memset(the_buffer_copy, 0, VIDEO_MODE_ROW_BYTES * VIDEO_MODE_Y); + } #endif } @@ -1168,8 +1249,7 @@ void SDL_monitor_desc::switch_to_current #ifdef SHEEPSHAVER bool video_can_change_cursor(void) { -// return hw_mac_cursor_accl && (display_type != DISPLAY_SCREEN); - return false; + return (display_type == DISPLAY_WINDOW); } #endif @@ -1181,7 +1261,7 @@ bool video_can_change_cursor(void) #ifdef SHEEPSHAVER void video_set_cursor(void) { -// cursor_changed = true; + cursor_changed = true; } #endif @@ -1549,15 +1629,43 @@ void VideoInstallAccel(void) /* - * Translate key event to Mac keycode, returns -1 if no keycode was found - * and -2 if the key was recognized as a hotkey + * Keyboard-related utilify functions */ +static bool is_modifier_key(SDL_KeyboardEvent const & e) +{ + switch (e.keysym.sym) { + case SDLK_NUMLOCK: + case SDLK_CAPSLOCK: + case SDLK_SCROLLOCK: + case SDLK_RSHIFT: + case SDLK_LSHIFT: + case SDLK_RCTRL: + case SDLK_LCTRL: + case SDLK_RALT: + case SDLK_LALT: + case SDLK_RMETA: + case SDLK_LMETA: + case SDLK_LSUPER: + case SDLK_RSUPER: + case SDLK_MODE: + case SDLK_COMPOSE: + return true; + } + return false; +} + static bool is_ctrl_down(SDL_keysym const & ks) { return ctrl_down || (ks.mod & KMOD_CTRL); } + +/* + * Translate key event to Mac keycode, returns -1 if no keycode was found + * and -2 if the key was recognized as a hotkey + */ + static int kc_decode(SDL_keysym const & ks, bool key_down) { switch (ks.sym) { @@ -1627,10 +1735,17 @@ static int kc_decode(SDL_keysym const & case SDLK_RCTRL: return 0x36; case SDLK_LSHIFT: return 0x38; case SDLK_RSHIFT: return 0x38; +#if (defined(__APPLE__) && defined(__MACH__)) + case SDLK_LALT: return 0x3a; + case SDLK_RALT: return 0x3a; + case SDLK_LMETA: return 0x37; + case SDLK_RMETA: return 0x37; +#else case SDLK_LALT: return 0x37; case SDLK_RALT: return 0x37; case SDLK_LMETA: return 0x3a; case SDLK_RMETA: return 0x3a; +#endif case SDLK_MENU: return 0x32; case SDLK_CAPSLOCK: return 0x39; case SDLK_NUMLOCK: return 0x47; @@ -1737,7 +1852,7 @@ static void handle_events(void) // Keyboard case SDL_KEYDOWN: { int code = -1; - if (use_keycodes) { + if (use_keycodes && !is_modifier_key(event.key)) { if (event2keycode(event.key, true) != -2) // This is called to process the hotkeys code = keycode_table[event.key.keysym.scancode & 0xff]; } else @@ -1765,13 +1880,22 @@ static void handle_events(void) } case SDL_KEYUP: { int code = -1; - if (use_keycodes) { + if (use_keycodes && !is_modifier_key(event.key)) { if (event2keycode(event.key, false) != -2) // This is called to process the hotkeys code = keycode_table[event.key.keysym.scancode & 0xff]; } else code = event2keycode(event.key, false); - if (code >= 0 && code != 0x39) { // Don't propagate Caps Lock releases - ADBKeyUp(code); + if (code >= 0) { + if (code == 0x39) { // Caps Lock released + if (caps_on) { + ADBKeyUp(code); + caps_on = false; + } else { + ADBKeyDown(code); + caps_on = true; + } + } else + ADBKeyUp(code); if (code == 0x36) ctrl_down = false; } @@ -1838,7 +1962,7 @@ static void update_display_static(driver // Check for first column from left and first column from right that have changed if (high) { - if (VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { + if ((int)VIDEO_MODE_DEPTH < VIDEO_DEPTH_8BIT) { const int src_bytes_per_row = bytes_per_row; const int dst_bytes_per_row = drv->s->pitch; const int pixels_per_byte = VIDEO_MODE_X / src_bytes_per_row; @@ -2105,6 +2229,17 @@ static int redraw_func(void *arg) // Refresh display video_refresh(); +#ifdef SHEEPSHAVER + // Set new cursor image if it was changed + if (cursor_changed && sdl_cursor) { + cursor_changed = false; + SDL_FreeCursor(sdl_cursor); + sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]); + if (sdl_cursor) + SDL_SetCursor(sdl_cursor); + } +#endif + // Set new palette if it was changed handle_palette_changes(); }