1 #include <SDL2/SDL.h>
2 #include "video.h"
3 #include "wx-sdl2-video.h"
4 #include "wx-utils.h"
5 #include "ibm.h"
6 #include "wx-display.h"
7 #include "plat-keyboard.h"
8
9 #ifdef __WINDOWS__
10 #define BITMAP WINDOWS_BITMAP
11 #undef UNICODE
12 #include <windows.h>
13 #include <windowsx.h>
14 #undef BITMAP
15
16 HHOOK hKeyboardHook;
17 int modkeystate[255];
18
19 #endif
20
21 SDL_mutex* rendererMutex;
22 SDL_cond* rendererCond;
23 SDL_Thread* renderthread = NULL;
24
25 SDL_Window* window = NULL;
26
27 int rendering = 0;
28
29 int mousecapture = 0;
30
31 extern int pause;
32 extern int video_scale;
33 extern int take_screenshot;
34
35 void* ghwnd;
36 void* menu;
37
38 SDL_Rect remembered_rect;
39 int remembered_mouse_x = 0;
40 int remembered_mouse_y = 0;
41
42 int custom_resolution_width = 640;
43 int custom_resolution_height = 480;
44
45 int win_doresize = 0;
46 int winsizex = 640, winsizey = 480;
47
48 void renderer_start();
49 void renderer_stop(int timeout);
50
51 int trigger_fullscreen = 0;
52 int trigger_screenshot = 0;
53 int trigger_togglewindow = 0;
54 int trigger_inputrelease = 0;
55
56 extern void device_force_redraw();
57 extern void mouse_wheel_update(int);
58 extern void toggle_fullscreen();
59
display_resize(int width,int height)60 void display_resize(int width, int height)
61 {
62 winsizex = width*(video_scale+1) >> 1;
63 winsizey = height*(video_scale+1) >> 1;
64
65 SDL_Rect rect;
66 rect.x = rect.y = 0;
67 rect.w = winsizex;
68 rect.h = winsizey;
69 sdl_scale(video_fullscreen_scale, rect, &rect, winsizex, winsizey);
70 winsizex = rect.w;
71 winsizey = rect.h;
72
73 win_doresize = 1;
74 }
75
releasemouse()76 void releasemouse()
77 {
78 if (mousecapture)
79 {
80 SDL_SetWindowGrab(window, SDL_FALSE);
81 SDL_SetRelativeMouseMode(SDL_FALSE);
82 mousecapture = 0;
83 }
84 }
85
display_init()86 int display_init()
87 {
88 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
89 {
90 printf("SDL could not initialize! Error: %s\n", SDL_GetError());
91 return 0;
92 }
93
94 SDL_version ver;
95 SDL_GetVersion(&ver);
96 printf("SDL %i.%i.%i initialized.\n", ver.major, ver.minor, ver.patch);
97 return 1;
98 }
99
display_close()100 void display_close()
101 {
102 SDL_Quit();
103 }
104
display_start(void * hwnd)105 void display_start(void* hwnd)
106 {
107 ghwnd = hwnd;
108 menu = wx_getmenu(hwnd);
109 atexit(releasemouse);
110 rendererMutex = SDL_CreateMutex();
111 rendererCond = SDL_CreateCond();
112 renderer_start();
113 }
114
display_stop()115 void display_stop()
116 {
117 renderer_stop(10 * 1000);
118
119 SDL_DestroyMutex(rendererMutex);
120 SDL_DestroyCond(rendererCond);
121 #if SDL_VERSION_ATLEAST(2, 0, 2)
122 SDL_DetachThread(renderthread);
123 #endif
124 releasemouse();
125 }
126
is_fullscreen()127 int is_fullscreen()
128 {
129 int flags = SDL_GetWindowFlags(window);
130 return (flags&SDL_WINDOW_FULLSCREEN) || (flags&SDL_WINDOW_FULLSCREEN_DESKTOP);
131 }
132
sdl_set_window_title(const char * title)133 void sdl_set_window_title(const char* title) {
134 if (window && !is_fullscreen())
135 SDL_SetWindowTitle(window, title);
136 }
137
get_border_size(int * top,int * left,int * bottom,int * right)138 int get_border_size(int* top, int* left, int* bottom, int* right)
139 {
140 #if SDL_VERSION_ATLEAST(2, 0, 5)
141 return SDL_GetWindowBordersSize(window, top, left, bottom, right);
142 #else
143 if (top) *top = 0;
144 if (left) *left = 0;
145 if (bottom) *bottom = 0;
146 if (right) *right = 0;
147 return 0;
148 #endif
149 }
150
151 static const struct {
152 SDL_Scancode sdl;
153 int system;
154 } SDLScancodeToSystemScancode[] = {
155 { SDL_SCANCODE_A, 0x1e },
156 { SDL_SCANCODE_B, 0x30 },
157 { SDL_SCANCODE_C, 0x2e },
158 { SDL_SCANCODE_D, 0x20 },
159 { SDL_SCANCODE_E, 0x12 },
160 { SDL_SCANCODE_F, 0x21 },
161 { SDL_SCANCODE_G, 0x22 },
162 { SDL_SCANCODE_H, 0x23 },
163 { SDL_SCANCODE_I, 0x17 },
164 { SDL_SCANCODE_J, 0x24 },
165 { SDL_SCANCODE_K, 0x25 },
166 { SDL_SCANCODE_L, 0x26 },
167 { SDL_SCANCODE_M, 0x32 },
168 { SDL_SCANCODE_N, 0x31 },
169 { SDL_SCANCODE_O, 0x18 },
170 { SDL_SCANCODE_P, 0x19 },
171 { SDL_SCANCODE_Q, 0x10 },
172 { SDL_SCANCODE_R, 0x13 },
173 { SDL_SCANCODE_S, 0x1f },
174 { SDL_SCANCODE_T, 0x14 },
175 { SDL_SCANCODE_U, 0x16 },
176 { SDL_SCANCODE_V, 0x2f },
177 { SDL_SCANCODE_W, 0x11 },
178 { SDL_SCANCODE_X, 0x2d },
179 { SDL_SCANCODE_Y, 0x15 },
180 { SDL_SCANCODE_Z, 0x2c },
181 { SDL_SCANCODE_0, 0x0B },
182 { SDL_SCANCODE_1, 0x02 },
183 { SDL_SCANCODE_2, 0x03 },
184 { SDL_SCANCODE_3, 0x04 },
185 { SDL_SCANCODE_4, 0x05 },
186 { SDL_SCANCODE_5, 0x06 },
187 { SDL_SCANCODE_6, 0x07 },
188 { SDL_SCANCODE_7, 0x08 },
189 { SDL_SCANCODE_8, 0x09 },
190 { SDL_SCANCODE_9, 0x0A },
191 { SDL_SCANCODE_GRAVE, 0x29 },
192 { SDL_SCANCODE_MINUS, 0x0c },
193 { SDL_SCANCODE_EQUALS, 0x0d },
194 { SDL_SCANCODE_NONUSBACKSLASH, 0x56 },
195 { SDL_SCANCODE_BACKSLASH, 0x2b },
196 { SDL_SCANCODE_BACKSPACE, 0x0e },
197 { SDL_SCANCODE_SPACE, 0x39 },
198 { SDL_SCANCODE_TAB, 0x0f },
199 { SDL_SCANCODE_CAPSLOCK, 0x3a },
200 { SDL_SCANCODE_LSHIFT, 0x2a },
201 { SDL_SCANCODE_LCTRL, 0x1d },
202 { SDL_SCANCODE_LGUI, 0xdb },
203 { SDL_SCANCODE_LALT, 0x38 },
204 { SDL_SCANCODE_RSHIFT, 0x36 },
205 { SDL_SCANCODE_RCTRL, 0x9d },
206 { SDL_SCANCODE_RGUI, 0xdc },
207 { SDL_SCANCODE_RALT, 0xb8 },
208 { SDL_SCANCODE_SYSREQ, 0x54 },
209 { SDL_SCANCODE_APPLICATION, 0xdd },
210 { SDL_SCANCODE_RETURN, 0x1c },
211 { SDL_SCANCODE_ESCAPE, 0x01 },
212 { SDL_SCANCODE_F1, 0x3B },
213 { SDL_SCANCODE_F2, 0x3C },
214 { SDL_SCANCODE_F3, 0x3D },
215 { SDL_SCANCODE_F4, 0x3e },
216 { SDL_SCANCODE_F5, 0x3f },
217 { SDL_SCANCODE_F6, 0x40 },
218 { SDL_SCANCODE_F7, 0x41 },
219 { SDL_SCANCODE_F8, 0x42 },
220 { SDL_SCANCODE_F9, 0x43 },
221 { SDL_SCANCODE_F10, 0x44 },
222 { SDL_SCANCODE_F11, 0x57 },
223 { SDL_SCANCODE_F12, 0x58 },
224 { SDL_SCANCODE_SCROLLLOCK, 0x46 },
225 { SDL_SCANCODE_LEFTBRACKET, 0x1a },
226 { SDL_SCANCODE_RIGHTBRACKET, 0x1b },
227 { SDL_SCANCODE_INSERT, 0xd2 },
228 { SDL_SCANCODE_HOME, 0xc7 },
229 { SDL_SCANCODE_PAGEUP, 0xc9 },
230 { SDL_SCANCODE_DELETE, 0xd3 },
231 { SDL_SCANCODE_END, 0xcf },
232 { SDL_SCANCODE_PAGEDOWN, 0xd1 },
233 { SDL_SCANCODE_UP, 0xc8 },
234 { SDL_SCANCODE_LEFT, 0xcb },
235 { SDL_SCANCODE_DOWN, 0xd0 },
236 { SDL_SCANCODE_RIGHT, 0xcd },
237 { SDL_SCANCODE_NUMLOCKCLEAR, 0x45 },
238 { SDL_SCANCODE_KP_DIVIDE, 0xb5 },
239 { SDL_SCANCODE_KP_MULTIPLY, 0x37 },
240 { SDL_SCANCODE_KP_MINUS, 0x4a },
241 { SDL_SCANCODE_KP_PLUS, 0x4e },
242 { SDL_SCANCODE_KP_ENTER, 0x9c },
243 { SDL_SCANCODE_KP_PERIOD, 0x53 },
244 { SDL_SCANCODE_KP_0, 0x52 },
245 { SDL_SCANCODE_KP_1, 0x4f },
246 { SDL_SCANCODE_KP_2, 0x50 },
247 { SDL_SCANCODE_KP_3, 0x51 },
248 { SDL_SCANCODE_KP_4, 0x4b },
249 { SDL_SCANCODE_KP_5, 0x4c },
250 { SDL_SCANCODE_KP_6, 0x4d },
251 { SDL_SCANCODE_KP_7, 0x47 },
252 { SDL_SCANCODE_KP_8, 0x48 },
253 { SDL_SCANCODE_KP_9, 0x49 },
254 { SDL_SCANCODE_SEMICOLON, 0x27 },
255 { SDL_SCANCODE_APOSTROPHE, 0x28 },
256 { SDL_SCANCODE_COMMA, 0x33 },
257 { SDL_SCANCODE_PERIOD, 0x34 },
258 { SDL_SCANCODE_SLASH, 0x35 },
259 { SDL_SCANCODE_PRINTSCREEN, 0xb7 }
260 };
261
sdl_scancode(SDL_Scancode scancode)262 int sdl_scancode(SDL_Scancode scancode)
263 {
264 int i;
265 for (i = 0; i < SDL_arraysize(SDLScancodeToSystemScancode); ++i) {
266 if (SDLScancodeToSystemScancode[i].sdl == scancode) {
267 return SDLScancodeToSystemScancode[i].system;
268 }
269 }
270 return -1;
271 }
272
273 SDL_Event event;
274 SDL_Rect rect;
275 int border_x, border_y = 0;
276
277 uint64_t render_time = 0;
278 int render_fps = 0;
279 uint32_t render_frame_time = 0;
280 uint32_t render_frames = 0;
281
window_setup()282 void window_setup()
283 {
284 SDL_SetHint(SDL_HINT_GRAB_KEYBOARD, "1");
285 #if SDL_VERSION_ATLEAST(2, 0, 5)
286 SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
287 #endif
288
289 if (start_in_fullscreen)
290 {
291 start_in_fullscreen = 0;
292 window_dofullscreen = 1;
293 window_doinputgrab = 1;
294 }
295
296 if (window_remember)
297 {
298 rect.x = window_x;
299 rect.y = window_y;
300 rect.w = window_w;
301 rect.h = window_h;
302 }
303 else
304 {
305 rect.x = SDL_WINDOWPOS_CENTERED;
306 rect.y = SDL_WINDOWPOS_CENTERED;
307 rect.w = 640;
308 rect.h = 480;
309 }
310
311 if (vid_resize == 2)
312 {
313 rect.w = custom_resolution_width;
314 rect.h = custom_resolution_height;
315 }
316 }
317
318 #ifdef __WINDOWS__
sdl_winhook(int code)319 int sdl_winhook(int code)
320 {
321 switch(code)
322 {
323 case VK_LMENU:
324 return SDL_SCANCODE_LALT;
325 case VK_LCONTROL:
326 return SDL_SCANCODE_LCTRL;
327 case VK_LWIN:
328 return SDL_SCANCODE_LGUI;
329 case VK_LSHIFT:
330 return SDL_SCANCODE_LSHIFT;
331 case VK_RMENU:
332 return SDL_SCANCODE_RALT;
333 case VK_RCONTROL:
334 return SDL_SCANCODE_RCTRL;
335 case VK_RWIN:
336 return SDL_SCANCODE_RGUI;
337 case VK_RSHIFT:
338 return SDL_SCANCODE_RSHIFT;
339 }
340
341 return -1;
342 }
343
LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)344 LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
345 {
346 KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
347
348 int c = p->vkCode;
349
350 int steal = 0;
351 int s = sdl_winhook(c);
352 if (s != -1)
353 {
354 int key_state = !(p->flags & LLKHF_UP);
355 if (abs(modkeystate[c]) != key_state)
356 {
357 /* if mousecapture is 0, key_state should be negative */
358 if (!mousecapture)
359 key_state = -key_state;
360 /* if key_state is 0 and modkeystate[c] is negative,
361 an sdl_event should not be generated */
362 if (key_state > 0 || modkeystate[c] > 0)
363 {
364 steal = key_state != 0;
365 SDL_Event event;
366 event.key.keysym.scancode = s;
367 event.key.timestamp = p->time;
368
369 event.type = key_state ? SDL_KEYDOWN : SDL_KEYUP;
370 SDL_PushEvent(&event);
371 }
372 modkeystate[c] = key_state;
373 }
374 if (steal)
375 return 1;
376 }
377
378 return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam );
379 }
380 #endif
381
window_create()382 int window_create()
383 {
384 window = SDL_CreateWindow("PCem Display",
385 rect.x, rect.y, rect.w, rect.h,
386 requested_render_driver.sdl_window_params | (vid_resize == 1 ? SDL_WINDOW_RESIZABLE : 0));
387 if (!window)
388 {
389 char message[200];
390 sprintf(message,
391 "SDL window could not be created! Error: %s\n",
392 SDL_GetError());
393 wx_messagebox(ghwnd, message, "SDL Error", WX_MB_OK);
394 return 0;
395 }
396
397 #ifdef __WINDOWS__
398 memset(modkeystate, 0, sizeof(modkeystate));
399 hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandle(NULL), 0);
400 #endif
401
402 render_time = 0;
403 render_fps = 0;
404 render_frame_time = SDL_GetTicks();
405 render_frames = 0;
406 return 1;
407 }
408
window_close()409 void window_close()
410 {
411 #ifdef __WINDOWS__
412 UnhookWindowsHookEx( hKeyboardHook );
413 #endif
414
415 sdl_renderer_close();
416
417 if (window) {
418 SDL_GetWindowPosition(window, &rect.x, &rect.y);
419 SDL_GetWindowSize(window, &rect.w, &rect.h);
420 get_border_size(&border_y, &border_x, 0, 0);
421 rect.x -= border_x;
422 rect.y -= border_y;
423
424 SDL_DestroyWindow(window);
425 }
426 window = NULL;
427 }
428
render()429 int render()
430 {
431 uint64_t start_time = timer_read();
432 uint64_t end_time;
433
434 if (window_dosetresize)
435 {
436 window_dosetresize = 0;
437 #if SDL_VERSION_ATLEAST(2, 0, 5)
438 SDL_GetWindowSize(window, &rect.w, &rect.h);
439 SDL_SetWindowResizable(window, vid_resize == 1);
440 SDL_SetWindowSize(window, rect.w, rect.h);
441 #else
442 window_doreset = 1;
443 #endif
444 if (vid_resize == 2)
445 SDL_SetWindowSize(window, custom_resolution_width, custom_resolution_height);
446
447 device_force_redraw();
448 }
449 if (window_doreset)
450 {
451 pclog("window_doreset\n");
452 window_doreset = 0;
453 renderer_doreset = 0;
454 return 0;
455 }
456 if (renderer_doreset)
457 {
458 pclog("renderer_doreset\n");
459 renderer_doreset = 0;
460 sdl_renderer_close();
461 sdl_renderer_init(window);
462
463 device_force_redraw();
464 video_wait_for_blit();
465 }
466 while(SDL_PollEvent(&event))
467 {
468 switch (event.type) {
469 case SDL_MOUSEBUTTONUP:
470 if (!mousecapture)
471 {
472 if (event.button.button == SDL_BUTTON_LEFT && !pause)
473 {
474 window_doinputgrab = 1;
475 if (video_fullscreen)
476 window_dofullscreen = 1;
477 }
478 else if (event.button.button == SDL_BUTTON_RIGHT)
479 wx_popupmenu(ghwnd, menu, 0, 0);
480
481 }
482 else if (event.button.button == SDL_BUTTON_MIDDLE && !is_fullscreen())
483 window_doinputrelease = 1;
484 break;
485 case SDL_MOUSEWHEEL:
486 if (mousecapture) mouse_wheel_update(event.wheel.y);
487 break;
488 case SDL_WINDOWEVENT:
489 if (event.window.event == SDL_WINDOWEVENT_CLOSE)
490 wx_stop_emulation(ghwnd);
491 if (event.window.event == SDL_WINDOWEVENT_RESIZED)
492 device_force_redraw();
493 if (event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
494 {
495 if (is_fullscreen())
496 window_dowindowed = 1;
497 window_doinputrelease = 1;
498 }
499
500 if (window_remember)
501 {
502 int flags = SDL_GetWindowFlags(window);
503 if (!(flags&SDL_WINDOW_FULLSCREEN) && !(flags&SDL_WINDOW_FULLSCREEN_DESKTOP))
504 {
505 if (event.window.event == SDL_WINDOWEVENT_MOVED)
506 {
507 get_border_size(&border_y, &border_x, 0, 0);
508 window_x = event.window.data1-border_x;
509 window_y = event.window.data2-border_y;
510 }
511 else if (event.window.event == SDL_WINDOWEVENT_RESIZED)
512 {
513 window_w = event.window.data1;
514 window_h = event.window.data2;
515 }
516 //save_window_pos = 1;
517 }
518 }
519
520 break;
521 case SDL_KEYDOWN:
522 {
523 #ifdef __WINDOWS__
524 /* international keyboard workaround */
525 if (event.key.keysym.scancode == SDL_SCANCODE_RALT &&
526 (event.key.keysym.mod&KMOD_LCTRL) &&
527 event.key.timestamp == rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)])
528 rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] = 0;
529 #endif
530 int key_idx = sdl_scancode(event.key.keysym.scancode);
531 if (key_idx != -1)
532 rawinputkey[key_idx] = event.key.timestamp;
533 break;
534 }
535 case SDL_KEYUP:
536 {
537 int key_idx = sdl_scancode(event.key.keysym.scancode);
538 if (key_idx != -1)
539 rawinputkey[key_idx] = 0;
540 break;
541 }
542 }
543 }
544 if (rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEDOWN)] &&
545 (rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]) &&
546 (rawinputkey[sdl_scancode(SDL_SCANCODE_LALT)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RALT)]))
547 trigger_fullscreen = 1;
548 else if (trigger_fullscreen)
549 {
550 trigger_fullscreen = 0;
551 toggle_fullscreen();
552 }
553 else if (rawinputkey[sdl_scancode(SDL_SCANCODE_PAGEUP)] &&
554 (rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]) &&
555 (rawinputkey[sdl_scancode(SDL_SCANCODE_LALT)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RALT)]))
556 trigger_screenshot = 1;
557 else if (trigger_screenshot)
558 {
559 trigger_screenshot = 0;
560 take_screenshot = 1;
561 }
562 else if (event.key.keysym.scancode == SDL_SCANCODE_END &&
563 (rawinputkey[sdl_scancode(SDL_SCANCODE_LCTRL)] || rawinputkey[sdl_scancode(SDL_SCANCODE_RCTRL)]))
564 trigger_inputrelease = 1;
565 else if (trigger_inputrelease)
566 {
567 trigger_inputrelease = 0;
568 if (!is_fullscreen())
569 window_doinputrelease = 1;
570 }
571 if (window_doremember)
572 {
573 window_doremember = 0;
574 SDL_GetWindowPosition(window, &window_x, &window_y);
575 SDL_GetWindowSize(window, &window_w, &window_h);
576 get_border_size(&border_y, &border_x, 0, 0);
577 window_x -= border_x;
578 window_y -= border_y;
579 saveconfig(NULL);
580 }
581
582 if (window_dotogglefullscreen)
583 {
584 window_dotogglefullscreen = 0;
585 if (SDL_GetWindowGrab(window) || is_fullscreen())
586 {
587 window_doinputrelease = 1;
588 if (is_fullscreen())
589 window_dowindowed = 1;
590 }
591 else
592 {
593 window_doinputgrab = 1;
594 window_dofullscreen = 1;
595 }
596 }
597
598 if (window_dofullscreen)
599 {
600 window_dofullscreen = 0;
601 video_wait_for_blit();
602 SDL_RaiseWindow(window);
603 #if SDL_VERSION_ATLEAST(2, 0, 4)
604 SDL_GetGlobalMouseState(&remembered_mouse_x, &remembered_mouse_y);
605 #endif
606 SDL_GetWindowPosition(window, &remembered_rect.x, &remembered_rect.y);
607 get_border_size(&border_y, &border_x, 0, 0);
608 remembered_rect.x -= border_x;
609 remembered_rect.y -= border_y;
610 SDL_GetWindowSize(window, &remembered_rect.w, &remembered_rect.h);
611 SDL_SetWindowFullscreen(window, video_fullscreen_mode == 0 ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN);
612 device_force_redraw();
613 }
614 if (window_doinputgrab) {
615 window_doinputgrab = 0;
616 mousecapture = 1;
617 SDL_GetRelativeMouseState(0, 0);
618 SDL_SetWindowGrab(window, SDL_TRUE);
619 SDL_SetRelativeMouseMode(SDL_TRUE);
620 }
621
622 if (window_doinputrelease) {
623 window_doinputrelease = 0;
624 mousecapture = 0;
625 SDL_SetWindowGrab(window, SDL_FALSE);
626 SDL_SetRelativeMouseMode(SDL_FALSE);
627 }
628 if (window_dowindowed)
629 {
630 window_dowindowed = 0;
631 SDL_SetWindowFullscreen(window, 0);
632 SDL_SetWindowSize(window, remembered_rect.w, remembered_rect.h);
633 SDL_SetWindowPosition(window, remembered_rect.x, remembered_rect.y);
634 #if SDL_VERSION_ATLEAST(2, 0, 4)
635 SDL_WarpMouseGlobal(remembered_mouse_x, remembered_mouse_y);
636 #endif
637 device_force_redraw();
638 }
639
640 if (win_doresize)
641 {
642 win_doresize = 0;
643 if (!vid_resize || (flags&SDL_WINDOW_FULLSCREEN)) {
644 SDL_GetWindowSize(window, &rect.w, &rect.h);
645 if (rect.w != winsizex || rect.h != winsizey) {
646 SDL_GetWindowPosition(window, &rect.x, &rect.y);
647 SDL_SetWindowSize(window, winsizex, winsizey);
648 SDL_SetWindowPosition(window, rect.x, rect.y);
649 device_force_redraw();
650 }
651 }
652 }
653
654 if (sdl_renderer_update(window)) sdl_renderer_present(window);
655
656 end_time = timer_read();
657 render_time += end_time - start_time;
658
659 ++render_frames;
660 uint32_t ticks = SDL_GetTicks();
661 if (ticks-render_frame_time >= 1000) {
662 render_fps = render_frames/((ticks-render_frame_time)/1000.0);
663 render_frames = 0;
664 render_frame_time = ticks;
665 }
666
667 return 1;
668 }
669
renderer_thread(void * params)670 int renderer_thread(void* params)
671 {
672 int internal_rendering;
673
674 SDL_LockMutex(rendererMutex);
675 SDL_CondSignal(rendererCond);
676 SDL_UnlockMutex(rendererMutex);
677
678 window_setup();
679
680 rendering = 1;
681 while (rendering) {
682
683 if (!window_create())
684 rendering = 0;
685
686 renderer_doreset = 1;
687 internal_rendering = 1;
688 while (rendering && internal_rendering)
689 {
690 if (!render())
691 internal_rendering = 0;
692
693 SDL_Delay(1);
694 }
695 window_close();
696 }
697
698 SDL_LockMutex(rendererMutex);
699 SDL_CondSignal(rendererCond);
700 SDL_UnlockMutex(rendererMutex);
701
702 return SDL_TRUE;
703 }
704
705 void* timer = 0;
706
render_timer()707 void render_timer()
708 {
709 #ifdef PCEM_RENDER_TIMER_LOOP
710 /* For some reason this while-loop works on OSX, which also fixes missing events. No idea why though. */
711 renderer_thread(0);
712 #else
713 if (rendering && !render())
714 {
715 window_close();
716 window_create();
717 renderer_doreset = 1;
718 }
719 #endif
720 }
721
render_start_timer()722 void render_start_timer()
723 {
724 #ifdef PCEM_RENDER_TIMER_LOOP
725 timer = wx_createtimer(render_timer);
726 wx_starttimer(timer, 500, 1);
727 #else
728 window_setup();
729 if (window_create())
730 {
731 rendering = 1;
732 renderer_doreset = 1;
733 wx_starttimer(timer, 1, 0);
734 }
735 #endif
736 }
737
renderer_start()738 void renderer_start()
739 {
740 if (!rendering)
741 {
742 #ifdef PCEM_RENDER_WITH_TIMER
743 render_start_timer();
744 #else
745 SDL_LockMutex(rendererMutex);
746 renderthread = SDL_CreateThread(renderer_thread, "SDL2 Thread", NULL);
747 SDL_CondWait(rendererCond, rendererMutex);
748 SDL_UnlockMutex(rendererMutex);
749 #endif
750 }
751 }
752
renderer_stop(int timeout)753 void renderer_stop(int timeout)
754 {
755 #if defined(PCEM_RENDER_WITH_TIMER) && !defined(PCEM_RENDER_TIMER_LOOP)
756 rendering = 0;
757 window_close();
758 wx_destroytimer(timer);
759 #else
760 if (rendering)
761 {
762 SDL_LockMutex(rendererMutex);
763 rendering = 0;
764 if (timeout)
765 SDL_CondWaitTimeout(rendererCond, rendererMutex, timeout);
766 else
767 SDL_CondWait(rendererCond, rendererMutex);
768 SDL_UnlockMutex(rendererMutex);
769 renderthread = NULL;
770 }
771 if (timer)
772 wx_destroytimer(timer);
773 #endif
774 }
775