Subversion Repositories eduke32

Rev

Rev 8613 | Rev 8707 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6828 terminx 1
// SDL interface layer for the Build Engine
4074 hendricks2 2
// Use SDL 1.2 or 2.0 from http://www.libsdl.org
5 Plagman 3
 
1485 helixhorne 4
#include <signal.h>
7186 terminx 5
 
5 Plagman 6
#include "a.h"
7
#include "build.h"
7186 terminx 8
#include "cache1d.h"
9
#include "compat.h"
8174 terminx 10
#include "build_cpuid.h"
7186 terminx 11
#include "engine_priv.h"
5 Plagman 12
#include "osd.h"
5789 terminx 13
#include "palette.h"
7186 terminx 14
#include "renderlayer.h"
15
#include "sdl_inc.h"
16
#include "softsurface.h"
5 Plagman 17
 
18
#ifdef USE_OPENGL
6656 pogokeen 19
# include "glad/glad.h"
5 Plagman 20
# include "glbuild.h"
6919 pogokeen 21
# include "glsurface.h"
5 Plagman 22
#endif
23
 
4548 hendricks2 24
#if defined HAVE_GTK2
5 Plagman 25
# include "gtkbits.h"
4548 hendricks2 26
#endif
7186 terminx 27
 
4749 terminx 28
#ifdef __ANDROID__
4852 hendricks2 29
# include <android/log.h>
7186 terminx 30
#elif defined __APPLE__
31
# include "osxbits.h"
32
# include <mach/mach.h>
33
# include <mach/mach_time.h>
34
#elif defined GEKKO
4820 hendricks2 35
# include "wiibits.h"
36
# include <ogc/lwp.h>
37
# include <ogc/lwp_watchdog.h>
7186 terminx 38
#elif defined _WIN32
39
# include "winbits.h"
4819 hendricks2 40
#endif
1935 helixhorne 41
 
7359 hendricks2 42
#include "vfs.h"
8094 hendricks2 43
#include "communityapi.h"
7359 hendricks2 44
 
5955 hendricks2 45
#if SDL_MAJOR_VERSION != 1
5903 hendricks2 46
static SDL_version linked;
8264 ny00123 47
#else
48
#define SDL_JoystickNameForIndex(x) SDL_JoystickName(x)
5955 hendricks2 49
#endif
5903 hendricks2 50
 
4648 hendricks2 51
#if !defined STARTUP_SETUP_WINDOW
1205 terminx 52
int32_t startwin_open(void) { return 0; }
53
int32_t startwin_close(void) { return 0; }
2158 helixhorne 54
int32_t startwin_puts(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
55
int32_t startwin_idle(void *s) { UNREFERENCED_PARAMETER(s); return 0; }
56
int32_t startwin_settitle(const char *s) { UNREFERENCED_PARAMETER(s); return 0; }
4766 hendricks2 57
int32_t startwin_run(void) { return 0; }
5 Plagman 58
#endif
59
 
1644 helixhorne 60
/// These can be useful for debugging sometimes...
61
//#define SDL_WM_GrabInput(x) SDL_WM_GrabInput(SDL_GRAB_OFF)
62
//#define SDL_ShowCursor(x) SDL_ShowCursor(SDL_ENABLE)
63
 
5 Plagman 64
#define SURFACE_FLAGS   (SDL_SWSURFACE|SDL_HWPALETTE|SDL_HWACCEL)
65
 
66
// undefine to restrict windowed resolutions to conventional sizes
67
#define ANY_WINDOWED_SIZE
68
 
258 terminx 69
// fix for mousewheel
4200 hendricks2 70
int32_t inputchecked = 0;
258 terminx 71
 
1762 terminx 72
char quitevent=0, appactive=1, novideo=0;
5 Plagman 73
 
74
// video
4089 hendricks2 75
static SDL_Surface *sdl_surface/*=NULL*/;
4432 terminx 76
 
2777 helixhorne 77
#if SDL_MAJOR_VERSION==2
4089 hendricks2 78
static SDL_Window *sdl_window=NULL;
79
static SDL_GLContext sdl_context=NULL;
2777 helixhorne 80
#endif
4432 terminx 81
 
8612 terminx 82
int32_t xres=-1, yres=-1, bpp=0, fullscreen=0, bytesperline;
83
double refreshfreq = 59.0;
618 terminx 84
intptr_t frameplace=0;
1205 terminx 85
int32_t lockcount=0;
5 Plagman 86
char modechange=1;
87
char offscreenrendering=0;
88
char videomodereset = 0;
4904 terminx 89
int32_t nofog=0;
5678 hendricks2 90
#ifndef EDUKE32_GLES
1205 terminx 91
static uint16_t sysgamma[3][256];
5678 hendricks2 92
#endif
5 Plagman 93
#ifdef USE_OPENGL
94
// OpenGL stuff
1036 terminx 95
char nogl=0;
5 Plagman 96
#endif
5956 hendricks2 97
static int32_t vsync_renderlayer;
5621 terminx 98
int32_t maxrefreshfreq=0;
2222 helixhorne 99
// last gamma, contrast, brightness
100
static float lastvidgcb[3];
101
 
2119 helixhorne 102
//#define KEY_PRINT_DEBUG
103
 
6056 hendricks2 104
#include "sdlkeytrans.cpp"
5 Plagman 105
 
1762 terminx 106
static SDL_Surface *appicon = NULL;
4852 hendricks2 107
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
1762 terminx 108
static SDL_Surface *loadappicon(void);
4644 hendricks2 109
#endif
5 Plagman 110
 
1658 terminx 111
static mutex_t m_initprintf;
112
 
1716 plagman 113
// Joystick dead and saturation zones
7968 hendricks2 114
uint16_t joydead[9], joysatur[9];
1716 plagman 115
 
3219 hendricks2 116
#ifdef _WIN32
4774 hendricks2 117
# if SDL_MAJOR_VERSION != 1
3219 hendricks2 118
//
4084 hendricks2 119
// win_gethwnd() -- gets the window handle
120
//
121
HWND win_gethwnd(void)
122
{
123
    struct SDL_SysWMinfo wmInfo;
124
    SDL_VERSION(&wmInfo.version);
125
 
126
    if (SDL_GetWindowWMInfo(sdl_window, &wmInfo) != SDL_TRUE)
127
        return 0;
128
 
129
    if (wmInfo.subsystem == SDL_SYSWM_WINDOWS)
130
        return wmInfo.info.win.window;
131
 
132
    initprintf("win_gethwnd: Unknown WM subsystem?!\n");
133
 
134
    return 0;
135
}
4774 hendricks2 136
# endif
4084 hendricks2 137
//
3219 hendricks2 138
// win_gethinstance() -- gets the application instance
139
//
3278 hendricks2 140
HINSTANCE win_gethinstance(void)
3219 hendricks2 141
{
3278 hendricks2 142
    return (HINSTANCE)GetModuleHandle(NULL);
3219 hendricks2 143
}
144
#endif
145
 
4469 hendricks2 146
 
4558 hendricks2 147
int32_t wm_msgbox(const char *name, const char *fmt, ...)
5 Plagman 148
{
298 terminx 149
    char buf[2048];
109 terminx 150
    va_list va;
5 Plagman 151
 
659 plagman 152
    UNREFERENCED_PARAMETER(name);
153
 
109 terminx 154
    va_start(va,fmt);
4120 helixhorne 155
    vsnprintf(buf,sizeof(buf),fmt,va);
109 terminx 156
    va_end(va);
5 Plagman 157
 
4942 hendricks2 158
#if defined EDUKE32_OSX
109 terminx 159
    return osx_msgbox(name, buf);
4254 hendricks2 160
#elif defined _WIN32
161
    MessageBox(win_gethwnd(),buf,name,MB_OK|MB_TASKMODAL);
162
    return 0;
4852 hendricks2 163
#elif defined EDUKE32_TOUCH_DEVICES
4440 terminx 164
    initprintf("wm_msgbox called. Message: %s: %s",name,buf);
165
    return 0;
4825 hendricks2 166
#elif defined GEKKO
167
    puts(buf);
168
    return 0;
5961 hendricks2 169
#else
5976 hendricks2 170
# if defined HAVE_GTK2
171
    if (gtkbuild_msgbox(name, buf) >= 0)
172
        return 0;
173
# endif
174
# if SDL_MAJOR_VERSION > 1
175
#  if !defined _WIN32
176
    // Replace all tab chars with spaces because the hand-rolled SDL message
177
    // box diplays the former as N/L instead of whitespace.
178
    for (size_t i=0; i<sizeof(buf); i++)
179
        if (buf[i] == '\t')
180
            buf[i] = ' ';
181
#  endif
182
    return SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, name, buf, NULL);
183
# else
109 terminx 184
    puts(buf);
185
    puts("   (press Return or Enter to continue)");
186
    getchar();
5 Plagman 187
 
109 terminx 188
    return 0;
5976 hendricks2 189
# endif
5961 hendricks2 190
#endif
5 Plagman 191
}
192
 
4558 hendricks2 193
int32_t wm_ynbox(const char *name, const char *fmt, ...)
5 Plagman 194
{
298 terminx 195
    char buf[2048];
109 terminx 196
    va_list va;
5 Plagman 197
 
659 plagman 198
    UNREFERENCED_PARAMETER(name);
199
 
109 terminx 200
    va_start(va,fmt);
5976 hendricks2 201
    vsnprintf(buf,sizeof(buf),fmt,va);
109 terminx 202
    va_end(va);
5 Plagman 203
 
4942 hendricks2 204
#if defined EDUKE32_OSX
109 terminx 205
    return osx_ynbox(name, buf);
4254 hendricks2 206
#elif defined _WIN32
4476 helixhorne 207
    return (MessageBox(win_gethwnd(),buf,name,MB_YESNO|MB_ICONQUESTION|MB_TASKMODAL) == IDYES);
4852 hendricks2 208
#elif defined EDUKE32_TOUCH_DEVICES
4440 terminx 209
    initprintf("wm_ynbox called, this is bad! Message: %s: %s",name,buf);
210
    initprintf("Returning false..");
211
    return 0;
5976 hendricks2 212
#elif defined GEKKO
213
    puts(buf);
214
    puts("Assuming yes...");
215
    return 1;
4749 terminx 216
#else
5976 hendricks2 217
# if defined HAVE_GTK2
218
    int ret = gtkbuild_ynbox(name, buf);
219
    if (ret >= 0)
220
        return ret;
221
# endif
222
# if SDL_MAJOR_VERSION > 1
223
    int r = -1;
4476 helixhorne 224
 
5976 hendricks2 225
    const SDL_MessageBoxButtonData buttons[] = {
226
        {
227
            SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
228
            0,
229
            "No"
230
        },{
231
            SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
232
            1,
233
            "Yes"
234
        },
235
    };
4469 hendricks2 236
 
5976 hendricks2 237
    SDL_MessageBoxData data = {
238
        SDL_MESSAGEBOX_INFORMATION,
239
        NULL, /* no parent window */
240
        name,
241
        buf,
242
        2,
243
        buttons,
244
        NULL /* Default color scheme */
245
    };
4469 hendricks2 246
 
5976 hendricks2 247
    SDL_ShowMessageBox(&data, &r);
4469 hendricks2 248
 
5976 hendricks2 249
    return r;
250
# else
251
    char c;
252
 
253
    puts(buf);
254
    puts("   (type 'Y' or 'N', and press Return or Enter to continue)");
255
    do c = getchar(); while (c != 'Y' && c != 'y' && c != 'N' && c != 'n');
256
    return c == 'Y' || c == 'y';
257
# endif
5 Plagman 258
#endif
259
}
260
 
4558 hendricks2 261
void wm_setapptitle(const char *name)
5 Plagman 262
{
4852 hendricks2 263
#ifndef EDUKE32_TOUCH_DEVICES
4749 terminx 264
    if (name != apptitle)
265
        Bstrncpyz(apptitle, name, sizeof(apptitle));
266
 
267
#if !defined(__APPLE__)
4774 hendricks2 268
    if (!appicon)
269
        appicon = loadappicon();
4440 terminx 270
#endif
271
 
2777 helixhorne 272
#if SDL_MAJOR_VERSION == 1
109 terminx 273
    SDL_WM_SetCaption(apptitle, NULL);
4749 terminx 274
 
4774 hendricks2 275
    if (appicon && sdl_surface)
4749 terminx 276
        SDL_WM_SetIcon(appicon, 0);
2777 helixhorne 277
#else
5904 hendricks2 278
    if (sdl_window)
279
    {
280
        SDL_SetWindowTitle(sdl_window, apptitle);
4749 terminx 281
 
5904 hendricks2 282
        if (appicon)
283
        {
284
#if defined _WIN32
285
        if (!EDUKE32_SDL_LINKED_PREREQ(linked, 2, 0, 5))
2777 helixhorne 286
#endif
5904 hendricks2 287
            SDL_SetWindowIcon(sdl_window, appicon);
288
        }
289
    }
290
#endif
5 Plagman 291
 
194 terminx 292
    startwin_settitle(apptitle);
4852 hendricks2 293
#else
294
    UNREFERENCED_PARAMETER(name);
4749 terminx 295
#endif
5 Plagman 296
}
297
 
298
//
299
//
300
// ---------------------------------------
301
//
302
// System
303
//
304
// ---------------------------------------
305
//
306
//
307
 
4749 terminx 308
/* XXX: libexecinfo could be used on systems without gnu libc. */
4852 hendricks2 309
#if !defined _WIN32 && defined __GNUC__ && !defined __OpenBSD__ && !(defined __APPLE__ && defined __BIG_ENDIAN__) && !defined GEKKO && !defined EDUKE32_TOUCH_DEVICES && !defined __OPENDINGUX__
4749 terminx 310
# define PRINTSTACKONSEGV 1
311
# include <execinfo.h>
4557 hendricks2 312
#endif
313
 
4749 terminx 314
static inline char grabmouse_low(char a);
315
 
5679 hendricks2 316
#ifndef __ANDROID__
8160 terminx 317
static void attach_debugger_here(void)
318
{
319
#ifdef DEBUGGINGAIDS
320
    debug_break();
321
#endif
322
}
5679 hendricks2 323
 
4749 terminx 324
static void sighandler(int signum)
325
{
326
    UNREFERENCED_PARAMETER(signum);
327
    //    if (signum==SIGSEGV)
328
    {
329
        grabmouse_low(0);
330
#if PRINTSTACKONSEGV
331
        {
332
            void *addr[32];
333
            int32_t errfd = fileno(stderr);
334
            int32_t n=backtrace(addr, ARRAY_SIZE(addr));
335
            backtrace_symbols_fd(addr, n, errfd);
336
        }
337
        // This is useful for attaching the debugger post-mortem. For those pesky
338
        // cases where the program runs through happily when inspected from the start.
339
        //        usleep(15000000);
340
#endif
341
        attach_debugger_here();
342
        app_crashhandler();
8190 terminx 343
        Bexit(EXIT_FAILURE);
4749 terminx 344
    }
345
}
5679 hendricks2 346
#endif
4749 terminx 347
 
4992 terminx 348
#ifdef __ANDROID__
349
int mobile_halted = 0;
350
#ifdef __cplusplus
351
extern "C"
352
{
353
#endif
354
void G_Shutdown(void);
355
#ifdef __cplusplus
356
}
357
#endif
358
 
359
int sdlayer_mobilefilter(void *userdata, SDL_Event *event)
360
{
361
    switch (event->type)
362
    {
363
        case SDL_APP_TERMINATING:
364
            // yes, this calls into the game, ugh
5000 terminx 365
            if (mobile_halted == 1)
366
                G_Shutdown();
367
 
368
            mobile_halted = 1;
4992 terminx 369
            return 0;
370
        case SDL_APP_LOWMEMORY:
371
            gltexinvalidatetype(INVALIDATE_ALL);
372
            return 0;
373
        case SDL_APP_WILLENTERBACKGROUND:
374
            mobile_halted = 1;
375
            return 0;
376
        case SDL_APP_DIDENTERBACKGROUND:
5663 terminx 377
            gltexinvalidatetype(INVALIDATE_ALL);
4992 terminx 378
            // tear down video?
379
            return 0;
380
        case SDL_APP_WILLENTERFOREGROUND:
381
            // restore video?
382
            return 0;
383
        case SDL_APP_DIDENTERFOREGROUND:
384
            mobile_halted = 0;
385
            return 0;
386
        default:
387
            return 1;//!halt;
388
    }
5679 hendricks2 389
 
390
    UNREFERENCED_PARAMETER(userdata);
4992 terminx 391
}
392
 
5706 hendricks2 393
# include <setjmp.h>
394
static jmp_buf eduke32_exit_jmp_buf;
395
static int eduke32_return_value;
396
 
397
void eduke32_exit_return(int retval)
398
{
399
    eduke32_return_value = retval;
400
    longjmp(eduke32_exit_jmp_buf, 1);
5717 hendricks2 401
    EDUKE32_UNREACHABLE_SECTION(return);
5706 hendricks2 402
}
403
#endif
404
 
8161 terminx 405
void sdlayer_sethints()
406
{
407
#if defined _WIN32
408
    // Thread naming interferes with debugging using MinGW-w64's GDB.
409
#if defined SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING
410
    SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
411
#endif
412
#if defined SDL_HINT_XINPUT_ENABLED
413
    if (!Bgetenv("EDUKE32_NO_XINPUT"))
414
        SDL_SetHint(SDL_HINT_XINPUT_ENABLED, "0");
415
#endif
416
#endif
417
 
418
#if defined SDL_HINT_NO_SIGNAL_HANDLERS
419
    SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
420
#endif
421
#if defined SDL_HINT_VIDEO_HIGHDPI_DISABLED
422
    SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
423
#endif
424
#if defined SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH
425
    SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "0");
426
#endif
8389 terminx 427
#if defined SDL_HINT_AUDIO_RESAMPLING_MODE
428
    SDL_SetHint(SDL_HINT_AUDIO_RESAMPLING_MODE, "3");
429
#endif
8161 terminx 430
}
431
 
4983 terminx 432
#ifdef _WIN32
5980 hendricks2 433
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
5717 hendricks2 434
#elif defined __ANDROID__
435
# ifdef __cplusplus
436
extern "C" int eduke32_android_main(int argc, char const *argv[]);
437
# endif
438
int eduke32_android_main(int argc, char const *argv[])
5981 hendricks2 439
#elif defined GEKKO
440
int SDL_main(int argc, char *argv[])
4983 terminx 441
#else
5980 hendricks2 442
int main(int argc, char *argv[])
4983 terminx 443
#endif
5 Plagman 444
{
5706 hendricks2 445
#ifdef __ANDROID__
446
    if (setjmp(eduke32_exit_jmp_buf))
447
    {
448
        return eduke32_return_value;
449
    }
450
#endif
451
 
8161 terminx 452
    sdlayer_sethints();
5902 hendricks2 453
 
3382 hendricks2 454
#ifdef USE_OPENGL
622 terminx 455
    char *argp;
109 terminx 456
 
8156 terminx 457
    if ((argp = Bgetenv("EDUKE32_NO_OPENGL_FOG")) != NULL)
4749 terminx 458
        nofog = Batol(argp);
6439 terminx 459
 
8318 hendricks2 460
#if defined __linux__ || defined EDUKE32_BSD
461
    if (!Bgetenv("EDUKE32_NO_GL_THREADED_OPTIMIZATIONS"))
462
    {
463
        if (!Bgetenv("EDUKE32_NO_NVIDIA_THREADED_OPTIMIZATIONS"))
464
            setenv("__GL_THREADED_OPTIMIZATIONS", "1", 0);
465
 
466
        if (!Bgetenv("EDUKE32_NO_MESA_THREADED_OPTIMIZATIONS"))
467
            setenv("mesa_glthread", "true", 0);
468
    }
4557 hendricks2 469
#endif
6444 terminx 470
#endif
4557 hendricks2 471
 
109 terminx 472
    buildkeytranslationtable();
473
 
4992 terminx 474
#ifndef __ANDROID__
4749 terminx 475
    signal(SIGSEGV, sighandler);
476
    signal(SIGILL, sighandler);  /* clang -fcatch-undefined-behavior uses an ill. insn */
477
    signal(SIGABRT, sighandler);
478
    signal(SIGFPE, sighandler);
4992 terminx 479
#else
480
    SDL_SetEventFilter(sdlayer_mobilefilter, NULL);
481
#endif
4447 Plagman 482
 
3221 hendricks2 483
#ifdef _WIN32
4983 terminx 484
    UNREFERENCED_PARAMETER(hInst);
485
    UNREFERENCED_PARAMETER(hPrevInst);
486
    UNREFERENCED_PARAMETER(lpCmdLine);
487
    UNREFERENCED_PARAMETER(nCmdShow);
488
 
8174 terminx 489
    if (windowsPreInit())
490
        return -1;
4749 terminx 491
 
492
#elif defined(GEKKO)
4820 hendricks2 493
    wii_open();
4749 terminx 494
#elif defined(HAVE_GTK2)
495
    // Pre-initialize SDL video system in order to make sure XInitThreads() is called
496
    // before GTK starts talking to X11.
8157 terminx 497
    if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO)
6704 hendricks2 498
        SDL_InitSubSystem(SDL_INIT_VIDEO);
8157 terminx 499
 
4749 terminx 500
    gtkbuild_init(&argc, &argv);
3221 hendricks2 501
#endif
502
 
8351 hendricks2 503
#ifdef EDUKE32_OSX
504
    osx_preopen();
505
#endif
194 terminx 506
    startwin_open();
8351 hendricks2 507
#ifdef EDUKE32_OSX
508
    osx_postopen();
509
#endif
3377 helixhorne 510
    maybe_redirect_outputs();
1736 helixhorne 511
 
4983 terminx 512
#ifdef _WIN32
513
    char *argvbuf;
8174 terminx 514
    int buildargc = windowsGetCommandLine(&argvbuf);
7079 terminx 515
    const char **buildargv = (const char **) Xmalloc(sizeof(char *)*(buildargc+1));
4983 terminx 516
    char *wp = argvbuf;
517
 
5829 terminx 518
    for (bssize_t i=0; i<buildargc; i++, wp++)
4983 terminx 519
    {
520
        buildargv[i] = wp;
521
        while (*wp) wp++;
522
    }
523
    buildargv[buildargc] = NULL;
524
 
7359 hendricks2 525
#ifdef USE_PHYSFS
526
    PHYSFS_init(buildargv[0]);
527
    PHYSFS_setWriteDir(PHYSFS_getBaseDir());
528
#endif
8161 terminx 529
    int const r = app_main(buildargc, (const char **)buildargv);
4983 terminx 530
#else
7359 hendricks2 531
#ifdef USE_PHYSFS
532
    int pfsi = PHYSFS_init(argv[0]);
533
    assert(pfsi != 0);
534
    PHYSFS_setWriteDir(PHYSFS_getUserDir());
535
#endif
8161 terminx 536
    int const r = app_main(argc, (char const * const *)argv);
4983 terminx 537
#endif
5 Plagman 538
 
194 terminx 539
    startwin_close();
4749 terminx 540
 
8248 terminx 541
#if defined(HAVE_GTK2)
4749 terminx 542
    gtkbuild_exit(r);
3221 hendricks2 543
#endif
544
 
109 terminx 545
    return r;
5 Plagman 546
}
547
 
5938 terminx 548
 
4769 hendricks2 549
#if SDL_MAJOR_VERSION != 1
8612 terminx 550
static int sdlayer_getswapinterval(int const syncMode)
551
{
552
    static int intervals[] = { -1, 0, 1, 0};
553
    Bassert((unsigned)(syncMode + 1) < ARRAY_SIZE(intervals));
554
    return intervals[syncMode + 1];
555
}
556
 
557
static int sdlayer_checkvsync(int checkSync)
558
{
559
    int const actualSync = SDL_GL_GetSwapInterval();
560
    if (actualSync != sdlayer_getswapinterval(checkSync))
561
    {
562
        OSD_Printf("debug: GL driver forcing SwapInterval %d!\n", actualSync);
563
        checkSync = actualSync;
564
    }
565
    return checkSync;
566
}
567
 
6828 terminx 568
int32_t videoSetVsync(int32_t newSync)
889 terminx 569
{
5953 hendricks2 570
    if (vsync_renderlayer == newSync)
5938 terminx 571
        return newSync;
4102 hendricks2 572
 
5938 terminx 573
#ifdef USE_OPENGL
4090 hendricks2 574
    if (sdl_context)
5938 terminx 575
    {
8612 terminx 576
        int result = SDL_GL_SetSwapInterval(sdlayer_getswapinterval(newSync));
5938 terminx 577
 
578
        if (result == -1)
579
        {
580
            if (newSync == -1)
581
            {
8612 terminx 582
                OSD_Printf("debug: GL driver rejected SwapInterval %d!\n", sdlayer_getswapinterval(newSync));
583
 
5938 terminx 584
                newSync = 1;
8612 terminx 585
                result  = SDL_GL_SetSwapInterval(sdlayer_getswapinterval(newSync));
5938 terminx 586
            }
587
 
588
            if (result == -1)
589
            {
8612 terminx 590
                OSD_Printf("debug: GL driver rejected SwapInterval %d!\n", sdlayer_getswapinterval(newSync));
5938 terminx 591
                newSync = 0;
592
            }
593
        }
594
 
8612 terminx 595
        vsync_renderlayer = sdlayer_checkvsync(newSync);
5938 terminx 596
    }
597
    else
598
#endif
599
    {
5953 hendricks2 600
        vsync_renderlayer = newSync;
5938 terminx 601
 
6828 terminx 602
        videoResetMode();
8612 terminx 603
 
6939 pogokeen 604
        if (videoSetGameMode(fullscreen, xres, yres, bpp, upscalefactor))
5938 terminx 605
            OSD_Printf("restartvid: Reset failed...\n");
606
    }
607
 
5954 hendricks2 608
    return newSync;
889 terminx 609
}
610
#endif
5 Plagman 611
 
4767 hendricks2 612
int32_t sdlayer_checkversion(void);
613
#if SDL_MAJOR_VERSION != 1
4749 terminx 614
int32_t sdlayer_checkversion(void)
615
{
616
    SDL_version compiled;
1485 helixhorne 617
 
4964 helixhorne 618
    SDL_GetVersion(&linked);
4749 terminx 619
    SDL_VERSION(&compiled);
3972 hendricks2 620
 
5536 terminx 621
    if (!Bmemcmp(&compiled, &linked, sizeof(SDL_version)))
622
        initprintf("Initializing SDL %d.%d.%d\n",
623
            compiled.major, compiled.minor, compiled.patch);
624
    else
625
    initprintf("Initializing SDL %d.%d.%d"
5759 hendricks2 626
               " (built against SDL version %d.%d.%d)\n",
5536 terminx 627
               linked.major, linked.minor, linked.patch, compiled.major, compiled.minor, compiled.patch);
1712 helixhorne 628
 
8154 terminx 629
    if (SDL_VERSIONNUM(linked.major, linked.minor, linked.patch) < SDL2_REQUIREDVERSION)
1485 helixhorne 630
    {
4749 terminx 631
        /*reject running under SDL versions older than what is stated in sdl_inc.h */
8154 terminx 632
        initprintf("You need at least v%d.%d.%d of SDL to run this game\n",SDL2_MIN_X,SDL2_MIN_Y,SDL2_MIN_Z);
4749 terminx 633
        return -1;
1485 helixhorne 634
    }
4749 terminx 635
 
636
    return 0;
1485 helixhorne 637
}
638
 
5 Plagman 639
//
640
// initsystem() -- init SDL systems
641
//
1205 terminx 642
int32_t initsystem(void)
5 Plagman 643
{
1658 terminx 644
    mutex_init(&m_initprintf);
645
 
3221 hendricks2 646
#ifdef _WIN32
8174 terminx 647
    windowsPlatformInit();
3221 hendricks2 648
#endif
8174 terminx 649
    sysReadCPUID();
650
 
4749 terminx 651
    if (sdlayer_checkversion())
710 terminx 652
        return -1;
653
 
6704 hendricks2 654
    int32_t err = 0;
655
 
8157 terminx 656
    if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO)
657
        err = SDL_InitSubSystem(SDL_INIT_VIDEO);
658
 
6704 hendricks2 659
    if (err)
342 terminx 660
    {
8157 terminx 661
        initprintf("SDL initialization failed! (%s)\nNon-interactive mode enabled.  This is probably not what you want.\n", SDL_GetError());
1810 plagman 662
        novideo = 1;
663
#ifdef USE_OPENGL
664
        nogl = 1;
665
#endif
109 terminx 666
    }
5 Plagman 667
 
5969 hendricks2 668
#if SDL_MAJOR_VERSION > 1
669
    SDL_StopTextInput();
670
#endif
671
 
109 terminx 672
    atexit(uninitsystem);
5 Plagman 673
 
8171 terminx 674
    timerInit(CLOCKTICKSPERSECOND);
675
 
109 terminx 676
    frameplace = 0;
677
    lockcount = 0;
5 Plagman 678
 
1762 terminx 679
    if (!novideo)
680
    {
4749 terminx 681
#ifdef USE_OPENGL
6656 pogokeen 682
        if (SDL_GL_LoadLibrary(0))
2777 helixhorne 683
        {
6656 pogokeen 684
            initprintf("Failed loading OpenGL Driver.  GL modes will be unavailable. Error: %s\n", SDL_GetError());
4749 terminx 685
            nogl = 1;
2777 helixhorne 686
        }
6656 pogokeen 687
#ifdef POLYMER
688
        if (loadglulibrary(getenv("BUILD_GLULIB")))
689
        {
8153 terminx 690
            initprintf("Failed loading GLU.  GL modes will be unavailable.\n");
6656 pogokeen 691
            nogl = 1;
692
        }
5 Plagman 693
#endif
6656 pogokeen 694
#endif
5 Plagman 695
 
5536 terminx 696
#ifndef _WIN32
697
        const char *drvname = SDL_GetVideoDriver(0);
698
 
2777 helixhorne 699
        if (drvname)
700
            initprintf("Using \"%s\" video driver\n", drvname);
5536 terminx 701
#endif
4749 terminx 702
        wm_setapptitle(apptitle);
2777 helixhorne 703
    }
5 Plagman 704
 
109 terminx 705
    return 0;
5 Plagman 706
}
4767 hendricks2 707
#endif
5 Plagman 708
 
709
 
710
//
711
// uninitsystem() -- uninit SDL systems
712
//
713
void uninitsystem(void)
714
{
109 terminx 715
    uninitinput();
6828 terminx 716
    timerUninit();
5 Plagman 717
 
1544 terminx 718
    if (appicon)
1552 terminx 719
    {
1544 terminx 720
        SDL_FreeSurface(appicon);
1552 terminx 721
        appicon = NULL;
722
    }
1544 terminx 723
 
8248 terminx 724
#ifdef _WIN32
725
    windowsPlatformCleanup();
726
#endif
727
 
109 terminx 728
    SDL_Quit();
5 Plagman 729
 
730
#ifdef USE_OPENGL
6939 pogokeen 731
# if SDL_MAJOR_VERSION!=1
6656 pogokeen 732
    SDL_GL_UnloadLibrary();
6939 pogokeen 733
# endif
734
# ifdef POLYMER
6656 pogokeen 735
    unloadglulibrary();
6939 pogokeen 736
# endif
5 Plagman 737
#endif
738
}
739
 
740
 
741
//
4090 hendricks2 742
// system_getcvars() -- propagate any cvars that are read post-initialization
743
//
744
void system_getcvars(void)
745
{
8613 terminx 746
# ifdef _WIN32
747
    windowsDwmSetupComposition(false);
748
# endif
749
 
6828 terminx 750
    vsync = videoSetVsync(vsync);
4090 hendricks2 751
}
752
 
753
//
8376 terminx 754
// initprintf() -- prints a formatted string to the initialization window
5 Plagman 755
//
756
void initprintf(const char *f, ...)
757
{
109 terminx 758
    va_list va;
1663 helixhorne 759
    char buf[2048];
5 Plagman 760
 
109 terminx 761
    va_start(va, f);
1663 helixhorne 762
    Bvsnprintf(buf, sizeof(buf), f, va);
109 terminx 763
    va_end(va);
5 Plagman 764
 
8376 terminx 765
    osdstrings.append(Xstrdup(buf));
4555 hendricks2 766
    initputs(buf);
767
}
768
 
769
 
770
//
8376 terminx 771
// initputs() -- prints a string to the initialization window
4555 hendricks2 772
//
773
void initputs(const char *buf)
774
{
775
    static char dabuf[2048];
776
 
4440 terminx 777
#ifdef __ANDROID__
778
    __android_log_print(ANDROID_LOG_INFO,"DUKE", "%s",buf);
779
#endif
4555 hendricks2 780
    OSD_Puts(buf);
1762 terminx 781
//    Bprintf("%s", buf);
109 terminx 782
 
7928 hendricks2 783
    mutex_lock(&m_initprintf);
1203 terminx 784
    if (Bstrlen(dabuf) + Bstrlen(buf) > 1022)
785
    {
786
        startwin_puts(dabuf);
787
        Bmemset(dabuf, 0, sizeof(dabuf));
788
    }
789
 
790
    Bstrcat(dabuf,buf);
791
 
6827 terminx 792
    if (g_logFlushWindow || Bstrlen(dabuf) > 768)
1203 terminx 793
    {
794
        startwin_puts(dabuf);
3219 hendricks2 795
#ifndef _WIN32
1203 terminx 796
        startwin_idle(NULL);
4086 hendricks2 797
#else
8607 terminx 798
        if (sdl_window)
799
            handleevents();
3219 hendricks2 800
#endif
1203 terminx 801
        Bmemset(dabuf, 0, sizeof(dabuf));
802
    }
7928 hendricks2 803
    mutex_unlock(&m_initprintf);
5 Plagman 804
}
805
 
806
//
4555 hendricks2 807
// debugprintf() -- prints a formatted debug string to stderr
5 Plagman 808
//
809
void debugprintf(const char *f, ...)
810
{
1935 helixhorne 811
#if defined DEBUGGINGAIDS && !(defined __APPLE__ && defined __BIG_ENDIAN__)
109 terminx 812
    va_list va;
5 Plagman 813
 
109 terminx 814
    va_start(va,f);
815
    Bvfprintf(stderr, f, va);
816
    va_end(va);
661 plagman 817
#else
818
    UNREFERENCED_PARAMETER(f);
5 Plagman 819
#endif
820
}
821
 
822
 
823
//
824
//
825
// ---------------------------------------
826
//
827
// All things Input
828
//
829
// ---------------------------------------
830
//
831
//
832
 
8251 hendricks2 833
// static int32_t joyblast=0;
834
static SDL_Joystick *joydev = NULL;
7958 hendricks2 835
#if SDL_MAJOR_VERSION >= 2
836
static SDL_GameController *controller = NULL;
5 Plagman 837
 
7958 hendricks2 838
static void LoadSDLControllerDB()
839
{
840
    buildvfs_kfd fh = kopen4load("gamecontrollerdb.txt", 0);
841
    if (fh == buildvfs_kfd_invalid)
842
        return;
843
 
8152 terminx 844
    int const flen = kfilelength(fh);
7958 hendricks2 845
    if (flen <= 0)
846
    {
847
        kclose(fh);
848
        return;
849
    }
850
 
8152 terminx 851
    char * dbuf = (char *)Xaligned_alloc(16, flen + 1);
7958 hendricks2 852
    if (!dbuf)
853
    {
854
        kclose(fh);
855
        return;
856
    }
857
 
858
    if (kread_and_test(fh, dbuf, flen))
859
    {
8152 terminx 860
        Xaligned_free(dbuf);
7958 hendricks2 861
        kclose(fh);
862
        return;
863
    }
864
 
865
    dbuf[flen] = '\0';
866
    kclose(fh);
867
 
868
    SDL_RWops * rwops = SDL_RWFromConstMem(dbuf, flen);
869
    if (!rwops)
870
    {
8152 terminx 871
        Xaligned_free(dbuf);
7958 hendricks2 872
        return;
873
    }
874
 
8151 terminx 875
    int i = SDL_GameControllerAddMappingsFromRW(rwops, 1);
876
 
7958 hendricks2 877
    if (i == -1)
878
        buildprintf("Failed loading game controller database: %s\n", SDL_GetError());
879
    else
880
        buildputs("Loaded game controller database\n");
881
 
8152 terminx 882
    Xaligned_free(dbuf);
7958 hendricks2 883
}
884
#endif
885
 
7985 hendricks2 886
void joyScanDevices()
887
{
888
    inputdevices &= ~4;
889
 
8264 ny00123 890
#if SDL_MAJOR_VERSION >= 2
7985 hendricks2 891
    if (controller)
892
    {
893
        SDL_GameControllerClose(controller);
894
        controller = nullptr;
895
    }
8264 ny00123 896
#endif
7985 hendricks2 897
    if (joydev)
898
    {
899
        SDL_JoystickClose(joydev);
900
        joydev = nullptr;
901
    }
902
 
8251 hendricks2 903
    int numjoysticks = SDL_NumJoysticks();
7985 hendricks2 904
    if (numjoysticks < 1)
905
    {
906
        buildputs("No game controllers found\n");
907
    }
8251 hendricks2 908
    else
7985 hendricks2 909
    {
8251 hendricks2 910
        buildputs("Game controllers:\n");
911
        for (int i = 0; i < numjoysticks; i++)
912
        {
913
            const char * name;
7985 hendricks2 914
#if SDL_MAJOR_VERSION >= 2
8251 hendricks2 915
            if (SDL_IsGameController(i))
916
                name = SDL_GameControllerNameForIndex(i);
917
            else
7985 hendricks2 918
#endif
8251 hendricks2 919
                name = SDL_JoystickNameForIndex(i);
7985 hendricks2 920
 
8251 hendricks2 921
            buildprintf("  %d. %s\n", i+1, name);
922
        }
923
 
7985 hendricks2 924
#if SDL_MAJOR_VERSION >= 2
8251 hendricks2 925
        for (int i = 0; i < numjoysticks; i++)
7985 hendricks2 926
        {
8251 hendricks2 927
            if ((controller = SDL_GameControllerOpen(i)))
928
            {
929
                buildprintf("Using controller %s\n", SDL_GameControllerName(controller));
7985 hendricks2 930
 
8251 hendricks2 931
                joystick.numAxes    = SDL_CONTROLLER_AXIS_MAX;
8367 terminx 932
                joystick.numBalls   = 0;
8251 hendricks2 933
                joystick.numButtons = SDL_CONTROLLER_BUTTON_MAX;
934
                joystick.numHats    = 0;
8367 terminx 935
 
8251 hendricks2 936
                joystick.isGameController = 1;
7985 hendricks2 937
 
8251 hendricks2 938
                Xfree(joystick.pAxis);
939
                joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t));
940
                Xfree(joystick.pHat);
941
                joystick.pHat = nullptr;
7985 hendricks2 942
 
8251 hendricks2 943
                inputdevices |= 4;
7985 hendricks2 944
 
8251 hendricks2 945
                return;
946
            }
7985 hendricks2 947
        }
8251 hendricks2 948
#endif
949
 
950
        for (int i = 0; i < numjoysticks; i++)
7985 hendricks2 951
        {
8251 hendricks2 952
            if ((joydev = SDL_JoystickOpen(i)))
953
            {
8264 ny00123 954
                buildprintf("Using joystick %s\n", SDL_JoystickNameForIndex(i));
7985 hendricks2 955
 
8251 hendricks2 956
                // KEEPINSYNC duke3d/src/gamedefs.h, mact/include/_control.h
8367 terminx 957
                joystick.numAxes    = min(9, SDL_JoystickNumAxes(joydev));
958
                joystick.numBalls   = SDL_JoystickNumBalls(joydev);
8251 hendricks2 959
                joystick.numButtons = min(32, SDL_JoystickNumButtons(joydev));
8367 terminx 960
                joystick.numHats    = min((36 - joystick.numButtons) / 4, SDL_JoystickNumHats(joydev));
961
 
8251 hendricks2 962
                joystick.isGameController = 0;
7985 hendricks2 963
 
8497 hendricks2 964
                buildprint("Joystick ", i+1, " has ", joystick.numAxes, " axes, ", joystick.numButtons, " buttons, ");
965
                if (joystick.numHats) buildprint(joystick.numHats); else buildprint("no");
966
                buildprint(" hats, and ");
967
                if (joystick.numBalls) buildprint(joystick.numBalls); else buildprint("no");
968
                buildprint(" balls.\n");
7985 hendricks2 969
 
8251 hendricks2 970
                Xfree(joystick.pAxis);
971
                joystick.pAxis = (int32_t *)Xcalloc(joystick.numAxes, sizeof(int32_t));
7985 hendricks2 972
 
8251 hendricks2 973
                Xfree(joystick.pHat);
974
                if (joystick.numHats)
975
                    joystick.pHat = (int32_t *)Xcalloc(joystick.numHats, sizeof(int32_t));
976
                else
977
                    joystick.pHat = nullptr;
7985 hendricks2 978
 
8251 hendricks2 979
                for (int j = 0; j < joystick.numHats; j++)
980
                    joystick.pHat[j] = -1; // center
7985 hendricks2 981
 
8251 hendricks2 982
                SDL_JoystickEventState(SDL_ENABLE);
983
                inputdevices |= 4;
7985 hendricks2 984
 
8251 hendricks2 985
                return;
986
            }
7985 hendricks2 987
        }
8251 hendricks2 988
 
989
        buildputs("No controllers are usable\n");
8150 terminx 990
    }
7985 hendricks2 991
}
992
 
5 Plagman 993
//
994
// initinput() -- init input system
995
//
8005 terminx 996
int32_t initinput(void)
5 Plagman 997
{
7045 terminx 998
    int32_t i;
109 terminx 999
 
5169 hendricks2 1000
#if defined EDUKE32_OSX
109 terminx 1001
    // force OS X to operate in >1 button mouse mode so that LMB isn't adulterated
4749 terminx 1002
    if (!getenv("SDL_HAS3BUTTONMOUSE"))
7045 terminx 1003
    {
1004
        static char sdl_has3buttonmouse[] = "SDL_HAS3BUTTONMOUSE=1";
5551 hendricks2 1005
        putenv(sdl_has3buttonmouse);
7045 terminx 1006
    }
5 Plagman 1007
#endif
4749 terminx 1008
 
1009
    inputdevices = 1 | 2;  // keyboard (1) and mouse (2)
6827 terminx 1010
    g_mouseGrabbed = 0;
5 Plagman 1011
 
6827 terminx 1012
    memset(g_keyNameTable, 0, sizeof(g_keyNameTable));
4432 terminx 1013
 
1014
#if SDL_MAJOR_VERSION == 1
4749 terminx 1015
#define SDL_SCANCODE_TO_KEYCODE(x) (SDLKey)(x)
1016
#define SDL_NUM_SCANCODES SDLK_LAST
1017
    if (SDL_EnableKeyRepeat(250, 30))
1018
        initprintf("Error enabling keyboard repeat.\n");
1019
    SDL_EnableUNICODE(1);  // let's hope this doesn't hit us too hard
4432 terminx 1020
#endif
1021
 
4749 terminx 1022
    for (i = SDL_NUM_SCANCODES - 1; i >= 0; i--)
342 terminx 1023
    {
4749 terminx 1024
        if (!keytranslation[i])
1025
            continue;
1026
 
7080 terminx 1027
        Bstrncpyz(g_keyNameTable[keytranslation[i]], SDL_GetKeyName(SDL_SCANCODE_TO_KEYCODE(i)), sizeof(g_keyNameTable[0]));
1109 terminx 1028
    }
5 Plagman 1029
 
7958 hendricks2 1030
#if SDL_MAJOR_VERSION >= 2
1031
    if (!SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER))
1032
#else
342 terminx 1033
    if (!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
7958 hendricks2 1034
#endif
342 terminx 1035
    {
7958 hendricks2 1036
#if SDL_MAJOR_VERSION >= 2
1037
        LoadSDLControllerDB();
1038
#endif
8005 terminx 1039
 
7985 hendricks2 1040
        joyScanDevices();
109 terminx 1041
    }
1042
 
1043
    return 0;
5 Plagman 1044
}
1045
 
1046
//
1047
// uninitinput() -- uninit input system
1048
//
1049
void uninitinput(void)
1050
{
6827 terminx 1051
    mouseUninit();
5 Plagman 1052
 
7958 hendricks2 1053
#if SDL_MAJOR_VERSION >= 2
1054
    if (controller)
1055
    {
1056
        SDL_GameControllerClose(controller);
1057
        controller = NULL;
1058
    }
8251 hendricks2 1059
#endif
1060
 
342 terminx 1061
    if (joydev)
1062
    {
109 terminx 1063
        SDL_JoystickClose(joydev);
1064
        joydev = NULL;
1065
    }
5 Plagman 1066
}
1067
 
2624 helixhorne 1068
#ifndef GEKKO
6827 terminx 1069
const char *joyGetName(int32_t what, int32_t num)
5 Plagman 1070
{
109 terminx 1071
    static char tmp[64];
5 Plagman 1072
 
342 terminx 1073
    switch (what)
1074
    {
4749 terminx 1075
        case 0:  // axis
6827 terminx 1076
            if ((unsigned)num > (unsigned)joystick.numAxes)
4749 terminx 1077
                return NULL;
7958 hendricks2 1078
 
1079
#if SDL_MAJOR_VERSION >= 2
1080
            if (controller)
1081
            {
1082
# if 0
1083
                // Use this if SDL's provided strings ever become user-friendly.
1084
                return SDL_GameControllerGetStringForAxis((SDL_GameControllerAxis)num);
1085
# else
1086
                static char const * axisStrings[] =
1087
                {
1088
                    "Left Stick X-Axis",
1089
                    "Left Stick Y-Axis",
1090
                    "Right Stick X-Axis",
1091
                    "Right Stick Y-Axis",
1092
                    "Left Trigger",
1093
                    "Right Trigger",
1094
                    NULL
1095
                };
1096
                return axisStrings[num];
1097
# endif
1098
            }
1099
#endif
1100
 
4749 terminx 1101
            Bsprintf(tmp, "Axis %d", num);
1102
            return (char *)tmp;
5 Plagman 1103
 
4749 terminx 1104
        case 1:  // button
6827 terminx 1105
            if ((unsigned)num > (unsigned)joystick.numButtons)
4749 terminx 1106
                return NULL;
7958 hendricks2 1107
 
1108
#if SDL_MAJOR_VERSION >= 2
1109
            if (controller)
1110
            {
1111
# if 0
1112
                // See above.
1113
                return SDL_GameControllerGetStringForButton((SDL_GameControllerButton)num);
1114
# else
1115
                static char const * buttonStrings[] =
1116
                {
1117
                    "A",
1118
                    "B",
1119
                    "X",
1120
                    "Y",
1121
                    "Back",
1122
                    "Guide",
1123
                    "Start",
1124
                    "Left Stick",
1125
                    "Right Stick",
1126
                    "Left Shoulder",
1127
                    "Right Shoulder",
1128
                    "D-Pad Up",
1129
                    "D-Pad Down",
1130
                    "D-Pad Left",
1131
                    "D-Pad Right",
1132
                    NULL
1133
                };
1134
                return buttonStrings[num];
1135
# endif
1136
            }
1137
#endif
1138
 
4749 terminx 1139
            Bsprintf(tmp, "Button %d", num);
1140
            return (char *)tmp;
5 Plagman 1141
 
4749 terminx 1142
        case 2:  // hat
6827 terminx 1143
            if ((unsigned)num > (unsigned)joystick.numHats)
4749 terminx 1144
                return NULL;
1145
            Bsprintf(tmp, "Hat %d", num);
1146
            return (char *)tmp;
5 Plagman 1147
 
4749 terminx 1148
        default: return NULL;
109 terminx 1149
    }
5 Plagman 1150
}
2624 helixhorne 1151
#endif
1152
 
1153
 
5 Plagman 1154
//
1155
// initmouse() -- init mouse input
1156
//
7181 terminx 1157
void mouseInit(void)
5 Plagman 1158
{
7181 terminx 1159
    mouseGrabInput(g_mouseEnabled = g_mouseLockedToWindow);  // FIXME - SA
5 Plagman 1160
}
1161
 
1162
//
1163
// uninitmouse() -- uninit mouse input
1164
//
6827 terminx 1165
void mouseUninit(void)
5 Plagman 1166
{
6827 terminx 1167
    mouseGrabInput(0);
1168
    g_mouseEnabled = 0;
5 Plagman 1169
}
1170
 
1171
 
4767 hendricks2 1172
#if SDL_MAJOR_VERSION != 1
5 Plagman 1173
//
4089 hendricks2 1174
// grabmouse_low() -- show/hide mouse cursor, lower level (doesn't check state).
1175
//                    furthermore return 0 if successful.
1176
//
1177
 
1178
static inline char grabmouse_low(char a)
1179
{
5921 hendricks2 1180
#if !defined EDUKE32_TOUCH_DEVICES
4089 hendricks2 1181
    /* FIXME: Maybe it's better to make sure that grabmouse_low
1182
       is called only when a window is ready?                */
1183
    if (sdl_window)
1184
        SDL_SetWindowGrab(sdl_window, a ? SDL_TRUE : SDL_FALSE);
1185
    return SDL_SetRelativeMouseMode(a ? SDL_TRUE : SDL_FALSE);
4446 helixhorne 1186
#else
1187
    UNREFERENCED_PARAMETER(a);
1188
    return 0;
4432 terminx 1189
#endif
4089 hendricks2 1190
}
4767 hendricks2 1191
#endif
4089 hendricks2 1192
 
1193
//
5 Plagman 1194
// grabmouse() -- show/hide mouse cursor
1195
//
6851 terminx 1196
void mouseGrabInput(bool grab)
5 Plagman 1197
{
6827 terminx 1198
    if (appactive && g_mouseEnabled)
342 terminx 1199
    {
5921 hendricks2 1200
#if !defined EDUKE32_TOUCH_DEVICES
6851 terminx 1201
        if ((grab != g_mouseGrabbed) && !grabmouse_low(grab))
4095 helixhorne 1202
#endif
6851 terminx 1203
            g_mouseGrabbed = grab;
342 terminx 1204
    }
1205
    else
6851 terminx 1206
        g_mouseGrabbed = grab;
4749 terminx 1207
 
6827 terminx 1208
    g_mousePos.x = g_mousePos.y = 0;
5 Plagman 1209
}
1210
 
6827 terminx 1211
void mouseLockToWindow(char a)
4738 hendricks2 1212
{
4906 terminx 1213
    if (!(a & 2))
1214
    {
6827 terminx 1215
        mouseGrabInput(a);
1216
        g_mouseLockedToWindow = g_mouseGrabbed;
4906 terminx 1217
    }
1218
 
1219
    SDL_ShowCursor((osd && osd->flags & OSD_CAPTURE) ? SDL_ENABLE : SDL_DISABLE);
4738 hendricks2 1220
}
1221
 
5 Plagman 1222
//
1223
// setjoydeadzone() -- sets the dead and saturation zones for the joystick
1224
//
6827 terminx 1225
void joySetDeadZone(int32_t axis, uint16_t dead, uint16_t satur)
655 terminx 1226
{
1716 plagman 1227
    joydead[axis] = dead;
1228
    joysatur[axis] = satur;
655 terminx 1229
}
5 Plagman 1230
 
1231
 
1232
//
1233
// getjoydeadzone() -- gets the dead and saturation zones for the joystick
1234
//
6827 terminx 1235
void joyGetDeadZone(int32_t axis, uint16_t *dead, uint16_t *satur)
5 Plagman 1236
{
1716 plagman 1237
    *dead = joydead[axis];
1238
    *satur = joysatur[axis];
5 Plagman 1239
}
1240
 
1241
 
1242
//
1243
//
1244
// ---------------------------------------
1245
//
1246
// All things Video
1247
//
1248
// ---------------------------------------
1249
//
109 terminx 1250
//
5 Plagman 1251
 
1252
 
1253
//
1254
// getvalidmodes() -- figure out what video modes are available
1255
//
4068 helixhorne 1256
static int sortmodes(const void *a_, const void *b_)
5 Plagman 1257
{
7922 terminx 1258
    auto a = (const struct validmode_t *)b_;
1259
    auto b = (const struct validmode_t *)a_;
4068 helixhorne 1260
 
7164 terminx 1261
    int x;
1262
 
109 terminx 1263
    if ((x = a->fs   - b->fs)   != 0) return x;
1264
    if ((x = a->bpp  - b->bpp)  != 0) return x;
1265
    if ((x = a->xdim - b->xdim) != 0) return x;
1266
    if ((x = a->ydim - b->ydim) != 0) return x;
5 Plagman 1267
 
109 terminx 1268
    return 0;
5 Plagman 1269
}
4432 terminx 1270
 
5 Plagman 1271
static char modeschecked=0;
4432 terminx 1272
 
4749 terminx 1273
#if SDL_MAJOR_VERSION != 1
6828 terminx 1274
void videoGetModes(void)
5 Plagman 1275
{
4749 terminx 1276
    int32_t i, maxx = 0, maxy = 0;
4432 terminx 1277
    SDL_DisplayMode dispmode;
8063 terminx 1278
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
4432 terminx 1279
 
4749 terminx 1280
    if (modeschecked || novideo)
1281
        return;
4432 terminx 1282
 
4749 terminx 1283
    validmodecnt = 0;
4432 terminx 1284
    //    initprintf("Detecting video modes:\n");
1285
 
1286
    // do fullscreen modes first
8063 terminx 1287
    for (i = 0; i < SDL_GetNumDisplayModes(display); i++)
4089 hendricks2 1288
    {
8063 terminx 1289
        SDL_GetDisplayMode(display, i, &dispmode);
6435 terminx 1290
 
1291
        if (!SDL_CHECKMODE(dispmode.w, dispmode.h) ||
5621 terminx 1292
            (maxrefreshfreq && (dispmode.refresh_rate > maxrefreshfreq)))
4749 terminx 1293
            continue;
4089 hendricks2 1294
 
1295
        // HACK: 8-bit == Software, 32-bit == OpenGL
4749 terminx 1296
        SDL_ADDMODE(dispmode.w, dispmode.h, 8, 1);
4089 hendricks2 1297
#ifdef USE_OPENGL
1298
        if (!nogl)
4749 terminx 1299
            SDL_ADDMODE(dispmode.w, dispmode.h, 32, 1);
4089 hendricks2 1300
#endif
4749 terminx 1301
        if ((dispmode.w > maxx) || (dispmode.h > maxy))
4089 hendricks2 1302
        {
1303
            maxx = dispmode.w;
1304
            maxy = dispmode.h;
1305
        }
1306
    }
5 Plagman 1307
 
4749 terminx 1308
    SDL_CHECKFSMODES(maxx, maxy);
1309
 
109 terminx 1310
    // add windowed modes next
7115 terminx 1311
    // SDL sorts display modes largest to smallest, so we can just compare with mode 0
1312
    // to make sure we aren't adding modes that are larger than the actual screen res
8063 terminx 1313
    SDL_GetDisplayMode(display, 0, &dispmode);
7115 terminx 1314
 
6827 terminx 1315
    for (i = 0; g_defaultVideoModes[i].x; i++)
342 terminx 1316
    {
7115 terminx 1317
        auto const &mode = g_defaultVideoModes[i];
1318
 
1319
        if (mode.x > dispmode.w || mode.y > dispmode.h || !SDL_CHECKMODE(mode.x, mode.y))
4749 terminx 1320
            continue;
1321
 
7115 terminx 1322
        // 8-bit == Software, 32-bit == OpenGL
1323
        SDL_ADDMODE(mode.x, mode.y, 8, 0);
4749 terminx 1324
 
4089 hendricks2 1325
#ifdef USE_OPENGL
4749 terminx 1326
        if (nogl)
1327
            continue;
1328
 
7115 terminx 1329
        SDL_ADDMODE(mode.x, mode.y, 32, 0);
4089 hendricks2 1330
#endif
4432 terminx 1331
    }
5 Plagman 1332
 
4749 terminx 1333
    qsort((void *)validmode, validmodecnt, sizeof(struct validmode_t), &sortmodes);
5 Plagman 1334
 
4749 terminx 1335
    modeschecked = 1;
5 Plagman 1336
}
4432 terminx 1337
#endif
5 Plagman 1338
 
1339
//
1340
// checkvideomode() -- makes sure the video mode passed is legal
1341
//
6828 terminx 1342
int32_t videoCheckMode(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t forced)
5 Plagman 1343
{
1205 terminx 1344
    int32_t i, nearest=-1, dx, dy, odx=9999, ody=9999;
5 Plagman 1345
 
6828 terminx 1346
    videoGetModes();
5 Plagman 1347
 
109 terminx 1348
    if (c>8
5 Plagman 1349
#ifdef USE_OPENGL
109 terminx 1350
            && nogl
5 Plagman 1351
#endif
109 terminx 1352
       ) return -1;
5 Plagman 1353
 
109 terminx 1354
    // fix up the passed resolution values to be multiples of 8
1355
    // and at least 320x200 or at most MAXXDIMxMAXYDIM
4749 terminx 1356
    *x = clamp(*x, 320, MAXXDIM);
1357
    *y = clamp(*y, 200, MAXYDIM);
5 Plagman 1358
 
4749 terminx 1359
    for (i = 0; i < validmodecnt; i++)
342 terminx 1360
    {
4749 terminx 1361
        if (validmode[i].bpp != c || validmode[i].fs != fs)
1362
            continue;
1363
 
109 terminx 1364
        dx = klabs(validmode[i].xdim - *x);
1365
        dy = klabs(validmode[i].ydim - *y);
4749 terminx 1366
 
342 terminx 1367
        if (!(dx | dy))
584 terminx 1368
        {
1369
            // perfect match
109 terminx 1370
            nearest = i;
1371
            break;
1372
        }
4749 terminx 1373
 
342 terminx 1374
        if ((dx <= odx) && (dy <= ody))
1375
        {
109 terminx 1376
            nearest = i;
4749 terminx 1377
            odx = dx;
1378
            ody = dy;
109 terminx 1379
        }
1380
    }
1381
 
331 terminx 1382
#ifdef ANY_WINDOWED_SIZE
194 terminx 1383
    if (!forced && (fs&1) == 0 && (nearest < 0 || (validmode[nearest].xdim!=*x || validmode[nearest].ydim!=*y)))
109 terminx 1384
        return 0x7fffffffl;
331 terminx 1385
#endif
5 Plagman 1386
 
342 terminx 1387
    if (nearest < 0)
109 terminx 1388
        return -1;
5 Plagman 1389
 
109 terminx 1390
    *x = validmode[nearest].xdim;
1391
    *y = validmode[nearest].ydim;
5 Plagman 1392
 
4749 terminx 1393
    return nearest;
5 Plagman 1394
}
1395
 
4089 hendricks2 1396
static void destroy_window_resources()
2777 helixhorne 1397
{
4749 terminx 1398
/* We should NOT destroy the window surface. This is done automatically
1399
   when SDL_DestroyWindow or SDL_SetVideoMode is called.             */
1400
 
1401
#if SDL_MAJOR_VERSION == 2
1402
    if (sdl_context)
1403
        SDL_GL_DeleteContext(sdl_context);
1404
    sdl_context = NULL;
1405
    if (sdl_window)
1406
        SDL_DestroyWindow(sdl_window);
1407
    sdl_window = NULL;
4088 hendricks2 1408
#endif
2777 helixhorne 1409
}
1410
 
4749 terminx 1411
#ifdef USE_OPENGL
1412
void sdlayer_setvideomode_opengl(void)
1413
{
6919 pogokeen 1414
    glsurface_destroy();
4749 terminx 1415
    polymost_glreset();
1416
 
6656 pogokeen 1417
    glShadeModel(GL_SMOOTH);  // GL_FLAT
1418
    glClearColor(0, 0, 0, 1.0);  // Black Background
1419
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Use FASTEST for ortho!
1420
//    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
4997 terminx 1421
 
1422
#ifndef EDUKE32_GLES
6656 pogokeen 1423
    glDisable(GL_DITHER);
4997 terminx 1424
#endif
4749 terminx 1425
 
6656 pogokeen 1426
    glinfo.vendor = (const char *) glGetString(GL_VENDOR);
1427
    glinfo.renderer = (const char *) glGetString(GL_RENDERER);
1428
    glinfo.version = (const char *) glGetString(GL_VERSION);
1429
    glinfo.extensions = (const char *) glGetString(GL_EXTENSIONS);
4749 terminx 1430
 
1431
#ifdef POLYMER
1432
    if (!Bstrcmp(glinfo.vendor, "ATI Technologies Inc."))
1433
    {
1434
        pr_ati_fboworkaround = 1;
1435
        initprintf("Enabling ATI FBO color attachment workaround.\n");
1436
 
1437
        if (Bstrstr(glinfo.renderer, "Radeon X1"))
1438
        {
1439
            pr_ati_nodepthoffset = 1;
1440
            initprintf("Enabling ATI R520 polygon offset workaround.\n");
1441
        }
1442
        else
1443
            pr_ati_nodepthoffset = 0;
1444
#ifdef __APPLE__
1445
        // See bug description at http://lists.apple.com/archives/mac-opengl/2005/Oct/msg00169.html
1446
        if (!Bstrncmp(glinfo.renderer, "ATI Radeon 9600", 15))
1447
        {
1448
            pr_ati_textureformat_one = 1;
1449
            initprintf("Enabling ATI Radeon 9600 texture format workaround.\n");
1450
        }
1451
        else
1452
            pr_ati_textureformat_one = 0;
1453
#endif
1454
    }
1455
    else
1456
        pr_ati_fboworkaround = 0;
1457
#endif  // defined POLYMER
1458
 
1459
    glinfo.maxanisotropy = 1.0;
1460
    glinfo.bgra = 0;
4992 terminx 1461
    glinfo.clamptoedge = 1;
1462
    glinfo.multitex = 1;
4749 terminx 1463
 
1464
    // process the extensions string and flag stuff we recognize
4992 terminx 1465
 
1466
    glinfo.texnpot = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_non_power_of_two") || !!Bstrstr(glinfo.extensions, "GL_OES_texture_npot");
4752 terminx 1467
    glinfo.arbfp = !!Bstrstr(glinfo.extensions, "GL_ARB_fragment_program");
1468
    glinfo.depthtex = !!Bstrstr(glinfo.extensions, "GL_ARB_depth_texture");
1469
    glinfo.shadow = !!Bstrstr(glinfo.extensions, "GL_ARB_shadow");
4992 terminx 1470
    glinfo.fbos = !!Bstrstr(glinfo.extensions, "GL_EXT_framebuffer_object") || !!Bstrstr(glinfo.extensions, "GL_OES_framebuffer_object");
1471
 
5690 hendricks2 1472
#if !defined EDUKE32_GLES
1473
    glinfo.texcompr = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_compression") && Bstrcmp(glinfo.vendor, "ATI Technologies Inc.");
5673 hendricks2 1474
# ifdef DYNAMIC_GLEXT
6656 pogokeen 1475
    if (glinfo.texcompr && (!glCompressedTexImage2D || !glGetCompressedTexImage))
5673 hendricks2 1476
    {
1477
        // lacking the necessary extensions to do this
1478
        initprintf("Warning: the GL driver lacks necessary functions to use caching\n");
1479
        glinfo.texcompr = 0;
1480
    }
1481
# endif
1482
 
4997 terminx 1483
    glinfo.bgra = !!Bstrstr(glinfo.extensions, "GL_EXT_bgra");
4992 terminx 1484
    glinfo.clamptoedge = !!Bstrstr(glinfo.extensions, "GL_EXT_texture_edge_clamp") ||
1485
                         !!Bstrstr(glinfo.extensions, "GL_SGIS_texture_edge_clamp");
4752 terminx 1486
    glinfo.rect =
1487
    !!Bstrstr(glinfo.extensions, "GL_NV_texture_rectangle") || !!Bstrstr(glinfo.extensions, "GL_EXT_texture_rectangle");
4992 terminx 1488
 
4752 terminx 1489
    glinfo.multitex = !!Bstrstr(glinfo.extensions, "GL_ARB_multitexture");
4992 terminx 1490
 
4752 terminx 1491
    glinfo.envcombine = !!Bstrstr(glinfo.extensions, "GL_ARB_texture_env_combine");
1492
    glinfo.vbos = !!Bstrstr(glinfo.extensions, "GL_ARB_vertex_buffer_object");
1493
    glinfo.sm4 = !!Bstrstr(glinfo.extensions, "GL_EXT_gpu_shader4");
1494
    glinfo.occlusionqueries = !!Bstrstr(glinfo.extensions, "GL_ARB_occlusion_query");
1495
    glinfo.glsl = !!Bstrstr(glinfo.extensions, "GL_ARB_shader_objects");
1496
    glinfo.debugoutput = !!Bstrstr(glinfo.extensions, "GL_ARB_debug_output");
5298 Plagman 1497
    glinfo.bufferstorage = !!Bstrstr(glinfo.extensions, "GL_ARB_buffer_storage");
6662 pogokeen 1498
    glinfo.sync = !!Bstrstr(glinfo.extensions, "GL_ARB_sync");
7753 pogokeen 1499
    glinfo.depthclamp = !!Bstrstr(glinfo.extensions, "GL_ARB_depth_clamp");
1500
    glinfo.clipcontrol = !!Bstrstr(glinfo.extensions, "GL_ARB_clip_control");
8252 hendricks2 1501
 
1502
#if 0
1503
    if (Bstrstr(glinfo.extensions, "WGL_3DFX_gamma_control"))
1504
    {
1505
        static int32_t warnonce;
1506
        // 3dfx cards have issues with fog
1507
        nofog = 1;
1508
        if (!(warnonce & 1))
1509
            initprintf("3dfx card detected: OpenGL fog disabled\n");
1510
        warnonce |= 1;
1511
    }
1512
#endif
5690 hendricks2 1513
#else
1514
    // don't bother checking because ETC2 et al. are not listed in extensions anyway
1515
    glinfo.texcompr = 1; // !!Bstrstr(glinfo.extensions, "GL_OES_compressed_ETC1_RGB8_texture");
4992 terminx 1516
#endif
4749 terminx 1517
 
4992 terminx 1518
//    if (Bstrstr(glinfo.extensions, "GL_EXT_texture_filter_anisotropic"))
6656 pogokeen 1519
        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glinfo.maxanisotropy);
4992 terminx 1520
 
4749 terminx 1521
    if (!glinfo.dumped)
1522
    {
1523
        int32_t oldbpp = bpp;
1524
        bpp = 32;
1525
        osdcmd_glinfo(NULL);
1526
        glinfo.dumped = 1;
1527
        bpp = oldbpp;
1528
    }
1529
}
1530
#endif  // defined USE_OPENGL
1531
 
5 Plagman 1532
//
1533
// setvideomode() -- set SDL video mode
1534
//
4749 terminx 1535
 
1536
int32_t setvideomode_sdlcommon(int32_t *x, int32_t *y, int32_t c, int32_t fs, int32_t *regrab)
5 Plagman 1537
{
4749 terminx 1538
    if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (c == bpp) && !videomodereset)
109 terminx 1539
        return 0;
5 Plagman 1540
 
6828 terminx 1541
    if (videoCheckMode(x, y, c, fs, 0) < 0)
4749 terminx 1542
        return -1;
109 terminx 1543
 
4820 hendricks2 1544
#ifdef GEKKO
1545
    if (!sdl_surface) // only run this the first time we set a video mode
1546
        wii_initgamevideo();
1547
#endif
1548
 
194 terminx 1549
    startwin_close();
5 Plagman 1550
 
6827 terminx 1551
    if (g_mouseGrabbed)
342 terminx 1552
    {
4749 terminx 1553
        *regrab = 1;
6827 terminx 1554
        mouseGrabInput(0);
109 terminx 1555
    }
5 Plagman 1556
 
6828 terminx 1557
    while (lockcount) videoEndDrawing();
5 Plagman 1558
 
1820 terminx 1559
#ifdef USE_OPENGL
6919 pogokeen 1560
    if (sdl_surface)
1561
    {
1562
        if (bpp > 8)
1563
            polymost_glreset();
6938 pogokeen 1564
    }
1565
    if (!nogl)
1566
    {
1567
        if (bpp == 8)
6919 pogokeen 1568
            glsurface_destroy();
6938 pogokeen 1569
        if ((fs == fullscreen) && (*x == xres) && (*y == yres) && (bpp != 0) && !videomodereset)
1570
            return 0;
6919 pogokeen 1571
    }
6939 pogokeen 1572
    else
5 Plagman 1573
#endif
6939 pogokeen 1574
    {
1575
       softsurface_destroy();
1576
    }
5 Plagman 1577
 
2222 helixhorne 1578
    // clear last gamma/contrast/brightness so that it will be set anew
1579
    lastvidgcb[0] = lastvidgcb[1] = lastvidgcb[2] = 0.0f;
1580
 
4749 terminx 1581
    return 1;
1582
}
1583
 
1584
void setvideomode_sdlcommonpost(int32_t x, int32_t y, int32_t c, int32_t fs, int32_t regrab)
1585
{
1586
    wm_setapptitle(apptitle);
1587
 
1588
#ifdef USE_OPENGL
6919 pogokeen 1589
    if (!nogl)
4749 terminx 1590
        sdlayer_setvideomode_opengl();
1591
#endif
1592
 
1593
    xres = x;
1594
    yres = y;
1595
    bpp = c;
1596
    fullscreen = fs;
1597
    // bytesperline = sdl_surface->pitch;
1598
    numpages = c > 8 ? 2 : 1;
1599
    frameplace = 0;
1600
    lockcount = 0;
1601
    modechange = 1;
1602
    videomodereset = 0;
1603
 
1604
    // save the current system gamma to determine if gamma is available
5659 terminx 1605
#ifndef EDUKE32_GLES
4749 terminx 1606
    if (!gammabrightness)
342 terminx 1607
    {
4749 terminx 1608
        //        float f = 1.0 + ((float)curbrightness / 10.0);
1609
#if SDL_MAJOR_VERSION != 1
1610
        if (SDL_GetWindowGammaRamp(sdl_window, sysgamma[0], sysgamma[1], sysgamma[2]) == 0)
1611
#else
1612
        if (SDL_GetGammaRamp(sysgamma[0], sysgamma[1], sysgamma[2]) >= 0)
1613
#endif
1614
            gammabrightness = 1;
1615
 
1616
        // see if gamma really is working by trying to set the brightness
6828 terminx 1617
        if (gammabrightness && videoSetGamma() < 0)
4749 terminx 1618
            gammabrightness = 0;  // nope
109 terminx 1619
    }
5659 terminx 1620
#endif
4080 hendricks2 1621
 
6829 terminx 1622
    videoFadePalette(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
4749 terminx 1623
 
1624
    if (regrab)
6827 terminx 1625
        mouseGrabInput(g_mouseLockedToWindow);
4749 terminx 1626
}
1627
 
1628
#if SDL_MAJOR_VERSION!=1
5621 terminx 1629
void setrefreshrate(void)
1630
{
8063 terminx 1631
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1632
 
5621 terminx 1633
    SDL_DisplayMode dispmode;
8063 terminx 1634
    SDL_GetCurrentDisplayMode(display, &dispmode);
5621 terminx 1635
 
1636
    dispmode.refresh_rate = maxrefreshfreq;
1637
 
1638
    SDL_DisplayMode newmode;
8063 terminx 1639
    SDL_GetClosestDisplayMode(display, &dispmode, &newmode);
5621 terminx 1640
 
8050 pogokeen 1641
    char error = 0;
1642
 
5621 terminx 1643
    if (dispmode.refresh_rate != newmode.refresh_rate)
8050 pogokeen 1644
        error = SDL_SetWindowDisplayMode(sdl_window, &newmode);
6689 pogokeen 1645
 
8612 terminx 1646
    if (!newmode.refresh_rate || error)
1647
        newmode.refresh_rate = 59;
8031 terminx 1648
 
8612 terminx 1649
#ifdef _WIN32
1650
    if (timingInfo.rateRefresh.uiNumerator)
1651
        refreshfreq = timingInfo.rateRefresh.uiNumerator / timingInfo.rateRefresh.uiDenominator;
1652
    else
1653
#endif
1654
        refreshfreq = newmode.refresh_rate;
1655
 
1656
    initprintf("Refresh rate: %.2fHz\n", refreshfreq);
5621 terminx 1657
}
1658
 
6828 terminx 1659
int32_t videoSetMode(int32_t x, int32_t y, int32_t c, int32_t fs)
4749 terminx 1660
{
1661
    int32_t regrab = 0, ret;
109 terminx 1662
 
4749 terminx 1663
    ret = setvideomode_sdlcommon(&x, &y, c, fs, &regrab);
8612 terminx 1664
 
6938 pogokeen 1665
    if (ret != 1)
1666
    {
1667
        if (ret == 0)
1668
        {
1669
            setvideomode_sdlcommonpost(x, y, c, fs, regrab);
1670
        }
1671
        return ret;
1672
    }
4749 terminx 1673
 
4089 hendricks2 1674
    // deinit
1675
    destroy_window_resources();
1676
 
4749 terminx 1677
    initprintf("Setting video mode %dx%d (%d-bpp %s)\n", x, y, c, ((fs & 1) ? "fullscreen" : "windowed"));
1678
 
8063 terminx 1679
    int const display = r_displayindex < SDL_GetNumVideoDisplays() ? r_displayindex : 0;
1680
 
7204 terminx 1681
    SDL_DisplayMode desktopmode;
8063 terminx 1682
    SDL_GetDesktopDisplayMode(display, &desktopmode);
7204 terminx 1683
 
8060 terminx 1684
    int const matchedResolution = (desktopmode.w == x && desktopmode.h == y);
8063 terminx 1685
    int const borderless = (r_borderless == 1 || (r_borderless == 2 && matchedResolution)) ? SDL_WINDOW_BORDERLESS : 0;
1820 terminx 1686
#ifdef USE_OPENGL
6919 pogokeen 1687
    if (c > 8 || !nogl)
342 terminx 1688
    {
7045 terminx 1689
        int32_t i;
8606 terminx 1690
 
4749 terminx 1691
        if (nogl)
1692
            return -1;
8612 terminx 1693
 
4755 helixhorne 1694
        struct glattribs
1695
        {
1696
            SDL_GLattr attr;
1697
            int32_t value;
4992 terminx 1698
        } sdlayer_gl_attributes[] =
4755 helixhorne 1699
        {
6603 hendricks2 1700
#ifdef EDUKE32_GLES
4992 terminx 1701
              { SDL_GL_CONTEXT_MAJOR_VERSION, 1 },
1702
              { SDL_GL_CONTEXT_MINOR_VERSION, 1 },
1703
#endif
1704
              { SDL_GL_DOUBLEBUFFER, 1 },
8606 terminx 1705
 
8035 terminx 1706
              { SDL_GL_STENCIL_SIZE, 1 },
4992 terminx 1707
              { SDL_GL_ACCELERATED_VISUAL, 1 },
1708
          };
3221 hendricks2 1709
 
8606 terminx 1710
        SDL_GL_ATTRIBUTES(i, sdlayer_gl_attributes);
109 terminx 1711
 
8606 terminx 1712
        /* HACK: changing SDL GL attribs only works before surface creation,
1713
            so we have to create a new surface in a different format first
1714
            to force the surface we WANT to be recreated instead of reused. */
8060 terminx 1715
 
1716
 
8606 terminx 1717
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display),
1718
                                        windowpos ? windowy : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display), x, y,
1719
                                        SDL_WINDOW_OPENGL | borderless);
2777 helixhorne 1720
 
8606 terminx 1721
        if (sdl_window)
1722
            sdl_context = SDL_GL_CreateContext(sdl_window);
2777 helixhorne 1723
 
8606 terminx 1724
        if (!sdl_window || !sdl_context)
1725
        {
1726
            initprintf("Unable to set video mode: %s failed: %s\n", sdl_window ? "SDL_GL_CreateContext" : "SDL_GL_CreateWindow",  SDL_GetError());
1727
            nogl = 1;
1728
            destroy_window_resources();
1729
            return -1;
1730
        }
4749 terminx 1731
 
8606 terminx 1732
        gladLoadGLLoader(SDL_GL_GetProcAddress);
1733
        if (GLVersion.major < 2)
1734
        {
1735
            initprintf("Your computer does not support OpenGL version 2 or greater. GL modes are unavailable.\n");
1736
            nogl = 1;
1737
            destroy_window_resources();
1738
            return -1;
1739
        }
6700 hendricks2 1740
 
8606 terminx 1741
        SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? (matchedResolution ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0));
8612 terminx 1742
        SDL_GL_SetSwapInterval(sdlayer_getswapinterval(vsync_renderlayer));
1743
        vsync_renderlayer = sdlayer_checkvsync(vsync_renderlayer);
4089 hendricks2 1744
 
8606 terminx 1745
        setrefreshrate();
342 terminx 1746
    }
1747
    else
2014 helixhorne 1748
#endif  // defined USE_OPENGL
109 terminx 1749
    {
2777 helixhorne 1750
        // init
8063 terminx 1751
        sdl_window = SDL_CreateWindow("", windowpos ? windowx : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display),
1752
                                      windowpos ? windowy : (int)SDL_WINDOWPOS_CENTERED_DISPLAY(display), x, y,
8060 terminx 1753
                                      borderless);
4089 hendricks2 1754
        if (!sdl_window)
4432 terminx 1755
            SDL2_VIDEO_ERR("SDL_CreateWindow");
2777 helixhorne 1756
 
5621 terminx 1757
        setrefreshrate();
1758
 
8675 ny00123 1759
        sdl_surface = SDL_GetWindowSurface(sdl_window);
4253 hendricks2 1760
        if (!sdl_surface)
8675 ny00123 1761
            SDL2_VIDEO_ERR("SDL_GetWindowSurface");
4253 hendricks2 1762
 
8060 terminx 1763
        SDL_SetWindowFullscreen(sdl_window, ((fs & 1) ? (matchedResolution ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) : 0));
109 terminx 1764
    }
5 Plagman 1765
 
4749 terminx 1766
    setvideomode_sdlcommonpost(x, y, c, fs, regrab);
5 Plagman 1767
 
109 terminx 1768
    return 0;
5 Plagman 1769
}
4749 terminx 1770
#endif
5 Plagman 1771
 
1772
//
1773
// resetvideomode() -- resets the video system
1774
//
6828 terminx 1775
void videoResetMode(void)
5 Plagman 1776
{
109 terminx 1777
    videomodereset = 1;
1778
    modeschecked = 0;
5 Plagman 1779
}
1780
 
1781
//
1782
// begindrawing() -- locks the framebuffer for drawing
1783
//
5311 helixhorne 1784
 
1785
#ifdef DEBUG_FRAME_LOCKING
1786
uint32_t begindrawing_line[BEGINDRAWING_SIZE];
1787
const char *begindrawing_file[BEGINDRAWING_SIZE];
1788
void begindrawing_real(void)
1789
#else
6828 terminx 1790
void videoBeginDrawing(void)
5311 helixhorne 1791
#endif
5 Plagman 1792
{
342 terminx 1793
    if (bpp > 8)
1794
    {
109 terminx 1795
        if (offscreenrendering) return;
1796
        frameplace = 0;
1797
        bytesperline = 0;
1798
        modechange = 0;
1799
        return;
1800
    }
6933 pogokeen 1801
 
1802
    // lock the frame
1803
    if (lockcount++ > 0)
1804
        return;
1805
 
7853 pogokeen 1806
    static intptr_t backupFrameplace = 0;
6933 pogokeen 1807
 
7733 pogokeen 1808
    if (inpreparemirror)
1809
    {
7853 pogokeen 1810
        //POGO: if we are offscreenrendering and we need to render a mirror
1811
        //      or we are rendering a mirror and we start offscreenrendering,
1812
        //      backup our offscreen target so we can restore it later
1813
        //      (but only allow one level deep,
1814
        //       i.e. no viewscreen showing a camera showing a mirror that reflects the same viewscreen and recursing)
1815
        if (offscreenrendering)
1816
        {
1817
            if (!backupFrameplace)
1818
                backupFrameplace = frameplace;
1819
            else if (frameplace != (intptr_t)mirrorBuffer &&
1820
                     frameplace != backupFrameplace)
1821
                return;
1822
        }
1823
 
7733 pogokeen 1824
        frameplace = (intptr_t)mirrorBuffer;
7853 pogokeen 1825
 
1826
        if (offscreenrendering)
1827
            return;
7733 pogokeen 1828
    }
7853 pogokeen 1829
    else if (offscreenrendering)
1830
    {
1831
        if (backupFrameplace)
1832
        {
1833
            frameplace = backupFrameplace;
1834
            backupFrameplace = 0;
1835
        }
1836
        return;
1837
    }
7733 pogokeen 1838
    else
6939 pogokeen 1839
#ifdef USE_OPENGL
6933 pogokeen 1840
    if (!nogl)
6919 pogokeen 1841
    {
1842
        frameplace = (intptr_t)glsurface_getBuffer();
1843
    }
7733 pogokeen 1844
    else
6939 pogokeen 1845
#endif
7733 pogokeen 1846
    {
1847
        frameplace = (intptr_t)softsurface_getBuffer();
1848
    }
6919 pogokeen 1849
 
6939 pogokeen 1850
    if (modechange)
342 terminx 1851
    {
6939 pogokeen 1852
        bytesperline = xdim;
3291 helixhorne 1853
        calc_ylookup(bytesperline, ydim);
109 terminx 1854
        modechange=0;
1855
    }
5 Plagman 1856
}
1857
 
1858
 
1859
//
1860
// enddrawing() -- unlocks the framebuffer
1861
//
6828 terminx 1862
void videoEndDrawing(void)
5 Plagman 1863
{
6933 pogokeen 1864
    if (bpp > 8)
342 terminx 1865
    {
109 terminx 1866
        if (!offscreenrendering) frameplace = 0;
1867
        return;
1868
    }
5 Plagman 1869
 
109 terminx 1870
    if (!frameplace) return;
584 terminx 1871
    if (lockcount > 1) { lockcount--; return; }
109 terminx 1872
    if (!offscreenrendering) frameplace = 0;
1873
    if (lockcount == 0) return;
1874
    lockcount = 0;
5 Plagman 1875
}
1876
 
1877
//
1878
// showframe() -- update the display
1879
//
4749 terminx 1880
#if SDL_MAJOR_VERSION != 1
4992 terminx 1881
 
1882
#ifdef __ANDROID__
5652 terminx 1883
extern "C" void AndroidDrawControls();
4992 terminx 1884
#endif
1885
 
6828 terminx 1886
void videoShowFrame(int32_t w)
5 Plagman 1887
{
655 terminx 1888
    UNREFERENCED_PARAMETER(w);
5 Plagman 1889
 
4992 terminx 1890
#ifdef __ANDROID__
1891
    if (mobile_halted) return;
1892
#endif
1893
 
5 Plagman 1894
#ifdef USE_OPENGL
6919 pogokeen 1895
    if (!nogl)
342 terminx 1896
    {
6919 pogokeen 1897
        if (bpp > 8)
1898
        {
1899
            if (palfadedelta)
1900
                fullscreen_tint_gl(palfadergb.r, palfadergb.g, palfadergb.b, palfadedelta);
5 Plagman 1901
 
4992 terminx 1902
#ifdef __ANDROID__
6919 pogokeen 1903
            AndroidDrawControls();
4992 terminx 1904
#endif
6919 pogokeen 1905
        }
1906
        else
1907
        {
6932 pogokeen 1908
            glsurface_blitBuffer();
6919 pogokeen 1909
        }
6700 hendricks2 1910
 
8612 terminx 1911
#ifdef _WIN32
1912
        if (vsync_renderlayer == 2)
1913
        {
1914
            glFinish();
8544 terminx 1915
 
8612 terminx 1916
            static uint64_t nextSwapTime = timerGetPerformanceCounter();
1917
            uint64_t const  swapInterval = (timerGetPerformanceFrequency() / refreshfreq);
1918
            uint64_t const  swapTime     = timerGetPerformanceCounter();
1919
 
1920
            // TODO: use timing information to determine swap time and just busy loop ourselves for more timing control
1921
            if (swapTime < nextSwapTime)
1922
                windowsWaitForVBlank();
1923
 
1924
            if (swapTime > nextSwapTime + swapInterval)
1925
                nextSwapTime += swapInterval;
1926
 
1927
            nextSwapTime += swapInterval;
7977 terminx 1928
        }
8612 terminx 1929
#endif
8163 terminx 1930
 
8612 terminx 1931
        SDL_GL_SwapWindow(sdl_window);
1932
 
109 terminx 1933
        return;
1934
    }
5 Plagman 1935
#endif
1936
 
109 terminx 1937
    if (offscreenrendering) return;
5 Plagman 1938
 
342 terminx 1939
    if (lockcount)
1940
    {
8612 terminx 1941
        OSD_Printf("Frame still locked %d times when showframe() called.\n", lockcount);
6828 terminx 1942
        while (lockcount) videoEndDrawing();
109 terminx 1943
    }
1944
 
6939 pogokeen 1945
    if (SDL_MUSTLOCK(sdl_surface)) SDL_LockSurface(sdl_surface);
1946
    softsurface_blitBuffer((uint32_t*) sdl_surface->pixels, sdl_surface->format->BitsPerPixel);
1947
    if (SDL_MUSTLOCK(sdl_surface)) SDL_UnlockSurface(sdl_surface);
2221 helixhorne 1948
 
6939 pogokeen 1949
    if (SDL_UpdateWindowSurface(sdl_window))
4089 hendricks2 1950
    {
1951
        // If a fullscreen X11 window is minimized then this may be required.
1952
        // FIXME: What to do if this fails...
1953
        sdl_surface = SDL_GetWindowSurface(sdl_window);
1954
        SDL_UpdateWindowSurface(sdl_window);
1955
    }
4749 terminx 1956
}
2777 helixhorne 1957
#endif
5 Plagman 1958
//
1959
// setpalette() -- set palette values
1960
//
6828 terminx 1961
int32_t videoUpdatePalette(int32_t start, int32_t num)
5 Plagman 1962
{
6939 pogokeen 1963
    UNREFERENCED_PARAMETER(start);
1964
    UNREFERENCED_PARAMETER(num);
1965
 
4749 terminx 1966
    if (bpp > 8)
1967
        return 0;  // no palette in opengl
5 Plagman 1968
 
6939 pogokeen 1969
#ifdef USE_OPENGL
1970
    if (!nogl)
1971
        glsurface_setPalette(curpalettefaded);
1972
    else
4074 hendricks2 1973
#endif
6939 pogokeen 1974
    {
1975
        if (sdl_surface)
1976
            softsurface_setPalette(curpalettefaded,
1977
                                   sdl_surface->format->Rmask,
1978
                                   sdl_surface->format->Gmask,
1979
                                   sdl_surface->format->Bmask);
1980
    }
109 terminx 1981
 
2221 helixhorne 1982
    return 0;
5 Plagman 1983
}
1984
 
1985
//
1986
// setgamma
1987
//
6828 terminx 1988
int32_t videoSetGamma(void)
5 Plagman 1989
{
6828 terminx 1990
    if (novideo)
1991
        return 0;
4440 terminx 1992
 
1205 terminx 1993
    int32_t i;
1994
    uint16_t gammaTable[768];
6828 terminx 1995
    float gamma = max(0.1f, min(4.f, g_videoGamma));
1996
    float contrast = max(0.1f, min(3.f, g_videoContrast));
1997
    float bright = max(-0.8f, min(0.8f, g_videoBrightness));
870 terminx 1998
 
4606 terminx 1999
    float invgamma = 1.f / gamma;
2000
    float norm = powf(255.f, invgamma - 1.f);
872 terminx 2001
 
4749 terminx 2002
    if (lastvidgcb[0] == gamma && lastvidgcb[1] == contrast && lastvidgcb[2] == bright)
2222 helixhorne 2003
        return 0;
2004
 
872 terminx 2005
    // This formula is taken from Doomsday
2006
 
2007
    for (i = 0; i < 256; i++)
2008
    {
4606 terminx 2009
        float val = i * contrast - (contrast - 1.f) * 127.f;
2010
        if (gamma != 1.f)
2011
            val = powf(val, invgamma) / norm;
872 terminx 2012
 
4606 terminx 2013
        val += bright * 128.f;
2014
 
4749 terminx 2015
        gammaTable[i] = gammaTable[i + 256] = gammaTable[i + 512] = (uint16_t)max(0.f, min(65535.f, val * 256.f));
872 terminx 2016
    }
4432 terminx 2017
 
4749 terminx 2018
#if SDL_MAJOR_VERSION == 1
4606 terminx 2019
    i = SDL_SetGammaRamp(&gammaTable[0], &gammaTable[256], &gammaTable[512]);
4432 terminx 2020
    if (i != -1)
2777 helixhorne 2021
#else
2022
    i = INT32_MIN;
4606 terminx 2023
 
2777 helixhorne 2024
    if (sdl_window)
4606 terminx 2025
        i = SDL_SetWindowGammaRamp(sdl_window, &gammaTable[0], &gammaTable[256], &gammaTable[512]);
2222 helixhorne 2026
 
2777 helixhorne 2027
    if (i < 0)
2222 helixhorne 2028
    {
4749 terminx 2029
#ifndef __ANDROID__  // Don't do this check, it is really supported, TODO
5884 terminx 2030
/*
2777 helixhorne 2031
        if (i != INT32_MIN)
2032
            initprintf("Unable to set gamma: SDL_SetWindowGammaRamp failed: %s\n", SDL_GetError());
5884 terminx 2033
*/
5962 hendricks2 2034
#endif
5884 terminx 2035
 
7316 terminx 2036
        OSD_Printf("videoSetGamma(): %s\n", SDL_GetError());
2037
 
5962 hendricks2 2038
#ifndef EDUKE32_GLES
5884 terminx 2039
#if SDL_MAJOR_VERSION == 1
2040
        SDL_SetGammaRamp(&sysgamma[0][0], &sysgamma[1][0], &sysgamma[2][0]);
2041
#else
7316 terminx 2042
 
5884 terminx 2043
        if (sdl_window)
2044
            SDL_SetWindowGammaRamp(sdl_window, &sysgamma[0][0], &sysgamma[1][0], &sysgamma[2][0]);
4440 terminx 2045
#endif
5884 terminx 2046
        gammabrightness = 0;
2047
#endif
2777 helixhorne 2048
    }
2049
    else
2050
#endif
2051
    {
2222 helixhorne 2052
        lastvidgcb[0] = gamma;
2053
        lastvidgcb[1] = contrast;
2054
        lastvidgcb[2] = bright;
5884 terminx 2055
 
2056
        gammabrightness = 1;
2222 helixhorne 2057
    }
2058
 
2059
    return i;
5 Plagman 2060
}
2061
 
4852 hendricks2 2062
#if !defined __APPLE__ && !defined EDUKE32_TOUCH_DEVICES
6982 terminx 2063
extern "C" struct sdlappicon sdlappicon;
4752 terminx 2064
static inline SDL_Surface *loadappicon(void)
5 Plagman 2065
{
4752 terminx 2066
    SDL_Surface *surf = SDL_CreateRGBSurfaceFrom((void *)sdlappicon.pixels, sdlappicon.width, sdlappicon.height, 32,
2067
                                                 sdlappicon.width * 4, 0xffl, 0xff00l, 0xff0000l, 0xff000000l);
109 terminx 2068
    return surf;
5 Plagman 2069
}
2070
#endif
2071
 
2072
//
2073
//
2074
// ---------------------------------------
2075
//
2076
// Miscellany
2077
//
2078
// ---------------------------------------
2079
//
109 terminx 2080
//
5 Plagman 2081
 
3022 helixhorne 2082
int32_t handleevents_peekkeys(void)
2083
{
2084
    SDL_PumpEvents();
4749 terminx 2085
 
4074 hendricks2 2086
#if SDL_MAJOR_VERSION==1
3022 helixhorne 2087
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_EVENTMASK(SDL_KEYDOWN));
2088
#else
4074 hendricks2 2089
    return SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN);
3022 helixhorne 2090
#endif
2091
}
5 Plagman 2092
 
4853 hendricks2 2093
void handleevents_updatemousestate(uint8_t state)
2094
{
6827 terminx 2095
    g_mouseClickState = state == SDL_RELEASED ? MOUSE_RELEASED : MOUSE_PRESSED;
4853 hendricks2 2096
}
3022 helixhorne 2097
 
4853 hendricks2 2098
 
5 Plagman 2099
//
2100
// handleevents() -- process the SDL message queue
2101
//   returns !0 if there was an important event worth checking (like quitting)
2102
//
1593 terminx 2103
 
4749 terminx 2104
int32_t handleevents_sdlcommon(SDL_Event *ev)
5 Plagman 2105
{
4749 terminx 2106
    switch (ev->type)
4200 hendricks2 2107
    {
5169 hendricks2 2108
#if !defined EDUKE32_IOS
4749 terminx 2109
        case SDL_MOUSEMOTION:
4753 terminx 2110
#ifndef GEKKO
6827 terminx 2111
            g_mouseAbs.x = ev->motion.x;
2112
            g_mouseAbs.y = ev->motion.y;
8367 terminx 2113
            fallthrough__;
4753 terminx 2114
#endif
8367 terminx 2115
        case SDL_JOYBALLMOTION:
4749 terminx 2116
            // SDL <VER> doesn't handle relative mouse movement correctly yet as the cursor still clips to the
2117
            // screen edges
2118
            // so, we call SDL_WarpMouse() to center the cursor and ignore the resulting motion event that occurs
2119
            //  <VER> is 1.3 for PK, 1.2 for tueidj
6827 terminx 2120
            if (appactive && g_mouseGrabbed)
4200 hendricks2 2121
            {
6797 terminx 2122
# if SDL_MAJOR_VERSION==1
4749 terminx 2123
                if (ev->motion.x != xdim >> 1 || ev->motion.y != ydim >> 1)
6797 terminx 2124
# endif
1109 terminx 2125
                {
6827 terminx 2126
                    g_mousePos.x += ev->motion.xrel;
2127
                    g_mousePos.y += ev->motion.yrel;
4754 terminx 2128
# if SDL_MAJOR_VERSION==1
2129
                    SDL_WarpMouse(xdim>>1, ydim>>1);
2130
# endif
4327 terminx 2131
                }
1109 terminx 2132
            }
109 terminx 2133
            break;
5 Plagman 2134
 
109 terminx 2135
        case SDL_MOUSEBUTTONDOWN:
2136
        case SDL_MOUSEBUTTONUP:
5169 hendricks2 2137
        {
2138
            int32_t j;
5768 hendricks2 2139
 
4749 terminx 2140
            // some of these get reordered to match winlayer
2141
            switch (ev->button.button)
342 terminx 2142
            {
4749 terminx 2143
                default: j = -1; break;
4853 hendricks2 2144
                case SDL_BUTTON_LEFT: j = 0; handleevents_updatemousestate(ev->button.state); break;
4749 terminx 2145
                case SDL_BUTTON_RIGHT: j = 1; break;
2146
                case SDL_BUTTON_MIDDLE: j = 2; break;
4190 helixhorne 2147
 
4755 helixhorne 2148
#if SDL_MAJOR_VERSION == 1
4749 terminx 2149
                case SDL_BUTTON_WHEELUP:    // 4
2150
                case SDL_BUTTON_WHEELDOWN:  // 5
2151
                    j = ev->button.button;
2152
                    break;
4190 helixhorne 2153
#endif
4755 helixhorne 2154
                /* Thumb buttons. */
8043 hendricks2 2155
#if SDL_MAJOR_VERSION==1
4755 helixhorne 2156
                // NOTE: SDL1 does have SDL_BUTTON_X1, but that's not what is
8043 hendricks2 2157
                // generated. (Only tested on Linux and Windows.)
4749 terminx 2158
                case 8: j = 3; break;
2159
                case 9: j = 6; break;
4190 helixhorne 2160
#else
8043 hendricks2 2161
                // On SDL2/Windows and SDL >= 2.0.?/Linux, everything is as it should be.
2162
                // If anyone cares about old versions of SDL2 on Linux, patches welcome.
4749 terminx 2163
                case SDL_BUTTON_X1: j = 3; break;
2164
                case SDL_BUTTON_X2: j = 6; break;
4190 helixhorne 2165
#endif
109 terminx 2166
            }
5 Plagman 2167
 
4749 terminx 2168
            if (j < 0)
2169
                break;
2170
 
2171
            if (ev->button.state == SDL_PRESSED)
6827 terminx 2172
                g_mouseBits |= (1 << j);
342 terminx 2173
            else
4775 hendricks2 2174
#if SDL_MAJOR_VERSION==1
2175
                if (j != SDL_BUTTON_WHEELUP && j != SDL_BUTTON_WHEELDOWN)
2176
#endif
6827 terminx 2177
                g_mouseBits &= ~(1 << j);
5 Plagman 2178
 
6827 terminx 2179
            if (g_mouseCallback)
2180
                g_mouseCallback(j+1, ev->button.state == SDL_PRESSED);
109 terminx 2181
            break;
5169 hendricks2 2182
        }
2183
#else
2184
# if SDL_MAJOR_VERSION != 1
2185
        case SDL_FINGERUP:
6827 terminx 2186
            g_mouseClickState = MOUSE_RELEASED;
5169 hendricks2 2187
            break;
2188
        case SDL_FINGERDOWN:
6827 terminx 2189
            g_mouseClickState = MOUSE_PRESSED;
5169 hendricks2 2190
        case SDL_FINGERMOTION:
6827 terminx 2191
            g_mouseAbs.x = Blrintf(ev->tfinger.x * xdim);
2192
            g_mouseAbs.y = Blrintf(ev->tfinger.y * ydim);
5169 hendricks2 2193
            break;
2194
# endif
2195
#endif
8005 terminx 2196
 
109 terminx 2197
        case SDL_JOYAXISMOTION:
7958 hendricks2 2198
#if SDL_MAJOR_VERSION >= 2
2199
            if (joystick.isGameController)
2200
                break;
2201
            fallthrough__;
2202
        case SDL_CONTROLLERAXISMOTION:
2203
#endif
6827 terminx 2204
            if (appactive && ev->jaxis.axis < joystick.numAxes)
1716 plagman 2205
            {
7956 hendricks2 2206
                joystick.pAxis[ev->jaxis.axis] = ev->jaxis.value;
2207
                int32_t const scaledValue = ev->jaxis.value * 10000 / 32767;
2208
                if ((scaledValue < joydead[ev->jaxis.axis]) &&
2209
                    (scaledValue > -joydead[ev->jaxis.axis]))
6827 terminx 2210
                    joystick.pAxis[ev->jaxis.axis] = 0;
7956 hendricks2 2211
                else if (scaledValue >= joysatur[ev->jaxis.axis])
2212
                    joystick.pAxis[ev->jaxis.axis] = 32767;
2213
                else if (scaledValue <= -joysatur[ev->jaxis.axis])
2214
                    joystick.pAxis[ev->jaxis.axis] = -32767;
1716 plagman 2215
                else
6827 terminx 2216
                    joystick.pAxis[ev->jaxis.axis] = joystick.pAxis[ev->jaxis.axis] * 10000 / joysatur[ev->jaxis.axis];
1716 plagman 2217
            }
109 terminx 2218
            break;
5 Plagman 2219
 
342 terminx 2220
        case SDL_JOYHATMOTION:
2221
        {
4749 terminx 2222
            int32_t hatvals[16] = {
2223
                -1,     // centre
2224
                0,      // up 1
2225
                9000,   // right 2
2226
                4500,   // up+right 3
2227
                18000,  // down 4
2228
                -1,     // down+up!! 5
2229
                13500,  // down+right 6
2230
                -1,     // down+right+up!! 7
2231
                27000,  // left 8
2232
                27500,  // left+up 9
2233
                -1,     // left+right!! 10
2234
                -1,     // left+right+up!! 11
2235
                22500,  // left+down 12
2236
                -1,     // left+down+up!! 13
2237
                -1,     // left+down+right!! 14
2238
                -1,     // left+down+right+up!! 15
584 terminx 2239
            };
6827 terminx 2240
            if (appactive && ev->jhat.hat < joystick.numHats)
2241
                joystick.pHat[ev->jhat.hat] = hatvals[ev->jhat.value & 15];
331 terminx 2242
            break;
2243
        }
5 Plagman 2244
 
109 terminx 2245
        case SDL_JOYBUTTONDOWN:
2246
        case SDL_JOYBUTTONUP:
7958 hendricks2 2247
#if SDL_MAJOR_VERSION >= 2
2248
            if (joystick.isGameController)
2249
                break;
2250
            fallthrough__;
2251
        case SDL_CONTROLLERBUTTONDOWN:
2252
        case SDL_CONTROLLERBUTTONUP:
2253
#endif
6827 terminx 2254
            if (appactive && ev->jbutton.button < joystick.numButtons)
342 terminx 2255
            {
4749 terminx 2256
                if (ev->jbutton.state == SDL_PRESSED)
6827 terminx 2257
                    joystick.bits |= 1 << ev->jbutton.button;
109 terminx 2258
                else
6827 terminx 2259
                    joystick.bits &= ~(1 << ev->jbutton.button);
4853 hendricks2 2260
 
2261
#ifdef GEKKO
2262
                if (ev->jbutton.button == 0) // WII_A
2263
                    handleevents_updatemousestate(ev->jbutton.state);
2264
#endif
109 terminx 2265
            }
2266
            break;
5 Plagman 2267
 
109 terminx 2268
        case SDL_QUIT:
2269
            quitevent = 1;
4749 terminx 2270
            return -1;
109 terminx 2271
    }
2272
 
4749 terminx 2273
    return 0;
2274
}
1644 helixhorne 2275
 
4767 hendricks2 2276
int32_t handleevents_pollsdl(void);
4749 terminx 2277
#if SDL_MAJOR_VERSION != 1
2278
// SDL 2.0 specific event handling
2279
int32_t handleevents_pollsdl(void)
2280
{
2281
    int32_t code, rv=0, j;
2282
    SDL_Event ev;
109 terminx 2283
 
4749 terminx 2284
    while (SDL_PollEvent(&ev))
2285
    {
2286
        switch (ev.type)
2287
        {
2288
            case SDL_TEXTINPUT:
2289
                j = 0;
2290
                do
2291
                {
2292
                    code = ev.text.text[j];
2293
 
6827 terminx 2294
                    if (code != g_keyAsciiTable[OSD_OSDKey()] && !keyBufferFull())
4749 terminx 2295
                    {
2296
                        if (OSD_HandleChar(code))
6827 terminx 2297
                            keyBufferInsert(code);
4749 terminx 2298
                    }
7080 terminx 2299
                } while (j < SDL_TEXTINPUTEVENT_TEXT_SIZE-1 && ev.text.text[++j]);
4749 terminx 2300
                break;
2301
 
2302
            case SDL_KEYDOWN:
2303
            case SDL_KEYUP:
5324 helixhorne 2304
            {
7164 terminx 2305
                auto const &sc = ev.key.keysym.scancode;
5324 helixhorne 2306
                code = keytranslation[sc];
4749 terminx 2307
 
5808 helixhorne 2308
                // Modifiers that have to be held down to be effective
2309
                // (excludes KMOD_NUM, for example).
2310
                static const int MODIFIERS =
2311
                    KMOD_LSHIFT|KMOD_RSHIFT|KMOD_LCTRL|KMOD_RCTRL|
2312
                    KMOD_LALT|KMOD_RALT|KMOD_LGUI|KMOD_RGUI;
2313
 
4749 terminx 2314
                // XXX: see osd.c, OSD_HandleChar(), there are more...
6827 terminx 2315
                if (ev.key.type == SDL_KEYDOWN && !keyBufferFull() &&
5324 helixhorne 2316
                    (sc == SDL_SCANCODE_RETURN || sc == SDL_SCANCODE_KP_ENTER ||
2317
                     sc == SDL_SCANCODE_ESCAPE ||
2318
                     sc == SDL_SCANCODE_BACKSPACE ||
2319
                     sc == SDL_SCANCODE_TAB ||
5808 helixhorne 2320
                     (((ev.key.keysym.mod) & MODIFIERS) == KMOD_LCTRL &&
5324 helixhorne 2321
                      (sc >= SDL_SCANCODE_A && sc <= SDL_SCANCODE_Z))))
4749 terminx 2322
                {
2323
                    char keyvalue;
5324 helixhorne 2324
                    switch (sc)
4749 terminx 2325
                    {
2326
                        case SDL_SCANCODE_RETURN: case SDL_SCANCODE_KP_ENTER: keyvalue = '\r'; break;
2327
                        case SDL_SCANCODE_ESCAPE: keyvalue = 27; break;
2328
                        case SDL_SCANCODE_BACKSPACE: keyvalue = '\b'; break;
2329
                        case SDL_SCANCODE_TAB: keyvalue = '\t'; break;
5324 helixhorne 2330
                        default: keyvalue = sc - SDL_SCANCODE_A + 1; break;  // Ctrl+A --> 1, etc.
4749 terminx 2331
                    }
2332
                    if (OSD_HandleChar(keyvalue))
6827 terminx 2333
                        keyBufferInsert(keyvalue);
4749 terminx 2334
                }
6027 hendricks2 2335
                else if (ev.key.type == SDL_KEYDOWN &&
6827 terminx 2336
                         ev.key.keysym.sym != g_keyAsciiTable[OSD_OSDKey()] && !keyBufferFull() &&
5968 hendricks2 2337
                         !SDL_IsTextInputActive())
2338
                {
2339
                    /*
2340
                    Necessary for Duke 3D's method of entering cheats to work without showing IMEs.
2341
                    SDL_TEXTINPUT is preferable overall, but with bitmap fonts it has no advantage.
2342
                    */
6027 hendricks2 2343
                    SDL_Keycode keyvalue = ev.key.keysym.sym;
4749 terminx 2344
 
5968 hendricks2 2345
                    if ('a' <= keyvalue && keyvalue <= 'z')
2346
                    {
2347
                        if (!!(ev.key.keysym.mod & KMOD_SHIFT) ^ !!(ev.key.keysym.mod & KMOD_CAPS))
2348
                            keyvalue -= 'a'-'A';
2349
                    }
2350
                    else if (ev.key.keysym.mod & KMOD_SHIFT)
2351
                    {
2352
                        switch (keyvalue)
2353
                        {
2354
                            case '\'': keyvalue = '"'; break;
2355
 
2356
                            case ',': keyvalue = '<'; break;
2357
                            case '-': keyvalue = '_'; break;
2358
                            case '.': keyvalue = '>'; break;
2359
                            case '/': keyvalue = '?'; break;
2360
                            case '0': keyvalue = ')'; break;
2361
                            case '1': keyvalue = '!'; break;
2362
                            case '2': keyvalue = '@'; break;
2363
                            case '3': keyvalue = '#'; break;
2364
                            case '4': keyvalue = '$'; break;
2365
                            case '5': keyvalue = '%'; break;
2366
                            case '6': keyvalue = '^'; break;
2367
                            case '7': keyvalue = '&'; break;
2368
                            case '8': keyvalue = '*'; break;
2369
                            case '9': keyvalue = '('; break;
2370
 
2371
                            case ';': keyvalue = ':'; break;
2372
 
2373
                            case '=': keyvalue = '+'; break;
2374
 
2375
                            case '[': keyvalue = '{'; break;
2376
                            case '\\': keyvalue = '|'; break;
2377
                            case ']': keyvalue = '}'; break;
2378
 
2379
                            case '`': keyvalue = '~'; break;
2380
                        }
2381
                    }
6027 hendricks2 2382
                    else if (ev.key.keysym.mod & KMOD_NUM) // && !(ev.key.keysym.mod & KMOD_SHIFT)
2383
                    {
2384
                        switch (keyvalue)
2385
                        {
2386
                            case SDLK_KP_1: keyvalue = '1'; break;
2387
                            case SDLK_KP_2: keyvalue = '2'; break;
2388
                            case SDLK_KP_3: keyvalue = '3'; break;
2389
                            case SDLK_KP_4: keyvalue = '4'; break;
2390
                            case SDLK_KP_5: keyvalue = '5'; break;
2391
                            case SDLK_KP_6: keyvalue = '6'; break;
2392
                            case SDLK_KP_7: keyvalue = '7'; break;
2393
                            case SDLK_KP_8: keyvalue = '8'; break;
2394
                            case SDLK_KP_9: keyvalue = '9'; break;
2395
                            case SDLK_KP_0: keyvalue = '0'; break;
2396
                            case SDLK_KP_PERIOD: keyvalue = '.'; break;
2397
                            case SDLK_KP_COMMA: keyvalue = ','; break;
2398
                        }
2399
                    }
5968 hendricks2 2400
 
6027 hendricks2 2401
                    switch (keyvalue)
2402
                    {
2403
                        case SDLK_KP_DIVIDE: keyvalue = '/'; break;
2404
                        case SDLK_KP_MULTIPLY: keyvalue = '*'; break;
2405
                        case SDLK_KP_MINUS: keyvalue = '-'; break;
2406
                        case SDLK_KP_PLUS: keyvalue = '+'; break;
2407
                    }
2408
 
2409
                    if ((unsigned)keyvalue <= 0x7Fu)
2410
                    {
2411
                        if (OSD_HandleChar(keyvalue))
6827 terminx 2412
                            keyBufferInsert(keyvalue);
6027 hendricks2 2413
                    }
5968 hendricks2 2414
                }
2415
 
4749 terminx 2416
                // initprintf("SDL2: got key %d, %d, %u\n", ev.key.keysym.scancode, code, ev.key.type);
2417
 
2418
                // hook in the osd
2419
                if ((j = OSD_HandleScanCode(code, (ev.key.type == SDL_KEYDOWN))) <= 0)
2420
                {
2421
                    if (j == -1)  // osdkey
7164 terminx 2422
                    {
6827 terminx 2423
                        for (j = 0; j < NUMKEYS; ++j)
7164 terminx 2424
                        {
6827 terminx 2425
                            if (keyGetState(j))
4749 terminx 2426
                            {
2427
                                if (keypresscallback)
2428
                                    keypresscallback(j, 0);
2429
                            }
8431 hendricks2 2430
                            keySetState(j, 0);
7164 terminx 2431
                        }
2432
                    }
4749 terminx 2433
                    break;
2434
                }
2435
 
2436
                if (ev.key.type == SDL_KEYDOWN)
2437
                {
6827 terminx 2438
                    if (!keyGetState(code))
4749 terminx 2439
                    {
2440
                        if (keypresscallback)
2441
                            keypresscallback(code, 1);
2442
                    }
8431 hendricks2 2443
                    keySetState(code, 1);
4749 terminx 2444
                }
2445
                else
2446
                {
2447
# if 1
2448
                    // The pause key generates a release event right after
2449
                    // the pressing one. As a result, it gets unseen
2450
                    // by the game most of the time.
2451
                    if (code == 0x59)  // pause
2452
                        break;
2453
# endif
6827 terminx 2454
                    keySetState(code, 0);
4749 terminx 2455
                    if (keypresscallback)
2456
                        keypresscallback(code, 0);
2457
                }
2458
                break;
5324 helixhorne 2459
            }
4749 terminx 2460
 
2461
            case SDL_MOUSEWHEEL:
2462
                // initprintf("wheel y %d\n",ev.wheel.y);
2463
                if (ev.wheel.y > 0)
2464
                {
6827 terminx 2465
                    g_mouseBits |= 16;
2466
                    if (g_mouseCallback)
2467
                        g_mouseCallback(5, 1);
4749 terminx 2468
                }
2469
                if (ev.wheel.y < 0)
2470
                {
6827 terminx 2471
                    g_mouseBits |= 32;
2472
                    if (g_mouseCallback)
2473
                        g_mouseCallback(6, 1);
4749 terminx 2474
                }
2475
                break;
2476
 
2477
            case SDL_WINDOWEVENT:
2478
                switch (ev.window.event)
2479
                {
2480
                    case SDL_WINDOWEVENT_FOCUS_GAINED:
2481
                    case SDL_WINDOWEVENT_FOCUS_LOST:
2482
                        appactive = (ev.window.event == SDL_WINDOWEVENT_FOCUS_GAINED);
6827 terminx 2483
                        if (g_mouseGrabbed && g_mouseEnabled)
4749 terminx 2484
                            grabmouse_low(appactive);
2485
#ifdef _WIN32
8415 hendricks2 2486
                        windowsHandleFocusChange(appactive);
3219 hendricks2 2487
#endif
4749 terminx 2488
                        break;
5 Plagman 2489
 
4749 terminx 2490
                    case SDL_WINDOWEVENT_MOVED:
8063 terminx 2491
                    {
8612 terminx 2492
                        windowx = ev.window.data1;
2493
                        windowy = ev.window.data2;
8063 terminx 2494
 
2495
                        r_displayindex = SDL_GetWindowDisplayIndex(sdl_window);
2496
                        modeschecked = 0;
2497
                        videoGetModes();
4749 terminx 2498
                        break;
8063 terminx 2499
                    }
4753 terminx 2500
                    case SDL_WINDOWEVENT_ENTER:
2501
                    case SDL_WINDOWEVENT_LEAVE:
8174 terminx 2502
                        g_mouseInsideWindow = (ev.window.event == SDL_WINDOWEVENT_ENTER);
4753 terminx 2503
                        break;
4749 terminx 2504
                }
8063 terminx 2505
 
4749 terminx 2506
                break;
5 Plagman 2507
 
4749 terminx 2508
            default:
2509
                rv = handleevents_sdlcommon(&ev);
2510
                break;
2511
        }
2512
    }
2513
 
109 terminx 2514
    return rv;
5 Plagman 2515
}
4749 terminx 2516
#endif
5 Plagman 2517
 
4749 terminx 2518
int32_t handleevents(void)
1644 helixhorne 2519
{
4992 terminx 2520
#ifdef __ANDROID__
2521
    if (mobile_halted) return 0;
2522
#endif
2523
 
4749 terminx 2524
    int32_t rv;
1644 helixhorne 2525
 
6827 terminx 2526
    if (inputchecked && g_mouseEnabled)
1762 terminx 2527
    {
6827 terminx 2528
        if (g_mouseCallback)
1762 terminx 2529
        {
6827 terminx 2530
            if (g_mouseBits & 16)
2531
                g_mouseCallback(5, 0);
2532
            if (g_mouseBits & 32)
2533
                g_mouseCallback(6, 0);
1644 helixhorne 2534
        }
8380 terminx 2535
 
2536
        OSD_HandleWheel();
6827 terminx 2537
        g_mouseBits &= ~(16 | 32);
1644 helixhorne 2538
    }
4749 terminx 2539
 
2540
    rv = handleevents_pollsdl();
2541
 
2542
    inputchecked = 0;
8169 terminx 2543
    timerUpdateClock();
4749 terminx 2544
 
8094 hendricks2 2545
    communityapiRunCallbacks();
2546
 
4749 terminx 2547
#ifndef _WIN32
2548
    startwin_idle(NULL);
1644 helixhorne 2549
#endif
2550
 
4749 terminx 2551
    return rv;
2552
}
109 terminx 2553
 
4749 terminx 2554
#if SDL_MAJOR_VERSION == 1
6056 hendricks2 2555
#include "sdlayer12.cpp"
4749 terminx 2556
#endif