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