Support for HID devices (mice and keyboards only for now) has been added
authorMike Gorchak <lestat@i.com.ua>
Tue, 28 Apr 2009 04:33:30 +0000
changeset 3109 7b3a09fb9c8b
parent 3108 aa1897bee1e9
child 3110 e6c21c14ce3a
Support for HID devices (mice and keyboards only for now) has been added
src/video/qnxgf/SDL_gf_input.c
src/video/qnxgf/SDL_gf_input.h
src/video/qnxgf/SDL_gf_opengles.c
src/video/qnxgf/SDL_gf_opengles.h
src/video/qnxgf/SDL_gf_render.c
src/video/qnxgf/SDL_hiddi_joystick.h
src/video/qnxgf/SDL_hiddi_keyboard.h
src/video/qnxgf/SDL_hiddi_mouse.h
src/video/qnxgf/SDL_qnxgf.c
src/video/qnxgf/SDL_qnxgf.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/qnxgf/SDL_gf_input.c	Tue Apr 28 04:33:30 2009 +0000
@@ -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; jt<surface->h; jt++)
+   {
+      for (it=0; it<surface->w; 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<<it))==(0x01<<it)) &&
+                        ((mouse_last_state_button[devno] & (0x01<<it))==0x00))
+                    {
+                       SDL_SendMouseButton(0, SDL_PRESSED, sdlbutton);
+                    }
+                    /* Button released */
+                    if (((packet->buttons & (0x01<<it))==0x00) &&
+                        ((mouse_last_state_button[devno] & (0x01<<it))==(0x01<<it)))
+                    {
+                       SDL_SendMouseButton(0, SDL_RELEASED, sdlbutton);
+                    }
+                 }
+                 mouse_last_state_button[devno]=packet->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<<it))==(0x01<<it)) &&
+                        ((mouse_last_state_button[devno] & (0x01<<it))==0x00))
+                    {
+                       SDL_SendMouseButton(0, SDL_PRESSED, sdlbutton);
+                    }
+                    /* Button released */
+                    if (((packet->buttons & (0x01<<it))==0x00) &&
+                        ((mouse_last_state_button[devno] & (0x01<<it))==(0x01<<it)))
+                    {
+                       SDL_SendMouseButton(0, SDL_RELEASED, sdlbutton);
+                    }
+                 }
+                 mouse_last_state_button[devno]=packet->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; it<num_col; it++)
+   {
+      hiddi_register_for_reports(hidd_collections[it], device_instance);
+   }
+
+   return EOK;
+}
+
+static void hiddi_insertion(struct hidd_connection* connection, hidd_device_instance_t* device_instance)
+{
+   uint32_t it;
+   struct hidd_collection** hidd_collections;
+   uint16_t num_col;
+
+   /* get root level collections */
+   hidd_get_collections(device_instance, NULL, &hidd_collections, &num_col);
+   for (it=0; it<num_col; it++)
+   {
+      hiddi_register_for_reports(hidd_collections[it], device_instance);
+   }
+}
+
+static void hiddi_removal(struct hidd_connection* connection, hidd_device_instance_t* instance)
+{
+   hidd_reports_detach(connection, instance);
+}
+
+static void hiddi_report(struct hidd_connection* connection, hidd_report_t* report, void* report_data, uint32_t report_len, uint32_t flags, void* user)
+{
+   if (report->dev_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<SDL_HIDDI_MAX_DEVICES; it++)
+   {
+      /* Get device instance */
+      status=hidd_get_device_instance(connection, it, &instance);
+      if (status!=EOK)
+      {
+         continue;
+      }
+
+      status=hidd_get_report_desc(connection, &instance, &report_data, &report_length);
+      if (status!=EOK)
+      {
+         continue;
+      }
+
+      status=hiddi_get_device_type(report_data, report_length);
+      sdl_input_devices[it]=status;
+
+      free(report_data);
+   }
+
+   /* Disconnect from HID server */
+   status=hidd_disconnect(connection);
+   if (status!=EOK)
+   {
+      return -1;
+   }
+
+   /* Add handlers for HID devices */
+   hidparams.funcs=&hidfuncs;
+
+   status=hidd_connect(&hidparams, &connection);
+   if (status!=EOK)
+   {
+      return -1;
+   }
+
+   return 0;
+}
+
+static int32_t hiddi_disconnect_devices()
+{
+   int32_t status;
+
+   hiddi_disable_mouse();
+
+   /* Disconnect from HID server */
+   status=hidd_disconnect(connection);
+   if (status!=EOK)
+   {
+      return -1;
+   }
+}
+
+void hiddi_enable_mouse()
+{
+   collect_reports=1;
+}
+
+void hiddi_disable_mouse()
+{
+   collect_reports=0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/qnxgf/SDL_gf_input.h	Tue Apr 28 04:33:30 2009 +0000
@@ -0,0 +1,165 @@
+/*
+    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_INPUT_H__
+#define __SDL_GF_INPUT_H__
+
+#include "SDL_config.h"
+#include "SDL_video.h"
+#include "../SDL_sysvideo.h"
+
+#include <errno.h>
+
+#include <gf/gf.h>
+
+#include <sys/hiddi.h>
+#include <sys/hidut.h>
+
+#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__ */
--- a/src/video/qnxgf/SDL_gf_opengles.c	Tue Apr 28 04:30:52 2009 +0000
+++ b/src/video/qnxgf/SDL_gf_opengles.c	Tue Apr 28 04:33:30 2009 +0000
@@ -1,8 +1,3 @@
-Date: Mon, 23 Mar 2009 09:17:24 +0200
-From: "Mike Gorchak" <mike@malva.ua>
-To: "Sam Lantinga" <slouken@devolution.com>
-Subject: New QNX patches
-
 /*
     SDL - Simple DirectMedia Layer
     Copyright (C) 1997-2009 Sam Lantinga
@@ -53,4 +48,3 @@
    glColor4f(((GLfloat)red)/255.f, ((GLfloat)green)/255.f, ((GLfloat)blue)/255.f, ((GLfloat)alpha)/255.f);
    return;
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/qnxgf/SDL_gf_opengles.h	Tue Apr 28 04:33:30 2009 +0000
@@ -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 <GLES/gl.h>
+#include <GLES/glext.h>
+
+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__ */
--- a/src/video/qnxgf/SDL_gf_render.c	Tue Apr 28 04:30:52 2009 +0000
+++ b/src/video/qnxgf/SDL_gf_render.c	Tue Apr 28 04:33:30 2009 +0000
@@ -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 @@
    for (it=0; it<rdata->surfaces_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 @@
          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 @@
    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 @@
 
    for (it=0; it<rdata->surfaces_count; it++)
    {
-      gf_surface_free(rdata->surface[it]);
+      if (rdata->surface[it]!=NULL)
+      {
+         gf_surface_free(rdata->surface[it]);
+      }
    }
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/qnxgf/SDL_hiddi_joystick.h	Tue Apr 28 04:33:30 2009 +0000
@@ -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 <inttypes.h>
+
+
+
+#endif /* __SDL_HIDDI_JOYSTICK_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/qnxgf/SDL_hiddi_keyboard.h	Tue Apr 28 04:33:30 2009 +0000
@@ -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 <inttypes.h>
+
+/* 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__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/qnxgf/SDL_hiddi_mouse.h	Tue Apr 28 04:33:30 2009 +0000
@@ -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 <inttypes.h>
+
+/* 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__ */
--- a/src/video/qnxgf/SDL_qnxgf.c	Tue Apr 28 04:30:52 2009 +0000
+++ b/src/video/qnxgf/SDL_qnxgf.c	Tue Apr 28 04:33:30 2009 +0000
@@ -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 @@
       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 @@
    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; it<gfdata->gfdev_info.ndisplays; it++)
@@ -319,7 +332,6 @@
       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 @@
          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 @@
       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 @@
       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 @@
       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;
+      }
+
+      /* 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);
 
-         /* Failed to attach to main layer */
+      /* 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 @@
 
       /* 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 @@
             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 @@
    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 @@
 {
    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 @@
       }
    }
 
+   /* 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 @@
    }
 
    /* 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 @@
    }
 
    /* 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 @@
       return -1;
    }
 
+   /* 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);
 
-   /* Mark main display layer is attached */
-   didata->layer_attached=SDL_TRUE;
-
    return 0;
 }
 
@@ -766,7 +985,7 @@
       }
    }
 
-   /* 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 @@
       #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 @@
          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 @@
          }
       }
 
+      /* 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 @@
       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 @@
          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 @@
       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; cit<configs; cit++)
+      {
+         uint32_t stencil_found;
+         uint32_t depth_found;
+
+         stencil_found=0;
+         depth_found=0;
+
+         if (_this->gl_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 @@
       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 @@
       }
 
       /* 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 @@
       /* 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 @@
       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");
--- a/src/video/qnxgf/SDL_qnxgf.h	Tue Apr 28 04:30:52 2009 +0000
+++ b/src/video/qnxgf/SDL_qnxgf.h	Tue Apr 28 04:33:30 2009 +0000
@@ -48,7 +48,8 @@
    #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 @@
    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 @@
 /****************************************************************************/
 
 /* 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);