This commit is contained in:
Nitload
2025-08-25 09:50:30 +08:00
parent bd0e31e922
commit 1359ff4ecc
1630 changed files with 738486 additions and 2399 deletions
@@ -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 bool glGetConfig(EGLConfig *pconf, int *pformat);
extern bool glLoadLibrary(SDL_VideoDevice *_this, const char *name);
extern SDL_FunctionPointer glGetProcAddress(SDL_VideoDevice *_this, const char *proc);
extern SDL_GLContext glCreateContext(SDL_VideoDevice *_this, SDL_Window *window);
extern bool glSetSwapInterval(SDL_VideoDevice *_this, int interval);
extern bool glSwapWindow(SDL_VideoDevice *_this, SDL_Window *window);
extern bool glMakeCurrent(SDL_VideoDevice *_this, SDL_Window * window, SDL_GLContext context);
extern void glDeleteContext(SDL_VideoDevice *_this, SDL_GLContext context);
extern void glUnloadLibrary(SDL_VideoDevice *_this);
#endif
@@ -0,0 +1,277 @@
/*
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 SDL_PIXELFORMAT_RGB24;
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 true if successful, -1 on error
*/
bool 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 false;
}
if (egl_num_configs == 0) {
return false;
}
// Allocate enough memory for all configurations.
egl_configs = SDL_malloc(egl_num_configs * sizeof(*egl_configs));
if (!egl_configs) {
return false;
}
// Get the list of configurations.
rc = eglGetConfigs(egl_disp, egl_configs, egl_num_configs,
&egl_num_configs);
if (rc != EGL_TRUE) {
SDL_free(egl_configs);
return false;
}
// 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;
}
SDL_free(egl_configs);
*pconf = egl_conf;
*pformat = chooseFormat(egl_conf);
return true;
}
/**
* Initializes the EGL library.
* @param SDL_VideoDevice *_this
* @param name unused
* @return 0 if successful, -1 on error
*/
bool glLoadLibrary(SDL_VideoDevice *_this, const char *name)
{
EGLNativeDisplayType disp_id = EGL_DEFAULT_DISPLAY;
egl_disp = eglGetDisplay(disp_id);
if (egl_disp == EGL_NO_DISPLAY) {
return false;
}
if (eglInitialize(egl_disp, NULL, NULL) == EGL_FALSE) {
return false;
}
return true;
}
/**
* Finds the address of an EGL extension function.
* @param proc Function name
* @return Function address
*/
SDL_FunctionPointer glGetProcAddress(SDL_VideoDevice *_this, const char *proc)
{
return eglGetProcAddress(proc);
}
/**
* Associates the given window with the necessary EGL structures for drawing and
* displaying content.
* @param SDL_VideoDevice *_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(SDL_VideoDevice *_this, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->internal;
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,
(EGLNativeWindowType)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 SDL_VideoDevice *_this
* @param interval New interval value
* @return 0 if successful, -1 on error
*/
bool glSetSwapInterval(SDL_VideoDevice *_this, int interval)
{
if (eglSwapInterval(egl_disp, interval) != EGL_TRUE) {
return false;
}
return true;
}
/**
* Swaps the EGL buffers associated with the given window
* @param SDL_VideoDevice *_this
* @param window Window to swap buffers for
* @return 0 if successful, -1 on error
*/
bool glSwapWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
// !!! FIXME: should we migrate this all over to use SDL_egl.c?
window_impl_t *impl = (window_impl_t *)window->internal;
return eglSwapBuffers(egl_disp, impl->surface) == EGL_TRUE ? 0 : -1;
}
/**
* Makes the given context the current one for drawing operations.
* @param SDL_VideoDevice *_this
* @param window SDL window associated with the context (maybe NULL)
* @param context The context to activate
* @return 0 if successful, -1 on error
*/
bool glMakeCurrent(SDL_VideoDevice *_this, SDL_Window *window, SDL_GLContext context)
{
window_impl_t *impl;
EGLSurface surface = NULL;
if (window) {
impl = (window_impl_t *)window->internal;
surface = impl->surface;
}
if (eglMakeCurrent(egl_disp, surface, surface, context) != EGL_TRUE) {
return false;
}
return true;
}
/**
* Destroys a context.
* @param SDL_VideoDevice *_this
* @param context The context to destroy
*/
bool glDeleteContext(SDL_VideoDevice *_this, SDL_GLContext context)
{
eglDestroyContext(egl_disp, context);
return true;
}
/**
* Terminates access to the EGL library.
* @param SDL_VideoDevice *_this
*/
void glUnloadLibrary(SDL_VideoDevice *_this)
{
eglTerminate(egl_disp);
}
@@ -0,0 +1,132 @@
/*
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 "SDL3/SDL_scancode.h"
#include "SDL3/SDL_events.h"
#include "SDL_qnx.h"
#include <sys/keycodes.h>
/**
* A map that 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 >= SDL_arraysize(key_to_sdl))) {
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(0, SDL_DEFAULT_KEYBOARD_ID, val, scancode, true);
} else {
SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, val, scancode, false);
}
}
@@ -0,0 +1,351 @@
/*
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 "../../events/SDL_keyboard_c.h"
#include "../../events/SDL_mouse_c.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 SDL_VideoDevice *_this
* @return 0 if successful, -1 on error
*/
static bool videoInit(SDL_VideoDevice *_this)
{
SDL_VideoDisplay display;
if (screen_create_context(&context, 0) < 0) {
return false;
}
if (screen_create_event(&event) < 0) {
return false;
}
SDL_zero(display);
if (SDL_AddVideoDisplay(&display, false) == 0) {
return false;
}
// Assume we have a mouse and keyboard
SDL_AddKeyboard(SDL_DEFAULT_KEYBOARD_ID, NULL, false);
SDL_AddMouse(SDL_DEFAULT_MOUSE_ID, NULL, false);
return true;
}
static void videoQuit(SDL_VideoDevice *_this)
{
}
/**
* Creates a new native Screen window and associates it with the given SDL
* window.
* @param SDL_VideoDevice *_this
* @param window SDL window to initialize
* @return 0 if successful, -1 on error
*/
static bool createWindow(SDL_VideoDevice *_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) {
return false;
}
// 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 false;
}
} 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->internal = impl;
return true;
fail:
if (impl->window) {
screen_destroy_window(impl->window);
}
SDL_free(impl);
return false;
}
/**
* Gets a pointer to the Screen buffer associated with the given window. Note
* that the buffer is actually created in createWindow().
* @param SDL_VideoDevice *_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 bool createWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window * window, SDL_PixelFormat * format,
void ** pixels, int *pitch)
{
window_impl_t *impl = (window_impl_t *)window->internal;
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 false;
}
if (screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER,
pixels) < 0) {
return false;
}
// Set format and pitch.
if (screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE,
pitch) < 0) {
return false;
}
*format = SDL_PIXELFORMAT_XRGB8888;
return true;
}
/**
* Informs the window manager that the window needs to be updated.
* @param SDL_VideoDevice *_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 bool updateWindowFramebuffer(SDL_VideoDevice *_this, SDL_Window *window, const SDL_Rect *rects,
int numrects)
{
window_impl_t *impl = (window_impl_t *)window->internal;
screen_buffer_t buffer;
if (screen_get_window_property_pv(impl->window, SCREEN_PROPERTY_BUFFERS,
(void **)&buffer) < 0) {
return false;
}
screen_post_window(impl->window, buffer, numrects, (int *)rects, 0);
screen_flush_context(context, 0);
return true;
}
/**
* Runs the main event loop.
* @param SDL_VideoDevice *_this
*/
static void pumpEvents(SDL_VideoDevice *_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 SDL_VideoDevice *_this
* @param window SDL window to update
*/
static void setWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->internal;
int size[2];
size[0] = window->pending.w;
size[1] = window->pending.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 SDL_VideoDevice *_this
* @param window SDL window to update
*/
static void showWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->internal;
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 SDL_VideoDevice *_this
* @param window SDL window to update
*/
static void hideWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->internal;
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 SDL_VideoDevice *_this
* @param window SDL window that is being destroyed
*/
static void destroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
{
window_impl_t *impl = (window_impl_t *)window->internal;
if (impl) {
screen_destroy_window(impl->window);
window->internal = 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.
* @return Initialized device if successful, NULL otherwise
*/
static SDL_VideoDevice *createDevice(void)
{
SDL_VideoDevice *device;
device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
return NULL;
}
device->internal = NULL;
device->VideoInit = videoInit;
device->VideoQuit = videoQuit;
device->CreateSDLWindow = 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_DestroyContext = glDeleteContext;
device->GL_UnloadLibrary = glUnloadLibrary;
device->free = deleteDevice;
return device;
}
VideoBootStrap QNX_bootstrap = {
"qnx", "QNX Screen",
createDevice,
NULL, // no ShowMessageBox implementation
false
};