~ubuntu-branches/ubuntu/feisty/basilisk2/feisty

« back to all changes in this revision

Viewing changes to src/SDL/video_sdl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2006-06-01 01:11:16 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060601011116-xjhegbgyfsxag5fl
Tags: 0.9.20060529-1
* New upstream CVS snapshot.
* Update local cdbs snippet copyright-check.mk:
  + Broaden scan to also look for "(c)" by default.
  + Make egrep options configurable.
  + Ignore auto-tools files.
* Bump up standards-version to 3.7.2 (no changes needed).
* Let dh_strip do the stripping (not the make install target).

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 *      Ctrl-F5 = grab mouse (in windowed mode)
28
28
 *
29
29
 *  FIXMEs and TODOs:
 
30
 *  - Windows requires an extra mouse event to update the actual cursor image?
30
31
 *  - Ctr-Tab for suspend/resume but how? SDL does not support that for non-Linux
31
32
 *  - Ctrl-Fn doesn't generate SDL_KEYDOWN events (SDL bug?)
32
33
 *  - Mouse acceleration, there is no API in SDL yet for that
33
34
 *  - Force relative mode in Grab mode even if SDL provides absolute coordinates?
34
 
 *  - Fullscreen mode
35
35
 *  - Gamma tables support is likely to be broken here
36
36
 *  - Events processing is bound to the general emulation thread as SDL requires
37
37
 *    to PumpEvents() within the same thread as the one that called SetVideoMode().
38
38
 *    Besides, there can't seem to be a way to call SetVideoMode() from a child thread.
39
 
 *  - Refresh performance is still slow. Use SDL_CreateRGBSurface()?
40
39
 *  - Backport hw cursor acceleration to Basilisk II?
41
40
 *  - Factor out code
42
41
 */
49
48
#include <errno.h>
50
49
#include <vector>
51
50
 
 
51
#ifdef WIN32
 
52
#include <malloc.h> /* alloca() */
 
53
#endif
 
54
 
52
55
#include "cpu_emulation.h"
53
56
#include "main.h"
54
57
#include "adb.h"
135
138
static bool sdl_palette_changed = false;                        // Flag: Palette changed, redraw thread must set new colors
136
139
static const int sdl_eventmask = SDL_MOUSEBUTTONDOWNMASK | SDL_MOUSEBUTTONUPMASK | SDL_MOUSEMOTIONMASK | SDL_KEYUPMASK | SDL_KEYDOWNMASK | SDL_VIDEOEXPOSEMASK | SDL_QUITMASK;
137
140
 
 
141
// Mutex to protect SDL events
 
142
static SDL_mutex *sdl_events_lock = NULL;
 
143
#define LOCK_EVENTS SDL_LockMutex(sdl_events_lock)
 
144
#define UNLOCK_EVENTS SDL_UnlockMutex(sdl_events_lock)
 
145
 
138
146
// Mutex to protect palette
139
147
static SDL_mutex *sdl_palette_lock = NULL;
140
148
#define LOCK_PALETTE SDL_LockMutex(sdl_palette_lock)
158
166
 
159
167
 
160
168
/*
 
169
 *  SDL surface locking glue
 
170
 */
 
171
 
 
172
#ifdef ENABLE_VOSF
 
173
#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE) do {                               \
 
174
        if ((SURFACE)->flags & (SDL_HWSURFACE | SDL_FULLSCREEN))        \
 
175
                the_host_buffer = (uint8 *)(SURFACE)->pixels;                   \
 
176
} while (0)
 
177
#else
 
178
#define SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE)
 
179
#endif
 
180
 
 
181
#define SDL_VIDEO_LOCK_SURFACE(SURFACE) do {    \
 
182
        if (SDL_MUSTLOCK(SURFACE)) {                            \
 
183
                SDL_LockSurface(SURFACE);                               \
 
184
                SDL_VIDEO_LOCK_VOSF_SURFACE(SURFACE);   \
 
185
        }                                                                                       \
 
186
} while (0)
 
187
 
 
188
#define SDL_VIDEO_UNLOCK_SURFACE(SURFACE) do {  \
 
189
        if (SDL_MUSTLOCK(SURFACE))                                      \
 
190
                SDL_UnlockSurface(SURFACE);                             \
 
191
} while (0)
 
192
 
 
193
 
 
194
/*
161
195
 *  Framebuffer allocation routines
162
196
 */
163
197
 
164
198
static void *vm_acquire_framebuffer(uint32 size)
165
199
{
166
 
#ifdef SHEEPSHAVER
167
 
#ifdef DIRECT_ADDRESSING_HACK
168
 
        const uint32 FRAME_BUFFER_BASE = 0x61000000;
169
 
        uint8 *fb = Mac2HostAddr(FRAME_BUFFER_BASE);
170
 
        if (vm_acquire_fixed(fb, size) < 0)
171
 
                fb = VM_MAP_FAILED;
172
 
        return fb;
173
 
#endif
174
 
#endif
175
200
        return vm_acquire(size);
176
201
}
177
202
 
182
207
 
183
208
 
184
209
/*
 
210
 *  Windows message handler
 
211
 */
 
212
 
 
213
#ifdef WIN32
 
214
#include <dbt.h>
 
215
static WNDPROC sdl_window_proc = NULL;                          // Window proc used by SDL
 
216
 
 
217
extern void SysMediaArrived(void);
 
218
extern void SysMediaRemoved(void);
 
219
extern HWND GetMainWindowHandle(void);
 
220
 
 
221
static LRESULT CALLBACK windows_message_handler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
222
{
 
223
        switch (msg) {
 
224
        case WM_DEVICECHANGE:
 
225
                if (wParam == DBT_DEVICEREMOVECOMPLETE) {
 
226
                        DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam;
 
227
                        if (p->dbch_devicetype == DBT_DEVTYP_VOLUME)
 
228
                                SysMediaRemoved();
 
229
                }
 
230
                else if (wParam == DBT_DEVICEARRIVAL) {
 
231
                        DEV_BROADCAST_HDR *p = (DEV_BROADCAST_HDR *)lParam;
 
232
                        if (p->dbch_devicetype == DBT_DEVTYP_VOLUME)
 
233
                                SysMediaArrived();
 
234
                }
 
235
                return 0;
 
236
 
 
237
        default:
 
238
                if (sdl_window_proc)
 
239
                        return CallWindowProc(sdl_window_proc, hwnd, msg, wParam, lParam);
 
240
        }
 
241
 
 
242
        return DefWindowProc(hwnd, msg, wParam, lParam);
 
243
}
 
244
#endif
 
245
 
 
246
 
 
247
/*
185
248
 *  SheepShaver glue
186
249
 */
187
250
 
226
289
// Find Apple mode matching best specified dimensions
227
290
static int find_apple_resolution(int xsize, int ysize)
228
291
{
229
 
        int apple_id;
230
 
        if (xsize < 800)
231
 
                apple_id = APPLE_640x480;
232
 
        else if (xsize < 1024)
233
 
                apple_id = APPLE_800x600;
234
 
        else if (xsize < 1152)
235
 
                apple_id = APPLE_1024x768;
236
 
        else if (xsize < 1280) {
237
 
                if (ysize < 900)
238
 
                        apple_id = APPLE_1152x768;
239
 
                else
240
 
                        apple_id = APPLE_1152x900;
241
 
        }
242
 
        else if (xsize < 1600)
243
 
                apple_id = APPLE_1280x1024;
244
 
        else
245
 
                apple_id = APPLE_1600x1200;
246
 
        return apple_id;
247
 
}
248
 
 
249
 
// Set parameters to specified Apple mode
250
 
static void set_apple_resolution(int apple_id, int &xsize, int &ysize)
251
 
{
252
 
        switch (apple_id) {
253
 
        case APPLE_640x480:
254
 
                xsize = 640;
255
 
                ysize = 480;
256
 
                break;
257
 
        case APPLE_800x600:
258
 
                xsize = 800;
259
 
                ysize = 600;
260
 
                break;
261
 
        case APPLE_1024x768:
262
 
                xsize = 1024;
263
 
                ysize = 768;
264
 
                break;
265
 
        case APPLE_1152x768:
266
 
                xsize = 1152;
267
 
                ysize = 768;
268
 
                break;
269
 
        case APPLE_1152x900:
270
 
                xsize = 1152;
271
 
                ysize = 900;
272
 
                break;
273
 
        case APPLE_1280x1024:
274
 
                xsize = 1280;
275
 
                ysize = 1024;
276
 
                break;
277
 
        case APPLE_1600x1200:
278
 
                xsize = 1600;
279
 
                ysize = 1200;
280
 
                break;
281
 
        default:
282
 
                abort();
283
 
        }
284
 
}
285
 
 
286
 
// Match Apple mode matching best specified dimensions
287
 
static int match_apple_resolution(int &xsize, int &ysize)
288
 
{
289
 
        int apple_id = find_apple_resolution(xsize, ysize);
290
 
        set_apple_resolution(apple_id, xsize, ysize);
291
 
        return apple_id;
 
292
        if (xsize == 640 && ysize == 480)
 
293
                return APPLE_640x480;
 
294
        if (xsize == 800 && ysize == 600)
 
295
                return APPLE_800x600;
 
296
        if (xsize == 1024 && ysize == 768)
 
297
                return APPLE_1024x768;
 
298
        if (xsize == 1152 && ysize == 768)
 
299
                return APPLE_1152x768;
 
300
        if (xsize == 1152 && ysize == 900)
 
301
                return APPLE_1152x900;
 
302
        if (xsize == 1280 && ysize == 1024)
 
303
                return APPLE_1280x1024;
 
304
        if (xsize == 1600 && ysize == 1200)
 
305
                return APPLE_1600x1200;
 
306
        return APPLE_CUSTOM;
292
307
}
293
308
 
294
309
// Display error alert
395
410
        return (video_depth <= VIDEO_DEPTH_8BIT) ? 8 : mac_depth_of_video_depth(video_depth);
396
411
}
397
412
 
 
413
// Get screen dimensions
 
414
static void sdl_display_dimensions(int &width, int &height)
 
415
{
 
416
        static int max_width, max_height;
 
417
        if (max_width == 0 && max_height == 0) {
 
418
                max_width = 640 ; max_height = 480;
 
419
                SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
 
420
                if (modes && modes != (SDL_Rect **)-1) {
 
421
                        // It turns out that on some implementations, and contrary to the documentation,
 
422
                        // the returned list is not sorted from largest to smallest (e.g. Windows)
 
423
                        for (int i = 0; modes[i] != NULL; i++) {
 
424
                                const int w = modes[i]->w;
 
425
                                const int h = modes[i]->h;
 
426
                                if (w > max_width && h > max_height) {
 
427
                                        max_width = w;
 
428
                                        max_height = h;
 
429
                                }
 
430
                        }
 
431
                }
 
432
        }
 
433
        width = max_width;
 
434
        height = max_height;
 
435
}
 
436
 
 
437
static inline int sdl_display_width(void)
 
438
{
 
439
        int width, height;
 
440
        sdl_display_dimensions(width, height);
 
441
        return width;
 
442
}
 
443
 
 
444
static inline int sdl_display_height(void)
 
445
{
 
446
        int width, height;
 
447
        sdl_display_dimensions(width, height);
 
448
        return height;
 
449
}
 
450
 
398
451
// Check wether specified mode is available
399
 
static bool has_mode(int type, int width, int height)
 
452
static bool has_mode(int type, int width, int height, int depth)
400
453
{
401
454
#ifdef SHEEPSHAVER
402
 
        // Filter out Classic resolutiosn
 
455
        // Filter out Classic resolutions
403
456
        if (width == 512 && height == 384)
404
457
                return false;
405
 
 
406
 
        // "screen" prefs items always succeeds
407
 
        if (PrefsFindString("screen"))
408
 
                return true;
409
 
 
410
 
        // Read window & screen modes prefs
411
 
        static uint32 window_modes = 0;
412
 
        static uint32 screen_modes = 0;
413
 
        if (window_modes == 0 || screen_modes == 0) {
414
 
                window_modes = PrefsFindInt32("windowmodes");
415
 
                screen_modes = PrefsFindInt32("screenmodes");
416
 
                if (window_modes == 0 || screen_modes == 0)
417
 
                        window_modes |= 3;                      // Allow at least 640x480 and 800x600 window modes
418
 
        }
419
 
 
420
 
        int test_modes;
421
 
        switch (type) {
422
 
        case DISPLAY_WINDOW:
423
 
                test_modes = window_modes;
424
 
                break;
425
 
        case DISPLAY_SCREEN:
426
 
                test_modes = screen_modes;
427
 
                break;
428
 
        default:
429
 
                test_modes = 0;
430
 
                break;
431
 
        }
432
 
 
433
 
        int apple_mask;
434
 
        switch (find_apple_resolution(width, height)) {
435
 
        case APPLE_640x480:             apple_mask = 0x01; break;
436
 
        case APPLE_800x600:             apple_mask = 0x02; break;
437
 
        case APPLE_1024x768:    apple_mask = 0x04; break;
438
 
        case APPLE_1152x768:    apple_mask = 0x40; break;
439
 
        case APPLE_1152x900:    apple_mask = 0x08; break;
440
 
        case APPLE_1280x1024:   apple_mask = 0x10; break;
441
 
        case APPLE_1600x1200:   apple_mask = 0x20; break;
442
 
        default:                                apple_mask = 0x00; break;
443
 
        }
444
 
        return (test_modes & apple_mask);
445
458
#endif
446
 
        return true;
 
459
 
 
460
        // Filter out out-of-bounds resolutions
 
461
        if (width > sdl_display_width() || height > sdl_display_height())
 
462
                return false;
 
463
 
 
464
        // Rely on SDL capabilities
 
465
        return SDL_VideoModeOK(width, height,
 
466
                                                   sdl_depth_of_video_depth(depth),
 
467
                                                   SDL_HWSURFACE | (type == DISPLAY_SCREEN ? SDL_FULLSCREEN : 0));
447
468
}
448
469
 
449
470
// Add mode to list of supported modes
450
471
static void add_mode(int type, int width, int height, int resolution_id, int bytes_per_row, int depth)
451
472
{
452
473
        // Filter out unsupported modes
453
 
        if (!has_mode(type, width, height))
 
474
        if (!has_mode(type, width, height, depth))
454
475
                return;
455
476
 
456
477
        // Fill in VideoMode entry
457
478
        VIDEO_MODE mode;
458
479
#ifdef SHEEPSHAVER
459
 
        // Recalculate dimensions to fit Apple modes
460
 
        resolution_id = match_apple_resolution(width, height);
 
480
        resolution_id = find_apple_resolution(width, height);
461
481
        mode.viType = type;
462
482
#endif
463
483
        VIDEO_MODE_X = width;
468
488
        VideoModes.push_back(mode);
469
489
}
470
490
 
471
 
// Add standard list of windowed modes for given color depth
472
 
static void add_window_modes(int depth)
473
 
{
474
 
        video_depth vdepth = (video_depth)depth;
475
 
        add_mode(DISPLAY_WINDOW, 512, 384, 0x80, TrivialBytesPerRow(512, vdepth), depth);
476
 
        add_mode(DISPLAY_WINDOW, 640, 480, 0x81, TrivialBytesPerRow(640, vdepth), depth);
477
 
        add_mode(DISPLAY_WINDOW, 800, 600, 0x82, TrivialBytesPerRow(800, vdepth), depth);
478
 
        add_mode(DISPLAY_WINDOW, 1024, 768, 0x83, TrivialBytesPerRow(1024, vdepth), depth);
479
 
        add_mode(DISPLAY_WINDOW, 1152, 870, 0x84, TrivialBytesPerRow(1152, vdepth), depth);
480
 
        add_mode(DISPLAY_WINDOW, 1280, 1024, 0x85, TrivialBytesPerRow(1280, vdepth), depth);
481
 
        add_mode(DISPLAY_WINDOW, 1600, 1200, 0x86, TrivialBytesPerRow(1600, vdepth), depth);
482
 
}
483
 
 
484
491
// Set Mac frame layout and base address (uses the_buffer/MacFrameBaseMac)
485
492
static void set_mac_frame_buffer(SDL_monitor_desc &monitor, int depth, bool native_byte_order)
486
493
{
524
531
        return (vi && vi->wm_available ? SDL_WM_GrabInput(mode) : SDL_GRAB_OFF);
525
532
}
526
533
 
 
534
// Migrate preferences items (XXX to be handled in MigratePrefs())
 
535
static void migrate_screen_prefs(void)
 
536
{
 
537
#ifdef SHEEPSHAVER
 
538
        // Look-up priorities are: "screen", "screenmodes", "windowmodes".
 
539
        if (PrefsFindString("screen"))
 
540
                return;
 
541
 
 
542
        uint32 window_modes = PrefsFindInt32("windowmodes");
 
543
        uint32 screen_modes = PrefsFindInt32("screenmodes");
 
544
        int width = 0, height = 0;
 
545
        if (screen_modes) {
 
546
                static const struct {
 
547
                        int id;
 
548
                        int width;
 
549
                        int height;
 
550
                }
 
551
                modes[] = {
 
552
                        {  1,    640,    480 },
 
553
                        {  2,    800,    600 },
 
554
                        {  4,   1024,    768 },
 
555
                        { 64,   1152,    768 },
 
556
                        {  8,   1152,    900 },
 
557
                        { 16,   1280,   1024 },
 
558
                        { 32,   1600,   1200 },
 
559
                        { 0, }
 
560
                };
 
561
                for (int i = 0; modes[i].id != 0; i++) {
 
562
                        if (screen_modes & modes[i].id) {
 
563
                                if (width < modes[i].width && height < modes[i].height) {
 
564
                                        width = modes[i].width;
 
565
                                        height = modes[i].height;
 
566
                                }
 
567
                        }
 
568
                }
 
569
        } else {
 
570
                if (window_modes & 1)
 
571
                        width = 640, height = 480;
 
572
                if (window_modes & 2)
 
573
                        width = 800, height = 600;
 
574
        }
 
575
        if (width && height) {
 
576
                char str[32];
 
577
                sprintf(str, "%s/%d/%d", screen_modes ? "dga" : "win", width, height);
 
578
                PrefsReplaceString("screen", str);
 
579
        }
 
580
#endif
 
581
}
 
582
 
527
583
 
528
584
/*
529
585
 *  Display "driver" classes
1003
1059
                return false;
1004
1060
        }
1005
1061
 
 
1062
#ifdef WIN32
 
1063
        // Chain in a new message handler for WM_DEVICECHANGE
 
1064
        HWND the_window = GetMainWindowHandle();
 
1065
        sdl_window_proc = (WNDPROC)GetWindowLongPtr(the_window, GWLP_WNDPROC);
 
1066
        SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)windows_message_handler);
 
1067
#endif
 
1068
 
1006
1069
        // Initialize VideoRefresh function
1007
1070
        VideoRefreshInit();
1008
1071
 
1040
1103
#endif
1041
1104
 
1042
1105
        // Create Mutexes
 
1106
        if ((sdl_events_lock = SDL_CreateMutex()) == NULL)
 
1107
                return false;
1043
1108
        if ((sdl_palette_lock = SDL_CreateMutex()) == NULL)
1044
1109
                return false;
1045
1110
        if ((frame_buffer_lock = SDL_CreateMutex()) == NULL)
1054
1119
        mouse_wheel_lines = PrefsFindInt32("mousewheellines");
1055
1120
 
1056
1121
        // Get screen mode from preferences
 
1122
        migrate_screen_prefs();
1057
1123
        const char *mode_str = NULL;
1058
1124
        if (classic_mode)
1059
1125
                mode_str = "win/512/342";
1077
1143
                else if (sscanf(mode_str, "dga/%d/%d", &default_width, &default_height) == 2)
1078
1144
                        display_type = DISPLAY_SCREEN;
1079
1145
        }
1080
 
        int max_width = 640, max_height = 480;
1081
 
        SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
1082
 
        if (modes && modes != (SDL_Rect **)-1) {
1083
 
                // It turns out that on some implementations, and contrary to the documentation,
1084
 
                // the returned list is not sorted from largest to smallest (e.g. Windows)
1085
 
                for (int i = 0; modes[i] != NULL; i++) {
1086
 
                        const int w = modes[i]->w;
1087
 
                        const int h = modes[i]->h;
1088
 
                        if (w > max_width && h > max_height) {
1089
 
                                max_width = w;
1090
 
                                max_height = h;
1091
 
                        }
1092
 
                }
1093
 
                if (default_width > max_width)
1094
 
                        default_width = max_width;
1095
 
                if (default_height > max_height)
1096
 
                        default_height = max_height;
1097
 
        }
1098
1146
        if (default_width <= 0)
1099
 
                default_width = max_width;
 
1147
                default_width = sdl_display_width();
 
1148
        else if (default_width > sdl_display_width())
 
1149
                default_width = sdl_display_width();
1100
1150
        if (default_height <= 0)
1101
 
                default_height = max_height;
 
1151
                default_height = sdl_display_height();
 
1152
        else if (default_height > sdl_display_height())
 
1153
                default_height = sdl_display_height();
1102
1154
 
1103
1155
        // Mac screen depth follows X depth
1104
1156
        screen_depth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
1118
1170
                break;
1119
1171
        }
1120
1172
 
 
1173
        // Initialize list of video modes to try
 
1174
        struct {
 
1175
                int w;
 
1176
                int h;
 
1177
                int resolution_id;
 
1178
        }
 
1179
        video_modes[] = {
 
1180
                {   -1,   -1, 0x80 },
 
1181
                {  512,  384, 0x80 },
 
1182
                {  640,  480, 0x81 },
 
1183
                {  800,  600, 0x82 },
 
1184
                { 1024,  768, 0x83 },
 
1185
                { 1152,  870, 0x84 },
 
1186
                { 1280, 1024, 0x85 },
 
1187
                { 1600, 1200, 0x86 },
 
1188
                { 0, }
 
1189
        };
 
1190
        video_modes[0].w = default_width;
 
1191
        video_modes[0].h = default_height;
 
1192
 
1121
1193
        // Construct list of supported modes
1122
1194
        if (display_type == DISPLAY_WINDOW) {
1123
1195
                if (classic)
1124
1196
                        add_mode(display_type, 512, 342, 0x80, 64, VIDEO_DEPTH_1BIT);
1125
1197
                else {
1126
 
                        for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) {
1127
 
                                int bpp = sdl_depth_of_video_depth(d);
1128
 
                                if (SDL_VideoModeOK(max_width, max_height, bpp, SDL_HWSURFACE))
1129
 
                                        add_window_modes(video_depth(d));
 
1198
                        for (int i = 0; video_modes[i].w != 0; i++) {
 
1199
                                const int w = video_modes[i].w;
 
1200
                                const int h = video_modes[i].h;
 
1201
                                if (i > 0 && (w >= default_width || h >= default_height))
 
1202
                                        continue;
 
1203
                                for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++)
 
1204
                                        add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
1130
1205
                        }
1131
1206
                }
1132
1207
        } else if (display_type == DISPLAY_SCREEN) {
1133
 
                struct {
1134
 
                        int w;
1135
 
                        int h;
1136
 
                        int resolution_id;
1137
 
                }
1138
 
                video_modes[] = {
1139
 
                        {   -1,   -1, 0x80 },
1140
 
                        {  640,  480, 0x81 },
1141
 
                        {  800,  600, 0x82 },
1142
 
                        { 1024,  768, 0x83 },
1143
 
                        { 1152,  870, 0x84 },
1144
 
                        { 1280, 1024, 0x85 },
1145
 
                        { 1600, 1200, 0x86 },
1146
 
                        { 0, }
1147
 
                };
1148
 
                video_modes[0].w = default_width;
1149
 
                video_modes[0].h = default_height;
1150
 
 
1151
1208
                for (int i = 0; video_modes[i].w != 0; i++) {
1152
1209
                        const int w = video_modes[i].w;
1153
1210
                        const int h = video_modes[i].h;
1154
1211
                        if (i > 0 && (w >= default_width || h >= default_height))
1155
1212
                                continue;
 
1213
                        if (w == 512 && h == 384)
 
1214
                                continue;
1156
1215
#ifdef ENABLE_VOSF
1157
 
                        for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++) {
1158
 
                                int bpp = sdl_depth_of_video_depth(d);
1159
 
                                if (SDL_VideoModeOK(w, h, bpp, SDL_HWSURFACE | SDL_FULLSCREEN))
1160
 
                                        add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
1161
 
                        }
 
1216
                        for (int d = VIDEO_DEPTH_1BIT; d <= default_depth; d++)
 
1217
                                add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)d), d);
1162
1218
#else
1163
1219
                        add_mode(display_type, w, h, video_modes[i].resolution_id, TrivialBytesPerRow(w, (video_depth)default_depth), default_depth);
1164
1220
#endif
1235
1291
{
1236
1292
        D(bug("video_close()\n"));
1237
1293
 
 
1294
#ifdef WIN32
 
1295
        // Remove message handler for WM_DEVICECHANGE
 
1296
        HWND the_window = GetMainWindowHandle();
 
1297
        SetWindowLongPtr(the_window, GWLP_WNDPROC, (LONG_PTR)sdl_window_proc);
 
1298
#endif
 
1299
 
1238
1300
        // Stop redraw thread
1239
1301
#ifndef USE_CPU_EMUL_SERVICES
1240
1302
        if (redraw_thread_active) {
1265
1327
                SDL_DestroyMutex(frame_buffer_lock);
1266
1328
        if (sdl_palette_lock)
1267
1329
                SDL_DestroyMutex(sdl_palette_lock);
 
1330
        if (sdl_events_lock)
 
1331
                SDL_DestroyMutex(sdl_events_lock);
1268
1332
}
1269
1333
 
1270
1334
 
1434
1498
void SDL_monitor_desc::switch_to_current_mode(void)
1435
1499
{
1436
1500
        // Close and reopen display
 
1501
        LOCK_EVENTS;
1437
1502
        video_close();
1438
1503
        video_open();
 
1504
        UNLOCK_EVENTS;
1439
1505
 
1440
1506
        if (drv == NULL) {
1441
1507
                ErrorAlert(STR_OPEN_WINDOW_ERR);
1921
1987
        }
1922
1988
}
1923
1989
 
 
1990
// Static display update (fixed frame rate, bounding boxes based)
 
1991
// XXX use NQD bounding boxes to help detect dirty areas?
 
1992
static void update_display_static_bbox(driver_window *drv)
 
1993
{
 
1994
        const VIDEO_MODE &mode = drv->mode;
 
1995
 
 
1996
        // Allocate bounding boxes for SDL_UpdateRects()
 
1997
        const int N_PIXELS = 64;
 
1998
        const int n_x_boxes = (VIDEO_MODE_X + N_PIXELS - 1) / N_PIXELS;
 
1999
        const int n_y_boxes = (VIDEO_MODE_Y + N_PIXELS - 1) / N_PIXELS;
 
2000
        SDL_Rect *boxes = (SDL_Rect *)alloca(sizeof(SDL_Rect) * n_x_boxes * n_y_boxes);
 
2001
        int nr_boxes = 0;
 
2002
 
 
2003
        // Lock surface, if required
 
2004
        if (SDL_MUSTLOCK(drv->s))
 
2005
                SDL_LockSurface(drv->s);
 
2006
 
 
2007
        // Update the surface from Mac screen
 
2008
        const int bytes_per_row = VIDEO_MODE_ROW_BYTES;
 
2009
        const int bytes_per_pixel = bytes_per_row / VIDEO_MODE_X;
 
2010
        int x, y;
 
2011
        for (y = 0; y < VIDEO_MODE_Y; y += N_PIXELS) {
 
2012
                int h = N_PIXELS;
 
2013
                if (h > VIDEO_MODE_Y - y)
 
2014
                        h = VIDEO_MODE_Y - y;
 
2015
                for (x = 0; x < VIDEO_MODE_X; x += N_PIXELS) {
 
2016
                        int w = N_PIXELS;
 
2017
                        if (w > VIDEO_MODE_X - x)
 
2018
                                w = VIDEO_MODE_X - x;
 
2019
                        const int xs = w * bytes_per_pixel;
 
2020
                        const int xb = x * bytes_per_pixel;
 
2021
                        bool dirty = false;
 
2022
                        for (int j = y; j < (y + h); j++) {
 
2023
                                const int yb = j * bytes_per_row;
 
2024
                                if (memcmp(&the_buffer[yb + xb], &the_buffer_copy[yb + xb], xs) != 0) {
 
2025
                                        memcpy(&the_buffer_copy[yb + xb], &the_buffer[yb + xb], xs);
 
2026
                                        Screen_blit((uint8 *)drv->s->pixels + yb + xb, the_buffer + yb + xb, xs);
 
2027
                                        dirty = true;
 
2028
                                }
 
2029
                        }
 
2030
                        if (dirty) {
 
2031
                                boxes[nr_boxes].x = x;
 
2032
                                boxes[nr_boxes].y = y;
 
2033
                                boxes[nr_boxes].w = w;
 
2034
                                boxes[nr_boxes].h = h;
 
2035
                                nr_boxes++;
 
2036
                        }
 
2037
                }
 
2038
        }
 
2039
 
 
2040
        // Unlock surface, if required
 
2041
        if (SDL_MUSTLOCK(drv->s))
 
2042
                SDL_UnlockSurface(drv->s);
 
2043
 
 
2044
        // Refresh display
 
2045
        if (nr_boxes)
 
2046
                SDL_UpdateRects(drv->s, nr_boxes, boxes);
 
2047
}
 
2048
 
1924
2049
 
1925
2050
// We suggest the compiler to inline the next two functions so that it
1926
2051
// may specialise the code according to the current screen depth and
2015
2140
        static int tick_counter = 0;
2016
2141
        if (++tick_counter >= frame_skip) {
2017
2142
                tick_counter = 0;
2018
 
                update_display_static(static_cast<driver_window *>(drv));
 
2143
                const VIDEO_MODE &mode = drv->mode;
 
2144
                if ((int)VIDEO_MODE_DEPTH >= VIDEO_DEPTH_8BIT)
 
2145
                        update_display_static_bbox(static_cast<driver_window *>(drv));
 
2146
                else
 
2147
                        update_display_static(static_cast<driver_window *>(drv));
2019
2148
        }
2020
2149
}
2021
2150
 
2057
2186
        // Set new cursor image if it was changed
2058
2187
        if (cursor_changed && sdl_cursor) {
2059
2188
                cursor_changed = false;
 
2189
                LOCK_EVENTS;
2060
2190
                SDL_FreeCursor(sdl_cursor);
2061
2191
                sdl_cursor = SDL_CreateCursor(MacCursor + 4, MacCursor + 36, 16, 16, MacCursor[2], MacCursor[3]);
2062
 
                if (sdl_cursor)
 
2192
                if (sdl_cursor) {
2063
2193
                        SDL_SetCursor(sdl_cursor);
 
2194
#ifdef WIN32
 
2195
                        // XXX Windows apparently needs an extra mouse event to
 
2196
                        // make the new cursor image visible
 
2197
                        int visible = SDL_ShowCursor(-1);
 
2198
                        if (visible) {
 
2199
                                int x, y;
 
2200
                                SDL_GetMouseState(&x, &y);
 
2201
                                SDL_WarpMouse(x, y);
 
2202
                        }
 
2203
#endif
 
2204
                }
 
2205
                UNLOCK_EVENTS;
2064
2206
        }
2065
2207
#endif
2066
2208
 
2118
2260
        return 0;
2119
2261
}
2120
2262
#endif
 
2263
 
 
2264
 
 
2265
/*
 
2266
 *  Record dirty area from NQD
 
2267
 */
 
2268
 
 
2269
#ifdef SHEEPSHAVER
 
2270
void video_set_dirty_area(int x, int y, int w, int h)
 
2271
{
 
2272
        const VIDEO_MODE &mode = drv->mode;
 
2273
        const int screen_width = VIDEO_MODE_X;
 
2274
        const int screen_height = VIDEO_MODE_Y;
 
2275
        const int bytes_per_row = VIDEO_MODE_ROW_BYTES;
 
2276
 
 
2277
#ifdef ENABLE_VOSF
 
2278
        if (use_vosf) {
 
2279
                vosf_set_dirty_area(x, y, w, h, screen_width, screen_height, bytes_per_row);
 
2280
                return;
 
2281
        }
 
2282
#endif
 
2283
 
 
2284
        // XXX handle dirty bounding boxes for non-VOSF modes
 
2285
}
 
2286
#endif