Support for QNX 7.0 (thanks, Elad!).

Fixes Bugzilla #3686.
This commit is contained in:
Ryan C. Gordon 2017-07-01 17:50:47 -04:00
parent b1fbab50c5
commit 22241ed0b0
11 changed files with 875 additions and 5 deletions

View File

@ -2098,6 +2098,30 @@ AC_HELP_STRING([--enable-video-dummy], [use dummy video driver [[default=yes]]])
fi
}
dnl Set up the QNX video driver if enabled
CheckQNXVideo()
{
if test x$enable_video = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_QNX, 1, [ ])
SOURCES="$SOURCES $srcdir/src/video/qnx/*.c"
have_video=yes
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lscreen -lEGL -lGLESv2"
SUMMARY_video="${SUMMARY_video} qnx"
fi
}
dnl Set up the QNX audio driver if enabled
CheckQNXAudio()
{
if test x$enable_audio = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_QSA, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/qsa/*.c"
have_video=yes
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lasound"
SUMMARY_audio="${SUMMARY_audio} qsa"
fi
}
dnl Check to see if OpenGL support is desired
AC_ARG_ENABLE(video-opengl,
AC_HELP_STRING([--enable-video-opengl], [include OpenGL support [[default=yes]]]),
@ -2573,6 +2597,10 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]])
pthread_cflags="-D_REENTRANT"
pthread_lib=""
;;
*-*-nto*)
pthread_cflags="-D_REENTRANT"
pthread_lib=""
;;
*)
pthread_cflags="-D_REENTRANT"
pthread_lib="-lpthread"
@ -3017,7 +3045,7 @@ CheckWarnAll
dnl Set up the configuration based on the host platform!
case "$host" in
*-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
*-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*|*-*-nto*)
case "$host" in
*-raspberry-linux*)
# Raspberry Pi
@ -3082,6 +3110,9 @@ case "$host" in
*-*-hpux*) ARCH=hpux ;;
*-*-aix*) ARCH=aix ;;
*-*-minix*) ARCH=minix ;;
*-*-nto*) ARCH=nto
CheckQNXVideo
;;
esac
CheckVisibilityHidden
CheckDeclarationAfterStatement
@ -3123,6 +3154,7 @@ case "$host" in
CheckLinuxVersion
CheckRPATH
CheckVivanteVideo
# Set up files for the audio library
if test x$enable_audio = xyes; then
case $ARCH in
@ -3147,6 +3179,9 @@ case "$host" in
SUMMARY_audio="${SUMMARY_audio} android"
have_audio=yes
;;
nto)
CheckQNXAudio
;;
esac
fi
# Set up files for the joystick library

View File

@ -317,6 +317,7 @@
#undef SDL_VIDEO_DRIVER_NACL
#undef SDL_VIDEO_DRIVER_VIVANTE
#undef SDL_VIDEO_DRIVER_VIVANTE_VDK
#undef SDL_VIDEO_DRIVER_QNX
#undef SDL_VIDEO_RENDER_D3D
#undef SDL_VIDEO_RENDER_D3D11

View File

@ -205,6 +205,7 @@ extern AudioBootStrap FUSIONSOUND_bootstrap;
extern AudioBootStrap ANDROIDAUDIO_bootstrap;
extern AudioBootStrap PSPAUDIO_bootstrap;
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
extern AudioBootStrap QNX_bootstrap;
#endif /* SDL_sysaudio_h_ */

View File

@ -370,13 +370,13 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->hidden->cardno = device->cardno;
status = snd_pcm_open(&this->hidden->audio_handle,
device->cardno, device->deviceno,
iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
} else {
/* Open system default audio device */
status = snd_pcm_open_preferred(&this->hidden->audio_handle,
&this->hidden->cardno,
&this->hidden->deviceno,
iscapture ? SND_PCM_OPEN_PLAYBACK : SND_PCM_OPEN_CAPTURE);
iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
}
/* Check if requested device is opened */
@ -385,6 +385,7 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
return QSA_SetError("snd_pcm_open", status);
}
#if 0
if (!QSA_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
/* Disable QSA MMAP plugin for buggy audio drivers */
status =
@ -394,6 +395,7 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
return QSA_SetError("snd_pcm_plugin_set_disable", status);
}
}
#endif
/* Try for a closest match on audio format */
format = 0;

View File

@ -216,7 +216,7 @@ static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
return retval;
}
#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
#elif defined(unix) || defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__) || defined(__QNX__)
#include <dlfcn.h>
static SDL_INLINE void *get_sdlapi_entry(const char *fname, const char *sym)
{
@ -302,4 +302,3 @@ SDL_InitDynamicAPI(void)
#endif /* SDL_DYNAMIC_API */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -390,6 +390,7 @@ extern VideoBootStrap Wayland_bootstrap;
extern VideoBootStrap NACL_bootstrap;
extern VideoBootStrap VIVANTE_bootstrap;
extern VideoBootStrap Emscripten_bootstrap;
extern VideoBootStrap QNX_bootstrap;
extern SDL_VideoDevice *SDL_GetVideoDevice(void);
extern int SDL_AddBasicVideoDisplay(const SDL_DisplayMode * desktop_mode);

View File

@ -111,6 +111,9 @@ static VideoBootStrap *bootstrap[] = {
#if SDL_VIDEO_DRIVER_EMSCRIPTEN
&Emscripten_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_QNX
&QNX_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_DUMMY
&DUMMY_bootstrap,
#endif

283
src/video/qnx/gl.c Normal file
View File

@ -0,0 +1,283 @@
/*
Simple DirectMedia Layer
Copyright (C) 2017 BlackBerry Limited
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#include "sdl_qnx.h"
static EGLDisplay egl_disp;
/**
* Detertmines the pixel format to use based on the current display and EGL
* configuration.
* @param egl_conf EGL configuration to use
* @return A SCREEN_FORMAT* constant for the pixel format to use
*/
static int
chooseFormat(EGLConfig egl_conf)
{
EGLint buffer_bit_depth;
EGLint alpha_bit_depth;
eglGetConfigAttrib(egl_disp, egl_conf, EGL_BUFFER_SIZE, &buffer_bit_depth);
eglGetConfigAttrib(egl_disp, egl_conf, EGL_ALPHA_SIZE, &alpha_bit_depth);
switch (buffer_bit_depth) {
case 32:
return SCREEN_FORMAT_RGBX8888;
case 24:
return SCREEN_FORMAT_RGB888;
case 16:
switch (alpha_bit_depth) {
case 4:
return SCREEN_FORMAT_RGBX4444;
case 1:
return SCREEN_FORMAT_RGBA5551;
default:
return SCREEN_FORMAT_RGB565;
}
default:
return 0;
}
}
/**
* Enumerates the supported EGL configurations and chooses a suitable one.
* @param[out] pconf The chosen configuration
* @param[out] pformat The chosen pixel format
* @return 0 if successful, -1 on error
*/
int
glGetConfig(EGLConfig *pconf, int *pformat)
{
EGLConfig egl_conf = (EGLConfig)0;
EGLConfig *egl_configs;
EGLint egl_num_configs;
EGLint val;
EGLBoolean rc;
EGLint i;
// Determine the numbfer of configurations.
rc = eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
if (rc != EGL_TRUE) {
return -1;
}
if (egl_num_configs == 0) {
return -1;
}
// Allocate enough memory for all configurations.
egl_configs = malloc(egl_num_configs * sizeof(*egl_configs));
if (egl_configs == NULL) {
return -1;
}
// Get the list of configurations.
rc = eglGetConfigs(egl_disp, egl_configs, egl_num_configs,
&egl_num_configs);
if (rc != EGL_TRUE) {
free(egl_configs);
return -1;
}
// Find a good configuration.
for (i = 0; i < egl_num_configs; i++) {
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
if (!(val & EGL_WINDOW_BIT)) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
if (!(val & EGL_OPENGL_ES2_BIT)) {
continue;
}
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_DEPTH_SIZE, &val);
if (val == 0) {
continue;
}
egl_conf = egl_configs[i];
break;
}
free(egl_configs);
*pconf = egl_conf;
*pformat = chooseFormat(egl_conf);
return 0;
}
/**
* Initializes the EGL library.
* @param _THIS
* @param name unused
* @return 0 if successful, -1 on error
*/
int
glLoadLibrary(_THIS, const char *name)
{
EGLNativeDisplayType disp_id = EGL_DEFAULT_DISPLAY;
egl_disp = eglGetDisplay(disp_id);
if (egl_disp == EGL_NO_DISPLAY) {
return -1;
}
if (eglInitialize(egl_disp, NULL, NULL) == EGL_FALSE) {
return -1;
}
return 0;
}
/**
* Finds the address of an EGL extension function.
* @param proc Function name
* @return Function address
*/
void *
glGetProcAddress(_THIS, const char *proc)
{
return eglGetProcAddress(proc);
}
/**
* Associates the given window with the necessary EGL structures for drawing and
* displaying content.
* @param _THIS
* @param window The SDL window to create the context for
* @return A pointer to the created context, if successful, NULL on error
*/
SDL_GLContext
glCreateContext(_THIS, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
EGLContext context;
EGLSurface surface;
struct {
EGLint client_version[2];
EGLint none;
} egl_ctx_attr = {
.client_version = { EGL_CONTEXT_CLIENT_VERSION, 2 },
.none = EGL_NONE
};
struct {
EGLint render_buffer[2];
EGLint none;
} egl_surf_attr = {
.render_buffer = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER },
.none = EGL_NONE
};
context = eglCreateContext(egl_disp, impl->conf, EGL_NO_CONTEXT,
(EGLint *)&egl_ctx_attr);
if (context == EGL_NO_CONTEXT) {
return NULL;
}
surface = eglCreateWindowSurface(egl_disp, impl->conf, impl->window,
(EGLint *)&egl_surf_attr);
if (surface == EGL_NO_SURFACE) {
return NULL;
}
eglMakeCurrent(egl_disp, surface, surface, context);
impl->surface = surface;
return context;
}
/**
* Sets a new value for the number of frames to display before swapping buffers.
* @param _THIS
* @param interval New interval value
* @return 0 if successful, -1 on error
*/
int
glSetSwapInterval(_THIS, int interval)
{
if (eglSwapInterval(egl_disp, interval) != EGL_TRUE) {
return -1;
}
return 0;
}
/**
* Swaps the EGL buffers associated with the given window
* @param _THIS
* @paran window Window to swap buffers for
*/
void
glSwapWindow(_THIS, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
eglSwapBuffers(egl_disp, impl->surface);
}
/**
* Makes the given context the current one for drawing operations.
* @param _THIS
* @param window SDL window associated with the context (maybe NULL)
* @param context The context to activate
* @return 0 if successful, -1 on error
*/
int
glMakeCurrent(_THIS, SDL_Window *window, SDL_GLContext context)
{
window_impl_t *impl;
EGLSurface surface = NULL;
if (window) {
impl = (window_impl_t *)window->driverdata;
surface = impl->surface;
}
if (eglMakeCurrent(egl_disp, surface, surface, context) != EGL_TRUE) {
return -1;
}
return 0;
}
/**
* Destroys a context.
* @param _THIS
* @param context The context to destroy
*/
void
glDeleteContext(_THIS, SDL_GLContext context)
{
eglDestroyContext(egl_disp, context);
}
/**
* Terminates access to the EGL library.
* @param _THIS
*/
void
glUnloadLibrary(_THIS)
{
eglTerminate(egl_disp);
}

133
src/video/qnx/keyboard.c Normal file
View File

@ -0,0 +1,133 @@
/*
Simple DirectMedia Layer
Copyright (C) 2017 BlackBerry Limited
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#include "../../events/SDL_keyboard_c.h"
#include "SDL_scancode.h"
#include "SDL_events.h"
#include "sdl_qnx.h"
#include <sys/keycodes.h>
/**
* A map thta translates Screen key names to SDL scan codes.
* This map is incomplete, but should include most major keys.
*/
static int key_to_sdl[] = {
[KEYCODE_SPACE] = SDL_SCANCODE_SPACE,
[KEYCODE_APOSTROPHE] = SDL_SCANCODE_APOSTROPHE,
[KEYCODE_COMMA] = SDL_SCANCODE_COMMA,
[KEYCODE_MINUS] = SDL_SCANCODE_MINUS,
[KEYCODE_PERIOD] = SDL_SCANCODE_PERIOD,
[KEYCODE_SLASH] = SDL_SCANCODE_SLASH,
[KEYCODE_ZERO] = SDL_SCANCODE_0,
[KEYCODE_ONE] = SDL_SCANCODE_1,
[KEYCODE_TWO] = SDL_SCANCODE_2,
[KEYCODE_THREE] = SDL_SCANCODE_3,
[KEYCODE_FOUR] = SDL_SCANCODE_4,
[KEYCODE_FIVE] = SDL_SCANCODE_5,
[KEYCODE_SIX] = SDL_SCANCODE_6,
[KEYCODE_SEVEN] = SDL_SCANCODE_7,
[KEYCODE_EIGHT] = SDL_SCANCODE_8,
[KEYCODE_NINE] = SDL_SCANCODE_9,
[KEYCODE_SEMICOLON] = SDL_SCANCODE_SEMICOLON,
[KEYCODE_EQUAL] = SDL_SCANCODE_EQUALS,
[KEYCODE_LEFT_BRACKET] = SDL_SCANCODE_LEFTBRACKET,
[KEYCODE_BACK_SLASH] = SDL_SCANCODE_BACKSLASH,
[KEYCODE_RIGHT_BRACKET] = SDL_SCANCODE_RIGHTBRACKET,
[KEYCODE_GRAVE] = SDL_SCANCODE_GRAVE,
[KEYCODE_A] = SDL_SCANCODE_A,
[KEYCODE_B] = SDL_SCANCODE_B,
[KEYCODE_C] = SDL_SCANCODE_C,
[KEYCODE_D] = SDL_SCANCODE_D,
[KEYCODE_E] = SDL_SCANCODE_E,
[KEYCODE_F] = SDL_SCANCODE_F,
[KEYCODE_G] = SDL_SCANCODE_G,
[KEYCODE_H] = SDL_SCANCODE_H,
[KEYCODE_I] = SDL_SCANCODE_I,
[KEYCODE_J] = SDL_SCANCODE_J,
[KEYCODE_K] = SDL_SCANCODE_K,
[KEYCODE_L] = SDL_SCANCODE_L,
[KEYCODE_M] = SDL_SCANCODE_M,
[KEYCODE_N] = SDL_SCANCODE_N,
[KEYCODE_O] = SDL_SCANCODE_O,
[KEYCODE_P] = SDL_SCANCODE_P,
[KEYCODE_Q] = SDL_SCANCODE_Q,
[KEYCODE_R] = SDL_SCANCODE_R,
[KEYCODE_S] = SDL_SCANCODE_S,
[KEYCODE_T] = SDL_SCANCODE_T,
[KEYCODE_U] = SDL_SCANCODE_U,
[KEYCODE_V] = SDL_SCANCODE_V,
[KEYCODE_W] = SDL_SCANCODE_W,
[KEYCODE_X] = SDL_SCANCODE_X,
[KEYCODE_Y] = SDL_SCANCODE_Y,
[KEYCODE_Z] = SDL_SCANCODE_Z,
[KEYCODE_UP] = SDL_SCANCODE_UP,
[KEYCODE_DOWN] = SDL_SCANCODE_DOWN,
[KEYCODE_LEFT] = SDL_SCANCODE_LEFT,
[KEYCODE_PG_UP] = SDL_SCANCODE_PAGEUP,
[KEYCODE_PG_DOWN] = SDL_SCANCODE_PAGEDOWN,
[KEYCODE_RIGHT] = SDL_SCANCODE_RIGHT,
[KEYCODE_RETURN] = SDL_SCANCODE_RETURN,
[KEYCODE_TAB] = SDL_SCANCODE_TAB,
[KEYCODE_ESCAPE] = SDL_SCANCODE_ESCAPE,
};
/**
* Called from the event dispatcher when a keyboard event is encountered.
* Translates the event such that it can be handled by SDL.
* @param event Screen keyboard event
*/
void
handleKeyboardEvent(screen_event_t event)
{
int val;
SDL_Scancode scancode;
// Get the key value.
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_SYM, &val) < 0) {
return;
}
// Skip unrecognized keys.
if ((val < 0) || (val > (sizeof(key_to_sdl) / sizeof(int)))) {
return;
}
// Translate to an SDL scan code.
scancode = key_to_sdl[val];
if (scancode == 0) {
return;
}
// Get event flags (key state).
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_FLAGS, &val) < 0) {
return;
}
// Propagate the event to SDL.
// FIXME:
// Need to handle more key states (such as key combinations).
if (val & KEY_DOWN) {
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
} else {
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
}

48
src/video/qnx/sdl_qnx.h Normal file
View File

@ -0,0 +1,48 @@
/*
Simple DirectMedia Layer
Copyright (C) 2017 BlackBerry Limited
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __SDL_QNX_H__
#define __SDL_QNX_H__
#include "../SDL_sysvideo.h"
#include <screen/screen.h>
#include <EGL/egl.h>
typedef struct
{
screen_window_t window;
EGLSurface surface;
EGLConfig conf;
} window_impl_t;
extern void handleKeyboardEvent(screen_event_t event);
extern int glGetConfig(EGLConfig *pconf, int *pformat);
extern int glLoadLibrary(_THIS, const char *name);
void *glGetProcAddress(_THIS, const char *proc);
extern SDL_GLContext glCreateContext(_THIS, SDL_Window *window);
extern int glSetSwapInterval(_THIS, int interval);
extern void glSwapWindow(_THIS, SDL_Window *window);
extern int glMakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
extern void glDeleteContext(_THIS, SDL_GLContext context);
extern void glUnloadLibrary(_THIS);
#endif

364
src/video/qnx/video.c Normal file
View File

@ -0,0 +1,364 @@
/*
Simple DirectMedia Layer
Copyright (C) 2017 BlackBerry Limited
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#include "../SDL_sysvideo.h"
#include "sdl_qnx.h"
static screen_context_t context;
static screen_event_t event;
/**
* Initializes the QNX video plugin.
* Creates the Screen context and event handles used for all window operations
* by the plugin.
* @param _THIS
* @return 0 if successful, -1 on error
*/
static int
videoInit(_THIS)
{
SDL_VideoDisplay display;
if (screen_create_context(&context, 0) < 0) {
return -1;
}
if (screen_create_event(&event) < 0) {
return -1;
}
SDL_zero(display);
if (SDL_AddVideoDisplay(&display) < 0) {
return -1;
}
_this->num_displays = 1;
return 0;
}
static void
videoQuit(_THIS)
{
}
/**
* Creates a new native Screen window and associates it with the given SDL
* window.
* @param _THIS
* @param window SDL window to initialize
* @return 0 if successful, -1 on error
*/
static int
createWindow(_THIS, SDL_Window *window)
{
window_impl_t *impl;
int size[2];
int numbufs;
int format;
int usage;
impl = SDL_calloc(1, sizeof(*impl));
if (impl == NULL) {
return -1;
}
// Create a native window.
if (screen_create_window(&impl->window, context) < 0) {
goto fail;
}
// Set the native window's size to match the SDL window.
size[0] = window->w;
size[1] = window->h;
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE,
size) < 0) {
goto fail;
}
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE,
size) < 0) {
goto fail;
}
// Create window buffer(s).
if (window->flags & SDL_WINDOW_OPENGL) {
if (glGetConfig(&impl->conf, &format) < 0) {
goto fail;
}
numbufs = 2;
usage = SCREEN_USAGE_OPENGL_ES2;
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_USAGE,
&usage) < 0) {
return -1;
}
} else {
format = SCREEN_FORMAT_RGBX8888;
numbufs = 1;
}
// Set pixel format.
if (screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_FORMAT,
&format) < 0) {
goto fail;
}
// Create buffer(s).
if (screen_create_window_buffers(impl->window, numbufs) < 0) {
goto fail;
}
window->driverdata = impl;
return 0;
fail:
if (impl->window) {
screen_destroy_window(impl->window);
}
SDL_free(impl);
return -1;
}
/**
* Gets a pointer to the Screen buffer associated with the given window. Note
* that the buffer is actually created in createWindow().
* @param _THIS
* @param window SDL window to get the buffer for
* @param[out] pixles Holds a pointer to the window's buffer
* @param[out] format Holds the pixel format for the buffer
* @param[out] pitch Holds the number of bytes per line
* @return 0 if successful, -1 on error
*/
static int
createWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format,
void ** pixels, int *pitch)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
screen_buffer_t buffer;
// Get a pointer to the buffer's memory.
if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
(void **)&buffer) < 0) {
return -1;
}
if (screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER,
pixels) < 0) {
return -1;
}
// Set format and pitch.
if (screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE,
pitch) < 0) {
return -1;
}
*format = SDL_PIXELFORMAT_RGB888;
return 0;
}
/**
* Informs the window manager that the window needs to be updated.
* @param _THIS
* @param window The window to update
* @param rects An array of reectangular areas to update
* @param numrects Rect array length
* @return 0 if successful, -1 on error
*/
static int
updateWindowFramebuffer(_THIS, SDL_Window *window, const SDL_Rect *rects,
int numrects)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
screen_buffer_t buffer;
if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
(void **)&buffer) < 0) {
return -1;
}
screen_post_window(impl->window, buffer, numrects, (int *)rects, 0);
screen_flush_context(context, 0);
return 0;
}
/**
* Runs the main event loop.
* @param _THIS
*/
static void
pumpEvents(_THIS)
{
int type;
for (;;) {
if (screen_get_event(context, event, 0) < 0) {
break;
}
if (screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type)
< 0) {
break;
}
if (type == SCREEN_EVENT_NONE) {
break;
}
switch (type) {
case SCREEN_EVENT_KEYBOARD:
handleKeyboardEvent(event);
break;
default:
break;
}
}
}
/**
* Updates the size of the native window using the geometry of the SDL window.
* @param _THIS
* @param window SDL window to update
*/
static void
setWindowSize(_THIS, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
int size[2];
size[0] = window->w;
size[1] = window->h;
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SIZE, size);
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_SOURCE_SIZE,
size);
}
/**
* Makes the native window associated with the given SDL window visible.
* @param _THIS
* @param window SDL window to update
*/
static void
showWindow(_THIS, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
const int visible = 1;
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE,
&visible);
}
/**
* Makes the native window associated with the given SDL window invisible.
* @param _THIS
* @param window SDL window to update
*/
static void
hideWindow(_THIS, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
const int visible = 0;
screen_set_window_property_iv(impl->window, SCREEN_PROPERTY_VISIBLE,
&visible);
}
/**
* Destroys the native window associated with the given SDL window.
* @param _THIS
* @param window SDL window that is being destroyed
*/
static void
destroyWindow(_THIS, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->driverdata;
if (impl) {
screen_destroy_window(impl->window);
window->driverdata = NULL;
}
}
/**
* Frees the plugin object created by createDevice().
* @param device Plugin object to free
*/
static void
deleteDevice(SDL_VideoDevice *device)
{
SDL_free(device);
}
/**
* Creates the QNX video plugin used by SDL.
* @param devindex Unused
* @return Initialized device if successful, NULL otherwise
*/
static SDL_VideoDevice *
createDevice(int devindex)
{
SDL_VideoDevice *device;
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (device == NULL) {
return NULL;
}
device->driverdata = NULL;
device->VideoInit = videoInit;
device->VideoQuit = videoQuit;
device->CreateWindow = createWindow;
device->CreateWindowFramebuffer = createWindowFramebuffer;
device->UpdateWindowFramebuffer = updateWindowFramebuffer;
device->SetWindowSize = setWindowSize;
device->ShowWindow = showWindow;
device->HideWindow = hideWindow;
device->PumpEvents = pumpEvents;
device->DestroyWindow = destroyWindow;
device->GL_LoadLibrary = glLoadLibrary;
device->GL_GetProcAddress = glGetProcAddress;
device->GL_CreateContext = glCreateContext;
device->GL_SetSwapInterval = glSetSwapInterval;
device->GL_SwapWindow = glSwapWindow;
device->GL_MakeCurrent = glMakeCurrent;
device->GL_DeleteContext = glDeleteContext;
device->GL_UnloadLibrary = glUnloadLibrary;
device->free = deleteDevice;
return device;
}
static int
available()
{
return 1;
}
VideoBootStrap QNX_bootstrap = {
"qnx", "QNX Screen",
available, createDevice
};