1 /** \brief video.c
2 * \brief SDL video (probably needs a more descriptive 'brief')
3 *
4 * \author Hannu Nuotio <hannu.nuotio@tut.fi>
5 * \author Marco van den Heuvel <blackystardust68@yahoo.com>
6 *
7 * Based on code by
8 * Ettore Perazzoli
9 * Andre Fachat
10 * Oliver Schaertel
11 * Martin Pottendorfer
12 *
13 * This file is part of VICE, the Versatile Commodore Emulator.
14 * See README for copyright notice.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 * 02111-1307 USA.
30 *
31 */
32
33 /* #define SDL_DEBUG */
34
35 #include "vice.h"
36
37 #include <stdio.h>
38 #include "vice_sdl.h"
39
40 #include "archdep.h"
41 #include "cmdline.h"
42 #include "fullscreen.h"
43 #include "fullscreenarch.h"
44 #include "icon.h"
45 #include "joy.h"
46 #include "joystick.h"
47 #include "keyboard.h"
48 #include "lib.h"
49 #include "lightpendrv.h"
50 #include "log.h"
51 #include "machine.h"
52 #include "mousedrv.h"
53 #include "palette.h"
54 #include "raster.h"
55 #include "resources.h"
56 #include "ui.h"
57 #include "uimenu.h"
58 #include "uistatusbar.h"
59 #include "util.h"
60 #include "videoarch.h"
61 #include "vkbd.h"
62 #include "vsidui_sdl.h"
63 #include "vsync.h"
64
65 #ifdef SDL_DEBUG
66 #define DBG(x) log_debug x
67 #else
68 #define DBG(x)
69 #endif
70
71 static log_t sdlvideo_log = LOG_ERR;
72
73 static int sdl_bitdepth;
74
75 static int sdl_limit_mode;
76 static int sdl_ui_finalized;
77
78 /* Custom w/h, used for fullscreen and limiting*/
79 static int sdl_custom_width = 0;
80 static int sdl_custom_height = 0;
81
82 /* window size, used for free scaling */
83 static int sdl_window_width = 0;
84 static int sdl_window_height = 0;
85
86 int sdl_active_canvas_num = 0;
87 static int sdl_num_screens = 0;
88 static video_canvas_t *sdl_canvaslist[MAX_CANVAS_NUM];
89 video_canvas_t *sdl_active_canvas = NULL;
90
91 #if defined(HAVE_HWSCALE)
92 static int sdl_gl_mode;
93 static GLint screen_texture;
94 static int sdl_gl_vertex_base = 0;
95
96 static const float sdl_gl_vertex_coord[4 * 4] = {
97 /* Normal */
98 -1.0f, +1.0f, -1.0f, +1.0f,
99 /* Flip X */
100 +1.0f, +1.0f, -1.0f, -1.0f,
101 /* Flip Y */
102 -1.0f, -1.0f, +1.0f, +1.0f,
103 /* Flip X&Y */
104 +1.0f, -1.0f, +1.0f, -1.0f
105 };
106
107 static int sdl_gl_aspect_mode;
108 static char *aspect_ratio_s = NULL;
109 static double aspect_ratio;
110
111 static int sdl_gl_flipx;
112 static int sdl_gl_flipy;
113
114 static int sdl_gl_filter_res;
115 static int sdl_gl_filter;
116 #endif
117
118 struct sdl_lightpen_adjust_s {
119 int offset_x, offset_y;
120 int max_x, max_y;
121 double scale_x, scale_y;
122 };
123 typedef struct sdl_lightpen_adjust_s sdl_lightpen_adjust_t;
124 static sdl_lightpen_adjust_t sdl_lightpen_adjust;
125
126 uint8_t *draw_buffer_vsid = NULL;
127 /* ------------------------------------------------------------------------- */
128 /* Video-related resources. */
129
set_sdl_bitdepth(int d,void * param)130 static int set_sdl_bitdepth(int d, void *param)
131 {
132 switch (d) {
133 case 0:
134 case 8:
135 case 15:
136 case 16:
137 case 24:
138 case 32:
139 break;
140 default:
141 return -1;
142 }
143
144 if (sdl_bitdepth == d) {
145 return 0;
146 }
147 sdl_bitdepth = d;
148 #if defined(HAVE_HWSCALE)
149 if (!((d == 0) || (d == 24) || (d == 32))) {
150 resources_set_int("HwScalePossible", 0);
151 }
152 #endif
153 /* update */
154 return 0;
155 }
156
set_sdl_limit_mode(int v,void * param)157 static int set_sdl_limit_mode(int v, void *param)
158 {
159 switch (v) {
160 case SDL_LIMIT_MODE_OFF:
161 case SDL_LIMIT_MODE_MAX:
162 case SDL_LIMIT_MODE_FIXED:
163 break;
164 default:
165 return -1;
166 }
167
168 if (sdl_limit_mode != v) {
169 sdl_limit_mode = v;
170 video_viewport_resize(sdl_active_canvas, 1);
171 }
172 return 0;
173 }
174
set_sdl_custom_width(int w,void * param)175 static int set_sdl_custom_width(int w, void *param)
176 {
177 if (w <= 0) {
178 return -1;
179 }
180
181 if (sdl_custom_width != w) {
182 sdl_custom_width = w;
183 if (sdl_active_canvas && sdl_active_canvas->fullscreenconfig->enable
184 && sdl_active_canvas->fullscreenconfig->mode == FULLSCREEN_MODE_CUSTOM) {
185 video_viewport_resize(sdl_active_canvas, 1);
186 }
187 }
188 return 0;
189 }
190
set_sdl_custom_height(int h,void * param)191 static int set_sdl_custom_height(int h, void *param)
192 {
193 if (h <= 0) {
194 return -1;
195 }
196
197 if (sdl_custom_height != h) {
198 sdl_custom_height = h;
199 if (sdl_active_canvas && sdl_active_canvas->fullscreenconfig->enable
200 && sdl_active_canvas->fullscreenconfig->mode == FULLSCREEN_MODE_CUSTOM) {
201 video_viewport_resize(sdl_active_canvas, 1);
202 }
203 }
204 return 0;
205 }
206
set_sdl_window_width(int w,void * param)207 static int set_sdl_window_width(int w, void *param)
208 {
209 if (w < 0) {
210 return -1;
211 }
212
213 sdl_window_width = w;
214 return 0;
215 }
216
set_sdl_window_height(int h,void * param)217 static int set_sdl_window_height(int h, void *param)
218 {
219 if (h < 0) {
220 return -1;
221 }
222
223 sdl_window_height = h;
224 return 0;
225 }
226
227 #if defined(HAVE_HWSCALE)
set_sdl_gl_aspect_mode(int v,void * param)228 static int set_sdl_gl_aspect_mode(int v, void *param)
229 {
230 int old_v = sdl_gl_aspect_mode;
231
232 switch (v) {
233 case SDL_ASPECT_MODE_OFF:
234 case SDL_ASPECT_MODE_CUSTOM:
235 case SDL_ASPECT_MODE_TRUE:
236 break;
237 default:
238 return -1;
239 }
240
241 sdl_gl_aspect_mode = v;
242
243 if (old_v != v) {
244 if (sdl_active_canvas && sdl_active_canvas->videoconfig->hwscale) {
245 video_viewport_resize(sdl_active_canvas, 1);
246 }
247 }
248
249 return 0;
250 }
251
set_aspect_ratio(const char * val,void * param)252 static int set_aspect_ratio(const char *val, void *param)
253 {
254 double old_aspect = aspect_ratio;
255 char buf[20];
256
257 if (val) {
258 char *endptr;
259
260 util_string_set(&aspect_ratio_s, val);
261
262 aspect_ratio = strtod(val, &endptr);
263 if (val == endptr) {
264 aspect_ratio = 1.0;
265 } else if (aspect_ratio < 0.5) {
266 aspect_ratio = 0.5;
267 } else if (aspect_ratio > 2.0) {
268 aspect_ratio = 2.0;
269 }
270 } else {
271 aspect_ratio = 1.0;
272 }
273
274 sprintf(buf, "%f", aspect_ratio);
275 util_string_set(&aspect_ratio_s, buf);
276
277 if (old_aspect != aspect_ratio) {
278 if (sdl_active_canvas && sdl_active_canvas->videoconfig->hwscale) {
279 video_viewport_resize(sdl_active_canvas, 1);
280 }
281 }
282
283 return 0;
284 }
285
update_vertex_base(void)286 static void update_vertex_base(void)
287 {
288 sdl_gl_vertex_base = (sdl_gl_flipx << 2) | (sdl_gl_flipy << 3);
289 }
290
set_sdl_gl_flipx(int v,void * param)291 static int set_sdl_gl_flipx(int v, void *param)
292 {
293 sdl_gl_flipx = v ? 1 : 0;
294 update_vertex_base();
295
296 return 0;
297 }
298
set_sdl_gl_flipy(int v,void * param)299 static int set_sdl_gl_flipy(int v, void *param)
300 {
301 sdl_gl_flipy = v ? 1 : 0;
302 update_vertex_base();
303
304 return 0;
305 }
306
set_sdl_gl_filter(int v,void * param)307 static int set_sdl_gl_filter(int v, void *param)
308 {
309 switch (v) {
310 case SDL_FILTER_NEAREST:
311 sdl_gl_filter = GL_NEAREST;
312 break;
313
314 case SDL_FILTER_LINEAR:
315 sdl_gl_filter = GL_LINEAR;
316 break;
317
318 default:
319 return -1;
320 }
321
322 sdl_gl_filter_res = v;
323 return 0;
324 }
325 #endif /* HAVE_HWSCALE */
326
327 static const resource_string_t resources_string[] = {
328 #if defined(HAVE_HWSCALE)
329 { "AspectRatio", "1.0", RES_EVENT_NO, NULL,
330 &aspect_ratio_s, set_aspect_ratio, NULL },
331 #endif
332 RESOURCE_STRING_LIST_END
333 };
334
335 #define VICE_DEFAULT_BITDEPTH 0
336
337 #ifdef ANDROID_COMPILE
338 #define SDLLIMITMODE_DEFAULT SDL_LIMIT_MODE_MAX
339 #define SDLCUSTOMWIDTH_DEFAULT 320
340 #define SDLCUSTOMHEIGHT_DEFAULT 200
341 #else
342 #define SDLLIMITMODE_DEFAULT SDL_LIMIT_MODE_OFF
343 #define SDLCUSTOMWIDTH_DEFAULT 800
344 #define SDLCUSTOMHEIGHT_DEFAULT 600
345 #endif
346
347 static const resource_int_t resources_int[] = {
348 { "SDLBitdepth", VICE_DEFAULT_BITDEPTH, RES_EVENT_NO, NULL,
349 &sdl_bitdepth, set_sdl_bitdepth, NULL },
350 { "SDLLimitMode", SDLLIMITMODE_DEFAULT, RES_EVENT_NO, NULL,
351 &sdl_limit_mode, set_sdl_limit_mode, NULL },
352 { "SDLCustomWidth", SDLCUSTOMWIDTH_DEFAULT, RES_EVENT_NO, NULL,
353 &sdl_custom_width, set_sdl_custom_width, NULL },
354 { "SDLCustomHeight", SDLCUSTOMHEIGHT_DEFAULT, RES_EVENT_NO, NULL,
355 &sdl_custom_height, set_sdl_custom_height, NULL },
356 { "SDLWindowWidth", 0, RES_EVENT_NO, NULL,
357 &sdl_window_width, set_sdl_window_width, NULL },
358 { "SDLWindowHeight", 0, RES_EVENT_NO, NULL,
359 &sdl_window_height, set_sdl_window_height, NULL },
360 #if defined(HAVE_HWSCALE)
361 { "SDLGLAspectMode", SDL_ASPECT_MODE_TRUE, RES_EVENT_NO, NULL,
362 &sdl_gl_aspect_mode, set_sdl_gl_aspect_mode, NULL },
363 { "SDLGLFlipX", 0, RES_EVENT_NO, NULL,
364 &sdl_gl_flipx, set_sdl_gl_flipx, NULL },
365 { "SDLGLFlipY", 0, RES_EVENT_NO, NULL,
366 &sdl_gl_flipy, set_sdl_gl_flipy, NULL },
367 { "SDLGLFilter", SDL_FILTER_LINEAR, RES_EVENT_NO, NULL,
368 &sdl_gl_filter_res, set_sdl_gl_filter, NULL },
369 #endif
370 RESOURCE_INT_LIST_END
371 };
372
video_arch_resources_init(void)373 int video_arch_resources_init(void)
374 {
375 DBG(("%s", __func__));
376
377 if (machine_class == VICE_MACHINE_VSID) {
378 if (joy_arch_resources_init() < 0) {
379 return -1;
380 }
381 }
382
383 if (resources_register_string(resources_string) < 0) {
384 return -1;
385 }
386
387 return resources_register_int(resources_int);
388 }
389
video_arch_resources_shutdown(void)390 void video_arch_resources_shutdown(void)
391 {
392 DBG(("%s", __func__));
393
394 if (machine_class == VICE_MACHINE_VSID) {
395 joy_arch_resources_shutdown();
396 }
397
398 #if defined(HAVE_HWSCALE)
399 lib_free(aspect_ratio_s);
400 #endif
401 }
402
403 /* ------------------------------------------------------------------------- */
404 /* Video-related command-line options. */
405
406 static const cmdline_option_t cmdline_options[] =
407 {
408 { "-sdlbitdepth", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
409 NULL, NULL, "SDLBitdepth", NULL,
410 "<bpp>", "Set bitdepth (0 = current, 8, 15, 16, 24, 32)" },
411 { "-sdllimitmode", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
412 NULL, NULL, "SDLLimitMode", NULL,
413 "<mode>", "Set resolution limiting mode (0 = off, 1 = max, 2 = fixed)" },
414 { "-sdlcustomw", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
415 NULL, NULL, "SDLCustomWidth", NULL,
416 "<width>", "Set custom resolution width" },
417 { "-sdlcustomh", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
418 NULL, NULL, "SDLCustomHeight", NULL,
419 "<height>", "Set custom resolution height" },
420 { "-sdlinitialw", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
421 NULL, NULL, "SDLWindowWidth", NULL,
422 "<width>", "Set intiial window width" },
423 { "-sdlinitialh", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
424 NULL, NULL, "SDLWindowHeight", NULL,
425 "<height>", "Set intiial window height" },
426 #if defined(HAVE_HWSCALE)
427 { "-sdlaspectmode", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
428 NULL, NULL, "SDLGLAspectMode", NULL,
429 "<mode>", "Set aspect ratio mode (0 = off, 1 = custom, 2 = true)" },
430 { "-aspect", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
431 NULL, NULL, "AspectRatio", NULL,
432 "<aspect ratio>", "Set custom aspect ratio (0.5 - 2.0)" },
433 { "-sdlflipx", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
434 NULL, NULL, "SDLGLFlipX", (resource_value_t)1,
435 NULL, "Enable X flip" },
436 { "+sdlflipx", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
437 NULL, NULL, "SDLGLFlipX", (resource_value_t)0,
438 NULL, "Disable X flip" },
439 { "-sdlflipy", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
440 NULL, NULL, "SDLGLFlipY", (resource_value_t)1,
441 NULL, "Enable Y flip" },
442 { "+sdlflipy", SET_RESOURCE, CMDLINE_ATTRIB_NONE,
443 NULL, NULL, "SDLGLFlipY", (resource_value_t)0,
444 NULL, "Disable Y flip" },
445 { "-sdlglfilter", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
446 NULL, NULL, "SDLGLFilter", NULL,
447 "<mode>", "Set OpenGL filtering mode (0 = nearest, 1 = linear)" },
448 #endif
449 CMDLINE_LIST_END
450 };
451
video_arch_cmdline_options_init(void)452 int video_arch_cmdline_options_init(void)
453 {
454 DBG(("%s", __func__));
455
456 if (machine_class == VICE_MACHINE_VSID) {
457 if (joystick_cmdline_options_init() < 0) {
458 return -1;
459 }
460 }
461
462 return cmdline_register_options(cmdline_options);
463 }
464
465 /* ------------------------------------------------------------------------- */
466
video_init(void)467 int video_init(void)
468 {
469 sdlvideo_log = log_open("SDLVideo");
470 return 0;
471 }
472
video_shutdown(void)473 void video_shutdown(void)
474 {
475 DBG(("%s", __func__));
476
477 if (draw_buffer_vsid) {
478 lib_free(draw_buffer_vsid);
479 }
480
481 sdl_active_canvas = NULL;
482 }
483
484 /* ------------------------------------------------------------------------- */
485 /* static helper functions */
486
sdl_video_canvas_limit(unsigned int limit_w,unsigned int limit_h,unsigned int * w,unsigned int * h,int mode)487 static int sdl_video_canvas_limit(unsigned int limit_w, unsigned int limit_h, unsigned int *w, unsigned int *h, int mode)
488 {
489 DBG(("%s", __func__));
490 switch (mode & 3) {
491 case SDL_LIMIT_MODE_MAX:
492 if ((*w > limit_w) || (*h > limit_h)) {
493 *w = MIN(*w, limit_w);
494 *h = MIN(*h, limit_h);
495 return 1;
496 }
497 break;
498 case SDL_LIMIT_MODE_FIXED:
499 if ((*w != limit_w) || (*h != limit_h)) {
500 *w = limit_w;
501 *h = limit_h;
502 return 1;
503 }
504 break;
505 case SDL_LIMIT_MODE_OFF:
506 default:
507 break;
508 }
509 return 0;
510 }
511
512 #if defined(HAVE_HWSCALE)
sdl_gl_set_viewport(unsigned int src_w,unsigned int src_h,unsigned int dest_w,unsigned int dest_h)513 static void sdl_gl_set_viewport(unsigned int src_w, unsigned int src_h, unsigned int dest_w, unsigned int dest_h)
514 {
515 int dest_x = 0, dest_y = 0;
516
517 if (sdl_gl_aspect_mode != SDL_ASPECT_MODE_OFF) {
518 double aspect = aspect_ratio;
519
520 /* Get "true" aspect ratio */
521 if (sdl_gl_aspect_mode == SDL_ASPECT_MODE_TRUE) {
522 aspect = sdl_active_canvas->geometry->pixel_aspect_ratio;
523 }
524
525 /* Keep aspect ratio of src image. */
526 if (dest_w * src_h < src_w * aspect * dest_h) {
527 dest_y = dest_h;
528 dest_h = (unsigned int)(dest_w * src_h / (src_w * aspect) + 0.5);
529 dest_y = (dest_y - dest_h) / 2;
530 } else {
531 dest_x = dest_w;
532 dest_w = (unsigned int)(dest_h * src_w * aspect / src_h + 0.5);
533 dest_x = (dest_x - dest_w) / 2;
534 }
535 }
536
537 /* Update lightpen adjustment parameters */
538 sdl_lightpen_adjust.offset_x = dest_x;
539 sdl_lightpen_adjust.offset_y = dest_y;
540
541 sdl_lightpen_adjust.max_x = dest_w;
542 sdl_lightpen_adjust.max_y = dest_h;
543
544 sdl_lightpen_adjust.scale_x = (double)(src_w) / (double)(dest_w);
545 sdl_lightpen_adjust.scale_y = (double)(src_h) / (double)(dest_h);
546
547 glViewport(dest_x, dest_y, dest_w, dest_h);
548 }
549 #endif
550
sdl_canvas_create(video_canvas_t * canvas,unsigned int * width,unsigned int * height)551 static video_canvas_t *sdl_canvas_create(video_canvas_t *canvas, unsigned int *width, unsigned int *height)
552 {
553 SDL_Surface *new_screen;
554 unsigned int new_width, new_height;
555 unsigned int actual_width, actual_height;
556 int flags;
557 int fullscreen = 0;
558 int limit = sdl_limit_mode;
559 unsigned int limit_w = (unsigned int)sdl_custom_width;
560 unsigned int limit_h = (unsigned int)sdl_custom_height;
561 int hwscale = 0;
562 int lightpen_updated = 0;
563 #ifdef HAVE_HWSCALE
564 int rbits = 0, gbits = 0, bbits = 0;
565 const Uint32
566
567 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
568 rmask = 0xff000000, gmask = 0x00ff0000, bmask = 0x0000ff00, amask = 0x000000ff;
569 #else
570 rmask = 0x000000ff, gmask = 0x0000ff00, bmask = 0x00ff0000, amask = 0xff000000;
571 #endif
572 #endif
573
574 DBG(("%s: %i,%i (%i)", __func__, *width, *height, canvas->index));
575
576 flags = SDL_SWSURFACE | SDL_RESIZABLE;
577
578 new_width = *width;
579 new_height = *height;
580
581 new_width *= canvas->videoconfig->scalex;
582 new_height *= canvas->videoconfig->scaley;
583
584 if ((canvas == sdl_active_canvas) && (canvas->fullscreenconfig->enable)) {
585 fullscreen = 1;
586 }
587
588 #ifdef HAVE_HWSCALE
589 if ((canvas == sdl_active_canvas) && (canvas->videoconfig->hwscale)) {
590 hwscale = 1;
591 }
592 #endif
593
594 if (fullscreen) {
595 flags = SDL_FULLSCREEN | SDL_SWSURFACE;
596
597 if (canvas->fullscreenconfig->mode == FULLSCREEN_MODE_CUSTOM) {
598 limit = SDL_LIMIT_MODE_FIXED;
599 }
600 }
601
602 if (!sdl_ui_finalized) { /* remember first size */
603 double aspect = 1.0;
604 #ifdef HAVE_HWSCALE
605 aspect = aspect_ratio;
606
607 if (sdl_gl_aspect_mode == SDL_ASPECT_MODE_TRUE) {
608 aspect = sdl_active_canvas->geometry->pixel_aspect_ratio;
609 }
610 #endif
611 sdl_active_canvas->real_width = (unsigned int)((double)new_width * aspect + 0.5);
612 sdl_active_canvas->real_height = new_height;
613 DBG(("first: %d:%d\n", sdl_active_canvas->real_width, sdl_active_canvas->real_height));
614 }
615
616 #ifdef HAVE_HWSCALE
617 if (hwscale) {
618 flags |= SDL_OPENGL;
619
620 if (fullscreen) {
621 limit = SDL_LIMIT_MODE_OFF;
622 } else {
623 double aspect = aspect_ratio;
624
625 if (sdl_gl_aspect_mode == SDL_ASPECT_MODE_TRUE) {
626 aspect = sdl_active_canvas->geometry->pixel_aspect_ratio;
627 }
628
629 /* if no window geometry given then create one. */
630 if (!sdl_window_width || !sdl_window_height) {
631 limit_w = (unsigned int)((double)new_width * aspect + 0.5);
632 limit_h = new_height;
633 } else { /* full window size remembering when aspect ratio is not important */
634 if (sdl_gl_aspect_mode == SDL_ASPECT_MODE_OFF) {
635 limit_w = (unsigned int)sdl_window_width;
636 limit_h = (unsigned int)sdl_window_height;
637 } else { /* only remember height, set width according to that and the aspect ratio */
638 limit_h = (unsigned int)sdl_window_height;
639 limit_w = (unsigned int)((double)new_width * (double)sdl_window_height * aspect / (double)new_height + 0.5);
640 }
641 }
642 limit = SDL_LIMIT_MODE_FIXED;
643 }
644
645 switch (sdl_bitdepth) {
646 case 0:
647 log_warning(sdlvideo_log, "bitdepth not set for OpenGL, trying 32...");
648 sdl_bitdepth = 32;
649 /* fall through */
650 case 32:
651 rbits = gbits = bbits = 8;
652 sdl_gl_mode = GL_RGBA;
653 break;
654 case 24:
655 rbits = gbits = bbits = 8;
656 sdl_gl_mode = GL_RGB;
657 break;
658 default:
659 log_error(sdlvideo_log, "%i bpp not supported in OpenGL.", sdl_bitdepth);
660 resources_set_int("HwScalePossible", 0);
661 hwscale = 0;
662 canvas->videoconfig->hwscale = 0;
663 flags = SDL_SWSURFACE;
664 break;
665 }
666
667 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, rbits);
668 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, gbits);
669 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, bbits);
670 }
671 #endif
672
673 actual_width = new_width;
674 actual_height = new_height;
675
676 if (canvas == sdl_active_canvas) {
677 #ifdef HAVE_HWSCALE
678 if (hwscale) {
679 double aspect = aspect_ratio;
680
681 if (sdl_gl_aspect_mode == SDL_ASPECT_MODE_TRUE) {
682 aspect = sdl_active_canvas->geometry->pixel_aspect_ratio;
683 }
684
685 actual_width = (unsigned int)((double)actual_width * aspect + 0.5);
686 }
687 #endif
688 if (sdl_video_canvas_limit(limit_w, limit_h, &actual_width, &actual_height, limit)) {
689 if (!hwscale) {
690 canvas->draw_buffer->canvas_physical_width = actual_width;
691 canvas->draw_buffer->canvas_physical_height = actual_height;
692 video_viewport_resize(sdl_active_canvas, 0);
693 if (sdl_ui_finalized) {
694 return canvas; /* exit here as video_viewport_resize will recall */
695 }
696 }
697 }
698 }
699
700 if (canvas == sdl_active_canvas) {
701 #ifndef ANDROID_COMPILE
702 SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
703 #endif
704 #ifndef HAVE_HWSCALE
705 new_screen = SDL_SetVideoMode(actual_width, actual_height, sdl_bitdepth, flags);
706 new_width = new_screen->w;
707 new_height = new_screen->h;
708 #else
709 if (hwscale) {
710 /* To get fullscreen resolution, SetVideoMode must be called with the
711 desired fullscreen resolution. If it is called with a smaller resolution,
712 it will display the undesirable black borders around the emulator display. */
713 if ((fullscreen) && (canvas->fullscreenconfig->mode == FULLSCREEN_MODE_CUSTOM)) {
714 new_screen = SDL_SetVideoMode(limit_w, limit_h, sdl_bitdepth, flags);
715 } else {
716 new_screen = SDL_SetVideoMode(actual_width, actual_height, sdl_bitdepth, flags);
717 }
718 if (!new_screen) { /* Did not work out quite well. Let's try without hwscale */
719 resources_set_int("HwScalePossible", 0);
720 canvas->videoconfig->hwscale = 0;
721 return sdl_canvas_create(canvas, width, height);
722 }
723 actual_width = new_screen->w;
724 actual_height = new_screen->h;
725
726 /* free the old rendering surface when staying in hwscale mode */
727 if ((canvas->hwscale_screen) && (canvas->screen)) {
728 SDL_FreeSurface(canvas->screen);
729 }
730
731 canvas->hwscale_screen = new_screen;
732 new_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, new_width, new_height, sdl_bitdepth, rmask, gmask, bmask, amask);
733 sdl_gl_set_viewport(new_width, new_height, actual_width, actual_height);
734 lightpen_updated = 1;
735 } else {
736 new_screen = SDL_SetVideoMode(actual_width, actual_height, sdl_bitdepth, flags);
737 new_width = new_screen->w;
738 new_height = new_screen->h;
739
740 /* free the old rendering surface when leaving hwscale mode */
741 if ((canvas->hwscale_screen) && (canvas->screen)) {
742 SDL_FreeSurface(canvas->screen);
743 SDL_FreeSurface(canvas->hwscale_screen);
744 canvas->hwscale_screen = NULL;
745 }
746 }
747 #endif
748 #ifndef ANDROID_COMPILE
749 SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
750 #endif
751 } else {
752 #ifdef HAVE_HWSCALE
753 /* free the old hwscale screen when hwscaled screen is switched away */
754 if (canvas->hwscale_screen) {
755 SDL_FreeSurface(canvas->hwscale_screen);
756 canvas->hwscale_screen = NULL;
757 }
758 if (!hwscale) {
759 new_width = actual_width;
760 new_height = actual_height;
761 }
762 #else
763 new_width = actual_width;
764 new_height = actual_height;
765 #endif
766 if (canvas->screen) {
767 SDL_FreeSurface(canvas->screen);
768 }
769 new_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, new_width, new_height, sdl_bitdepth, 0, 0, 0, 0);
770 }
771
772 if (!new_screen) {
773 log_error(sdlvideo_log, "SDL_SetVideoMode failed!");
774 return NULL;
775 }
776 sdl_bitdepth = new_screen->format->BitsPerPixel;
777
778 canvas->depth = sdl_bitdepth;
779 canvas->width = new_width;
780 canvas->height = new_height;
781 canvas->screen = new_screen;
782 canvas->actual_width = actual_width;
783 canvas->actual_height = actual_height;
784
785 if (canvas == sdl_active_canvas) {
786 if (!fullscreen) {
787 resources_set_int("SDLWindowWidth", actual_width);
788 resources_set_int("SDLWindowHeight", actual_height);
789 }
790 }
791
792 log_message(sdlvideo_log, "%s (%s) %ux%u %ibpp %s%s",
793 canvas->videoconfig->chip_name,
794 (canvas == sdl_active_canvas) ? "active" : "inactive",
795 actual_width,
796 actual_height,
797 sdl_bitdepth,
798 hwscale ? "OpenGL " : "",
799 (canvas->fullscreenconfig->enable) ? "(fullscreen)" : "");
800 #ifdef SDL_DEBUG
801 log_message(sdlvideo_log, "Canvas %ix%i, real %ix%i", new_width, new_height, canvas->real_width, canvas->real_height);
802 #endif
803
804 /* Update lightpen adjustment parameters */
805 if (canvas == sdl_active_canvas && !lightpen_updated) {
806 sdl_lightpen_adjust.max_x = actual_width;
807 sdl_lightpen_adjust.max_y = actual_height;
808
809 sdl_lightpen_adjust.scale_x = (double)*width / (double)actual_width;
810 sdl_lightpen_adjust.scale_y = (double)*height / (double)actual_height;
811 }
812
813 video_canvas_set_palette(canvas, canvas->palette);
814
815 return canvas;
816 }
817
818 /* ------------------------------------------------------------------------- */
819 /* Main API */
820
821 /* called from raster/raster.c:realize_canvas */
video_canvas_create(video_canvas_t * canvas,unsigned int * width,unsigned int * height,int mapped)822 video_canvas_t *video_canvas_create(video_canvas_t *canvas, unsigned int *width, unsigned int *height, int mapped)
823 {
824 /* nothing to do here, the real work is done in sdl_ui_init_finalize */
825 return canvas;
826 }
827
video_canvas_refresh(struct video_canvas_s * canvas,unsigned int xs,unsigned int ys,unsigned int xi,unsigned int yi,unsigned int w,unsigned int h)828 void video_canvas_refresh(struct video_canvas_s *canvas, unsigned int xs, unsigned int ys, unsigned int xi, unsigned int yi, unsigned int w, unsigned int h)
829 {
830 uint8_t *backup;
831
832 if ((canvas == NULL) || (canvas->screen == NULL) || (canvas != sdl_active_canvas)) {
833 return;
834 }
835
836 if (sdl_vsid_state & SDL_VSID_ACTIVE) {
837 sdl_vsid_draw();
838 }
839
840 if (sdl_vkbd_state & SDL_VKBD_ACTIVE) {
841 sdl_vkbd_draw();
842 }
843
844 if (uistatusbar_state & UISTATUSBAR_ACTIVE) {
845 uistatusbar_draw();
846 }
847
848 xi *= canvas->videoconfig->scalex;
849 w *= canvas->videoconfig->scalex;
850
851 yi *= canvas->videoconfig->scaley;
852 h *= canvas->videoconfig->scaley;
853
854 w = MIN(w, canvas->width);
855 h = MIN(h, canvas->height);
856
857 /* FIXME attempt to draw outside canvas */
858 if ((xi + w > canvas->width) || (yi + h > canvas->height)) {
859 return;
860 }
861
862 if (SDL_MUSTLOCK(canvas->screen)) {
863 canvas->videoconfig->readable = 0;
864 if (SDL_LockSurface(canvas->screen) < 0) {
865 return;
866 }
867 } else { /* no direct rendering, safe to read */
868 canvas->videoconfig->readable = !(canvas->screen->flags & SDL_HWSURFACE);
869 }
870
871 if (machine_class == VICE_MACHINE_VSID) {
872 canvas->draw_buffer_vsid->draw_buffer_width = canvas->draw_buffer->draw_buffer_width;
873 canvas->draw_buffer_vsid->draw_buffer_height = canvas->draw_buffer->draw_buffer_height;
874 canvas->draw_buffer_vsid->draw_buffer_pitch = canvas->draw_buffer->draw_buffer_pitch;
875 canvas->draw_buffer_vsid->canvas_physical_width = canvas->draw_buffer->canvas_physical_width;
876 canvas->draw_buffer_vsid->canvas_physical_height = canvas->draw_buffer->canvas_physical_height;
877 canvas->draw_buffer_vsid->canvas_width = canvas->draw_buffer->canvas_width;
878 canvas->draw_buffer_vsid->canvas_height = canvas->draw_buffer->canvas_height;
879 canvas->draw_buffer_vsid->visible_width = canvas->draw_buffer->visible_width;
880 canvas->draw_buffer_vsid->visible_height = canvas->draw_buffer->visible_height;
881
882 backup = canvas->draw_buffer->draw_buffer;
883 canvas->draw_buffer->draw_buffer = canvas->draw_buffer_vsid->draw_buffer;
884 video_canvas_render(canvas, (uint8_t *)canvas->screen->pixels, w, h, xs, ys, xi, yi, canvas->screen->pitch, canvas->screen->format->BitsPerPixel);
885 canvas->draw_buffer->draw_buffer = backup;
886 } else {
887 video_canvas_render(canvas, (uint8_t *)canvas->screen->pixels, w, h, xs, ys, xi, yi, canvas->screen->pitch, canvas->screen->format->BitsPerPixel);
888 }
889
890 if (SDL_MUSTLOCK(canvas->screen)) {
891 SDL_UnlockSurface(canvas->screen);
892 }
893
894 #if defined(HAVE_HWSCALE)
895 if (canvas->videoconfig->hwscale) {
896 const float *v = &(sdl_gl_vertex_coord[sdl_gl_vertex_base]);
897
898 if (canvas != sdl_active_canvas) {
899 DBG(("%s: not active SDL canvas, ignoring", __func__));
900 return;
901 }
902
903 if (!(canvas->hwscale_screen)) {
904 DBG(("%s: hwscale refresh without hwscale screen, ignoring", __func__));
905 return;
906 }
907
908 /* XXX make use of glXBindTexImageEXT aka texture from pixmap extension */
909
910 glClear(GL_COLOR_BUFFER_BIT);
911 glDisable(GL_DEPTH_TEST);
912
913 /* GL_TEXTURE_RECTANGLE is standardised as _EXT in OpenGL 1.4. Here's some
914 * aliases in the meantime. */
915 #ifndef GL_TEXTURE_RECTANGLE_EXT
916 #if defined(GL_TEXTURE_RECTANGLE_NV)
917 #define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_NV
918 #elif defined(GL_TEXTURE_RECTANGLE_ARB)
919 #define GL_TEXTURE_RECTANGLE_EXT GL_TEXTURE_RECTANGLE_ARB
920 #else
921 #error "Your headers do not supply GL_TEXTURE_RECTANGLE. Disable HWSCALE and try again."
922 #endif
923 #endif
924
925 glEnable(GL_TEXTURE_RECTANGLE_EXT);
926 glBindTexture(GL_TEXTURE_RECTANGLE_EXT, screen_texture);
927 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, sdl_gl_filter);
928 glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, sdl_gl_filter);
929 glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, sdl_gl_mode, canvas->width, canvas->height, 0, sdl_gl_mode, GL_UNSIGNED_BYTE, canvas->screen->pixels);
930
931 glBegin(GL_QUADS);
932
933 /* Lower Right Of Texture */
934 glTexCoord2f(0.0f, 0.0f);
935 glVertex2f(v[0], v[1]);
936
937 /* Upper Right Of Texture */
938 glTexCoord2f(0.0f, (float)(canvas->height));
939 glVertex2f(v[0], v[2]);
940
941 /* Upper Left Of Texture */
942 glTexCoord2f((float)(canvas->width), (float)(canvas->height));
943 glVertex2f(v[3], v[2]);
944
945 /* Lower Left Of Texture */
946 glTexCoord2f((float)(canvas->width), 0.0f);
947 glVertex2f(v[3], v[1]);
948
949 glEnd();
950
951 SDL_GL_SwapBuffers();
952 } else
953 #endif
954
955 SDL_UpdateRect(canvas->screen, xi, yi, w, h);
956 ui_autohide_mouse_cursor();
957 }
958
video_canvas_set_palette(struct video_canvas_s * canvas,struct palette_s * palette)959 int video_canvas_set_palette(struct video_canvas_s *canvas, struct palette_s *palette)
960 {
961 unsigned int i, col = 0;
962 SDL_PixelFormat *fmt;
963 SDL_Color colors[256];
964
965 DBG(("video_canvas_set_palette canvas: %p", canvas));
966
967 if (palette == NULL) {
968 return 0; /* no palette, nothing to do */
969 }
970
971 canvas->palette = palette;
972
973 fmt = canvas->screen->format;
974
975 /* Fixme: needs further investigation how it can reach here without being fully initialized */
976 if (canvas != sdl_active_canvas || canvas->width != canvas->screen->w) {
977 DBG(("video_canvas_set_palette not active canvas or window not created, don't update hw palette"));
978 return 0;
979 }
980
981 for (i = 0; i < palette->num_entries; i++) {
982 if (canvas->depth == 8) {
983 colors[i].r = palette->entries[i].red;
984 colors[i].b = palette->entries[i].blue;
985 colors[i].g = palette->entries[i].green;
986 col = i;
987 } else {
988 col = SDL_MapRGB(fmt, palette->entries[i].red, palette->entries[i].green, palette->entries[i].blue);
989 }
990 video_render_setphysicalcolor(canvas->videoconfig, i, col, canvas->depth);
991 }
992
993 if (canvas->depth == 8) {
994 SDL_SetColors(canvas->screen, colors, 0, palette->num_entries);
995 } else {
996 for (i = 0; i < 256; i++) {
997 video_render_setrawrgb(i, SDL_MapRGB(fmt, (Uint8)i, 0, 0), SDL_MapRGB(fmt, 0, (Uint8)i, 0), SDL_MapRGB(fmt, 0, 0, (Uint8)i));
998 }
999 video_render_initraw(canvas->videoconfig);
1000 }
1001
1002 return 0;
1003 }
1004
1005 /* called from video_viewport_resize */
video_canvas_resize(struct video_canvas_s * canvas,char resize_canvas)1006 void video_canvas_resize(struct video_canvas_s *canvas, char resize_canvas)
1007 {
1008 unsigned int width = canvas->draw_buffer->canvas_width;
1009 unsigned int height = canvas->draw_buffer->canvas_height;
1010 DBG(("%s: %ix%i (%i)", __func__, width, height, canvas->index));
1011 /* Check if canvas needs to be resized to real size first */
1012 if (sdl_ui_finalized) {
1013 /* NOTE: setting the resources to zero like this here would actually
1014 not only force a recalculation of the resources, but also
1015 result in the window size being recalculated from the default
1016 dimensions instead of the (saved and supposed to be persistant)
1017 values in the resources. what goes wrong when this is done can
1018 be observed when x128 starts up.
1019 FIXME: remove this note and code below after some testing. hopefully
1020 nothing else relies on the broken behavior...
1021 */
1022 #if 0
1023 sdl_window_width = 0; /* force recalculate */
1024 sdl_window_height = 0;
1025 #endif
1026 sdl_canvas_create(canvas, &width, &height); /* set the real canvas size */
1027
1028 if (resize_canvas) {
1029 DBG(("%s: set and resize to real size (%ix%i)", __func__, width, height));
1030 canvas->real_width = canvas->actual_width;
1031 canvas->real_height = canvas->actual_height;
1032 }
1033 /* Recreating the video like this sometimes makes us lose the
1034 fact that keys were released or pressed. Reset the keyboard
1035 state. */
1036 keyboard_key_clear();
1037 }
1038 }
1039
1040 /* Resize window to w/h. */
sdl_video_resize(unsigned int w,unsigned int h)1041 static void sdl_video_resize(unsigned int w, unsigned int h)
1042 {
1043 DBG(("%s: %ix%i", __func__, w, h));
1044
1045 if ((w == 0) || (h == 0)) {
1046 DBG(("%s: ERROR, ignored!", __func__));
1047 return;
1048 }
1049
1050 vsync_suspend_speed_eval();
1051
1052 #if defined(HAVE_HWSCALE)
1053 if (sdl_active_canvas->videoconfig->hwscale && sdl_active_canvas->hwscale_screen) {
1054 int flags;
1055
1056 if (sdl_active_canvas->fullscreenconfig->enable) {
1057 flags = SDL_OPENGL | SDL_SWSURFACE | SDL_FULLSCREEN;
1058 } else {
1059 flags = SDL_OPENGL | SDL_SWSURFACE | SDL_RESIZABLE;
1060 }
1061
1062 #ifndef ANDROID_COMPILE
1063 SDL_EventState(SDL_VIDEORESIZE, SDL_IGNORE);
1064 #endif
1065 sdl_active_canvas->hwscale_screen = SDL_SetVideoMode((int)w, (int)h, sdl_bitdepth, flags);
1066 #ifndef ANDROID_COMPILE
1067 SDL_EventState(SDL_VIDEORESIZE, SDL_ENABLE);
1068 #endif
1069
1070 #ifdef SDL_DEBUG
1071 if (!sdl_active_canvas->hwscale_screen) {
1072 DBG(("%s: setting video mode failed", __func__));
1073 }
1074 #endif
1075 sdl_gl_set_viewport(sdl_active_canvas->width, sdl_active_canvas->height, w, h);
1076 sdl_active_canvas->actual_width = w;
1077 sdl_active_canvas->actual_height = h;
1078 } else
1079 #endif /* HAVE_HWSCALE */
1080 {
1081 sdl_active_canvas->draw_buffer->canvas_physical_width = w;
1082 sdl_active_canvas->draw_buffer->canvas_physical_height = h;
1083 video_viewport_resize(sdl_active_canvas, 0);
1084 }
1085 }
1086
1087 /* Resize window to stored real size */
sdl_video_restore_size(void)1088 void sdl_video_restore_size(void)
1089 {
1090 unsigned int w, h;
1091
1092 w = sdl_active_canvas->real_width;
1093 h = sdl_active_canvas->real_height;
1094
1095 DBG(("%s: %ix%i->%ix%i", __func__, sdl_active_canvas->real_width, sdl_active_canvas->real_height, w, h));
1096 sdl_video_resize(w, h);
1097 }
1098
1099 /* special case handling for the SDL window resize event */
sdl_video_resize_event(unsigned int w,unsigned int h)1100 void sdl_video_resize_event(unsigned int w, unsigned int h)
1101 {
1102 #if defined(HAVE_HWSCALE)
1103
1104 DBG(("%s: %ix%i", __func__, w, h));
1105 if ((w == 0) || (h == 0)) {
1106 DBG(("%s: ERROR, ignored!", __func__));
1107 return;
1108 }
1109 sdl_video_resize(w, h);
1110 if (!sdl_active_canvas->fullscreenconfig->enable) {
1111 resources_set_int("SDLWindowWidth", sdl_active_canvas->actual_width);
1112 resources_set_int("SDLWindowHeight", sdl_active_canvas->actual_height);
1113 }
1114
1115 #endif /* HAVE_HWSCALE */
1116 }
1117
sdl_video_canvas_switch(int index)1118 void sdl_video_canvas_switch(int index)
1119 {
1120 struct video_canvas_s *canvas;
1121
1122 DBG(("%s: %i->%i", __func__, sdl_active_canvas_num, index));
1123
1124 if (sdl_active_canvas_num == index) {
1125 return;
1126 }
1127
1128 if (index >= sdl_num_screens) {
1129 return;
1130 }
1131
1132 if (sdl_canvaslist[index]->screen != NULL) {
1133 SDL_FreeSurface(sdl_canvaslist[index]->screen);
1134 sdl_canvaslist[index]->screen = NULL;
1135 }
1136
1137 sdl_active_canvas_num = index;
1138
1139 canvas = sdl_canvaslist[sdl_active_canvas_num];
1140 sdl_active_canvas = canvas;
1141
1142 video_viewport_resize(canvas, 1);
1143 }
1144
video_arch_canvas_init(struct video_canvas_s * canvas)1145 void video_arch_canvas_init(struct video_canvas_s *canvas)
1146 {
1147 DBG(("%s: (%p, %i)", __func__, canvas, sdl_num_screens));
1148
1149 if (sdl_num_screens == MAX_CANVAS_NUM) {
1150 log_error(sdlvideo_log, "Too many canvases!");
1151 archdep_vice_exit(-1);
1152 }
1153
1154 canvas->video_draw_buffer_callback = NULL;
1155
1156 canvas->fullscreenconfig = lib_calloc(1, sizeof(fullscreenconfig_t));
1157
1158 if (sdl_active_canvas_num == sdl_num_screens) {
1159 sdl_active_canvas = canvas;
1160 }
1161
1162 canvas->index = sdl_num_screens;
1163
1164 sdl_canvaslist[sdl_num_screens++] = canvas;
1165
1166 canvas->screen = NULL;
1167 #if defined(HAVE_HWSCALE)
1168 canvas->hwscale_screen = NULL;
1169 #endif
1170 canvas->real_width = 0;
1171 canvas->real_height = 0;
1172 }
1173
video_canvas_destroy(struct video_canvas_s * canvas)1174 void video_canvas_destroy(struct video_canvas_s *canvas)
1175 {
1176 int i;
1177
1178 DBG(("%s: (%p, %i)", __func__, canvas, canvas->index));
1179
1180 for (i = 0; i < sdl_num_screens; ++i) {
1181 if ((sdl_canvaslist[i] == canvas) && (canvas == sdl_active_canvas)) {
1182 SDL_FreeSurface(sdl_canvaslist[i]->screen);
1183 sdl_canvaslist[i]->screen = NULL;
1184 }
1185 }
1186
1187 lib_free(canvas->fullscreenconfig);
1188 }
1189
video_canvas_can_resize(video_canvas_t * canvas)1190 char video_canvas_can_resize(video_canvas_t *canvas)
1191 {
1192 return 1;
1193 }
1194
sdl_ui_init_finalize(void)1195 void sdl_ui_init_finalize(void)
1196 {
1197 unsigned int width = sdl_active_canvas->draw_buffer->canvas_width;
1198 unsigned int height = sdl_active_canvas->draw_buffer->canvas_height;
1199 int minimized = 0;
1200
1201 /* unfortunately we cant create the window minimized in SDL1 */
1202 resources_get_int("StartMinimized", &minimized);
1203
1204 sdl_canvas_create(sdl_active_canvas, &width, &height); /* set the real canvas size */
1205 /* minimize window after it was created */
1206 if (minimized) {
1207 SDL_WM_IconifyWindow();
1208 }
1209
1210 sdl_ui_finalized = 1;
1211
1212 mousedrv_mouse_changed();
1213 }
1214
sdl_ui_get_mouse_state(int * px,int * py,unsigned int * pbuttons)1215 int sdl_ui_get_mouse_state(int *px, int *py, unsigned int *pbuttons)
1216 {
1217 int local_x, local_y, local_buttons;
1218 if (!(SDL_GetAppState() & SDL_APPMOUSEFOCUS)) {
1219 /* We don't have mouse focus */
1220 return 0;
1221 }
1222
1223 local_buttons = SDL_GetMouseState(&local_x, &local_y);
1224
1225 #ifdef SDL_DEBUG
1226 fprintf(stderr, "%s pre : x = %i, y = %i, buttons = %02x, on_screen = %i\n", __func__, x, y, buttons, on_screen);
1227 #endif
1228
1229 local_x -= sdl_lightpen_adjust.offset_x;
1230 local_y -= sdl_lightpen_adjust.offset_y;
1231
1232 if ((local_x < 0) || (local_y < 0) || (local_x >= sdl_lightpen_adjust.max_x) || (local_y >= sdl_lightpen_adjust.max_y)) {
1233 return 0;
1234 } else {
1235 local_x = (int)(local_x * sdl_lightpen_adjust.scale_x);
1236 local_y = (int)(local_y * sdl_lightpen_adjust.scale_y);
1237 }
1238
1239 #ifdef SDL_DEBUG
1240 fprintf(stderr, "%s post: x = %i, y = %i\n", __func__, x, y);
1241 #endif
1242 if (px) {
1243 *px = local_x;
1244 }
1245 if (py) {
1246 *py = local_y;
1247 }
1248 if (pbuttons) {
1249 *pbuttons = local_buttons;
1250 }
1251 return 1;
1252 }
1253
sdl_ui_consume_mouse_event(SDL_Event * event)1254 void sdl_ui_consume_mouse_event(SDL_Event *event)
1255 {
1256 /* This is a no-op on SDL1 */
1257 ui_autohide_mouse_cursor();
1258 }
1259
sdl_ui_set_window_title(char * title)1260 void sdl_ui_set_window_title(char *title)
1261 {
1262 char *dummy = NULL;
1263 char *icon = NULL;
1264
1265 if (sdl_ui_finalized) {
1266 SDL_WM_GetCaption(&dummy, &icon);
1267 SDL_WM_SetCaption(title, icon);
1268 }
1269 }
1270