Support for QNX 7.0 (thanks, Elad!).
authorRyan C. Gordon <icculus@icculus.org>
Sat, 01 Jul 2017 17:50:47 -0400
changeset 1111928d3a50e276e
parent 11118 5d7fc5c843a0
child 11120 e1fc7d3b46fb
Support for QNX 7.0 (thanks, Elad!).

Fixes Bugzilla #3686.
configure.in
include/SDL_config.h.in
src/audio/SDL_sysaudio.h
src/audio/qsa/SDL_qsa_audio.c
src/dynapi/SDL_dynapi.c
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/qnx/gl.c
src/video/qnx/keyboard.c
src/video/qnx/sdl_qnx.h
src/video/qnx/video.c
     1.1 --- a/configure.in	Sat Jul 01 23:01:57 2017 +0200
     1.2 +++ b/configure.in	Sat Jul 01 17:50:47 2017 -0400
     1.3 @@ -2098,6 +2098,30 @@
     1.4      fi
     1.5  }
     1.6  
     1.7 +dnl Set up the QNX video driver if enabled
     1.8 +CheckQNXVideo()
     1.9 +{
    1.10 +    if test x$enable_video = xyes; then
    1.11 +        AC_DEFINE(SDL_VIDEO_DRIVER_QNX, 1, [ ])
    1.12 +        SOURCES="$SOURCES $srcdir/src/video/qnx/*.c"
    1.13 +        have_video=yes
    1.14 +        EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lscreen -lEGL -lGLESv2"
    1.15 +        SUMMARY_video="${SUMMARY_video} qnx"
    1.16 +    fi
    1.17 +}
    1.18 +
    1.19 +dnl Set up the QNX audio driver if enabled
    1.20 +CheckQNXAudio()
    1.21 +{
    1.22 +    if test x$enable_audio = xyes; then
    1.23 +        AC_DEFINE(SDL_AUDIO_DRIVER_QSA, 1, [ ])
    1.24 +        SOURCES="$SOURCES $srcdir/src/audio/qsa/*.c"
    1.25 +        have_video=yes
    1.26 +        EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lasound"
    1.27 +        SUMMARY_audio="${SUMMARY_audio} qsa"
    1.28 +    fi
    1.29 +}
    1.30 +
    1.31  dnl Check to see if OpenGL support is desired
    1.32  AC_ARG_ENABLE(video-opengl,
    1.33  AC_HELP_STRING([--enable-video-opengl], [include OpenGL support [[default=yes]]]),
    1.34 @@ -2573,6 +2597,10 @@
    1.35              pthread_cflags="-D_REENTRANT"
    1.36              pthread_lib=""
    1.37              ;;
    1.38 +        *-*-nto*)
    1.39 +            pthread_cflags="-D_REENTRANT"
    1.40 +            pthread_lib=""
    1.41 +            ;;
    1.42          *)
    1.43              pthread_cflags="-D_REENTRANT"
    1.44              pthread_lib="-lpthread"
    1.45 @@ -3017,7 +3045,7 @@
    1.46  
    1.47  dnl Set up the configuration based on the host platform!
    1.48  case "$host" in
    1.49 -    *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
    1.50 +    *-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
    1.51          case "$host" in
    1.52              *-raspberry-linux*)
    1.53                  # Raspberry Pi
    1.54 @@ -3082,6 +3110,9 @@
    1.55              *-*-hpux*)          ARCH=hpux ;;
    1.56              *-*-aix*)           ARCH=aix ;;
    1.57              *-*-minix*)         ARCH=minix ;;
    1.58 +            *-*-nto*)           ARCH=nto
    1.59 +                CheckQNXVideo
    1.60 +                ;;
    1.61          esac
    1.62          CheckVisibilityHidden
    1.63          CheckDeclarationAfterStatement
    1.64 @@ -3123,6 +3154,7 @@
    1.65          CheckLinuxVersion
    1.66          CheckRPATH
    1.67          CheckVivanteVideo
    1.68 +
    1.69          # Set up files for the audio library
    1.70          if test x$enable_audio = xyes; then
    1.71            case $ARCH in
    1.72 @@ -3147,6 +3179,9 @@
    1.73                  SUMMARY_audio="${SUMMARY_audio} android"
    1.74                  have_audio=yes
    1.75              ;;
    1.76 +            nto)
    1.77 +                CheckQNXAudio
    1.78 +            ;;
    1.79            esac
    1.80          fi
    1.81          # Set up files for the joystick library
     2.1 --- a/include/SDL_config.h.in	Sat Jul 01 23:01:57 2017 +0200
     2.2 +++ b/include/SDL_config.h.in	Sat Jul 01 17:50:47 2017 -0400
     2.3 @@ -317,6 +317,7 @@
     2.4  #undef SDL_VIDEO_DRIVER_NACL
     2.5  #undef SDL_VIDEO_DRIVER_VIVANTE
     2.6  #undef SDL_VIDEO_DRIVER_VIVANTE_VDK
     2.7 +#undef SDL_VIDEO_DRIVER_QNX
     2.8  
     2.9  #undef SDL_VIDEO_RENDER_D3D
    2.10  #undef SDL_VIDEO_RENDER_D3D11
     3.1 --- a/src/audio/SDL_sysaudio.h	Sat Jul 01 23:01:57 2017 +0200
     3.2 +++ b/src/audio/SDL_sysaudio.h	Sat Jul 01 17:50:47 2017 -0400
     3.3 @@ -205,6 +205,7 @@
     3.4  extern AudioBootStrap ANDROIDAUDIO_bootstrap;
     3.5  extern AudioBootStrap PSPAUDIO_bootstrap;
     3.6  extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
     3.7 +extern AudioBootStrap QNX_bootstrap;
     3.8  
     3.9  #endif /* SDL_sysaudio_h_ */
    3.10  
     4.1 --- a/src/audio/qsa/SDL_qsa_audio.c	Sat Jul 01 23:01:57 2017 +0200
     4.2 +++ b/src/audio/qsa/SDL_qsa_audio.c	Sat Jul 01 17:50:47 2017 -0400
     4.3 @@ -370,13 +370,13 @@
     4.4          this->hidden->cardno = device->cardno;
     4.5          status = snd_pcm_open(&this->hidden->audio_handle,
     4.6                                device->cardno, device->deviceno,
     4.7 -                              iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
     4.8 +                              iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
     4.9      } else {
    4.10          /* Open system default audio device */
    4.11          status = snd_pcm_open_preferred(&this->hidden->audio_handle,
    4.12                                          &this->hidden->cardno,
    4.13                                          &this->hidden->deviceno,
    4.14 -                                        iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
    4.15 +                                        iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
    4.16      }
    4.17  
    4.18      /* Check if requested device is opened */
    4.19 @@ -385,6 +385,7 @@
    4.20          return QSA_SetError("snd_pcm_open", status);
    4.21      }
    4.22  
    4.23 +#if 0
    4.24      if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
    4.25          /* Disable QSA MMAP plugin for buggy audio drivers */
    4.26          status =
    4.27 @@ -394,6 +395,7 @@
    4.28              return QSA_SetError("snd_pcm_plugin_set_disable", status);
    4.29          }
    4.30      }
    4.31 +#endif
    4.32  
    4.33      /* Try for a closest match on audio format */
    4.34      format = 0;
     5.1 --- a/src/dynapi/SDL_dynapi.c	Sat Jul 01 23:01:57 2017 +0200
     5.2 +++ b/src/dynapi/SDL_dynapi.c	Sat Jul 01 17:50:47 2017 -0400
     5.3 @@ -216,7 +216,7 @@
     5.4      return retval;
     5.5  }
     5.6  
     5.7 -#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
     5.8 +#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__QNX__)
     5.9  #include <dlfcn.h>
    5.10  static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
    5.11  {
    5.12 @@ -302,4 +302,3 @@
    5.13  #endif  /* SDL_DYNAMIC_API */
    5.14  
    5.15  /* vi: set ts=4 sw=4 expandtab: */
    5.16 -
     6.1 --- a/src/video/SDL_sysvideo.h	Sat Jul 01 23:01:57 2017 +0200
     6.2 +++ b/src/video/SDL_sysvideo.h	Sat Jul 01 17:50:47 2017 -0400
     6.3 @@ -390,6 +390,7 @@
     6.4  extern VideoBootStrap NACL_bootstrap;
     6.5  extern VideoBootStrap VIVANTE_bootstrap;
     6.6  extern VideoBootStrap Emscripten_bootstrap;
     6.7 +extern VideoBootStrap QNX_bootstrap;
     6.8  
     6.9  extern SDL_VideoDevice *SDL_GetVideoDevice(void);
    6.10  extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);
     7.1 --- a/src/video/SDL_video.c	Sat Jul 01 23:01:57 2017 +0200
     7.2 +++ b/src/video/SDL_video.c	Sat Jul 01 17:50:47 2017 -0400
     7.3 @@ -111,6 +111,9 @@
     7.4  #if SDL_VIDEO_DRIVER_EMSCRIPTEN
     7.5      &Emscripten_bootstrap,
     7.6  #endif
     7.7 +#if SDL_VIDEO_DRIVER_QNX
     7.8 +    &QNX_bootstrap,
     7.9 +#endif
    7.10  #if SDL_VIDEO_DRIVER_DUMMY
    7.11      &DUMMY_bootstrap,
    7.12  #endif
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/src/video/qnx/gl.c	Sat Jul 01 17:50:47 2017 -0400
     8.3 @@ -0,0 +1,283 @@
     8.4 +/*
     8.5 +  Simple DirectMedia Layer
     8.6 +  Copyright (C) 2017 BlackBerry Limited
     8.7 +
     8.8 +  This software is provided 'as-is', without any express or implied
     8.9 +  warranty.  In no event will the authors be held liable for any damages
    8.10 +  arising from the use of this software.
    8.11 +
    8.12 +  Permission is granted to anyone to use this software for any purpose,
    8.13 +  including commercial applications, and to alter it and redistribute it
    8.14 +  freely, subject to the following restrictions:
    8.15 +
    8.16 +  1. The origin of this software must not be misrepresented; you must not
    8.17 +     claim that you wrote the original software. If you use this software
    8.18 +     in a product, an acknowledgment in the product documentation would be
    8.19 +     appreciated but is not required.
    8.20 +  2. Altered source versions must be plainly marked as such, and must not be
    8.21 +     misrepresented as being the original software.
    8.22 +  3. This notice may not be removed or altered from any source distribution.
    8.23 +*/
    8.24 +
    8.25 +#include "../../SDL_internal.h"
    8.26 +#include "sdl_qnx.h"
    8.27 +
    8.28 +static EGLDisplay   egl_disp;
    8.29 +
    8.30 +/**
    8.31 + * Detertmines the pixel format to use based on the current display and EGL
    8.32 + * configuration.
    8.33 + * @param   egl_conf    EGL configuration to use
    8.34 + * @return  A SCREEN_FORMAT* constant for the pixel format to use
    8.35 + */
    8.36 +static int
    8.37 +chooseFormat(EGLConfig egl_conf)
    8.38 +{
    8.39 +    EGLint buffer_bit_depth;
    8.40 +    EGLint alpha_bit_depth;
    8.41 +
    8.42 +    eglGetConfigAttrib(egl_disp, egl_conf, EGL_BUFFER_SIZE, &buffer_bit_depth);
    8.43 +    eglGetConfigAttrib(egl_disp, egl_conf, EGL_ALPHA_SIZE, &alpha_bit_depth);
    8.44 +
    8.45 +    switch (buffer_bit_depth) {
    8.46 +        case 32:
    8.47 +            return SCREEN_FORMAT_RGBX8888;
    8.48 +        case 24:
    8.49 +            return SCREEN_FORMAT_RGB888;
    8.50 +        case 16:
    8.51 +            switch (alpha_bit_depth) {
    8.52 +                case 4:
    8.53 +                    return SCREEN_FORMAT_RGBX4444;
    8.54 +                case 1:
    8.55 +                    return SCREEN_FORMAT_RGBA5551;
    8.56 +                default:
    8.57 +                    return SCREEN_FORMAT_RGB565;
    8.58 +            }
    8.59 +        default:
    8.60 +            return 0;
    8.61 +    }
    8.62 +}
    8.63 +
    8.64 +/**
    8.65 + * Enumerates the supported EGL configurations and chooses a suitable one.
    8.66 + * @param[out]  pconf   The chosen configuration
    8.67 + * @param[out]  pformat The chosen pixel format
    8.68 + * @return 0 if successful, -1 on error
    8.69 + */
    8.70 +int
    8.71 +glGetConfig(EGLConfig *pconf, int *pformat)
    8.72 +{
    8.73 +    EGLConfig egl_conf = (EGLConfig)0;
    8.74 +    EGLConfig *egl_configs;
    8.75 +    EGLint egl_num_configs;
    8.76 +    EGLint val;
    8.77 +    EGLBoolean rc;
    8.78 +    EGLint i;
    8.79 +
    8.80 +    // Determine the numbfer of configurations.
    8.81 +    rc = eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
    8.82 +    if (rc != EGL_TRUE) {
    8.83 +        return -1;
    8.84 +    }
    8.85 +
    8.86 +    if (egl_num_configs == 0) {
    8.87 +        return -1;
    8.88 +    }
    8.89 +
    8.90 +    // Allocate enough memory for all configurations.
    8.91 +    egl_configs = malloc(egl_num_configs * sizeof(*egl_configs));
    8.92 +    if (egl_configs == NULL) {
    8.93 +        return -1;
    8.94 +    }
    8.95 +
    8.96 +    // Get the list of configurations.
    8.97 +    rc = eglGetConfigs(egl_disp, egl_configs, egl_num_configs,
    8.98 +                       &egl_num_configs);
    8.99 +    if (rc != EGL_TRUE) {
   8.100 +        free(egl_configs);
   8.101 +        return -1;
   8.102 +    }
   8.103 +
   8.104 +    // Find a good configuration.
   8.105 +    for (i = 0; i < egl_num_configs; i++) {
   8.106 +        eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
   8.107 +        if (!(val & EGL_WINDOW_BIT)) {
   8.108 +            continue;
   8.109 +        }
   8.110 +
   8.111 +        eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
   8.112 +        if (!(val & EGL_OPENGL_ES2_BIT)) {
   8.113 +            continue;
   8.114 +        }
   8.115 +
   8.116 +        eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_DEPTH_SIZE, &val);
   8.117 +        if (val == 0) {
   8.118 +            continue;
   8.119 +        }
   8.120 +
   8.121 +        egl_conf = egl_configs[i];
   8.122 +        break;
   8.123 +    }
   8.124 +
   8.125 +    free(egl_configs);
   8.126 +    *pconf = egl_conf;
   8.127 +    *pformat = chooseFormat(egl_conf);
   8.128 +
   8.129 +    return 0;
   8.130 +}
   8.131 +
   8.132 +/**
   8.133 + * Initializes the EGL library.
   8.134 + * @param   _THIS
   8.135 + * @param   name    unused
   8.136 + * @return  0 if successful, -1 on error
   8.137 + */
   8.138 +int
   8.139 +glLoadLibrary(_THIS, const char *name)
   8.140 +{
   8.141 +    EGLNativeDisplayType    disp_id = EGL_DEFAULT_DISPLAY;
   8.142 +
   8.143 +    egl_disp = eglGetDisplay(disp_id);
   8.144 +    if (egl_disp == EGL_NO_DISPLAY) {
   8.145 +        return -1;
   8.146 +    }
   8.147 +
   8.148 +    if (eglInitialize(egl_disp, NULL, NULL) == EGL_FALSE) {
   8.149 +        return -1;
   8.150 +    }
   8.151 +
   8.152 +    return 0;
   8.153 +}
   8.154 +
   8.155 +/**
   8.156 + * Finds the address of an EGL extension function.
   8.157 + * @param   proc    Function name
   8.158 + * @return  Function address
   8.159 + */
   8.160 +void *
   8.161 +glGetProcAddress(_THIS, const char *proc)
   8.162 +{
   8.163 +    return eglGetProcAddress(proc);
   8.164 +}
   8.165 +
   8.166 +/**
   8.167 + * Associates the given window with the necessary EGL structures for drawing and
   8.168 + * displaying content.
   8.169 + * @param   _THIS
   8.170 + * @param   window  The SDL window to create the context for
   8.171 + * @return  A pointer to the created context, if successful, NULL on error
   8.172 + */
   8.173 +SDL_GLContext
   8.174 +glCreateContext(_THIS, SDL_Window *window)
   8.175 +{
   8.176 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
   8.177 +    EGLContext      context;
   8.178 +    EGLSurface      surface;
   8.179 +
   8.180 +    struct {
   8.181 +        EGLint client_version[2];
   8.182 +        EGLint none;
   8.183 +    } egl_ctx_attr = {
   8.184 +        .client_version = { EGL_CONTEXT_CLIENT_VERSION, 2 },
   8.185 +        .none = EGL_NONE
   8.186 +    };
   8.187 +
   8.188 +    struct {
   8.189 +        EGLint render_buffer[2];
   8.190 +        EGLint none;
   8.191 +    } egl_surf_attr = {
   8.192 +        .render_buffer = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER },
   8.193 +        .none = EGL_NONE
   8.194 +    };
   8.195 +
   8.196 +    context = eglCreateContext(egl_disp, impl->conf, EGL_NO_CONTEXT,
   8.197 +                               (EGLint *)&egl_ctx_attr);
   8.198 +    if (context == EGL_NO_CONTEXT) {
   8.199 +        return NULL;
   8.200 +    }
   8.201 +
   8.202 +    surface = eglCreateWindowSurface(egl_disp, impl->conf, impl->window,
   8.203 +                                     (EGLint *)&egl_surf_attr);
   8.204 +    if (surface == EGL_NO_SURFACE) {
   8.205 +        return NULL;
   8.206 +    }
   8.207 +
   8.208 +    eglMakeCurrent(egl_disp, surface, surface, context);
   8.209 +
   8.210 +    impl->surface = surface;
   8.211 +    return context;
   8.212 +}
   8.213 +
   8.214 +/**
   8.215 + * Sets a new value for the number of frames to display before swapping buffers.
   8.216 + * @param   _THIS
   8.217 + * @param   interval    New interval value
   8.218 + * @return  0 if successful, -1 on error
   8.219 + */
   8.220 +int
   8.221 +glSetSwapInterval(_THIS, int interval)
   8.222 +{
   8.223 +    if (eglSwapInterval(egl_disp, interval) != EGL_TRUE) {
   8.224 +        return -1;
   8.225 +    }
   8.226 +
   8.227 +    return 0;
   8.228 +}
   8.229 +
   8.230 +/**
   8.231 + * Swaps the EGL buffers associated with the given window
   8.232 + * @param   _THIS
   8.233 + * @paran   window  Window to swap buffers for
   8.234 + */
   8.235 +void
   8.236 +glSwapWindow(_THIS, SDL_Window *window)
   8.237 +{
   8.238 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
   8.239 +    eglSwapBuffers(egl_disp, impl->surface);
   8.240 +}
   8.241 +
   8.242 +/**
   8.243 + * Makes the given context the current one for drawing operations.
   8.244 + * @param   _THIS
   8.245 + * @param   window  SDL window associated with the context (maybe NULL)
   8.246 + * @param   context The context to activate
   8.247 + * @return  0 if successful, -1 on error
   8.248 + */
   8.249 +int
   8.250 +glMakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
   8.251 +{
   8.252 +    window_impl_t   *impl;
   8.253 +    EGLSurface      surface = NULL;
   8.254 +
   8.255 +    if (window) {
   8.256 +        impl = (window_impl_t *)window->driverdata;
   8.257 +        surface = impl->surface;
   8.258 +    }
   8.259 +
   8.260 +    if (eglMakeCurrent(egl_disp, surface, surface, context) != EGL_TRUE) {
   8.261 +        return -1;
   8.262 +    }
   8.263 +
   8.264 +    return 0;
   8.265 +}
   8.266 +
   8.267 +/**
   8.268 + * Destroys a context.
   8.269 + * @param   _THIS
   8.270 + * @param   context The context to destroy
   8.271 + */
   8.272 +void
   8.273 +glDeleteContext(_THIS, SDL_GLContext context)
   8.274 +{
   8.275 +    eglDestroyContext(egl_disp, context);
   8.276 +}
   8.277 +
   8.278 +/**
   8.279 + * Terminates access to the EGL library.
   8.280 + * @param   _THIS
   8.281 + */
   8.282 +void
   8.283 +glUnloadLibrary(_THIS)
   8.284 +{
   8.285 +    eglTerminate(egl_disp);
   8.286 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/src/video/qnx/keyboard.c	Sat Jul 01 17:50:47 2017 -0400
     9.3 @@ -0,0 +1,133 @@
     9.4 +/*
     9.5 +  Simple DirectMedia Layer
     9.6 +  Copyright (C) 2017 BlackBerry Limited
     9.7 +
     9.8 +  This software is provided 'as-is', without any express or implied
     9.9 +  warranty.  In no event will the authors be held liable for any damages
    9.10 +  arising from the use of this software.
    9.11 +
    9.12 +  Permission is granted to anyone to use this software for any purpose,
    9.13 +  including commercial applications, and to alter it and redistribute it
    9.14 +  freely, subject to the following restrictions:
    9.15 +
    9.16 +  1. The origin of this software must not be misrepresented; you must not
    9.17 +     claim that you wrote the original software. If you use this software
    9.18 +     in a product, an acknowledgment in the product documentation would be
    9.19 +     appreciated but is not required.
    9.20 +  2. Altered source versions must be plainly marked as such, and must not be
    9.21 +     misrepresented as being the original software.
    9.22 +  3. This notice may not be removed or altered from any source distribution.
    9.23 +*/
    9.24 +
    9.25 +#include "../../SDL_internal.h"
    9.26 +#include "../../events/SDL_keyboard_c.h"
    9.27 +#include "SDL_scancode.h"
    9.28 +#include "SDL_events.h"
    9.29 +#include "sdl_qnx.h"
    9.30 +#include <sys/keycodes.h>
    9.31 +
    9.32 +/**
    9.33 + * A map thta translates Screen key names to SDL scan codes.
    9.34 + * This map is incomplete, but should include most major keys.
    9.35 + */
    9.36 +static int  key_to_sdl[] = {
    9.37 +    [KEYCODE_SPACE] = SDL_SCANCODE_SPACE,
    9.38 +    [KEYCODE_APOSTROPHE] = SDL_SCANCODE_APOSTROPHE,
    9.39 +    [KEYCODE_COMMA] = SDL_SCANCODE_COMMA,
    9.40 +    [KEYCODE_MINUS] = SDL_SCANCODE_MINUS,
    9.41 +    [KEYCODE_PERIOD] = SDL_SCANCODE_PERIOD,
    9.42 +    [KEYCODE_SLASH] = SDL_SCANCODE_SLASH,
    9.43 +    [KEYCODE_ZERO] = SDL_SCANCODE_0,
    9.44 +    [KEYCODE_ONE] = SDL_SCANCODE_1,
    9.45 +    [KEYCODE_TWO] = SDL_SCANCODE_2,
    9.46 +    [KEYCODE_THREE] = SDL_SCANCODE_3,
    9.47 +    [KEYCODE_FOUR] = SDL_SCANCODE_4,
    9.48 +    [KEYCODE_FIVE] = SDL_SCANCODE_5,
    9.49 +    [KEYCODE_SIX] = SDL_SCANCODE_6,
    9.50 +    [KEYCODE_SEVEN] = SDL_SCANCODE_7,
    9.51 +    [KEYCODE_EIGHT] = SDL_SCANCODE_8,
    9.52 +    [KEYCODE_NINE] = SDL_SCANCODE_9,
    9.53 +    [KEYCODE_SEMICOLON] = SDL_SCANCODE_SEMICOLON,
    9.54 +    [KEYCODE_EQUAL] = SDL_SCANCODE_EQUALS,
    9.55 +    [KEYCODE_LEFT_BRACKET] = SDL_SCANCODE_LEFTBRACKET,
    9.56 +    [KEYCODE_BACK_SLASH] = SDL_SCANCODE_BACKSLASH,
    9.57 +    [KEYCODE_RIGHT_BRACKET] = SDL_SCANCODE_RIGHTBRACKET,
    9.58 +    [KEYCODE_GRAVE] = SDL_SCANCODE_GRAVE,
    9.59 +    [KEYCODE_A] = SDL_SCANCODE_A,
    9.60 +    [KEYCODE_B] = SDL_SCANCODE_B,
    9.61 +    [KEYCODE_C] = SDL_SCANCODE_C,
    9.62 +    [KEYCODE_D] = SDL_SCANCODE_D,
    9.63 +    [KEYCODE_E] = SDL_SCANCODE_E,
    9.64 +    [KEYCODE_F] = SDL_SCANCODE_F,
    9.65 +    [KEYCODE_G] = SDL_SCANCODE_G,
    9.66 +    [KEYCODE_H] = SDL_SCANCODE_H,
    9.67 +    [KEYCODE_I] = SDL_SCANCODE_I,
    9.68 +    [KEYCODE_J] = SDL_SCANCODE_J,
    9.69 +    [KEYCODE_K] = SDL_SCANCODE_K,
    9.70 +    [KEYCODE_L] = SDL_SCANCODE_L,
    9.71 +    [KEYCODE_M] = SDL_SCANCODE_M,
    9.72 +    [KEYCODE_N] = SDL_SCANCODE_N,
    9.73 +    [KEYCODE_O] = SDL_SCANCODE_O,
    9.74 +    [KEYCODE_P] = SDL_SCANCODE_P,
    9.75 +    [KEYCODE_Q] = SDL_SCANCODE_Q,
    9.76 +    [KEYCODE_R] = SDL_SCANCODE_R,
    9.77 +    [KEYCODE_S] = SDL_SCANCODE_S,
    9.78 +    [KEYCODE_T] = SDL_SCANCODE_T,
    9.79 +    [KEYCODE_U] = SDL_SCANCODE_U,
    9.80 +    [KEYCODE_V] = SDL_SCANCODE_V,
    9.81 +    [KEYCODE_W] = SDL_SCANCODE_W,
    9.82 +    [KEYCODE_X] = SDL_SCANCODE_X,
    9.83 +    [KEYCODE_Y] = SDL_SCANCODE_Y,
    9.84 +    [KEYCODE_Z] = SDL_SCANCODE_Z,
    9.85 +    [KEYCODE_UP] = SDL_SCANCODE_UP,
    9.86 +    [KEYCODE_DOWN] = SDL_SCANCODE_DOWN,
    9.87 +    [KEYCODE_LEFT] = SDL_SCANCODE_LEFT,
    9.88 +    [KEYCODE_PG_UP] = SDL_SCANCODE_PAGEUP,
    9.89 +    [KEYCODE_PG_DOWN] = SDL_SCANCODE_PAGEDOWN,
    9.90 +    [KEYCODE_RIGHT] = SDL_SCANCODE_RIGHT,
    9.91 +    [KEYCODE_RETURN] = SDL_SCANCODE_RETURN,
    9.92 +    [KEYCODE_TAB] = SDL_SCANCODE_TAB,
    9.93 +    [KEYCODE_ESCAPE] = SDL_SCANCODE_ESCAPE,
    9.94 +};
    9.95 +
    9.96 +/**
    9.97 + * Called from the event dispatcher when a keyboard event is encountered.
    9.98 + * Translates the event such that it can be handled by SDL.
    9.99 + * @param   event   Screen keyboard event
   9.100 + */
   9.101 +void
   9.102 +handleKeyboardEvent(screen_event_t event)
   9.103 +{
   9.104 +    int             val;
   9.105 +    SDL_Scancode    scancode;
   9.106 +
   9.107 +    // Get the key value.
   9.108 +    if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &val) < 0) {
   9.109 +        return;
   9.110 +    }
   9.111 +
   9.112 +    // Skip unrecognized keys.
   9.113 +    if ((val < 0) || (val > (sizeof(key_to_sdl) / sizeof(int)))) {
   9.114 +        return;
   9.115 +    }
   9.116 +
   9.117 +    // Translate to an SDL scan code.
   9.118 +    scancode = key_to_sdl[val];
   9.119 +    if (scancode == 0) {
   9.120 +        return;
   9.121 +    }
   9.122 +
   9.123 +    // Get event flags (key state).
   9.124 +    if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &val) < 0) {
   9.125 +        return;
   9.126 +    }
   9.127 +
   9.128 +    // Propagate the event to SDL.
   9.129 +    // FIXME:
   9.130 +    // Need to handle more key states (such as key combinations).
   9.131 +    if (val & KEY_DOWN) {
   9.132 +        SDL_SendKeyboardKey(SDL_PRESSED, scancode);
   9.133 +    } else {
   9.134 +        SDL_SendKeyboardKey(SDL_RELEASED, scancode);
   9.135 +    }
   9.136 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/src/video/qnx/sdl_qnx.h	Sat Jul 01 17:50:47 2017 -0400
    10.3 @@ -0,0 +1,48 @@
    10.4 +/*
    10.5 +  Simple DirectMedia Layer
    10.6 +  Copyright (C) 2017 BlackBerry Limited
    10.7 +
    10.8 +  This software is provided 'as-is', without any express or implied
    10.9 +  warranty.  In no event will the authors be held liable for any damages
   10.10 +  arising from the use of this software.
   10.11 +
   10.12 +  Permission is granted to anyone to use this software for any purpose,
   10.13 +  including commercial applications, and to alter it and redistribute it
   10.14 +  freely, subject to the following restrictions:
   10.15 +
   10.16 +  1. The origin of this software must not be misrepresented; you must not
   10.17 +     claim that you wrote the original software. If you use this software
   10.18 +     in a product, an acknowledgment in the product documentation would be
   10.19 +     appreciated but is not required.
   10.20 +  2. Altered source versions must be plainly marked as such, and must not be
   10.21 +     misrepresented as being the original software.
   10.22 +  3. This notice may not be removed or altered from any source distribution.
   10.23 +*/
   10.24 +
   10.25 +#ifndef __SDL_QNX_H__
   10.26 +#define __SDL_QNX_H__
   10.27 +
   10.28 +#include "../SDL_sysvideo.h"
   10.29 +#include <screen/screen.h>
   10.30 +#include <EGL/egl.h>
   10.31 +
   10.32 +typedef struct
   10.33 +{
   10.34 +    screen_window_t window;
   10.35 +    EGLSurface      surface;
   10.36 +    EGLConfig       conf;
   10.37 +} window_impl_t;
   10.38 +
   10.39 +extern void handleKeyboardEvent(screen_event_t event);
   10.40 +
   10.41 +extern int glGetConfig(EGLConfig *pconf, int *pformat);
   10.42 +extern int glLoadLibrary(_THIS, const char *name);
   10.43 +void *glGetProcAddress(_THIS, const char *proc);
   10.44 +extern SDL_GLContext glCreateContext(_THIS, SDL_Window *window);
   10.45 +extern int glSetSwapInterval(_THIS, int interval);
   10.46 +extern void glSwapWindow(_THIS, SDL_Window *window);
   10.47 +extern int glMakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
   10.48 +extern void glDeleteContext(_THIS, SDL_GLContext context);
   10.49 +extern void glUnloadLibrary(_THIS);
   10.50 +
   10.51 +#endif
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/src/video/qnx/video.c	Sat Jul 01 17:50:47 2017 -0400
    11.3 @@ -0,0 +1,364 @@
    11.4 +/*
    11.5 +  Simple DirectMedia Layer
    11.6 +  Copyright (C) 2017 BlackBerry Limited
    11.7 +
    11.8 +  This software is provided 'as-is', without any express or implied
    11.9 +  warranty.  In no event will the authors be held liable for any damages
   11.10 +  arising from the use of this software.
   11.11 +
   11.12 +  Permission is granted to anyone to use this software for any purpose,
   11.13 +  including commercial applications, and to alter it and redistribute it
   11.14 +  freely, subject to the following restrictions:
   11.15 +
   11.16 +  1. The origin of this software must not be misrepresented; you must not
   11.17 +     claim that you wrote the original software. If you use this software
   11.18 +     in a product, an acknowledgment in the product documentation would be
   11.19 +     appreciated but is not required.
   11.20 +  2. Altered source versions must be plainly marked as such, and must not be
   11.21 +     misrepresented as being the original software.
   11.22 +  3. This notice may not be removed or altered from any source distribution.
   11.23 +*/
   11.24 +#include "../../SDL_internal.h"
   11.25 +#include "../SDL_sysvideo.h"
   11.26 +#include "sdl_qnx.h"
   11.27 +
   11.28 +static screen_context_t context;
   11.29 +static screen_event_t   event;
   11.30 +
   11.31 +/**
   11.32 + * Initializes the QNX video plugin.
   11.33 + * Creates the Screen context and event handles used for all window operations
   11.34 + * by the plugin.
   11.35 + * @param   _THIS
   11.36 + * @return  0 if successful, -1 on error
   11.37 + */
   11.38 +static int
   11.39 +videoInit(_THIS)
   11.40 +{
   11.41 +    SDL_VideoDisplay display;
   11.42 +
   11.43 +    if (screen_create_context(&context, 0) < 0) {
   11.44 +        return -1;
   11.45 +    }
   11.46 +
   11.47 +    if (screen_create_event(&event) < 0) {
   11.48 +        return -1;
   11.49 +    }
   11.50 +
   11.51 +    SDL_zero(display);
   11.52 +
   11.53 +    if (SDL_AddVideoDisplay(&display) < 0) {
   11.54 +        return -1;
   11.55 +    }
   11.56 +
   11.57 +    _this->num_displays = 1;
   11.58 +    return 0;
   11.59 +}
   11.60 +
   11.61 +static void
   11.62 +videoQuit(_THIS)
   11.63 +{
   11.64 +}
   11.65 +
   11.66 +/**
   11.67 + * Creates a new native Screen window and associates it with the given SDL
   11.68 + * window.
   11.69 + * @param   _THIS
   11.70 + * @param   window  SDL window to initialize
   11.71 + * @return  0 if successful, -1 on error
   11.72 + */
   11.73 +static int
   11.74 +createWindow(_THIS, SDL_Window *window)
   11.75 +{
   11.76 +    window_impl_t   *impl;
   11.77 +    int             size[2];
   11.78 +    int             numbufs;
   11.79 +    int             format;
   11.80 +    int             usage;
   11.81 +
   11.82 +    impl = SDL_calloc(1, sizeof(*impl));
   11.83 +    if (impl == NULL) {
   11.84 +        return -1;
   11.85 +    }
   11.86 +
   11.87 +    // Create a native window.
   11.88 +    if (screen_create_window(&impl->window, context) < 0) {
   11.89 +        goto fail;
   11.90 +    }
   11.91 +
   11.92 +    // Set the native window's size to match the SDL window.
   11.93 +    size[0] = window->w;
   11.94 +    size[1] = window->h;
   11.95 +
   11.96 +    if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE,
   11.97 +                                      size) < 0) {
   11.98 +        goto fail;
   11.99 +    }
  11.100 +
  11.101 +    if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE,
  11.102 +                                      size) < 0) {
  11.103 +        goto fail;
  11.104 +    }
  11.105 +
  11.106 +    // Create window buffer(s).
  11.107 +    if (window->flags & SDL_WINDOW_OPENGL) {
  11.108 +        if (glGetConfig(&impl->conf, &format) < 0) {
  11.109 +            goto fail;
  11.110 +        }
  11.111 +        numbufs = 2;
  11.112 +
  11.113 +        usage = SCREEN_USAGE_OPENGL_ES2;
  11.114 +        if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_USAGE,
  11.115 +                                          &usage) < 0) {
  11.116 +            return -1;
  11.117 +        }
  11.118 +    } else {
  11.119 +        format = SCREEN_FORMAT_RGBX8888;
  11.120 +        numbufs = 1;
  11.121 +    }
  11.122 +
  11.123 +    // Set pixel format.
  11.124 +    if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_FORMAT,
  11.125 +                                      &format) < 0) {
  11.126 +        goto fail;
  11.127 +    }
  11.128 +
  11.129 +    // Create buffer(s).
  11.130 +    if (screen_create_window_buffers(impl->window, numbufs) < 0) {
  11.131 +        goto fail;
  11.132 +    }
  11.133 +
  11.134 +    window->driverdata = impl;
  11.135 +    return 0;
  11.136 +
  11.137 +fail:
  11.138 +    if (impl->window) {
  11.139 +        screen_destroy_window(impl->window);
  11.140 +    }
  11.141 +
  11.142 +    SDL_free(impl);
  11.143 +    return -1;
  11.144 +}
  11.145 +
  11.146 +/**
  11.147 + * Gets a pointer to the Screen buffer associated with the given window. Note
  11.148 + * that the buffer is actually created in createWindow().
  11.149 + * @param       _THIS
  11.150 + * @param       window  SDL window to get the buffer for
  11.151 + * @param[out]  pixles  Holds a pointer to the window's buffer
  11.152 + * @param[out]  format  Holds the pixel format for the buffer
  11.153 + * @param[out]  pitch   Holds the number of bytes per line
  11.154 + * @return  0 if successful, -1 on error
  11.155 + */
  11.156 +static int
  11.157 +createWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format,
  11.158 +                        void ** pixels, int *pitch)
  11.159 +{
  11.160 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
  11.161 +    screen_buffer_t buffer;
  11.162 +
  11.163 +    // Get a pointer to the buffer's memory.
  11.164 +    if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
  11.165 +                                      (void **)&buffer) < 0) {
  11.166 +        return -1;
  11.167 +    }
  11.168 +
  11.169 +    if (screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER,
  11.170 +                                      pixels) < 0) {
  11.171 +        return -1;
  11.172 +    }
  11.173 +
  11.174 +    // Set format and pitch.
  11.175 +    if (screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE,
  11.176 +                                      pitch) < 0) {
  11.177 +        return -1;
  11.178 +    }
  11.179 +
  11.180 +    *format = SDL_PIXELFORMAT_RGB888;
  11.181 +    return 0;
  11.182 +}
  11.183 +
  11.184 +/**
  11.185 + * Informs the window manager that the window needs to be updated.
  11.186 + * @param   _THIS
  11.187 + * @param   window      The window to update
  11.188 + * @param   rects       An array of reectangular areas to update
  11.189 + * @param   numrects    Rect array length
  11.190 + * @return  0 if successful, -1 on error
  11.191 + */
  11.192 +static int
  11.193 +updateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects,
  11.194 +                        int numrects)
  11.195 +{
  11.196 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
  11.197 +    screen_buffer_t buffer;
  11.198 +
  11.199 +    if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
  11.200 +                                      (void **)&buffer) < 0) {
  11.201 +        return -1;
  11.202 +    }
  11.203 +
  11.204 +    screen_post_window(impl->window, buffer, numrects, (int *)rects, 0);
  11.205 +    screen_flush_context(context, 0);
  11.206 +    return 0;
  11.207 +}
  11.208 +
  11.209 +/**
  11.210 + * Runs the main event loop.
  11.211 + * @param   _THIS
  11.212 + */
  11.213 +static void
  11.214 +pumpEvents(_THIS)
  11.215 +{
  11.216 +    int             type;
  11.217 +
  11.218 +    for (;;) {
  11.219 +        if (screen_get_event(context, event, 0) < 0) {
  11.220 +            break;
  11.221 +        }
  11.222 +
  11.223 +        if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type)
  11.224 +            < 0) {
  11.225 +            break;
  11.226 +        }
  11.227 +
  11.228 +        if (type == SCREEN_EVENT_NONE) {
  11.229 +            break;
  11.230 +        }
  11.231 +
  11.232 +        switch (type) {
  11.233 +        case SCREEN_EVENT_KEYBOARD:
  11.234 +            handleKeyboardEvent(event);
  11.235 +            break;
  11.236 +
  11.237 +        default:
  11.238 +            break;
  11.239 +        }
  11.240 +    }
  11.241 +}
  11.242 +
  11.243 +/**
  11.244 + * Updates the size of the native window using the geometry of the SDL window.
  11.245 + * @param   _THIS
  11.246 + * @param   window  SDL window to update
  11.247 + */
  11.248 +static void
  11.249 +setWindowSize(_THIS, SDL_Window *window)
  11.250 +{
  11.251 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
  11.252 +    int             size[2];
  11.253 +
  11.254 +    size[0] = window->w;
  11.255 +    size[1] = window->h;
  11.256 +
  11.257 +    screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, size);
  11.258 +    screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE,
  11.259 +                                  size);
  11.260 +}
  11.261 +
  11.262 +/**
  11.263 + * Makes the native window associated with the given SDL window visible.
  11.264 + * @param   _THIS
  11.265 + * @param   window  SDL window to update
  11.266 + */
  11.267 +static void
  11.268 +showWindow(_THIS, SDL_Window *window)
  11.269 +{
  11.270 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
  11.271 +    const int       visible = 1;
  11.272 +
  11.273 +    screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE,
  11.274 +                                  &visible);
  11.275 +}
  11.276 +
  11.277 +/**
  11.278 + * Makes the native window associated with the given SDL window invisible.
  11.279 + * @param   _THIS
  11.280 + * @param   window  SDL window to update
  11.281 + */
  11.282 +static void
  11.283 +hideWindow(_THIS, SDL_Window *window)
  11.284 +{
  11.285 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
  11.286 +    const int       visible = 0;
  11.287 +
  11.288 +    screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE,
  11.289 +        &visible);
  11.290 +}
  11.291 +
  11.292 +/**
  11.293 + * Destroys the native window associated with the given SDL window.
  11.294 + * @param   _THIS
  11.295 + * @param   window  SDL window that is being destroyed
  11.296 + */
  11.297 +static void
  11.298 +destroyWindow(_THIS, SDL_Window *window)
  11.299 +{
  11.300 +    window_impl_t   *impl = (window_impl_t *)window->driverdata;
  11.301 +
  11.302 +    if (impl) {
  11.303 +        screen_destroy_window(impl->window);
  11.304 +        window->driverdata = NULL;
  11.305 +    }
  11.306 +}
  11.307 +
  11.308 +/**
  11.309 + * Frees the plugin object created by createDevice().
  11.310 + * @param   device  Plugin object to free
  11.311 + */
  11.312 +static void
  11.313 +deleteDevice(SDL_VideoDevice *device)
  11.314 +{
  11.315 +    SDL_free(device);
  11.316 +}
  11.317 +
  11.318 +/**
  11.319 + * Creates the QNX video plugin used by SDL.
  11.320 + * @param   devindex    Unused
  11.321 + * @return  Initialized device if successful, NULL otherwise
  11.322 + */
  11.323 +static SDL_VideoDevice *
  11.324 +createDevice(int devindex)
  11.325 +{
  11.326 +    SDL_VideoDevice *device;
  11.327 +
  11.328 +    device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
  11.329 +    if (device == NULL) {
  11.330 +        return NULL;
  11.331 +    }
  11.332 +
  11.333 +    device->driverdata = NULL;
  11.334 +    device->VideoInit = videoInit;
  11.335 +    device->VideoQuit = videoQuit;
  11.336 +    device->CreateWindow = createWindow;
  11.337 +    device->CreateWindowFramebuffer = createWindowFramebuffer;
  11.338 +    device->UpdateWindowFramebuffer = updateWindowFramebuffer;
  11.339 +    device->SetWindowSize = setWindowSize;
  11.340 +    device->ShowWindow = showWindow;
  11.341 +    device->HideWindow = hideWindow;
  11.342 +    device->PumpEvents = pumpEvents;
  11.343 +    device->DestroyWindow = destroyWindow;
  11.344 +
  11.345 +    device->GL_LoadLibrary = glLoadLibrary;
  11.346 +    device->GL_GetProcAddress = glGetProcAddress;
  11.347 +    device->GL_CreateContext = glCreateContext;
  11.348 +    device->GL_SetSwapInterval = glSetSwapInterval;
  11.349 +    device->GL_SwapWindow = glSwapWindow;
  11.350 +    device->GL_MakeCurrent = glMakeCurrent;
  11.351 +    device->GL_DeleteContext = glDeleteContext;
  11.352 +    device->GL_UnloadLibrary = glUnloadLibrary;
  11.353 +
  11.354 +    device->free = deleteDevice;
  11.355 +    return device;
  11.356 +}
  11.357 +
  11.358 +static int
  11.359 +available()
  11.360 +{
  11.361 +    return 1;
  11.362 +}
  11.363 +
  11.364 +VideoBootStrap QNX_bootstrap = {
  11.365 +    "qnx", "QNX Screen",
  11.366 +    available, createDevice
  11.367 +};