From 7c54f601447a71e25a4a2490fad8e1b846752454 Mon Sep 17 00:00:00 2001 From: Mike Gorchak Date: Tue, 28 Apr 2009 04:33:30 +0000 Subject: [PATCH] Support for HID devices (mice and keyboards only for now) has been added --- src/video/qnxgf/SDL_gf_input.c | 1187 ++++++++++++++++++++++++++ src/video/qnxgf/SDL_gf_input.h | 165 ++++ src/video/qnxgf/SDL_gf_opengles.c | 6 - src/video/qnxgf/SDL_gf_opengles.h | 37 + src/video/qnxgf/SDL_gf_render.c | 43 +- src/video/qnxgf/SDL_hiddi_joystick.h | 34 + src/video/qnxgf/SDL_hiddi_keyboard.h | 159 ++++ src/video/qnxgf/SDL_hiddi_mouse.h | 69 ++ src/video/qnxgf/SDL_qnxgf.c | 606 ++++++++++++- src/video/qnxgf/SDL_qnxgf.h | 29 +- 10 files changed, 2260 insertions(+), 75 deletions(-) create mode 100644 src/video/qnxgf/SDL_gf_input.c create mode 100644 src/video/qnxgf/SDL_gf_input.h create mode 100644 src/video/qnxgf/SDL_gf_opengles.h create mode 100644 src/video/qnxgf/SDL_hiddi_joystick.h create mode 100644 src/video/qnxgf/SDL_hiddi_keyboard.h create mode 100644 src/video/qnxgf/SDL_hiddi_mouse.h diff --git a/src/video/qnxgf/SDL_gf_input.c b/src/video/qnxgf/SDL_gf_input.c new file mode 100644 index 000000000..176907d7a --- /dev/null +++ b/src/video/qnxgf/SDL_gf_input.c @@ -0,0 +1,1187 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Graphics Framework SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#include "SDL_gf_input.h" + +#include "SDL_config.h" +#include "SDL_events.h" +#include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_keyboard_c.h" + +/* Include QNX HIDDI definitions */ +#include "SDL_hiddi_keyboard.h" +#include "SDL_hiddi_mouse.h" +#include "SDL_hiddi_joystick.h" + +/* Mouse related functions */ +SDL_Cursor* gf_createcursor(SDL_Surface* surface, int hot_x, int hot_y); +int gf_showcursor(SDL_Cursor* cursor); +void gf_movecursor(SDL_Cursor* cursor); +void gf_freecursor(SDL_Cursor* cursor); +void gf_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y); +void gf_freemouse(SDL_Mouse* mouse); + +/* HIDDI interacting functions */ +static int32_t hiddi_connect_devices(); +static int32_t hiddi_disconnect_devices(); + +int32_t gf_addinputdevices(_THIS) +{ + SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; + SDL_DisplayData* didata; + struct SDL_Mouse gf_mouse; + SDL_Keyboard gf_keyboard; + SDLKey keymap[SDL_NUM_SCANCODES]; + SDL_MouseData* mdata; + uint32_t it; + + for (it=0; it<_this->num_displays; it++) + { + /* Clear SDL mouse structure */ + SDL_memset(&gf_mouse, 0x00, sizeof(struct SDL_Mouse)); + + /* Allocate SDL_MouseData structure */ + mdata=(SDL_MouseData*)SDL_calloc(1, sizeof(SDL_MouseData)); + if (mdata==NULL) + { + SDL_OutOfMemory(); + return -1; + } + + /* Mark this mouse with ID 0 */ + gf_mouse.id=it; + gf_mouse.driverdata=(void*)mdata; + gf_mouse.CreateCursor=gf_createcursor; + gf_mouse.ShowCursor=gf_showcursor; + gf_mouse.MoveCursor=gf_movecursor; + gf_mouse.FreeCursor=gf_freecursor; + gf_mouse.WarpMouse=gf_warpmouse; + gf_mouse.FreeMouse=gf_freemouse; + + /* Get display data */ + didata=(SDL_DisplayData*)_this->displays[it].driverdata; + + /* Store SDL_DisplayData pointer in the mouse driver internals */ + mdata->didata=didata; + + /* Set cursor pos to 0,0 to avoid cursor disappearing in some drivers */ + gf_cursor_set_pos(didata->display, 0, 0, 0); + + /* Register mouse cursor in SDL */ + SDL_AddMouse(&gf_mouse, "GF mouse cursor", 0, 0, 1); + } + + /* Keyboard could be one only */ + SDL_zero(gf_keyboard); + SDL_AddKeyboard(&gf_keyboard, -1); + + /* Add scancode to key mapping, HIDDI uses USB HID codes, so */ + /* map will be exact one-to-one */ + SDL_GetDefaultKeymap(keymap); + SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES); + + /* Connect to HID server and enumerate all input devices */ + hiddi_connect_devices(); + + return 0; +} + +int32_t gf_delinputdevices(_THIS) +{ + /* Disconnect from HID server and release input devices */ + hiddi_disconnect_devices(); + + /* Delete keyboard */ + SDL_KeyboardQuit(); + + /* Destroy all of the mice */ + SDL_MouseQuit(); +} + +/*****************************************************************************/ +/* GF Mouse related functions */ +/*****************************************************************************/ +SDL_Cursor* gf_createcursor(SDL_Surface* surface, int hot_x, int hot_y) +{ + gf_cursor_t* internal_cursor; + SDL_Cursor* sdl_cursor; + uint8_t* image0=NULL; + uint8_t* image1=NULL; + uint32_t it; + uint32_t jt; + uint32_t shape_color; + + /* SDL converts monochrome cursor shape to 32bpp cursor shape */ + /* and we must convert it back to monochrome, this routine handles */ + /* 24/32bpp surfaces only */ + if ((surface->format->BitsPerPixel!=32) && (surface->format->BitsPerPixel!=24)) + { + SDL_SetError("GF: Cursor shape is not 24/32bpp."); + return NULL; + } + + /* Since GF is not checking data, we must check */ + if ((surface->w==0) || (surface->h==0)) + { + SDL_SetError("GF: Cursor shape dimensions are zero"); + return NULL; + } + + /* Allocate memory for the internal cursor format */ + internal_cursor=(gf_cursor_t*)SDL_calloc(1, sizeof(gf_cursor_t)); + if (internal_cursor==NULL) + { + SDL_OutOfMemory(); + return NULL; + } + + /* Allocate memory for the SDL cursor */ + sdl_cursor=(SDL_Cursor*)SDL_calloc(1, sizeof(SDL_Cursor)); + if (sdl_cursor==NULL) + { + SDL_free(internal_cursor); + SDL_OutOfMemory(); + return NULL; + } + + /* Allocate two monochrome images */ + image0=(uint8_t*)SDL_calloc(1, ((surface->w+7)/8)*surface->h); + if (image0==NULL) + { + SDL_free(sdl_cursor); + SDL_free(internal_cursor); + SDL_OutOfMemory(); + return NULL; + } + image1=(uint8_t*)SDL_calloc(1, ((surface->w+7)>>3)*surface->h); + if (image1==NULL) + { + SDL_free(image0); + SDL_free(sdl_cursor); + SDL_free(internal_cursor); + SDL_OutOfMemory(); + return NULL; + } + + /* Set driverdata as GF cursor format */ + sdl_cursor->driverdata=(void*)internal_cursor; + internal_cursor->type=GF_CURSOR_BITMAP; + internal_cursor->hotspot.x=hot_x; + internal_cursor->hotspot.y=hot_y; + internal_cursor->cursor.bitmap.w=surface->w; + internal_cursor->cursor.bitmap.h=surface->h; + internal_cursor->cursor.bitmap.color0=SDL_GF_MOUSE_COLOR_BLACK; + internal_cursor->cursor.bitmap.color1=SDL_GF_MOUSE_COLOR_WHITE; + + /* Setup cursor shape images */ + internal_cursor->cursor.bitmap.stride=((surface->w+7)>>3); + internal_cursor->cursor.bitmap.image0=image0; + internal_cursor->cursor.bitmap.image1=image1; + + /* Convert cursor from 32 bpp */ + for (jt=0; jth; jt++) + { + for (it=0; itw; it++) + { + shape_color=*((uint32_t*)((uint8_t*)surface->pixels+jt*surface->pitch+it*surface->format->BytesPerPixel)); + switch(shape_color) + { + case SDL_GF_MOUSE_COLOR_BLACK: + { + *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))|=0x80>>(it%8); + *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8)); + } + break; + case SDL_GF_MOUSE_COLOR_WHITE: + { + *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8)); + *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))|=0x80>>(it%8); + } + break; + case SDL_GF_MOUSE_COLOR_TRANS: + { + *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8)); + *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8)); + } + break; + default: + { + /* The same as transparent color, must not happen */ + *(image0+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8)); + *(image1+jt*(internal_cursor->cursor.bitmap.stride)+(it>>3))&=~(0x80>>(it%8)); + } + break; + } + } + } + + return sdl_cursor; +} + +int gf_showcursor(SDL_Cursor* cursor) +{ + SDL_VideoDisplay* display; + SDL_DisplayData* didata; + SDL_Window* window; + SDL_WindowID window_id; + gf_cursor_t* internal_cursor; + int32_t status; + + /* Get current window id */ + window_id=SDL_GetFocusWindow(); + if (window_id<=0) + { + SDL_MouseData* mdata=NULL; + + /* If there is no current window, then someone calls this function */ + /* to set global mouse settings during SDL initialization */ + if (cursor!=NULL) + { + mdata=(SDL_MouseData*)cursor->mouse->driverdata; + didata=(SDL_DisplayData*)mdata->didata; + } + else + { + /* We can't get SDL_DisplayData at this point, return fake success */ + return 0; + } + } + else + { + /* Sanity checks */ + window=SDL_GetWindowFromID(window_id); + if (window!=NULL) + { + display=SDL_GetDisplayFromWindow(window); + if (display!=NULL) + { + didata=(SDL_DisplayData*)display->driverdata; + if (didata==NULL) + { + return -1; + } + } + else + { + return -1; + } + } + else + { + return -1; + } + } + + /* Check if we need to set new shape or disable cursor shape */ + if (cursor!=NULL) + { + /* Retrieve GF cursor shape */ + internal_cursor=(gf_cursor_t*)cursor->driverdata; + if (internal_cursor==NULL) + { + SDL_SetError("GF: Internal cursor data is absent"); + return -1; + } + if ((internal_cursor->cursor.bitmap.image0==NULL) || + (internal_cursor->cursor.bitmap.image1==NULL)) + { + SDL_SetError("GF: Cursor shape is absent"); + return -1; + } + + /* Store last shown cursor to display data */ + didata->cursor.type=internal_cursor->type; + didata->cursor.hotspot.x=internal_cursor->hotspot.x; + didata->cursor.hotspot.y=internal_cursor->hotspot.y; + if (internal_cursor->cursor.bitmap.w>SDL_VIDEO_GF_MAX_CURSOR_SIZE) + { + didata->cursor.cursor.bitmap.w=SDL_VIDEO_GF_MAX_CURSOR_SIZE; + } + else + { + didata->cursor.cursor.bitmap.w=internal_cursor->cursor.bitmap.w; + } + + if (didata->cursor.cursor.bitmap.h>SDL_VIDEO_GF_MAX_CURSOR_SIZE) + { + didata->cursor.cursor.bitmap.h=SDL_VIDEO_GF_MAX_CURSOR_SIZE; + } + else + { + didata->cursor.cursor.bitmap.h=internal_cursor->cursor.bitmap.h; + } + + didata->cursor.cursor.bitmap.color0=internal_cursor->cursor.bitmap.color0; + didata->cursor.cursor.bitmap.color1=internal_cursor->cursor.bitmap.color1; + didata->cursor.cursor.bitmap.stride=internal_cursor->cursor.bitmap.stride; + SDL_memcpy(didata->cursor.cursor.bitmap.image0, + internal_cursor->cursor.bitmap.image0, + ((internal_cursor->cursor.bitmap.w+7)/(sizeof(uint8_t)*8))*internal_cursor->cursor.bitmap.h); + SDL_memcpy(didata->cursor.cursor.bitmap.image1, + internal_cursor->cursor.bitmap.image1, + ((internal_cursor->cursor.bitmap.w+7)/(sizeof(uint8_t)*8))*internal_cursor->cursor.bitmap.h); + + /* Setup cursor shape */ + status=gf_cursor_set(didata->display, 0, internal_cursor); + if (status!=GF_ERR_OK) + { + if (status!=GF_ERR_NOSUPPORT) + { + SDL_SetError("GF: Can't set hardware cursor shape"); + return -1; + } + } + + /* Enable just set cursor */ + status=gf_cursor_enable(didata->display, 0); + if (status!=GF_ERR_OK) + { + if (status!=GF_ERR_NOSUPPORT) + { + SDL_SetError("GF: Can't enable hardware cursor"); + return -1; + } + } + + /* Set cursor visible */ + didata->cursor_visible=SDL_TRUE; + } + else + { + /* SDL requests to disable cursor */ + status=gf_cursor_disable(didata->display, 0); + if (status!=GF_ERR_OK) + { + if (status!=GF_ERR_NOSUPPORT) + { + SDL_SetError("GF: Can't disable hardware cursor"); + return -1; + } + } + + /* Set cursor invisible */ + didata->cursor_visible=SDL_FALSE; + } + + /* New cursor shape is set */ + return 0; +} + +void gf_movecursor(SDL_Cursor* cursor) +{ + SDL_VideoDisplay* display; + SDL_DisplayData* didata; + SDL_Window* window; + SDL_WindowID window_id; + int32_t status; + uint32_t xmax; + uint32_t ymax; + + /* Get current window id */ + window_id=SDL_GetFocusWindow(); + if (window_id<=0) + { + didata=(SDL_DisplayData*)cursor->mouse->driverdata; + } + else + { + /* Sanity checks */ + window=SDL_GetWindowFromID(window_id); + if (window!=NULL) + { + display=SDL_GetDisplayFromWindow(window); + if (display!=NULL) + { + didata=(SDL_DisplayData*)display->driverdata; + if (didata==NULL) + { + return; + } + } + else + { + return; + } + } + else + { + return; + } + } + + /* Add checks for out of screen bounds position */ + if (cursor->mouse->x<0) + { + cursor->mouse->x=0; + } + if (cursor->mouse->y<0) + { + cursor->mouse->y=0; + } + + /* Get window size to clamp maximum coordinates */ + SDL_GetWindowSize(window_id, &xmax, &ymax); + if (cursor->mouse->x>=xmax) + { + cursor->mouse->x=xmax-1; + } + if (cursor->mouse->y>=ymax) + { + cursor->mouse->y=ymax-1; + } + + status=gf_cursor_set_pos(didata->display, 0, cursor->mouse->x, cursor->mouse->y); + if (status!=GF_ERR_OK) + { + if (status!=GF_ERR_NOSUPPORT) + { + SDL_SetError("GF: Can't set hardware cursor position"); + return; + } + } +} + +void gf_freecursor(SDL_Cursor* cursor) +{ + gf_cursor_t* internal_cursor; + + if (cursor!=NULL) + { + internal_cursor=(gf_cursor_t*)cursor->driverdata; + if (internal_cursor!=NULL) + { + if (internal_cursor->cursor.bitmap.image0!=NULL) + { + SDL_free((uint8_t*)internal_cursor->cursor.bitmap.image0); + } + if (internal_cursor->cursor.bitmap.image1!=NULL) + { + SDL_free((uint8_t*)internal_cursor->cursor.bitmap.image1); + } + SDL_free(internal_cursor); + } + } +} + +void gf_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y) +{ + SDL_VideoDisplay* display; + SDL_DisplayData* didata; + SDL_Window* window; + uint32_t xmax; + uint32_t ymax; + int32_t status; + + /* Sanity checks */ + window=SDL_GetWindowFromID(windowID); + if (window!=NULL) + { + display=SDL_GetDisplayFromWindow(window); + if (display!=NULL) + { + didata=(SDL_DisplayData*)display->driverdata; + if (didata==NULL) + { + return; + } + } + else + { + return; + } + } + else + { + return; + } + + /* Add checks for out of screen bounds position */ + if (x<0) + { + x=0; + } + if (y<0) + { + y=0; + } + + /* Get window size to clamp maximum coordinates */ + SDL_GetWindowSize(windowID, &xmax, &ymax); + if (x>=xmax) + { + x=xmax-1; + } + if (y>=ymax) + { + y=ymax-1; + } + + status=gf_cursor_set_pos(didata->display, 0, x, y); + if (status!=GF_ERR_OK) + { + if (status!=GF_ERR_NOSUPPORT) + { + SDL_SetError("GF: Can't set hardware cursor position"); + return; + } + } +} + +void gf_freemouse(SDL_Mouse* mouse) +{ + if (mouse->driverdata==NULL) + { + return; + } + + /* Mouse framework doesn't deletes automatically our driverdata */ + SDL_free(mouse->driverdata); + mouse->driverdata=NULL; + + return; +} + +/*****************************************************************************/ +/* HIDDI handlers code */ +/*****************************************************************************/ +static key_packet key_last_state[SDL_HIDDI_MAX_DEVICES]; + +static void hiddi_keyboard_handler(uint32_t devno, uint8_t* report_data, uint32_t report_len) +{ + key_packet* packet; + uint32_t it; + uint32_t jt; + + packet=(key_packet*)report_data; + + /* Check for special states */ + switch (report_len) + { + case 8: /* 8 bytes of report length */ + { + for (it=0; it<6; it++) + { + /* Check for keyboard overflow, when it can't handle */ + /* many simultaneous pressed keys */ + if (packet->codes[it]==HIDDI_KEY_OVERFLOW) + { + return; + } + } + } + break; + default: + { + /* Do not process unknown reports */ + return; + } + break; + } + + /* Check if modifier key was pressed */ + if (packet->modifiers!=key_last_state[devno].modifiers) + { + if (((packet->modifiers & HIDDI_MKEY_LEFT_CTRL)==HIDDI_MKEY_LEFT_CTRL) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_CTRL)==0) + { + /* Left Ctrl key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LCTRL); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_CTRL)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_CTRL)==HIDDI_MKEY_LEFT_CTRL) + { + /* Left Ctrl key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LCTRL); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_SHIFT)==HIDDI_MKEY_LEFT_SHIFT) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_SHIFT)==0) + { + /* Left Shift key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LSHIFT); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_SHIFT)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_SHIFT)==HIDDI_MKEY_LEFT_SHIFT) + { + /* Left Shift key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LSHIFT); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_ALT)==HIDDI_MKEY_LEFT_ALT) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_ALT)==0) + { + /* Left Alt key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LALT); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_ALT)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_ALT)==HIDDI_MKEY_LEFT_ALT) + { + /* Left Alt key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LALT); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_WFLAG)==HIDDI_MKEY_LEFT_WFLAG) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_WFLAG)==0) + { + /* Left Windows flag key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_LGUI); + } + if (((packet->modifiers & HIDDI_MKEY_LEFT_WFLAG)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_LEFT_WFLAG)==HIDDI_MKEY_LEFT_WFLAG) + { + /* Left Windows flag key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_LGUI); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_CTRL)==HIDDI_MKEY_RIGHT_CTRL) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_CTRL)==0) + { + /* Right Ctrl key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RCTRL); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_CTRL)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_CTRL)==HIDDI_MKEY_RIGHT_CTRL) + { + /* Right Ctrl key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RCTRL); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_SHIFT)==HIDDI_MKEY_RIGHT_SHIFT) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_SHIFT)==0) + { + /* Right Shift key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RSHIFT); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_SHIFT)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_SHIFT)==HIDDI_MKEY_RIGHT_SHIFT) + { + /* Right Shift key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RSHIFT); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_ALT)==HIDDI_MKEY_RIGHT_ALT) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_ALT)==0) + { + /* Right Alt key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RALT); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_ALT)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_ALT)==HIDDI_MKEY_RIGHT_ALT) + { + /* Right Alt key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RALT); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_WFLAG)==HIDDI_MKEY_RIGHT_WFLAG) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_WFLAG)==0) + { + /* Right Windows flag key was pressed */ + SDL_SendKeyboardKey(0, SDL_PRESSED, SDL_SCANCODE_RGUI); + } + if (((packet->modifiers & HIDDI_MKEY_RIGHT_WFLAG)==0) && + (key_last_state[devno].modifiers & HIDDI_MKEY_RIGHT_WFLAG)==HIDDI_MKEY_RIGHT_WFLAG) + { + /* Right Windows flag key was released */ + SDL_SendKeyboardKey(0, SDL_RELEASED, SDL_SCANCODE_RGUI); + } + } + + /* Check each key in the press/release buffer */ + switch (report_len) + { + case 8: /* 8 bytes of report length */ + { + /* Check if at least one key was unpressed */ + for (it=0; it<6; it++) + { + if (key_last_state[devno].codes[it]==HIDDI_KEY_UNPRESSED) + { + /* if stored keycode is zero, find another */ + continue; + } + for (jt=0; jt<6; jt++) + { + /* Find stored keycode in the current pressed codes */ + if (packet->codes[jt]==key_last_state[devno].codes[it]) + { + /* If found then particular key state is not changed */ + break; + } + } + + /* Check if pressed key can't longer be found */ + if (jt==6) + { + SDL_SendKeyboardKey(0, SDL_RELEASED, key_last_state[devno].codes[it]); + } + } + + /* Check if at least one new key was pressed */ + for (it=0; it<6; it++) + { + if (packet->codes[it]==HIDDI_KEY_UNPRESSED) + { + continue; + } + for (jt=0; jt<6; jt++) + { + /* Find new keycode it the array of old pressed keys */ + if (packet->codes[it]==key_last_state[devno].codes[jt]) + { + break; + } + } + + /* Check if new key was pressed */ + if (jt==6) + { + SDL_SendKeyboardKey(0, SDL_PRESSED, packet->codes[it]); + } + } + } + default: /* unknown keyboard report type */ + { + /* Ignore all unknown reports */ + } + break; + } + + /* Store last state */ + key_last_state[devno]=*packet; +} + +static uint32_t mouse_last_state_button[SDL_HIDDI_MAX_DEVICES]; +static uint32_t collect_reports=0; + +static void hiddi_mouse_handler(uint32_t devno, uint8_t* report_data, uint32_t report_len) +{ + uint32_t it; + uint32_t sdlbutton; + + /* We do not want to collect stored events */ + if (collect_reports==0) + { + return; + } + + /* Check for special states */ + switch (report_len) + { + case 8: /* 8 bytes of report length, usually multi-button USB mice */ + { + mouse_packet8* packet; + packet=(mouse_packet8*)report_data; + + /* Send motion event if motion really was */ + if ((packet->horizontal_precision!=0) || (packet->vertical_precision!=0)) + { + SDL_SendMouseMotion(0, 1, packet->horizontal_precision, packet->vertical_precision, 0); + } + + /* Send mouse button press/release events */ + if (mouse_last_state_button[devno]!=packet->buttons) + { + /* Cycle all buttons status */ + for (it=0; it<8; it++) + { + /* convert hiddi button id to sdl button id */ + switch(it) + { + case 0: + { + sdlbutton=SDL_BUTTON_LEFT; + } + break; + case 1: + { + sdlbutton=SDL_BUTTON_RIGHT; + } + break; + case 2: + { + sdlbutton=SDL_BUTTON_MIDDLE; + } + break; + default: + { + sdlbutton=it+1; + } + break; + } + + /* Button pressed */ + if (((packet->buttons & (0x01<buttons & (0x01<buttons; + } + + /* Send mouse wheel events */ + if (packet->wheel!=0) + { + /* Send vertical wheel event only */ + SDL_SendMouseWheel(0, 0, packet->wheel); + } + } + break; + case 4: /* 4 bytes of report length, usually PS/2 mice */ + { + mouse_packet4* packet; + packet=(mouse_packet4*)report_data; + + /* Send motion event if motion really was */ + if ((packet->horizontal!=0) || (packet->vertical!=0)) + { + SDL_SendMouseMotion(0, 1, packet->horizontal, packet->vertical, 0); + } + + /* Send mouse button press/release events */ + if (mouse_last_state_button[devno]!=packet->buttons) + { + /* Cycle all buttons status */ + for (it=0; it<8; it++) + { + /* convert hiddi button id to sdl button id */ + switch(it) + { + case 0: + { + sdlbutton=SDL_BUTTON_LEFT; + } + break; + case 1: + { + sdlbutton=SDL_BUTTON_RIGHT; + } + break; + case 2: + { + sdlbutton=SDL_BUTTON_MIDDLE; + } + break; + default: + { + sdlbutton=it+1; + } + break; + } + + /* Button pressed */ + if (((packet->buttons & (0x01<buttons & (0x01<buttons; + } + + /* Send mouse wheel events */ + if (packet->wheel!=0) + { + /* Send vertical wheel event only */ + SDL_SendMouseWheel(0, 0, packet->wheel); + } + } + break; + } +} + +/*****************************************************************************/ +/* HIDDI interacting code */ +/*****************************************************************************/ +static hidd_device_ident_t hiddevice= +{ + HIDD_CONNECT_WILDCARD, /* vendor id: any */ + HIDD_CONNECT_WILDCARD, /* product id: any */ + HIDD_CONNECT_WILDCARD, /* version: any */ +}; + +static hidd_connect_parm_t hidparams={NULL, HID_VERSION, HIDD_VERSION, 0, 0, &hiddevice, NULL, 0}; + +static void hiddi_insertion(struct hidd_connection* connection, hidd_device_instance_t* device_instance); +static void hiddi_removal(struct hidd_connection* connection, hidd_device_instance_t* instance); +static void hiddi_report(struct hidd_connection* connection, struct hidd_report* report, void* report_data, uint32_t report_len, uint32_t flags, void* user); + +static hidd_funcs_t hidfuncs={_HIDDI_NFUNCS, hiddi_insertion, hiddi_removal, hiddi_report, NULL}; + +/* HID handle, singletone */ +struct hidd_connection* connection=NULL; + +/* SDL detected input device types, singletone */ +static uint32_t sdl_input_devices[SDL_HIDDI_MAX_DEVICES]; + +static int hiddi_register_for_reports(struct hidd_collection* col, hidd_device_instance_t* device_instance) +{ + int it; + uint16_t num_col; + struct hidd_collection** hidd_collections; + struct hidd_report_instance* report_instance; + struct hidd_report* report; + int status=0; + hidview_device_t* device; + + for (it=0 ; it<10 && !status; it++) + { + status=hidd_get_report_instance(col, it, HID_INPUT_REPORT, &report_instance); + if (status==EOK) + { + status=hidd_report_attach(connection, device_instance, report_instance, 0, sizeof(hidview_device_t), &report); + if (status==EOK) + { + device=hidd_report_extra(report); + device->report=report; + device->instance=report_instance; + } + } + } + hidd_get_collections(NULL, col, &hidd_collections, &num_col); + + for (it=0; itdev_inst->devno>=SDL_HIDDI_MAX_DEVICES) + { + /* Unknown HID device, with devno number out of supported range */ + return; + } + + /* Check device type which generates event */ + switch (sdl_input_devices[report->dev_inst->devno]) + { + case SDL_GF_HIDDI_NONE: + { + /* We do not handle other devices type*/ + return; + } + break; + case SDL_GF_HIDDI_MOUSE: + { + /* Call mouse handler */ + hiddi_mouse_handler(report->dev_inst->devno, report_data, report_len); + } + break; + case SDL_GF_HIDDI_KEYBOARD: + { + /* Call keyboard handler */ + hiddi_keyboard_handler(report->dev_inst->devno, report_data, report_len); + } + break; + case SDL_GF_HIDDI_JOYSTICK: + { + /* Call joystick handler */ + } + break; + } +} + +static hiddi_get_device_type(uint8_t* report_data, uint16_t report_length) +{ + hid_byte_t byte; + uint16_t usage_page=0; + uint16_t usage=0; + uint16_t data=0; + + while (report_length && !(usage_page && usage)) + { + if (hidp_analyse_byte(*report_data, &byte)) + { + /* Error in parser, do nothing */ + } + data=hidp_get_data((report_data+1), &byte); + switch (byte.HIDB_Type) + { + case HID_TYPE_GLOBAL: + if (!usage_page && byte.HIDB_Tag==HID_GLOBAL_USAGE_PAGE) + { + usage_page=data; + } + break; + case HID_TYPE_LOCAL: + if (!usage && byte.HIDB_Tag==HID_LOCAL_USAGE) + { + usage=data; + } + break; + } + report_data+=byte.HIDB_Length+1; + report_length-=byte.HIDB_Length+1; + } + + switch (usage_page) + { + case HIDD_PAGE_DESKTOP: + { + switch (usage) + { + case HIDD_USAGE_MOUSE: + { + return SDL_GF_HIDDI_MOUSE; + } + break; + case HIDD_USAGE_JOYSTICK: + { + return SDL_GF_HIDDI_JOYSTICK; + } + break; + case HIDD_USAGE_KEYBOARD: + { + return SDL_GF_HIDDI_KEYBOARD; + } + break; + } + } + break; + case HIDD_PAGE_DIGITIZER: + { + /* Do not handle digitizers */ + } + break; + case HIDD_PAGE_CONSUMER: + { + /* Do not handle consumer input devices */ + } + break; + } + + return SDL_GF_HIDDI_NONE; +} + +static int32_t hiddi_connect_devices() +{ + int32_t status; + uint32_t it; + uint8_t* report_data; + uint16_t report_length; + hidd_device_instance_t instance; + + /* Cleanup initial keys and mice state */ + SDL_memset(key_last_state, 0x00, sizeof(key_packet)*SDL_HIDDI_MAX_DEVICES); + SDL_memset(mouse_last_state_button, 0x00, sizeof(uint32_t)*SDL_HIDDI_MAX_DEVICES); + + status=hidd_connect(&hidparams, &connection); + if (status!=EOK) + { + return -1; + } + + for (it=0; it + +#include + +#include +#include + +#include "SDL_qnxgf.h" + +typedef struct SDL_MouseData +{ + SDL_DisplayData* didata; +} SDL_MouseData; + +int32_t gf_addinputdevices(_THIS); +int32_t gf_delinputdevices(_THIS); + +#define SDL_GF_MOUSE_COLOR_BLACK 0xFF000000 +#define SDL_GF_MOUSE_COLOR_WHITE 0xFFFFFFFF +#define SDL_GF_MOUSE_COLOR_TRANS 0x00000000 + +/*****************************************************************************/ +/* This is HIDDI closed interface declarations */ +/*****************************************************************************/ +#define HID_TYPE_MAIN 0x0 +#define HID_TYPE_GLOBAL 0x1 +#define HID_TYPE_LOCAL 0x2 +#define HID_TYPE_RESERVED 0x3 + +#define HID_GLOBAL_USAGE_PAGE 0x0 +#define HID_LOCAL_USAGE 0x0 + +typedef struct _hid_byte +{ + uint8_t HIDB_Length; + uint8_t HIDB_Type; + uint8_t HIDB_Tag; + uint8_t reserved[1]; +} hid_byte_t; + +typedef struct _hidd_global_item +{ + uint16_t usage_page; + uint16_t logical_min; + uint16_t logical_max; + uint16_t physical_min; + uint16_t physical_max; + uint16_t unit_expo; + uint16_t unit; + uint16_t report_size; + uint16_t report_id; + uint16_t report_count; +} hidd_global_item_t; + +typedef struct _hidd_local_item +{ + uint16_t type; + uint8_t reserved[2]; + uint32_t value; + struct _hidd_local_item* next_local; + struct _hidd_local_item* alt_local; +} hidd_local_item_t; + +typedef struct _hidd_local_table +{ + hidd_local_item_t* usage_info; + hidd_local_item_t* designator_info; + hidd_local_item_t* string_info; + uint8_t delimiter; + uint8_t reserved[3]; +} hidd_local_table_t; + +typedef struct _hidd_field +{ + struct hidd_report_instance* report; + struct hidd_collection* collection; + uint16_t report_offset; + uint16_t flags; + hidd_global_item_t gitem; + hidd_local_table_t* ltable; + struct _hidd_field* next_field; + void* user; +} hidd_field_t; + +typedef struct hidd_report_instance +{ + uint8_t report_id; + uint8_t reserved[1]; + uint16_t report_type; + hidd_field_t* field; + uint16_t num_field; + uint16_t byte_len; + uint16_t bit_len; + uint8_t reserved2[2]; + struct hidd_collection* collection; + struct hidd_report_instance* next_col_report; + struct hidd_report_instance* next_report; +} hidd_report_instance_t; + +typedef struct hidd_report +{ + TAILQ_ENTRY(hidd_report) link; + hidd_report_instance_t* rinst; + hidd_device_instance_t* dev_inst; + uint32_t flags; + struct hidd_connection* connection; + void* user; +} hidd_report_t; + +typedef struct hidview_device +{ + struct hidd_report_instance* instance; + struct hidd_report* report; +} hidview_device_t; + +/*****************************************************************************/ +/* Closed HIDDI interface declarations end */ +/*****************************************************************************/ + +/* Maximum devices and subdevices amount per host */ +#define SDL_HIDDI_MAX_DEVICES 64 + +/* Detected device/subdevice type for SDL */ +#define SDL_GF_HIDDI_NONE 0x00000000 +#define SDL_GF_HIDDI_MOUSE 0x00000001 +#define SDL_GF_HIDDI_KEYBOARD 0x00000002 +#define SDL_GF_HIDDI_JOYSTICK 0x00000003 + +extern void hiddi_enable_mouse(); +extern void hiddi_disable_mouse(); + +#endif /* __SDL_GF_INPUT_H__ */ diff --git a/src/video/qnxgf/SDL_gf_opengles.c b/src/video/qnxgf/SDL_gf_opengles.c index 12b596275..3163a8b61 100644 --- a/src/video/qnxgf/SDL_gf_opengles.c +++ b/src/video/qnxgf/SDL_gf_opengles.c @@ -1,8 +1,3 @@ -Date: Mon, 23 Mar 2009 09:17:24 +0200 -From: "Mike Gorchak" -To: "Sam Lantinga" -Subject: New QNX patches - /* SDL - Simple DirectMedia Layer Copyright (C) 1997-2009 Sam Lantinga @@ -53,4 +48,3 @@ GLAPI void APIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte glColor4f(((GLfloat)red)/255.f, ((GLfloat)green)/255.f, ((GLfloat)blue)/255.f, ((GLfloat)alpha)/255.f); return; } - diff --git a/src/video/qnxgf/SDL_gf_opengles.h b/src/video/qnxgf/SDL_gf_opengles.h new file mode 100644 index 000000000..11d05fdad --- /dev/null +++ b/src/video/qnxgf/SDL_gf_opengles.h @@ -0,0 +1,37 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Graphics Framework SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#ifndef __SDL_GF_OPENGLES_H__ +#define __SDL_GF_OPENGLES_H__ + +#include +#include + +GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params); +GLAPI void APIENTRY glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); + +#endif /* __SDL_GF_OPENGLES_H__ */ diff --git a/src/video/qnxgf/SDL_gf_render.c b/src/video/qnxgf/SDL_gf_render.c index fbd32b76c..3f2338470 100644 --- a/src/video/qnxgf/SDL_gf_render.c +++ b/src/video/qnxgf/SDL_gf_render.c @@ -35,24 +35,24 @@ #include "SDL_qnxgf.h" static SDL_Renderer* gf_createrenderer(SDL_Window* window, Uint32 flags); -static int gf_displaymodechanged(SDL_Renderer* renderer); -static int gf_activaterenderer(SDL_Renderer* renderer); -static int gf_createtexture(SDL_Renderer* renderer, SDL_Texture* texture); -static int gf_querytexturepixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch); -static int gf_settexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Color* colors, int firstcolor, int ncolors); -static int gf_gettexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Color* colors, int firstcolor, int ncolors); -static int gf_settexturecolormod(SDL_Renderer* renderer, SDL_Texture* texture); -static int gf_settexturealphamod(SDL_Renderer* renderer, SDL_Texture* texture); -static int gf_settextureblendmode(SDL_Renderer* renderer, SDL_Texture* texture); -static int gf_settexturescalemode(SDL_Renderer* renderer, SDL_Texture* texture); -static int gf_updatetexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, const void* pixels, int pitch); -static int gf_locktexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, int markDirty, void** pixels, int* pitch); +static int gf_displaymodechanged(SDL_Renderer* renderer); +static int gf_activaterenderer(SDL_Renderer* renderer); +static int gf_createtexture(SDL_Renderer* renderer, SDL_Texture* texture); +static int gf_querytexturepixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch); +static int gf_settexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Color* colors, int firstcolor, int ncolors); +static int gf_gettexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Color* colors, int firstcolor, int ncolors); +static int gf_settexturecolormod(SDL_Renderer* renderer, SDL_Texture* texture); +static int gf_settexturealphamod(SDL_Renderer* renderer, SDL_Texture* texture); +static int gf_settextureblendmode(SDL_Renderer* renderer, SDL_Texture* texture); +static int gf_settexturescalemode(SDL_Renderer* renderer, SDL_Texture* texture); +static int gf_updatetexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, const void* pixels, int pitch); +static int gf_locktexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, int markDirty, void** pixels, int* pitch); static void gf_unlocktexture(SDL_Renderer* renderer, SDL_Texture* texture); static void gf_dirtytexture(SDL_Renderer* renderer, SDL_Texture* texture, int numrects, const SDL_Rect* rects); -static int gf_renderpoint(SDL_Renderer* renderer, int x, int y); -static int gf_renderline(SDL_Renderer* renderer, int x1, int y1, int x2, int y2); -static int gf_renderfill(SDL_Renderer* renderer, const SDL_Rect* rect); -static int gf_rendercopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect); +static int gf_renderpoint(SDL_Renderer* renderer, int x, int y); +static int gf_renderline(SDL_Renderer* renderer, int x1, int y1, int x2, int y2); +static int gf_renderfill(SDL_Renderer* renderer, const SDL_Rect* rect); +static int gf_rendercopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect); static void gf_renderpresent(SDL_Renderer* renderer); static void gf_destroytexture(SDL_Renderer* renderer, SDL_Texture* texture); static void gf_destroyrenderer(SDL_Renderer* renderer); @@ -222,7 +222,6 @@ static SDL_Renderer* gf_createrenderer(SDL_Window* window, Uint32 flags) for (it=0; itsurfaces_count; it++) { /* TODO: add palette creation */ - /* do not waste surfaces when using GL ES */ /* Create displayable surfaces */ status=gf_surface_create_layer(&rdata->surface[it], &didata->layer, 1, 0, @@ -236,6 +235,7 @@ static SDL_Renderer* gf_createrenderer(SDL_Window* window, Uint32 flags) for (jt=it-1; jt>0; jt--) { gf_surface_free(rdata->surface[jt]); + rdata->surface[jt]=NULL; } SDL_free(rdata); SDL_free(renderer); @@ -288,10 +288,10 @@ static int gf_activaterenderer(SDL_Renderer* renderer) SDL_DisplayData* didata = (SDL_DisplayData*)display->driverdata; /* Setup current surface as visible */ - gf_layer_set_surfaces(didata->layer, &rdata->surface[rdata->surface_visible_idx], 1); +// gf_layer_set_surfaces(didata->layer, &rdata->surface[rdata->surface_visible_idx], 1); /* Set visible surface when hardware in idle state */ - gf_layer_update(didata->layer, GF_LAYER_UPDATE_NO_WAIT_IDLE); +// gf_layer_update(didata->layer, GF_LAYER_UPDATE_NO_WAIT_IDLE); return 0; } @@ -391,7 +391,10 @@ static void gf_destroyrenderer(SDL_Renderer* renderer) for (it=0; itsurfaces_count; it++) { - gf_surface_free(rdata->surface[it]); + if (rdata->surface[it]!=NULL) + { + gf_surface_free(rdata->surface[it]); + } } } diff --git a/src/video/qnxgf/SDL_hiddi_joystick.h b/src/video/qnxgf/SDL_hiddi_joystick.h new file mode 100644 index 000000000..ca6cea8fc --- /dev/null +++ b/src/video/qnxgf/SDL_hiddi_joystick.h @@ -0,0 +1,34 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Graphics Framework SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#ifndef __SDL_HIDDI_JOYSTICK_H__ +#define __SDL_HIDDI_JOYSTICK_H__ + +#include + + + +#endif /* __SDL_HIDDI_JOYSTICK_H__ */ diff --git a/src/video/qnxgf/SDL_hiddi_keyboard.h b/src/video/qnxgf/SDL_hiddi_keyboard.h new file mode 100644 index 000000000..7b0551021 --- /dev/null +++ b/src/video/qnxgf/SDL_hiddi_keyboard.h @@ -0,0 +1,159 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Graphics Framework SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#ifndef __SDL_HIDDI_KEYBOARD_H__ +#define __SDL_HIDDI_KEYBOARD_H__ + +#include + +/* PS/2 and USB keyboards are generating this packet */ +typedef struct key_packet +{ + uint8_t modifiers; + uint8_t data; + uint8_t codes[6]; +} key_packet; + +/* Key modifier codes */ +#define HIDDI_MKEY_LEFT_CTRL 0x00000001 +#define HIDDI_MKEY_LEFT_SHIFT 0x00000002 +#define HIDDI_MKEY_LEFT_ALT 0x00000004 +#define HIDDI_MKEY_LEFT_WFLAG 0x00000008 +#define HIDDI_MKEY_RIGHT_CTRL 0x00000010 +#define HIDDI_MKEY_RIGHT_SHIFT 0x00000020 +#define HIDDI_MKEY_RIGHT_ALT 0x00000040 +#define HIDDI_MKEY_RIGHT_WFLAG 0x00000080 + +/* Key codes */ +#define HIDDI_KEY_UNPRESSED 0x00000000 +#define HIDDI_KEY_OVERFLOW 0x00000001 +#define HIDDI_KEY_ESC 0x00000029 +#define HIDDI_KEY_F1 0x0000003A +#define HIDDI_KEY_F2 0x0000003B +#define HIDDI_KEY_F3 0x0000003C +#define HIDDI_KEY_F4 0x0000003D +#define HIDDI_KEY_F5 0x0000003E +#define HIDDI_KEY_F6 0x0000003F +#define HIDDI_KEY_F7 0x00000040 +#define HIDDI_KEY_F8 0x00000041 +#define HIDDI_KEY_F9 0x00000042 +#define HIDDI_KEY_F10 0x00000043 +#define HIDDI_KEY_F11 0x00000044 +#define HIDDI_KEY_F12 0x00000045 + +#define HIDDI_KEY_BACKQUOTE 0x00000035 +#define HIDDI_KEY_1 0x0000001E +#define HIDDI_KEY_2 0x0000001F +#define HIDDI_KEY_3 0x00000020 +#define HIDDI_KEY_4 0x00000021 +#define HIDDI_KEY_5 0x00000022 +#define HIDDI_KEY_6 0x00000023 +#define HIDDI_KEY_7 0x00000024 +#define HIDDI_KEY_8 0x00000025 +#define HIDDI_KEY_9 0x00000026 +#define HIDDI_KEY_0 0x00000027 +#define HIDDI_KEY_MINUS 0x0000002D +#define HIDDI_KEY_EQUAL 0x0000002E +#define HIDDI_KEY_BACKSPACE 0x0000002A + +#define HIDDI_KEY_TAB 0x0000002B +#define HIDDI_KEY_Q 0x00000014 +#define HIDDI_KEY_W 0x0000001A +#define HIDDI_KEY_E 0x00000008 +#define HIDDI_KEY_R 0x00000015 +#define HIDDI_KEY_T 0x00000017 +#define HIDDI_KEY_Y 0x0000001C +#define HIDDI_KEY_U 0x00000018 +#define HIDDI_KEY_I 0x0000000C +#define HIDDI_KEY_O 0x00000012 +#define HIDDI_KEY_P 0x00000013 +#define HIDDI_KEY_LEFT_SQ_BRACKET 0x0000002F +#define HIDDI_KEY_RIGHT_SQ_BRACKET 0x00000030 +#define HIDDI_KEY_BACKSLASH 0x00000031 + +#define HIDDI_KEY_CAPSLOCK 0x00000039 +#define HIDDI_KEY_A 0x00000004 +#define HIDDI_KEY_S 0x00000016 +#define HIDDI_KEY_D 0x00000007 +#define HIDDI_KEY_F 0x00000009 +#define HIDDI_KEY_G 0x0000000A +#define HIDDI_KEY_H 0x0000000B +#define HIDDI_KEY_J 0x0000000D +#define HIDDI_KEY_K 0x0000000E +#define HIDDI_KEY_L 0x0000000F +#define HIDDI_KEY_SEMICOLON 0x00000033 +#define HIDDI_KEY_QUOTE 0x00000034 +#define HIDDI_KEY_ENTER 0x00000028 + +#define HIDDI_KEY_Z 0x0000001D +#define HIDDI_KEY_X 0x0000001B +#define HIDDI_KEY_C 0x00000006 +#define HIDDI_KEY_V 0x00000019 +#define HIDDI_KEY_B 0x00000005 +#define HIDDI_KEY_N 0x00000011 +#define HIDDI_KEY_M 0x00000010 +#define HIDDI_KEY_COMMA 0x00000036 +#define HIDDI_KEY_POINT 0x00000037 +#define HIDDI_KEY_SLASH 0x00000038 + +#define HIDDI_KEY_SPACE 0x0000002C +#define HIDDI_KEY_MENU 0x00000065 + +#define HIDDI_KEY_PRINTSCREEN 0x00000046 +#define HIDDI_KEY_SCROLLLOCK 0x00000047 +#define HIDDI_KEY_PAUSE 0x00000048 + +#define HIDDI_KEY_INSERT 0x00000049 +#define HIDDI_KEY_HOME 0x0000004A +#define HIDDI_KEY_PAGEUP 0x0000004B +#define HIDDI_KEY_DELETE 0x0000004C +#define HIDDI_KEY_END 0x0000004D +#define HIDDI_KEY_PAGEDOWN 0x0000004E + +#define HIDDI_KEY_UP 0x00000052 +#define HIDDI_KEY_LEFT 0x00000050 +#define HIDDI_KEY_DOWN 0x00000051 +#define HIDDI_KEY_RIGHT 0x0000004F + +#define HIDDI_KEY_NUMLOCK 0x00000053 +#define HIDDI_KEY_GR_SLASH 0x00000054 +#define HIDDI_KEY_GR_ASTERISK 0x00000055 +#define HIDDI_KEY_GR_MINUS 0x00000056 +#define HIDDI_KEY_GR_7 0x0000005F +#define HIDDI_KEY_GR_8 0x00000060 +#define HIDDI_KEY_GR_9 0x00000061 +#define HIDDI_KEY_GR_PLUS 0x00000057 +#define HIDDI_KEY_GR_4 0x0000005C +#define HIDDI_KEY_GR_5 0x0000005D +#define HIDDI_KEY_GR_6 0x0000005E +#define HIDDI_KEY_GR_1 0x00000059 +#define HIDDI_KEY_GR_2 0x0000005A +#define HIDDI_KEY_GR_3 0x0000005B +#define HIDDI_KEY_GR_ENTER 0x00000058 +#define HIDDI_KEY_GR_0 0x00000062 +#define HIDDI_KEY_GR_DELETE 0x00000063 + +#endif /* __SDL_HIDDI_KEYBOARD_H__ */ diff --git a/src/video/qnxgf/SDL_hiddi_mouse.h b/src/video/qnxgf/SDL_hiddi_mouse.h new file mode 100644 index 000000000..61bee5924 --- /dev/null +++ b/src/video/qnxgf/SDL_hiddi_mouse.h @@ -0,0 +1,69 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2009 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org + + QNX Graphics Framework SDL driver + Copyright (C) 2009 Mike Gorchak + (mike@malva.ua, lestat@i.com.ua) +*/ + +#ifndef __SDL_HIDDI_MOUSE_H__ +#define __SDL_HIDDI_MOUSE_H__ + +#include + +/* USB keyboard multimedia keys are generating this packet */ +typedef struct mouse_packet2 +{ + uint8_t buttons; + int8_t wheel; +} mouse_packet2; + +/* PS/2 mice are generating this packet */ +typedef struct mouse_packet4 +{ + uint8_t buttons; + int8_t horizontal; + int8_t vertical; + int8_t wheel; +} mouse_packet4; + +/* USB keyboard with mice wheel onboard generating this packet */ +typedef struct mouse_packet5 +{ + uint8_t buttons; + int8_t horizontal; + int8_t vertical; + int8_t wheel; + uint8_t state; +} mouse_packet5; + +/* USB multi-button mice are generating this packet */ +typedef struct mouse_packet8 +{ + uint8_t buttons; + int8_t horizontal; + int8_t vertical; + int8_t wheel; + int16_t horizontal_precision; + int16_t vertical_precision; +} mouse_packet8; + +#endif /* __SDL_HIDDI_MOUSE_H__ */ diff --git a/src/video/qnxgf/SDL_qnxgf.c b/src/video/qnxgf/SDL_qnxgf.c index e94bd3735..807bde8ca 100644 --- a/src/video/qnxgf/SDL_qnxgf.c +++ b/src/video/qnxgf/SDL_qnxgf.c @@ -37,6 +37,8 @@ #include "SDL_qnxgf.h" #include "SDL_gf_render.h" #include "SDL_gf_pixelfmt.h" +#include "SDL_gf_opengles.h" +#include "SDL_gf_input.h" /******************************************************************************/ /* SDL Generic video modes, which could provide GF */ @@ -248,6 +250,13 @@ static SDL_VideoDevice* qnxgf_create(int devindex) return NULL; } + if (gfdata->gfdev_info.description==NULL) + { + gf_dev_detach(gfdata->gfdev); + SDL_SetError("GF: Failed to initialize graphics driver"); + return NULL; + } + /* Setup amount of available displays and current display */ device->num_displays=0; device->current_display=0; @@ -312,6 +321,10 @@ int qnxgf_videoinit(_THIS) uint32_t it; uint32_t jt; char* override; + int32_t status; + + /* By default GF uses buffer swap on vsync */ + gfdata->swapinterval=1; /* Add each detected output to SDL */ for (it=0; itgfdev_info.ndisplays; it++) @@ -319,7 +332,6 @@ int qnxgf_videoinit(_THIS) SDL_VideoDisplay display; SDL_DisplayMode current_mode; SDL_DisplayData* didata; - int status; didata=(SDL_DisplayData*)SDL_calloc(1, sizeof(SDL_DisplayData)); if (didata==NULL) @@ -329,6 +341,36 @@ int qnxgf_videoinit(_THIS) return -1; } + /* Set default cursor settings, maximum 128x128 cursor */ + didata->cursor_visible=SDL_FALSE; + didata->cursor.type=GF_CURSOR_BITMAP; + didata->cursor.hotspot.x=0; + didata->cursor.hotspot.y=0; + didata->cursor.cursor.bitmap.w=SDL_VIDEO_GF_MAX_CURSOR_SIZE; + didata->cursor.cursor.bitmap.h=SDL_VIDEO_GF_MAX_CURSOR_SIZE; + didata->cursor.cursor.bitmap.stride=(didata->cursor.cursor.bitmap.w+7)/ + (sizeof(uint8_t)*8); + didata->cursor.cursor.bitmap.color0=0x00000000; + didata->cursor.cursor.bitmap.color1=0x00000000; + didata->cursor.cursor.bitmap.image0=SDL_calloc(sizeof(uint8_t), (didata->cursor.cursor.bitmap.w+7)* + didata->cursor.cursor.bitmap.h/(sizeof(uint8_t)*8)); + if (didata->cursor.cursor.bitmap.image0==NULL) + { + SDL_free(didata); + SDL_OutOfMemory(); + return -1; + } + didata->cursor.cursor.bitmap.image1=SDL_calloc(sizeof(uint8_t), (didata->cursor.cursor.bitmap.w+7)* + didata->cursor.cursor.bitmap.h/(sizeof(uint8_t)*8)); + if (didata->cursor.cursor.bitmap.image1==NULL) + { + SDL_OutOfMemory(); + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + SDL_free(didata); + return -1; + } + + /* Query current display settings */ status=gf_display_query(gfdata->gfdev, it, &didata->display_info); if (status==GF_ERR_OK) { @@ -342,6 +384,8 @@ int qnxgf_videoinit(_THIS) else { /* video initialization problem */ + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + SDL_free((void*)didata->cursor.cursor.bitmap.image1); SDL_free(didata); SDL_SetError("GF: Display query failed"); return -1; @@ -352,6 +396,8 @@ int qnxgf_videoinit(_THIS) if (status!=GF_ERR_OK) { /* video initialization problem */ + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + SDL_free((void*)didata->cursor.cursor.bitmap.image1); SDL_free(didata); SDL_SetError("GF: Couldn't attach to display"); return -1; @@ -364,18 +410,64 @@ int qnxgf_videoinit(_THIS) status=gf_layer_attach(&didata->layer, didata->display, didata->display_info.main_layer_index, 0); if (status!=GF_ERR_OK) { + /* Failed to attach to main layer */ + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + SDL_free((void*)didata->cursor.cursor.bitmap.image1); + SDL_free(didata); SDL_SetError("GF: Couldn't attach to main layer, it could be busy"); + return -1; + } - /* Failed to attach to main layer */ + /* Mark main display layer is attached */ + didata->layer_attached=SDL_TRUE; + + /* Set layer source and destination viewport */ + gf_layer_set_src_viewport(didata->layer, 0, 0, current_mode.w-1, current_mode.h-1); + gf_layer_set_dst_viewport(didata->layer, 0, 0, current_mode.w-1, current_mode.h-1); + + /* Create main visible on display surface */ + status=gf_surface_create_layer(&didata->surface[0], &didata->layer, + 1, 0, current_mode.w, current_mode.h, + qnxgf_sdl_to_gf_pixelformat(current_mode.format), + NULL, GF_SURFACE_CREATE_2D_ACCESSIBLE | GF_SURFACE_CREATE_3D_ACCESSIBLE | + GF_SURFACE_CREATE_SHAREABLE); + if (status!=GF_ERR_OK) + { + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + SDL_free((void*)didata->cursor.cursor.bitmap.image1); + SDL_free(didata); + SDL_SetError("GF: Can't create main layer surface at init (%d)\n", status); + return -1; + } + + /* Set just created surface as main visible on the layer */ +// gf_layer_set_surfaces(didata->layer, &didata->surface[0], 1); + + /* Update layer parameters */ + status=gf_layer_update(didata->layer, GF_LAYER_UPDATE_NO_WAIT_IDLE); + if (status!=GF_ERR_OK) + { + /* Free allocated surface */ + gf_surface_free(didata->surface[0]); + didata->surface[0]=NULL; + + /* Disable and detach from layer */ + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + SDL_free((void*)didata->cursor.cursor.bitmap.image1); + SDL_free(didata); + SDL_SetError("GF: Can't update layer parameters\n"); return -1; } /* Enable layer in case if hardware supports layer enable/disable */ gf_layer_enable(didata->layer); - /* Mark main display layer is attached */ - didata->layer_attached=SDL_TRUE; - /* Copy device name for each display */ SDL_strlcpy(didata->description, gfdata->gfdev_info.description, SDL_VIDEO_GF_DEVICENAME_MAX-1); @@ -395,9 +487,9 @@ int qnxgf_videoinit(_THIS) /* Initialize display structure */ SDL_zero(display); - display.desktop_mode = current_mode; - display.current_mode = current_mode; - display.driverdata = didata; + display.desktop_mode=current_mode; + display.current_mode=current_mode; + display.driverdata=didata; didata->current_mode=current_mode; SDL_AddVideoDisplay(&display); @@ -411,11 +503,26 @@ int qnxgf_videoinit(_THIS) didata->custom_refresh=0; } } + + /* Get all display modes for this display */ + _this->current_display=it; + qnxgf_getdisplaymodes(_this); } + /* Restore default display */ + _this->current_display=0; + /* Add GF renderer to SDL */ gf_addrenderdriver(_this); + /* Add GF input devices */ + status=gf_addinputdevices(_this); + if (status!=0) + { + /* SDL error is set by gf_addinputdevices() function */ + return -1; + } + /* video has been initialized successfully */ return 1; } @@ -425,11 +532,58 @@ void qnxgf_videoquit(_THIS) SDL_DisplayData* didata; uint32_t it; - /* SDL will restore our desktop mode on exit */ + /* Delete GF input devices */ + gf_delinputdevices(_this); + + /* SDL will restore old desktop mode on exit */ for(it=0; it<_this->num_displays; it++) { didata=_this->displays[it].driverdata; + /* Free cursor image */ + if (didata->cursor.cursor.bitmap.image0!=NULL) + { + SDL_free((void*)didata->cursor.cursor.bitmap.image0); + } + if (didata->cursor.cursor.bitmap.image1!=NULL) + { + SDL_free((void*)didata->cursor.cursor.bitmap.image1); + } + + /* Free main surface */ + if (didata->surface[0]!=NULL) + { + gf_surface_free(didata->surface[0]); + didata->surface[0]=NULL; + } + + /* Free back surface */ + if (didata->surface[1]!=NULL) + { + gf_surface_free(didata->surface[1]); + didata->surface[1]=NULL; + } + + /* Free second back surface */ + if (didata->surface[2]!=NULL) + { + gf_surface_free(didata->surface[2]); + didata->surface[2]=NULL; + } + + /* Detach layer before quit */ + if (didata->layer_attached==SDL_TRUE) + { + /* Disable layer if hardware supports this */ + gf_layer_disable(didata->layer); + + /* Detach from layer, free it for others */ + gf_layer_detach(didata->layer); + + /* Mark it as detached */ + didata->layer_attached=SDL_FALSE; + } + /* Detach from selected display */ gf_display_detach(didata->display); } @@ -523,7 +677,7 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) { SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata; uint32_t refresh_rate=0; - int result; + int status; /* Current display dimensions and bpp are no more valid */ didata->current_mode.format=SDL_PIXELFORMAT_UNKNOWN; @@ -617,6 +771,27 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) } } + /* Free main surface */ + if (didata->surface[0]!=NULL) + { + gf_surface_free(didata->surface[0]); + didata->surface[0]=NULL; + } + + /* Free back surface */ + if (didata->surface[1]!=NULL) + { + gf_surface_free(didata->surface[1]); + didata->surface[1]=NULL; + } + + /* Free second back surface */ + if (didata->surface[2]!=NULL) + { + gf_surface_free(didata->surface[2]); + didata->surface[2]=NULL; + } + /* Detach layer before switch to new graphics mode */ if (didata->layer_attached==SDL_TRUE) { @@ -631,9 +806,9 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) } /* Set new display video mode */ - result=gf_display_set_mode(didata->display, mode->w, mode->h, refresh_rate, + status=gf_display_set_mode(didata->display, mode->w, mode->h, refresh_rate, qnxgf_sdl_to_gf_pixelformat(mode->format), 0); - if (result!=GF_ERR_OK) + if (status!=GF_ERR_OK) { /* Display mode/resolution switch has been failed */ SDL_SetError("GF: Mode is not supported by graphics driver"); @@ -646,8 +821,8 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) } /* Attach to main display layer */ - result=gf_layer_attach(&didata->layer, didata->display, didata->display_info.main_layer_index, 0); - if (result!=GF_ERR_OK) + status=gf_layer_attach(&didata->layer, didata->display, didata->display_info.main_layer_index, 0); + if (status!=GF_ERR_OK) { SDL_SetError("GF: Couldn't attach to main layer, it could be busy"); @@ -655,12 +830,56 @@ int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode) return -1; } - /* Enable layer in case if hardware supports layer enable/disable */ - gf_layer_enable(didata->layer); - /* Mark main display layer is attached */ didata->layer_attached=SDL_TRUE; + /* Set layer source and destination viewport */ + gf_layer_set_src_viewport(didata->layer, 0, 0, mode->w-1, mode->h-1); + gf_layer_set_dst_viewport(didata->layer, 0, 0, mode->w-1, mode->h-1); + + /* Create main visible on display surface */ + status=gf_surface_create_layer(&didata->surface[0], &didata->layer, 1, 0, + mode->w, mode->h, qnxgf_sdl_to_gf_pixelformat(mode->format), + NULL, GF_SURFACE_CREATE_2D_ACCESSIBLE | GF_SURFACE_CREATE_3D_ACCESSIBLE | + GF_SURFACE_CREATE_SHAREABLE); + if (status!=GF_ERR_OK) + { + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_SetError("GF: Can't create main layer surface at modeswitch (%d)\n", status); + return -1; + } + + /* Set just created surface as main visible on the layer */ + gf_layer_set_surfaces(didata->layer, &didata->surface[0], 1); + + /* Update layer parameters */ + status=gf_layer_update(didata->layer, GF_LAYER_UPDATE_NO_WAIT_IDLE); + if (status!=GF_ERR_OK) + { + /* Free main surface */ + gf_surface_free(didata->surface[0]); + didata->surface[0]=NULL; + + /* Detach layer */ + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_SetError("GF: Can't update layer parameters\n"); + return -1; + } + + /* Restore cursor if it was visible */ + if (didata->cursor_visible==SDL_TRUE) + { + gf_cursor_set(didata->display, 0, &didata->cursor); + gf_cursor_enable(didata->display, 0); + } + + /* Enable layer in case if hardware supports layer enable/disable */ + gf_layer_enable(didata->layer); + return 0; } @@ -766,7 +985,7 @@ int qnxgf_createwindow(_THIS, SDL_Window* window) } } - /* Setup our own window decorations, which are depend on fullscreen mode */ + /* Setup our own window decorations and states, which are depend on fullscreen mode */ window->flags|=SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS | SDL_WINDOW_MAXIMIZED | SDL_WINDOW_INPUT_GRABBED | SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS; @@ -823,6 +1042,13 @@ int qnxgf_createwindow(_THIS, SDL_Window* window) #endif /* SDL_VIDEO_OPENGL_ES */ } + /* Enable mouse event collecting */ + hiddi_enable_mouse(); + + /* By default last created window got a input focus */ + SDL_SetKeyboardFocus(0, window->id); + SDL_SetMouseFocus(0, window->id); + /* Window has been successfully created */ return 0; } @@ -896,9 +1122,9 @@ void qnxgf_destroywindow(_THIS, SDL_Window* window) if (wdata->target_created==SDL_TRUE) { gf_3d_target_free(wdata->target); + wdata->target_created==SDL_FALSE; } - gfdata->egl_refcount--; if (gfdata->egl_refcount==0) { @@ -1001,8 +1227,22 @@ void* qnxgf_gl_getprocaddres(_THIS, const char* proc) } } + /* Add emulated OpenGL ES 1.1 functions */ + if (SDL_strcmp(proc, "glTexParameteri")==0) + { + return glTexParameteri; + } + if (SDL_strcmp(proc, "glTexParameteriv")==0) + { + return glTexParameteriv; + } + if (SDL_strcmp(proc, "glColor4ub")==0) + { + return glColor4ub; + } + /* Failed to get GL ES function address pointer */ - SDL_SetError("GF: Cannot locate given function name"); + SDL_SetError("GF: Cannot locate OpenGL ES function name"); return NULL; #else SDL_SetError("GF: OpenGL ES support is not compiled in"); @@ -1036,6 +1276,125 @@ SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) EGLint configs; uint32_t surfaces; uint32_t attr_pos; + EGLint attr_value; + EGLint cit; + + /* Choose buffeingr scheme */ + if (!_this->gl_config.double_buffer) + { + surfaces=1; + } + else + { + surfaces=2; + } + + /* Free main surface */ + if (didata->surface[0]!=NULL) + { + gf_surface_free(didata->surface[0]); + didata->surface[0]=NULL; + } + + /* Free back surface */ + if (didata->surface[1]!=NULL) + { + gf_surface_free(didata->surface[1]); + didata->surface[1]=NULL; + } + + /* Free second back surface */ + if (didata->surface[2]!=NULL) + { + gf_surface_free(didata->surface[2]); + didata->surface[2]=NULL; + } + + /* Detach layer before switch to new graphics mode */ + if (didata->layer_attached==SDL_TRUE) + { + /* Disable layer if hardware supports this */ + gf_layer_disable(didata->layer); + + /* Detach from layer, free it for others */ + gf_layer_detach(didata->layer); + + /* Mark it as detached */ + didata->layer_attached=SDL_FALSE; + } + + /* Attach to main display layer */ + gfstatus=gf_layer_attach(&didata->layer, didata->display, didata->display_info.main_layer_index, 0); + if (gfstatus!=GF_ERR_OK) + { + SDL_SetError("GF: Couldn't attach to main layer, it could be busy"); + + /* Failed to attach to main displayable layer */ + return NULL; + } + + /* Mark main display layer is attached */ + didata->layer_attached=SDL_TRUE; + + /* Set layer source and destination viewport */ + gf_layer_set_src_viewport(didata->layer, 0, 0, didata->current_mode.w-1, didata->current_mode.h-1); + gf_layer_set_dst_viewport(didata->layer, 0, 0, didata->current_mode.w-1, didata->current_mode.h-1); + + /* Create main visible on display surface */ + gfstatus=gf_surface_create_layer(&didata->surface[0], &didata->layer, 1, 0, + didata->current_mode.w, didata->current_mode.h, qnxgf_sdl_to_gf_pixelformat(didata->current_mode.format), + NULL, GF_SURFACE_CREATE_2D_ACCESSIBLE | GF_SURFACE_CREATE_3D_ACCESSIBLE | + GF_SURFACE_CREATE_SHAREABLE); + if (gfstatus!=GF_ERR_OK) + { + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_SetError("GF: Can't create main layer surface at glctx (%d)\n", gfstatus); + return NULL; + } + + /* Set just created surface as main visible on the layer */ +// gf_layer_set_surfaces(didata->layer, &didata->surface[0], 1); + + if (surfaces>1) + { + /* Create back display surface */ + gfstatus=gf_surface_create_layer(&didata->surface[1], &didata->layer, 1, 0, + didata->current_mode.w, didata->current_mode.h, qnxgf_sdl_to_gf_pixelformat(didata->current_mode.format), + NULL, GF_SURFACE_CREATE_2D_ACCESSIBLE | GF_SURFACE_CREATE_3D_ACCESSIBLE | + GF_SURFACE_CREATE_SHAREABLE); + if (gfstatus!=GF_ERR_OK) + { + gf_surface_free(didata->surface[0]); + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_SetError("GF: Can't create main layer surface at glctx (%d)\n", gfstatus); + return NULL; + } + } + + /* Update layer parameters */ + gfstatus=gf_layer_update(didata->layer, GF_LAYER_UPDATE_NO_WAIT_IDLE); + if (gfstatus!=GF_ERR_OK) + { + /* Free main and back surfaces */ + gf_surface_free(didata->surface[1]); + didata->surface[1]=NULL; + gf_surface_free(didata->surface[0]); + didata->surface[0]=NULL; + + /* Detach layer */ + gf_layer_disable(didata->layer); + gf_layer_detach(didata->layer); + didata->layer_attached=SDL_FALSE; + SDL_SetError("GF: Can't update layer parameters\n"); + return NULL; + } + + /* Enable layer in case if hardware supports layer enable/disable */ + gf_layer_enable(didata->layer); /* Prepare attributes list to pass them to OpenGL ES */ attr_pos=0; @@ -1069,19 +1428,6 @@ SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) wdata->gles_attributes[attr_pos++]=_this->gl_config.buffer_size; } - /* OpenGL ES 1.0 uses double buffer by default, so if application */ - /* do not requested double buffering, switch to single buffer */ - if (!_this->gl_config.double_buffer) - { - wdata->gles_attributes[attr_pos++]=EGL_SINGLE_BUFFER; - wdata->gles_attributes[attr_pos++]=EGL_TRUE; - surfaces=1; - } - else - { - surfaces=2; - } - /* Set number of samples in multisampling */ if (_this->gl_config.multisamplesamples) { @@ -1100,15 +1446,161 @@ SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) wdata->gles_attributes[attr_pos]=EGL_NONE; /* Request first suitable framebuffer configuration */ - status=eglChooseConfig(gfdata->egldisplay, wdata->gles_attributes, &wdata->gles_config, 1, &configs); + status=eglChooseConfig(gfdata->egldisplay, wdata->gles_attributes, + wdata->gles_configs, SDL_VIDEO_GF_OPENGLES_CONFS, &configs); if (status!=EGL_TRUE) { SDL_SetError("GF: Can't find closest configuration for OpenGL ES"); return NULL; } + /* Check if nothing has been found, try "don't care" settings */ + if (configs==0) + { + int32_t it; + int32_t jt; + GLint depthbits[4]={32, 24, 16, EGL_DONT_CARE}; + + for (it=0; it<4; it++) + { + for (jt=16; jt>=0; jt--) + { + /* Don't care about color buffer bits, use what exist */ + /* Replace previous data set with EGL_DONT_CARE */ + attr_pos=0; + wdata->gles_attributes[attr_pos++]=EGL_NATIVE_VISUAL_ID; + wdata->gles_attributes[attr_pos++]=qnxgf_sdl_to_gf_pixelformat(didata->current_mode.format); + wdata->gles_attributes[attr_pos++]=EGL_RED_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + wdata->gles_attributes[attr_pos++]=EGL_GREEN_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + wdata->gles_attributes[attr_pos++]=EGL_BLUE_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + wdata->gles_attributes[attr_pos++]=EGL_ALPHA_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + wdata->gles_attributes[attr_pos++]=EGL_BUFFER_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + + /* Try to find requested or smallest depth */ + if (_this->gl_config.depth_size) + { + wdata->gles_attributes[attr_pos++]=EGL_DEPTH_SIZE; + wdata->gles_attributes[attr_pos++]=depthbits[it]; + } + else + { + wdata->gles_attributes[attr_pos++]=EGL_DEPTH_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + } + + if (_this->gl_config.stencil_size) + { + wdata->gles_attributes[attr_pos++]=EGL_STENCIL_SIZE; + wdata->gles_attributes[attr_pos++]=jt; + } + else + { + wdata->gles_attributes[attr_pos++]=EGL_STENCIL_SIZE; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + + /* exit from stencil loop */ + jt=0; + } + + /* Don't care about antialiasing */ + wdata->gles_attributes[attr_pos++]=EGL_SAMPLES; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + wdata->gles_attributes[attr_pos++]=EGL_SAMPLE_BUFFERS; + wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE; + wdata->gles_attributes[attr_pos]=EGL_NONE; + + /* Request first suitable framebuffer configuration */ + status=eglChooseConfig(gfdata->egldisplay, wdata->gles_attributes, + wdata->gles_configs, SDL_VIDEO_GF_OPENGLES_CONFS, &configs); + if (status!=EGL_TRUE) + { + SDL_SetError("Photon: Can't find closest configuration for OpenGL ES"); + return NULL; + } + if (configs!=0) + { + break; + } + } + if (configs!=0) + { + break; + } + } + + /* No available configs */ + if (configs==0) + { + SDL_SetError("Photon: Can't find any configuration for OpenGL ES"); + return NULL; + } + } + + /* Initialize config index */ + wdata->gles_config=0; + + /* Now check each configuration to find out the best */ + for (cit=0; citgl_config.stencil_size) + { + status=eglGetConfigAttrib(gfdata->egldisplay, wdata->gles_configs[cit], EGL_STENCIL_SIZE, &attr_value); + if (status==EGL_TRUE) + { + if (attr_value!=0) + { + stencil_found=1; + } + } + } + else + { + stencil_found=1; + } + + if (_this->gl_config.depth_size) + { + status=eglGetConfigAttrib(gfdata->egldisplay, wdata->gles_configs[cit], EGL_DEPTH_SIZE, &attr_value); + if (status==EGL_TRUE) + { + if (attr_value!=0) + { + depth_found=1; + } + } + } + else + { + depth_found=1; + } + + /* Exit from loop if found appropriate configuration */ + if ((depth_found!=0) && (stencil_found!=0)) + { + break; + } + } + + /* If best could not be found, use first */ + if (cit==configs) + { + cit=0; + } + wdata->gles_config=cit; + /* Create OpenGL ES context */ - wdata->gles_context=eglCreateContext(gfdata->egldisplay, wdata->gles_config, EGL_NO_CONTEXT, NULL); + wdata->gles_context=eglCreateContext(gfdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_NO_CONTEXT, NULL); if (wdata->gles_context==EGL_NO_CONTEXT) { SDL_SetError("GF: OpenGL ES context creation has been failed"); @@ -1119,13 +1611,13 @@ SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) if (wdata->target_created==SDL_TRUE) { gf_3d_target_free(wdata->target); + wdata->target_created==SDL_FALSE; } /* Create surface(s) target for OpenGL ES */ - gfstatus=gf_3d_target_create(&wdata->target, didata->layer, NULL, + gfstatus=gf_3d_target_create(&wdata->target, didata->layer, &didata->surface[0], surfaces, didata->current_mode.w, didata->current_mode.h, qnxgf_sdl_to_gf_pixelformat(didata->current_mode.format)); - if (gfstatus!=GF_ERR_OK) { /* Destroy just created context */ @@ -1143,7 +1635,7 @@ SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) } /* Create target rendering surface on whole screen */ - wdata->gles_surface=eglCreateWindowSurface(gfdata->egldisplay, wdata->gles_config, wdata->target, NULL); + wdata->gles_surface=eglCreateWindowSurface(gfdata->egldisplay, wdata->gles_configs[wdata->gles_config], wdata->target, NULL); if (wdata->gles_surface==EGL_NO_SURFACE) { /* Destroy 3d target */ @@ -1192,7 +1684,39 @@ SDL_GLContext qnxgf_gl_createcontext(_THIS, SDL_Window* window) /* Always clear stereo enable, since OpenGL ES do not supports stereo */ _this->gl_config.stereo=0; - /* Failed to create GL ES context */ + /* Get back samples and samplebuffers configurations. Rest framebuffer */ + /* parameters could be obtained through the OpenGL ES API */ + status=eglGetConfigAttrib(gfdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_SAMPLES, &attr_value); + if (status==EGL_TRUE) + { + _this->gl_config.multisamplesamples=attr_value; + } + status=eglGetConfigAttrib(gfdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_SAMPLE_BUFFERS, &attr_value); + if (status==EGL_TRUE) + { + _this->gl_config.multisamplebuffers=attr_value; + } + + /* Get back stencil and depth buffer sizes */ + status=eglGetConfigAttrib(gfdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_DEPTH_SIZE, &attr_value); + if (status==EGL_TRUE) + { + _this->gl_config.depth_size=attr_value; + } + status=eglGetConfigAttrib(gfdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_STENCIL_SIZE, &attr_value); + if (status==EGL_TRUE) + { + _this->gl_config.stencil_size=attr_value; + } + + /* Restore cursor if it was visible */ + if (didata->cursor_visible==SDL_TRUE) + { + gf_cursor_set(didata->display, 0, &didata->cursor); + gf_cursor_enable(didata->display, 0); + } + + /* GL ES context was successfully created */ return wdata->gles_context; #else SDL_SetError("GF: OpenGL ES support is not compiled in"); @@ -1283,6 +1807,10 @@ void qnxgf_gl_swapwindow(_THIS, SDL_Window* window) SDL_VideoData* gfdata=(SDL_VideoData*)_this->driverdata; SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata; + /* Finish all drawings */ + glFinish(); + + /* Swap buffers */ eglSwapBuffers(gfdata->egldisplay, wdata->gles_surface); #else SDL_SetError("GF: OpenGL ES support is not compiled in"); diff --git a/src/video/qnxgf/SDL_qnxgf.h b/src/video/qnxgf/SDL_qnxgf.h index b080ac145..ff911bf1a 100644 --- a/src/video/qnxgf/SDL_qnxgf.h +++ b/src/video/qnxgf/SDL_qnxgf.h @@ -48,7 +48,8 @@ typedef struct SDL_VideoData #endif /* SDL_VIDEO_OPENGL_ES */ } SDL_VideoData; -#define SDL_VIDEO_GF_DEVICENAME_MAX 257 +#define SDL_VIDEO_GF_DEVICENAME_MAX 257 +#define SDL_VIDEO_GF_MAX_CURSOR_SIZE 128 typedef struct SDL_DisplayData { @@ -61,15 +62,23 @@ typedef struct SDL_DisplayData uint32_t caps; /* Device capabilities */ SDL_bool layer_attached; /* Layer attach status */ gf_layer_t layer; /* Graphics layer to which attached */ + gf_surface_t surface[3]; /* Visible surface on the display */ + SDL_bool cursor_visible; /* SDL_TRUE if cursor visible */ + gf_cursor_t cursor; /* Cursor shape which was set last */ } SDL_DisplayData; +/* Maximum amount of OpenGL ES framebuffer configurations */ +#define SDL_VIDEO_GF_OPENGLES_CONFS 32 + typedef struct SDL_WindowData { SDL_bool uses_gles; /* true if window support OpenGL ES */ #if defined(SDL_VIDEO_OPENGL_ES) gf_3d_target_t target; /* OpenGL ES window target */ SDL_bool target_created; /* GF 3D target is created if true */ - EGLConfig gles_config; /* OpenGL ES framebuffer configuration*/ + EGLConfig gles_configs[SDL_VIDEO_GF_OPENGLES_CONFS]; + /* OpenGL ES framebuffer confs */ + EGLint gles_config; /* Config index in the array of cfgs */ EGLContext gles_context; /* OpenGL ES context */ EGLint gles_attributes[256]; /* OpenGL ES attributes for context */ EGLSurface gles_surface; /* OpenGL ES target rendering surface */ @@ -103,16 +112,16 @@ typedef struct GF_DeviceCaps /****************************************************************************/ /* Display and window functions */ -int qnxgf_videoinit(_THIS); +int qnxgf_videoinit(_THIS); void qnxgf_videoquit(_THIS); void qnxgf_getdisplaymodes(_THIS); -int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode); -int qnxgf_setdisplaypalette(_THIS, SDL_Palette* palette); -int qnxgf_getdisplaypalette(_THIS, SDL_Palette* palette); -int qnxgf_setdisplaygammaramp(_THIS, Uint16* ramp); -int qnxgf_getdisplaygammaramp(_THIS, Uint16* ramp); -int qnxgf_createwindow(_THIS, SDL_Window* window); -int qnxgf_createwindowfrom(_THIS, SDL_Window* window, const void* data); +int qnxgf_setdisplaymode(_THIS, SDL_DisplayMode* mode); +int qnxgf_setdisplaypalette(_THIS, SDL_Palette* palette); +int qnxgf_getdisplaypalette(_THIS, SDL_Palette* palette); +int qnxgf_setdisplaygammaramp(_THIS, Uint16* ramp); +int qnxgf_getdisplaygammaramp(_THIS, Uint16* ramp); +int qnxgf_createwindow(_THIS, SDL_Window* window); +int qnxgf_createwindowfrom(_THIS, SDL_Window* window, const void* data); void qnxgf_setwindowtitle(_THIS, SDL_Window* window); void qnxgf_setwindowicon(_THIS, SDL_Window* window, SDL_Surface* icon); void qnxgf_setwindowposition(_THIS, SDL_Window* window);