Continue working on QNX Photon with OpenGL ES support
authorMike Gorchak <lestat@i.com.ua>
Tue, 28 Apr 2009 04:30:52 +0000
changeset 3108 aa1897bee1e9
parent 3107 3cf236d3cd81
child 3109 7b3a09fb9c8b
Continue working on QNX Photon with OpenGL ES support
src/video/photon/SDL_photon.c
src/video/photon/SDL_photon.h
src/video/photon/SDL_photon_input.c
src/video/photon/SDL_photon_input.h
src/video/photon/SDL_photon_keycodes.h
src/video/photon/SDL_photon_pixelfmt.c
src/video/photon/SDL_photon_pixelfmt.h
src/video/photon/SDL_photon_render.c
--- a/src/video/photon/SDL_photon.c	Fri Apr 24 03:46:54 2009 +0000
+++ b/src/video/photon/SDL_photon.c	Tue Apr 28 04:30:52 2009 +0000
@@ -24,15 +24,104 @@
     (mike@malva.ua, lestat@i.com.ua)
 */
 
+/* SDL internals */
 #include "SDL_config.h"
-
 #include "../SDL_sysvideo.h"
 #include "SDL_version.h"
 #include "SDL_syswm.h"
+#include "SDL_loadso.h"
+#include "SDL_events.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_keyboard_c.h"
 
-#include "../SDL_sysvideo.h"
+/* Photon declarations */
+#include "SDL_photon.h"
+
+/* Pixel format conversion routines */
+#include "SDL_photon_pixelfmt.h"
+
+/* Use GF's pixel format functions for OpenGL ES context creation */
+#if defined(SDL_VIDEO_OPENGL_ES)
+   #include "../qnxgf/SDL_gf_pixelfmt.h"
+
+   /* If GF driver is not compiled in, include some of usefull functions */
+   #if !defined(SDL_VIDEO_DRIVER_QNXGF)
+      #include "../qnxgf/SDL_gf_pixelfmt.c"
+   #endif /* SDL_VIDEO_DRIVER_QNXGF */
+#endif /* SDL_VIDEO_OPENGL_ES */
+
+/* Use GF's OpenGL ES 1.1 functions emulation */
+#if defined(SDL_VIDEO_OPENGL_ES)
+   #include "../qnxgf/SDL_gf_opengles.h"
+
+   /* If GF driver is not compiled in, include some of usefull functions */
+   #if !defined(SDL_VIDEO_DRIVER_QNXGF)
+      #include "../qnxgf/SDL_gf_opengles.c"
+   #endif /* SDL_VIDEO_DRIVER_QNXGF */
+#endif /* SDL_VIDEO_OPENGL_ES */
 
-#include "SDL_photon.h"
+/* Low level device graphics driver names, which they are reporting */
+Photon_DeviceCaps photon_devicename[]=
+{
+   /* ATI Rage 128 graphics driver (devg-ati_rage128)      */
+   {"ati_rage128", SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Fujitsu Carmine graphics driver (devg-carmine.so)    */
+   {"carmine",     SDL_PHOTON_ACCELERATED | SDL_PHOTON_ACCELERATED_3D},
+   /* C&T graphics driver (devg-chips.so)                  */
+   {"chips",       SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Fujitsu Coral graphics driver (devg-coral.so)        */
+   {"coral",       SDL_PHOTON_ACCELERATED | SDL_PHOTON_ACCELERATED_3D},
+   /* Intel integrated graphics driver (devg-extreme2.so)  */
+   {"extreme2",    SDL_PHOTON_ACCELERATED | SDL_PHOTON_ACCELERATED_3D},
+   /* Unaccelerated FB driver (devg-flat.so)               */
+   {"flat",        SDL_PHOTON_UNACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* NS Geode graphics driver (devg-geode.so)             */
+   {"geode",       SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Geode LX graphics driver (devg-geodelx.so)           */
+   {"geodelx",     SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Intel integrated graphics driver (devg-gma9xx.so)    */
+   {"gma",         SDL_PHOTON_ACCELERATED | SDL_PHOTON_ACCELERATED_3D},
+   /* Intel integrated graphics driver (devg-i810.so)      */
+   {"i810",        SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Intel integrated graphics driver (devg-i830.so)      */
+   {"i830",        SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Geode LX graphics driver (devg-lx800.so)             */
+   {"lx800",       SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Matrox Gxx graphics driver (devg-matroxg.so)         */
+   {"matroxg",     SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Intel Poulsbo graphics driver (devg-poulsbo.so)      */
+   {"poulsbo",     SDL_PHOTON_ACCELERATED | SDL_PHOTON_ACCELERATED_3D},
+   /* ATI Radeon driver (devg-radeon.so)                   */
+   {"radeon",      SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* ATI Rage driver (devg-rage.so)                       */
+   {"rage",        SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* S3 Savage graphics driver (devg-s3_savage.so)        */
+   {"s3_savage",   SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* SiS630 integrated graphics driver (devg-sis630.so)   */
+   {"sis630",      SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* PowerVR SGX 535 graphics driver (devg-poulsbo.so)    */
+   {"sgx",         SDL_PHOTON_ACCELERATED | SDL_PHOTON_ACCELERATED_3D},
+   /* SM Voyager GX graphics driver (devg-smi5xx.so)       */
+   {"smi5xx",      SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* Silicon Motion graphics driver (devg-smi7xx.so)      */
+   {"smi7xx",      SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* SVGA unaccelerated gfx driver (devg-svga.so)         */
+   {"svga",        SDL_PHOTON_UNACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* nVidia TNT graphics driver (devg-tnt.so)             */
+   {"tnt",         SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* VIA integrated graphics driver (devg-tvia.so)        */
+   {"tvia",        SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* VIA UniChrome graphics driver (devg-unichrome.so)    */
+   {"unichrome",   SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* VESA unaccelerated gfx driver (devg-vesa.so)         */
+   {"vesa",        SDL_PHOTON_UNACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* VmWare graphics driver (devg-volari.so)              */
+   {"vmware",      SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* XGI XP10 graphics driver (devg-volari.so), OpenGL 1.5*/
+   {"volari",      SDL_PHOTON_ACCELERATED | SDL_PHOTON_UNACCELERATED_3D},
+   /* End of list */
+   {NULL,          0x00000000}
+};
 
 static SDL_bool photon_initialized=SDL_FALSE;
 
@@ -62,13 +151,26 @@
 
 static void photon_destroy(SDL_VideoDevice* device)
 {
+   SDL_VideoData* phdata=(SDL_VideoData*) device->driverdata;
+
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      if (phdata->gfinitialized!=SDL_FALSE)
+      {
+         gf_dev_detach(phdata->gfdev);
+      }
+   #endif /* SDL_VIDEO_OPENGL_ES */
+
+   if (device->driverdata!=NULL)
+   {
+      device->driverdata=NULL;
+   }
 }
 
 static SDL_VideoDevice* photon_create(int devindex)
 {
-   SDL_VideoDevice* device;
-   SDL_VideoData*   phdata;
-   int              status;
+   SDL_VideoDevice*  device;
+   SDL_VideoData*    phdata;
+   int               status;
 
    /* Check if photon could be initialized */
    status=photon_available();
@@ -78,6 +180,13 @@
       return NULL;
    }
 
+   /* Photon agregates all video devices to one with multiple heads */
+   if (devindex!=0)
+   {
+      /* devindex could be zero only in Photon SDL driver */
+      return NULL;
+   }
+
    /* Initialize SDL_VideoDevice structure */
    device=(SDL_VideoDevice*)SDL_calloc(1, sizeof(SDL_VideoDevice));
    if (device==NULL)
@@ -96,9 +205,85 @@
    }
    device->driverdata=phdata;
 
+   /* Get all photon display devices */
+   phdata->avail_rids=PdGetDevices(&phdata->rid[0], SDL_VIDEO_PHOTON_MAX_RIDS);
+   if (phdata->avail_rids>SDL_VIDEO_PHOTON_MAX_RIDS)
+   {
+      phdata->avail_rids=SDL_VIDEO_PHOTON_MAX_RIDS;
+   }
+
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      /* TODO: add real device detection versus multiple heads */
+      status=gf_dev_attach(&phdata->gfdev, GF_DEVICE_INDEX(0), &phdata->gfdev_info);
+      if (status!=GF_ERR_OK)
+      {
+         /* Do not fail right now, if GF can't be attached */
+         phdata->gfinitialized=SDL_FALSE;
+      }
+      else
+      {
+         phdata->gfinitialized=SDL_TRUE;
+      }
+   #endif /* SDL_VIDEO_OPENGL_ES */
+
+   /* Set default target device */
+   status=PdSetTargetDevice(NULL, phdata->rid[0]);
+   if (status==-1)
+   {
+      SDL_SetError("Photon: Can't set default target device");
+      #if defined(SDL_VIDEO_OPENGL_ES)
+         gf_dev_detach(phdata->gfdev);
+      #endif /* SDL_VIDEO_OPENGL_ES */
+      SDL_free(phdata);
+      SDL_free(device);
+      return NULL;
+   }
+   phdata->current_device_id=0;
+
    /* Setup amount of available displays and current display */
    device->num_displays=0;
    device->current_display=0;
+
+   /* Set device free function */
+   device->free=photon_destroy;
+
+   /* Setup all functions which we can handle */
+   device->VideoInit=photon_videoinit;
+   device->VideoQuit=photon_videoquit;
+   device->GetDisplayModes=photon_getdisplaymodes;
+   device->SetDisplayMode=photon_setdisplaymode;
+   device->SetDisplayPalette=photon_setdisplaypalette;
+   device->GetDisplayPalette=photon_getdisplaypalette;
+   device->SetDisplayGammaRamp=photon_setdisplaygammaramp;
+   device->GetDisplayGammaRamp=photon_getdisplaygammaramp;
+   device->CreateWindow=photon_createwindow;
+   device->CreateWindowFrom=photon_createwindowfrom;
+   device->SetWindowTitle=photon_setwindowtitle;
+   device->SetWindowIcon=photon_setwindowicon;
+   device->SetWindowPosition=photon_setwindowposition;
+   device->SetWindowSize=photon_setwindowsize;
+   device->ShowWindow=photon_showwindow;
+   device->HideWindow=photon_hidewindow;
+   device->RaiseWindow=photon_raisewindow;
+   device->MaximizeWindow=photon_maximizewindow;
+   device->MinimizeWindow=photon_minimizewindow;
+   device->RestoreWindow=photon_restorewindow;
+   device->SetWindowGrab=photon_setwindowgrab;
+   device->DestroyWindow=photon_destroywindow;
+   device->GetWindowWMInfo=photon_getwindowwminfo;
+   device->GL_LoadLibrary=photon_gl_loadlibrary;
+   device->GL_GetProcAddress=photon_gl_getprocaddres;
+   device->GL_UnloadLibrary=photon_gl_unloadlibrary;
+   device->GL_CreateContext=photon_gl_createcontext;
+   device->GL_MakeCurrent=photon_gl_makecurrent;
+   device->GL_SetSwapInterval=photon_gl_setswapinterval;
+   device->GL_GetSwapInterval=photon_gl_getswapinterval;
+   device->GL_SwapWindow=photon_gl_swapwindow;
+   device->GL_DeleteContext=photon_gl_deletecontext;
+   device->PumpEvents=photon_pumpevents;
+   device->SuspendScreenSaver=photon_suspendscreensaver;
+
+   return device;
 }
 
 VideoBootStrap photon_bootstrap=
@@ -114,18 +299,147 @@
 /*****************************************************************************/
 int photon_videoinit(_THIS)
 {
-   SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+   SDL_VideoData*    phdata=(SDL_VideoData*)_this->driverdata;
+   PgHWCaps_t        hwcaps;
+   PgVideoModeInfo_t modeinfo;
+   int32_t           status;
+   SDL_VideoDisplay  display;
+   SDL_DisplayMode   current_mode;
+   SDL_DisplayData*  didata;
+   uint32_t          it;
+   uint32_t          jt;
+   char*             override;
+
+   /* By default Photon do not uses swap on VSYNC */
+   phdata->swapinterval=0;
+
+   for (it=0; it<phdata->avail_rids; it++)
+   {
+      didata=(SDL_DisplayData*)SDL_calloc(1, sizeof(SDL_DisplayData));
+      if (didata==NULL)
+      {
+         /* memory allocation error */
+         SDL_OutOfMemory();
+         return -1;
+      }
+
+      /* Allocate two cursors with SDL_VIDEO_PHOTON_MAX_CURSOR_SIZE size */
+      /* and 128 bytes of spare place                                    */
+      didata->cursor_size=((SDL_VIDEO_PHOTON_MAX_CURSOR_SIZE*4)>>3)+128;
+      didata->cursor=(PhCursorDef_t*)SDL_calloc(1, didata->cursor_size);
+      if (didata->cursor==NULL)
+      {
+         /* memory allocation error */
+         SDL_OutOfMemory();
+         SDL_free(didata);
+         return -1;
+      }
+
+      /* Initialize GF in case of OpenGL ES support is compiled in */
+      #if defined(SDL_VIDEO_OPENGL_ES)
+         /* TODO: add real device detection versus multiple heads */
+         if (phdata->gfinitialized==SDL_TRUE)
+         {
+            status=gf_display_attach(&didata->display, phdata->gfdev, it, &didata->display_info);
+            if (status!=GF_ERR_OK)
+            {
+               /* Just shutdown GF, do not fail */
+               gf_dev_detach(phdata->gfdev);
+               phdata->gfinitialized=SDL_FALSE;
+            }
+         }
+      #endif /* SDL_VIDEO_OPENGL_ES */
+
+      /* Check if current device is not the same as target */
+      if (phdata->current_device_id!=it)
+      {
+         /* Set target device as default for Pd and Pg functions */
+         status=PdSetTargetDevice(NULL, phdata->rid[it]);
+         if (status!=0)
+         {
+            SDL_SetError("Photon: Can't set default target device\n");
+            SDL_free(didata->cursor);
+            SDL_free(didata);
+            return -1;
+         }
+         phdata->current_device_id=it;
+      }
+
+      /* Store device id */
+      didata->device_id=it;
 
-   /* Check for environment variables which could override some SDL settings */
-//   didata->custom_refresh=0;
-//   override = SDL_getenv("SDL_VIDEO_PHOTON_REFRESH_RATE");
-//   if (override!=NULL)
-//   {
-//      if (SDL_sscanf(override, "%u", &didata->custom_refresh)!=1)
-//      {
-//         didata->custom_refresh=0;
-//      }
-//   }
+      /* Query photon about graphics hardware caps and current video mode */
+      status=PgGetGraphicsHWCaps(&hwcaps);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't get graphics capabilities");
+         SDL_free(didata->cursor);
+         SDL_free(didata);
+         return -1;
+      }
+
+      /* Get current video mode details */
+      status=PgGetVideoModeInfo(hwcaps.current_video_mode, &modeinfo);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't get current video mode information");
+         SDL_free(didata->cursor);
+         SDL_free(didata);
+         return -1;
+      }
+
+      /* Setup current desktop mode for SDL */
+      SDL_zero(current_mode);
+      current_mode.w=modeinfo.width;
+      current_mode.h=modeinfo.height;
+      current_mode.refresh_rate=hwcaps.current_rrate;
+      current_mode.format=photon_image_to_sdl_pixelformat(modeinfo.type);
+      current_mode.driverdata=NULL;
+
+      /* Copy device name */
+      SDL_strlcpy(didata->description, hwcaps.chip_name, SDL_VIDEO_PHOTON_DEVICENAME_MAX-1);
+
+      /* Search device capabilities and possible workarounds */
+      jt=0;
+      do {
+         if (photon_devicename[jt].name==NULL)
+         {
+            break;
+         }
+         if (SDL_strncmp(photon_devicename[jt].name, didata->description, SDL_strlen(photon_devicename[jt].name))==0)
+         {
+            didata->caps=photon_devicename[jt].caps;
+         }
+         jt++;
+      } while(1);
+
+      /* Initialize display structure */
+      SDL_zero(display);
+      display.desktop_mode=current_mode;
+      display.current_mode=current_mode;
+      display.driverdata=didata;
+      didata->current_mode=current_mode;
+      SDL_AddVideoDisplay(&display);
+
+      /* Check for environment variables which could override some SDL settings */
+      didata->custom_refresh=0;
+      override=SDL_getenv("SDL_VIDEO_PHOTON_REFRESH_RATE");
+      if (override!=NULL)
+      {
+         if (SDL_sscanf(override, "%u", &didata->custom_refresh)!=1)
+         {
+            didata->custom_refresh=0;
+         }
+      }
+   }
+
+   /* Add photon input devices */
+   status=photon_addinputdevices(_this);
+   if (status!=0)
+   {
+      /* SDL error is set by photon_addinputdevices() function */
+      return -1;
+   }
 
    /* Add photon renderer to SDL */
    photon_addrenderdriver(_this);
@@ -136,6 +450,7 @@
 
 void photon_videoquit(_THIS)
 {
+   SDL_VideoData*   phdata=(SDL_VideoData*)_this->driverdata;
    SDL_DisplayData* didata;
    uint32_t it;
 
@@ -143,19 +458,270 @@
    for(it=0; it<_this->num_displays; it++)
    {
       didata=_this->displays[it].driverdata;
+
+      if (didata->cursor!=NULL)
+      {
+         SDL_free(didata->cursor);
+      }
+
+      #if defined(SDL_VIDEO_OPENGL_ES)
+         if (phdata->gfinitialized==SDL_TRUE)
+         {
+            /* Detach GF display */
+            gf_display_detach(didata->display);
+         }
+      #endif /* SDL_VIDEO_OPENGL_ES */
    }
 }
 
 void photon_getdisplaymodes(_THIS)
 {
-   SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
-   SDL_DisplayMode  mode;
+   SDL_VideoData*    phdata=(SDL_VideoData*)_this->driverdata;
+   SDL_DisplayData*  didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
+   SDL_DisplayMode   mode;
+   PgVideoModes_t    modes;
+   PgVideoModeInfo_t modeinfo;
+   int32_t           status;
+   uint32_t          it;
+   uint32_t          jt;
+
+   /* Check if current device is not the same as target */
+   if (phdata->current_device_id!=didata->device_id)
+   {
+      /* Set target device as default for Pd and Pg functions */
+      status=PdSetTargetDevice(NULL, phdata->rid[didata->device_id]);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't set default target device\n");
+         return;
+      }
+      phdata->current_device_id=didata->device_id;
+   }
 
+   /* Get array of available video modes */
+   status=PgGetVideoModeList(&modes);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't get video mode list");
+      return;
+   }
+
+   for (it=0; it<modes.num_modes; it++)
+   {
+      status=PgGetVideoModeInfo(modes.modes[it], &modeinfo);
+      if (status!=0)
+      {
+         /* Maybe something wrong with this particular mode, skip it */
+         continue;
+      }
+
+      jt=0;
+      do {
+         if (modeinfo.refresh_rates[jt]!=0)
+         {
+            mode.w=modeinfo.width;
+            mode.h=modeinfo.height;
+            mode.refresh_rate=modeinfo.refresh_rates[jt];
+            mode.format=photon_image_to_sdl_pixelformat(modeinfo.type);
+            mode.driverdata=NULL;
+            SDL_AddDisplayMode(_this->current_display, &mode);
+            jt++;
+         }
+         else
+         {
+            break;
+         }
+      } while(1);
+   }
 }
 
 int photon_setdisplaymode(_THIS, SDL_DisplayMode* mode)
 {
-   SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
+   SDL_VideoData*      phdata=(SDL_VideoData*)_this->driverdata;
+   SDL_DisplayData*    didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
+   PgVideoModes_t      modes;
+   PgVideoModeInfo_t   modeinfo;
+   PgDisplaySettings_t modesettings;
+   uint32_t refresh_rate=0;
+   int32_t  status;
+   uint32_t it;
+
+   /* Check if current device is not the same as target */
+   if (phdata->current_device_id!=didata->device_id)
+   {
+      /* Set target device as default for Pd and Pg functions */
+      status=PdSetTargetDevice(NULL, phdata->rid[didata->device_id]);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't set default target device\n");
+         return;
+      }
+      phdata->current_device_id=didata->device_id;
+   }
+
+   /* Get array of available video modes */
+   status=PgGetVideoModeList(&modes);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't get video mode list");
+      return;
+   }
+
+   /* Current display dimensions and bpp are no more valid */
+   didata->current_mode.format=SDL_PIXELFORMAT_UNKNOWN;
+   didata->current_mode.w=0;
+   didata->current_mode.h=0;
+
+   /* Check if custom refresh rate requested */
+   if (didata->custom_refresh!=0)
+   {
+      refresh_rate=didata->custom_refresh;
+   }
+   else
+   {
+      refresh_rate=mode->refresh_rate;
+   }
+
+   /* Check if SDL GF driver needs to find appropriate refresh rate itself */
+   if (refresh_rate==0)
+   {
+      SDL_DisplayMode tempmode;
+
+      /* Clear display mode structure */
+      SDL_memset(&tempmode, 0x00, sizeof(SDL_DisplayMode));
+      tempmode.refresh_rate=0x0000FFFF;
+
+      /* Check if window width and height matches one of our modes */
+      for (it=0; it<SDL_CurrentDisplay.num_display_modes; it++)
+      {
+         if ((SDL_CurrentDisplay.display_modes[it].w==mode->w) &&
+             (SDL_CurrentDisplay.display_modes[it].h==mode->h) &&
+             (SDL_CurrentDisplay.display_modes[it].format==mode->format))
+         {
+            /* Find the lowest refresh rate available */
+            if (tempmode.refresh_rate>SDL_CurrentDisplay.display_modes[it].refresh_rate)
+            {
+               tempmode=SDL_CurrentDisplay.display_modes[it];
+            }
+         }
+      }
+      if (tempmode.refresh_rate!=0x0000FFFF)
+      {
+         refresh_rate=tempmode.refresh_rate;
+      }
+      else
+      {
+         /* Let video driver decide what to do with this */
+         refresh_rate=0;
+      }
+   }
+
+   /* Check if SDL GF driver needs to check custom refresh rate */
+   if (didata->custom_refresh!=0)
+   {
+      SDL_DisplayMode tempmode;
+
+      /* Clear display mode structure */
+      SDL_memset(&tempmode, 0x00, sizeof(SDL_DisplayMode));
+      tempmode.refresh_rate=0x0000FFFF;
+
+      /* Check if window width and height matches one of our modes */
+      for (it=0; it<SDL_CurrentDisplay.num_display_modes; it++)
+      {
+         if ((SDL_CurrentDisplay.display_modes[it].w==mode->w) &&
+             (SDL_CurrentDisplay.display_modes[it].h==mode->h) &&
+             (SDL_CurrentDisplay.display_modes[it].format==mode->format))
+         {
+            /* Find the lowest refresh rate available */
+            if (tempmode.refresh_rate>SDL_CurrentDisplay.display_modes[it].refresh_rate)
+            {
+               tempmode=SDL_CurrentDisplay.display_modes[it];
+            }
+
+            /* Check if requested refresh rate found */
+            if (refresh_rate==SDL_CurrentDisplay.display_modes[it].refresh_rate)
+            {
+               tempmode=SDL_CurrentDisplay.display_modes[it];
+               break;
+            }
+         }
+      }
+      if (tempmode.refresh_rate!=0x0000FFFF)
+      {
+         refresh_rate=tempmode.refresh_rate;
+      }
+      else
+      {
+         /* Let video driver decide what to do with this */
+         refresh_rate=0;
+      }
+   }
+
+   /* Find photon's video mode number */
+   for (it=0; it<modes.num_modes; it++)
+   {
+      uint32_t jt;
+      uint32_t foundrefresh;
+
+      /* Get current video mode details */
+      status=PgGetVideoModeInfo(modes.modes[it], &modeinfo);
+      if (status!=0)
+      {
+         /* Maybe something wrong with this particular mode, skip it */
+         continue;
+      }
+      if ((modeinfo.width==mode->w) && (modeinfo.height==mode->h) &&
+          (modeinfo.type==photon_sdl_to_image_pixelformat(mode->format)))
+      {
+         /* Mode is found, find requested refresh rate, this case is for */
+         /* video drivers, which provide non-generic video modes.        */
+         jt=0;
+         foundrefresh=0;
+         do {
+            if (modeinfo.refresh_rates[jt]!=0)
+            {
+               if (modeinfo.refresh_rates[jt]==refresh_rate)
+               {
+                  foundrefresh=1;
+                  break;
+               }
+               jt++;
+            }
+            else
+            {
+               break;
+            }
+         } while(1);
+         if (foundrefresh!=0)
+         {
+            break;
+         }
+      }
+   }
+
+   /* Check if video mode has not been found */
+   if (it==modes.num_modes)
+   {
+      SDL_SetError("Photon: Can't find appropriate video mode");
+      return -1;
+   }
+
+   /* Fill mode settings */
+   modesettings.flags=0x00000000;
+   modesettings.mode=modes.modes[it];
+   modesettings.refresh=refresh_rate;
+
+   /* Finally set new video mode */
+   status=PgSetVideoMode(&modesettings);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't set new video mode");
+      return -1;
+   }
+
+   /* Store new video mode parameters */
+   didata->current_mode=*mode;
+   didata->current_mode.refresh_rate=refresh_rate;
 
    return 0;
 }
@@ -192,8 +758,15 @@
 
 int photon_createwindow(_THIS, SDL_Window* window)
 {
+   SDL_VideoData*   phdata=(SDL_VideoData*)_this->driverdata;
    SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
    SDL_WindowData*  wdata;
+   PhDim_t          winsize;
+   PhPoint_t        winpos;
+   PtArg_t          winargs[32];
+   uint32_t         winargc=0;
+   int32_t          status;
+   PhRegion_t       wregion;
 
    /* Allocate window internal data */
    wdata=(SDL_WindowData*)SDL_calloc(1, sizeof(SDL_WindowData));
@@ -206,75 +779,490 @@
    /* Setup driver data for this window */
    window->driverdata=wdata;
 
+   /* Set initial window title */
+   if (window->title!=NULL)
+   {
+      PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_TITLE, window->title, 0);
+   }
+   else
+   {
+      PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_TITLE, "", 0);
+   }
+
+   /* TODO: handle SDL_WINDOW_INPUT_GRABBED */
+
+   /* Disable default window filling on redraw */
+   PtSetArg(&winargs[winargc++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL);
+
+   /* Set default maximum and minimum window sizes */
+   winsize.w=0;
+   winsize.h=0;
+   PtSetArg(&winargs[winargc++], Pt_ARG_MAX_HEIGHT, 0, 0);
+   PtSetArg(&winargs[winargc++], Pt_ARG_MAX_WIDTH, 0, 0);
+   PtSetArg(&winargs[winargc++], Pt_ARG_MIN_HEIGHT, 0, 0);
+   PtSetArg(&winargs[winargc++], Pt_ARG_MIN_WIDTH, 0, 0);
+   PtSetArg(&winargs[winargc++], Pt_ARG_MAXIMUM_DIM, &winsize, 0);
+   PtSetArg(&winargs[winargc++], Pt_ARG_MINIMUM_DIM, &winsize, 0);
+
+   /* Reset default managed events to disable */
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_FALSE,
+            Ph_WM_APP_DEF_MANAGED);
+   /* Set which events we will not handle, let WM to handle them */
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE,
+            Ph_WM_BACKDROP | Ph_WM_TOFRONT | Ph_WM_COLLAPSE | Ph_WM_FFRONT  |
+            Ph_WM_FOCUS    | Ph_WM_HELP    | Ph_WM_HIDE     | Ph_WM_MAX     |
+            Ph_WM_MENU     | Ph_WM_MOVE    | Ph_WM_RESIZE   | Ph_WM_RESTORE |
+            Ph_WM_TASKBAR  | Ph_WM_TOBACK);
+
+   /* Reset default notify events to disable */
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_FALSE,
+            Ph_WM_RESIZE | Ph_WM_CLOSE | Ph_WM_HELP);
+   /* Set which events we will handle */
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE,
+            Ph_WM_CLOSE | Ph_WM_COLLAPSE | Ph_WM_FOCUS   | Ph_WM_MAX  |
+            Ph_WM_MOVE  | Ph_WM_RESIZE   | Ph_WM_RESTORE | Ph_WM_HIDE);
+
+   /* Borderless window can't be resizeable */
+   if ((window->flags & SDL_WINDOW_BORDERLESS)==SDL_WINDOW_BORDERLESS)
+   {
+      window->flags&=~(SDL_WINDOW_RESIZABLE);
+   }
+
+   /* Reset all default decorations */
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_FALSE, Ph_WM_APP_DEF_RENDER);
+
+   /* Fullscreen window has its own decorations */
+   if ((window->flags & SDL_WINDOW_FULLSCREEN)==SDL_WINDOW_FULLSCREEN)
+   {
+      window->flags|=SDL_WINDOW_BORDERLESS;
+      window->flags&=~(SDL_WINDOW_RESIZABLE);
+      PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE,
+               Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_TITLE);
+   }
+   else
+   {
+      uint32_t decorations=Ph_WM_RENDER_CLOSE | Ph_WM_RENDER_MENU | Ph_WM_RENDER_MIN |
+                           Ph_WM_RENDER_TITLE | Ph_WM_RENDER_MOVE;
+
+      if ((window->flags & SDL_WINDOW_RESIZABLE)==SDL_WINDOW_RESIZABLE)
+      {
+         decorations|=Ph_WM_RENDER_BORDER | Ph_WM_RENDER_RESIZE | Ph_WM_RENDER_MAX;
+      }
+      if ((window->flags & SDL_WINDOW_BORDERLESS)!=SDL_WINDOW_BORDERLESS)
+      {
+         decorations|=Ph_WM_RENDER_BORDER;
+      }
+      PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_RENDER_FLAGS, Pt_TRUE, decorations);
+   }
+
+   /* Set initial window state */
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_STATE, Pt_FALSE, Ph_WM_STATE_ISFOCUS);
+   PtSetArg(&winargs[winargc++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISALTKEY);
+
+   /* Set window dimensions */
+   winsize.w=window->w;
+   winsize.h=window->h;
+   PtSetArg(&winargs[winargc++], Pt_ARG_DIM, &winsize, 0);
+
+   /* Check if upper level requests WM to position window */
+   if ((window->x==SDL_WINDOWPOS_UNDEFINED) && (window->y==SDL_WINDOWPOS_UNDEFINED))
+   {
+      /* Do not set widget position, let WM to set it */
+   }
+   else
+   {
+      if (window->x==SDL_WINDOWPOS_UNDEFINED)
+      {
+         window->x=0;
+      }
+      if (window->y==SDL_WINDOWPOS_UNDEFINED)
+      {
+         window->y=0;
+      }
+      if (window->x==SDL_WINDOWPOS_CENTERED)
+      {
+         window->x=(didata->current_mode.w-window->w)/2;
+      }
+      if (window->y==SDL_WINDOWPOS_CENTERED)
+      {
+         window->y=(didata->current_mode.h-window->h)/2;
+      }
+
+      /* Now set window position */
+      winpos.x=window->x;
+      winpos.y=window->y;
+      PtSetArg(&winargs[winargc++], Pt_ARG_POS, &winpos, 0);
+   }
+
+   /* Add SDL window id as user data */
+   PtSetArg(&winargs[winargc++], Pt_ARG_POINTER, (void*)window->id, 0);
+
    /* Check if window must support OpenGL ES rendering */
    if ((window->flags & SDL_WINDOW_OPENGL)==SDL_WINDOW_OPENGL)
    {
-      /* Mark this window as OpenGL ES compatible */
-      wdata->uses_gles=SDL_TRUE;
+      #if defined(SDL_VIDEO_OPENGL_ES)
+         EGLBoolean initstatus;
+
+         /* Check if GF was initialized correctly */
+         if (phdata->gfinitialized==SDL_FALSE)
+         {
+            SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+            return -1;
+         }
+
+         /* Mark this window as OpenGL ES compatible */
+         wdata->uses_gles=SDL_TRUE;
+
+         /* Create connection to OpenGL ES */
+         if (phdata->egldisplay==EGL_NO_DISPLAY)
+         {
+            phdata->egldisplay=eglGetDisplay(phdata->gfdev);
+            if (phdata->egldisplay==EGL_NO_DISPLAY)
+            {
+               SDL_SetError("Photon: Can't get connection to OpenGL ES");
+               return -1;
+            }
+
+            /* Initialize OpenGL ES library, ignore EGL version */
+            initstatus=eglInitialize(phdata->egldisplay, NULL, NULL);
+            if (initstatus!=EGL_TRUE)
+            {
+               SDL_SetError("Photon: Can't init OpenGL ES library");
+               return -1;
+            }
+         }
+
+         /* Increment GL ES reference count usage */
+         phdata->egl_refcount++;
+      #else
+         SDL_SetError("Photon: OpenGL ES support is not compiled in");
+         return -1;
+      #endif /* SDL_VIDEO_OPENGL_ES */
+   }
+
+   /* Finally create the window */
+   wdata->window=PtCreateWidget(PtWindow, Pt_NO_PARENT, winargc, winargs);
+   if (wdata->window==NULL)
+   {
+      SDL_SetError("Photon: Can't create window widget");
+      SDL_free(wdata);
+      return -1;
    }
 
+   /* Show widget */
+   status=PtRealizeWidget(wdata->window);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't realize window widget");
+      PtDestroyWidget(wdata->window);
+      SDL_free(wdata);
+      return;
+   }
+
+   /* Just created SDL window always gets focus */
+   window->flags|=SDL_WINDOW_INPUT_FOCUS;
+
+   /* Create window-specific cursor after creation */
+   if (didata->cursor_visible==SDL_TRUE)
+   {
+      /* Setup cursor type. shape and default color */
+      PtSetResource(wdata->window, Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR, 0);
+      PtSetResource(wdata->window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0);
+      PtSetResource(wdata->window, Pt_ARG_BITMAP_CURSOR, didata->cursor, didata->cursor->hdr.len+sizeof(PhRegionDataHdr_t));
+   }
+   else
+   {
+      PtSetResource(wdata->window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0);
+   }
+
+   /* Set window region sensible to mouse motion events */
+   status=PhRegionQuery(PtWidgetRid(wdata->window), &wregion, NULL, NULL, 0);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't set region sensivity to mouse motion events");
+      PtDestroyWidget(wdata->window);
+      SDL_free(wdata);
+      return -1;
+   }
+   wregion.events_sense|=Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
+   status=PhRegionChange(Ph_REGION_EV_SENSE, 0, &wregion, NULL, NULL);
+   if (status<0)
+   {
+      SDL_SetError("Photon: Can't change region sensivity");
+      PtDestroyWidget(wdata->window);
+      SDL_free(wdata);
+      return -1;
+   }
+
+   /* Flush all widget operations again */
+   PtFlush();
+
+   /* By default last created window got a input focus */
+   SDL_SetKeyboardFocus(0, window->id);
+
    /* Window has been successfully created */
    return 0;
 }
 
 int photon_createwindowfrom(_THIS, SDL_Window* window, const void* data)
 {
+   /* TODO: it is possible */
+
    /* Failed to create window from another window */
    return -1;
 }
 
 void photon_setwindowtitle(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   int32_t status;
+
+   /* Set window title */
+   if (window->title!=NULL)
+   {
+      status=PtSetResource(wdata->window, Pt_ARG_WINDOW_TITLE, window->title, 0);
+   }
+   else
+   {
+      status=PtSetResource(wdata->window, Pt_ARG_WINDOW_TITLE, "", 0);
+   }
+
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't set window title");
+   }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_setwindowicon(_THIS, SDL_Window* window, SDL_Surface* icon)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   int32_t   status;
+
+   /* TODO: Use iconify ? */
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_setwindowposition(_THIS, SDL_Window* window)
 {
+   SDL_WindowData*  wdata=(SDL_WindowData*)window->driverdata;
+   SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
+   PhPoint_t winpos;
+   int32_t   status;
+
+   /* Check if upper level requests WM to position window */
+   if ((window->x==SDL_WINDOWPOS_UNDEFINED) && (window->y==SDL_WINDOWPOS_UNDEFINED))
+   {
+      /* Do not set widget position, let WM to set it */
+   }
+   else
+   {
+      if (window->x==SDL_WINDOWPOS_UNDEFINED)
+      {
+         window->x=0;
+      }
+      if (window->y==SDL_WINDOWPOS_UNDEFINED)
+      {
+         window->y=0;
+      }
+      if (window->x==SDL_WINDOWPOS_CENTERED)
+      {
+         window->x=(didata->current_mode.w-window->w)/2;
+      }
+      if (window->y==SDL_WINDOWPOS_CENTERED)
+      {
+         window->y=(didata->current_mode.h-window->h)/2;
+      }
+
+      /* Now set window position */
+      winpos.x=window->x;
+      winpos.y=window->y;
+      status=PtSetResource(wdata->window, Pt_ARG_POS, &winpos, 0);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't set window position");
+      }
+   }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_setwindowsize(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhDim_t winsize;
+   int32_t status;
+
+   winsize.w=window->w;
+   winsize.h=window->h;
+
+   status=PtSetResource(wdata->window, Pt_ARG_DIM, &winsize, 0);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't set window size");
+   }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_showwindow(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   int32_t status;
+
+   /* Bring focus to window and put it in front of others */
+   PtWindowToFront(wdata->window);
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_hidewindow(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhWindowEvent_t winevent;
+   int32_t status;
+
+   SDL_memset(&winevent, 0x00, sizeof(PhWindowEvent_t));
+   winevent.event_f=Ph_WM_HIDE;
+   winevent.rid=PtWidgetRid(wdata->window);
+   winevent.event_state=Ph_WM_EVSTATE_HIDE;
+
+   status=PtForwardWindowEvent(&winevent);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't hide window");
+   }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_raisewindow(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhWindowEvent_t winevent;
+   int32_t status;
+
+   SDL_memset(&winevent, 0x00, sizeof(PhWindowEvent_t));
+   winevent.event_f=Ph_WM_HIDE;
+   winevent.rid=PtWidgetRid(wdata->window);
+   winevent.event_state=Ph_WM_EVSTATE_UNHIDE;
+
+   status=PtForwardWindowEvent(&winevent);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't hide window");
+   }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_maximizewindow(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhWindowEvent_t winevent;
+   int32_t status;
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_minimizewindow(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhWindowEvent_t winevent;
+   int32_t status;
+
+   SDL_memset(&winevent, 0x00, sizeof(PhWindowEvent_t));
+   winevent.event_f=Ph_WM_HIDE;
+   winevent.rid=PtWidgetRid(wdata->window);
+   winevent.event_state=Ph_WM_EVSTATE_HIDE;
+
+   status=PtForwardWindowEvent(&winevent);
+   if (status!=0)
+   {
+      SDL_SetError("Photon: Can't hide window");
+   }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_restorewindow(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhWindowEvent_t winevent;
+   int32_t status;
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_setwindowgrab(_THIS, SDL_Window* window)
 {
+   SDL_WindowData* wdata=(SDL_WindowData*)window->driverdata;
+   PhWindowEvent_t winevent;
+   int32_t status;
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 void photon_destroywindow(_THIS, SDL_Window* window)
 {
+   SDL_VideoData*   phdata=(SDL_VideoData*)_this->driverdata;
    SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
    SDL_WindowData*  wdata=(SDL_WindowData*)window->driverdata;
+   int32_t status;
 
    if (wdata!=NULL)
    {
+      status=PtDestroyWidget(wdata->window);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't destroy window widget");
+      }
+      wdata->window=NULL;
+
+      #if defined(SDL_VIDEO_OPENGL_ES)
+         if (phdata->gfinitialized==SDL_TRUE)
+         {
+            /* Destroy OpenGL ES surface if it was created */
+            if (wdata->gles_surface!=EGL_NO_SURFACE)
+            {
+               eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
+            }
+
+            /* Free OpenGL ES target surface */
+            if (wdata->gfsurface!=NULL)
+            {
+               gf_surface_free(wdata->gfsurface);
+            }
+
+            phdata->egl_refcount--;
+            if (phdata->egl_refcount==0)
+            {
+               /* Terminate connection to OpenGL ES */
+               if (phdata->egldisplay!=EGL_NO_DISPLAY)
+               {
+                  eglTerminate(phdata->egldisplay);
+                  phdata->egldisplay=EGL_NO_DISPLAY;
+               }
+            }
+         }
+      #endif /* SDL_VIDEO_OPENGL_ES */
    }
+
+   /* Flush all widget operations */
+   PtFlush();
 }
 
 /*****************************************************************************/
@@ -301,50 +1289,691 @@
 /*****************************************************************************/
 int photon_gl_loadlibrary(_THIS, const char* path)
 {
-   /* Failed to load new GL library */
-   return -1;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return NULL;
+      }
+
+      /* Check if OpenGL ES library is specified for GF driver */
+      if (path==NULL)
+      {
+         path=SDL_getenv("SDL_OPENGL_LIBRARY");
+         if (path==NULL)
+         {
+            path=SDL_getenv("SDL_OPENGLES_LIBRARY");
+         }
+      }
+
+      /* Check if default library loading requested */
+      if (path==NULL)
+      {
+         /* Already linked with GF library which provides egl* subset of  */
+         /* functions, use Common profile of OpenGL ES library by default */
+         path="/usr/lib/libGLES_CM.so.1";
+      }
+
+      /* Load dynamic library */
+      _this->gl_config.dll_handle=SDL_LoadObject(path);
+      if (!_this->gl_config.dll_handle)
+      {
+         /* Failed to load new GL ES library */
+         SDL_SetError("Photon: Failed to locate OpenGL ES library");
+         return -1;
+      }
+
+      /* Store OpenGL ES library path and name */
+      SDL_strlcpy(_this->gl_config.driver_path, path, SDL_arraysize(_this->gl_config.driver_path));
+
+      /* New OpenGL ES library is loaded */
+      return 0;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return -1;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 void* photon_gl_getprocaddres(_THIS, const char* proc)
 {
-   /* Failed to get GL function address pointer */
-   return NULL;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+      void* function_address;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return NULL;
+      }
+
+      /* Try to get function address through the egl interface */
+      function_address=eglGetProcAddress(proc);
+      if (function_address!=NULL)
+      {
+         return function_address;
+      }
+
+      /* Then try to get function in the OpenGL ES library */
+      if (_this->gl_config.dll_handle)
+      {
+         function_address=SDL_LoadFunction(_this->gl_config.dll_handle, proc);
+         if (function_address!=NULL)
+         {
+            return function_address;
+         }
+      }
+
+      /* 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("Photon: Cannot locate OpenGL ES function name");
+      return NULL;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return NULL;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 void photon_gl_unloadlibrary(_THIS)
 {
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+
+      if (phdata->gfinitialized==SDL_TRUE)
+      {
+         /* Unload OpenGL ES library */
+         if (_this->gl_config.dll_handle)
+         {
+            SDL_UnloadObject(_this->gl_config.dll_handle);
+            _this->gl_config.dll_handle=NULL;
+         }
+      }
+      else
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+      }
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 SDL_GLContext photon_gl_createcontext(_THIS, SDL_Window* window)
 {
-   /* Failed to create GL context */
-   return NULL;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData*   phdata=(SDL_VideoData*)_this->driverdata;
+      SDL_WindowData*  wdata=(SDL_WindowData*)window->driverdata;
+      SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
+      EGLBoolean       status;
+      int32_t          gfstatus;
+      EGLint           configs;
+      uint32_t         attr_pos;
+      EGLint           attr_value;
+      EGLint           cit;
+
+      /* Check if GF was initialized */
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return NULL;
+      }
+
+      /* Prepare attributes list to pass them to OpenGL ES */
+      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++]=_this->gl_config.red_size;
+      wdata->gles_attributes[attr_pos++]=EGL_GREEN_SIZE;
+      wdata->gles_attributes[attr_pos++]=_this->gl_config.green_size;
+      wdata->gles_attributes[attr_pos++]=EGL_BLUE_SIZE;
+      wdata->gles_attributes[attr_pos++]=_this->gl_config.blue_size;
+      wdata->gles_attributes[attr_pos++]=EGL_ALPHA_SIZE;
+
+      /* Setup alpha size in bits */
+      if (_this->gl_config.alpha_size)
+      {
+         wdata->gles_attributes[attr_pos++]=_this->gl_config.alpha_size;
+      }
+      else
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE;
+      }
+
+      /* Setup color buffer size */
+      if (_this->gl_config.buffer_size)
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_BUFFER_SIZE;
+         wdata->gles_attributes[attr_pos++]=_this->gl_config.buffer_size;
+      }
+      else
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_BUFFER_SIZE;
+         wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE;
+      }
+
+      /* Setup depth buffer bits */
+      wdata->gles_attributes[attr_pos++]=EGL_DEPTH_SIZE;
+      wdata->gles_attributes[attr_pos++]=_this->gl_config.depth_size;
+
+      /* Setup stencil bits */
+      if (_this->gl_config.stencil_size)
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_STENCIL_SIZE;
+         wdata->gles_attributes[attr_pos++]=_this->gl_config.buffer_size;
+      }
+      else
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_STENCIL_SIZE;
+         wdata->gles_attributes[attr_pos++]=EGL_DONT_CARE;
+      }
+
+      /* Set number of samples in multisampling */
+      if (_this->gl_config.multisamplesamples)
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_SAMPLES;
+         wdata->gles_attributes[attr_pos++]=_this->gl_config.multisamplesamples;
+      }
+
+      /* Multisample buffers, OpenGL ES 1.0 spec defines 0 or 1 buffer */
+      if (_this->gl_config.multisamplebuffers)
+      {
+         wdata->gles_attributes[attr_pos++]=EGL_SAMPLE_BUFFERS;
+         wdata->gles_attributes[attr_pos++]=_this->gl_config.multisamplebuffers;
+      }
+
+      /* Finish attributes list */
+      wdata->gles_attributes[attr_pos]=EGL_NONE;
+
+      /* Request first suitable framebuffer configuration */
+      status=eglChooseConfig(phdata->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;
+      }
+
+      /* 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 set data 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;
+               }
+
+               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(phdata->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(phdata->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(phdata->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(phdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_NO_CONTEXT, NULL);
+      if (wdata->gles_context==EGL_NO_CONTEXT)
+      {
+         SDL_SetError("Photon: OpenGL ES context creation has been failed");
+         return NULL;
+      }
+
+      /* Check if surface is exist */
+      if (wdata->gfsurface!=NULL)
+      {
+         gf_surface_free(wdata->gfsurface);
+         wdata->gfsurface=NULL;
+      }
+
+      /* Create GF surface */
+      gfstatus=gf_surface_create(&wdata->gfsurface, phdata->gfdev, window->w, window->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)
+      {
+         eglDestroyContext(phdata->egldisplay, wdata->gles_context);
+         wdata->gles_context=EGL_NO_CONTEXT;
+         SDL_SetError("Photon: Can't create GF 3D surface (%08X)", gfstatus);
+         return NULL;
+      }
+
+      /* Create pixmap 3D target surface */
+      wdata->gles_surface=eglCreatePixmapSurface(phdata->egldisplay, wdata->gles_configs[wdata->gles_config], wdata->gfsurface, NULL);
+      if (wdata->gles_surface==EGL_NO_SURFACE)
+      {
+         gf_surface_free(wdata->gfsurface);
+         eglDestroyContext(phdata->egldisplay, wdata->gles_context);
+         wdata->gles_context=EGL_NO_CONTEXT;
+         SDL_SetError("Photon: Can't create EGL pixmap surface");
+         return NULL;
+      }
+
+      /* Make just created context current */
+      status=eglMakeCurrent(phdata->egldisplay, wdata->gles_surface, wdata->gles_surface, wdata->gles_context);
+      if (status!=EGL_TRUE)
+      {
+         /* Destroy OpenGL ES surface */
+         eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
+         gf_surface_free(wdata->gfsurface);
+         eglDestroyContext(phdata->egldisplay, wdata->gles_context);
+         wdata->gles_context=EGL_NO_CONTEXT;
+         SDL_SetError("Photon: Can't set OpenGL ES context on creation");
+         return NULL;
+      }
+
+      /* Setup into SDL internals state of OpenGL ES:  */
+      /* it is accelerated or not                      */
+      if ((didata->caps & SDL_PHOTON_ACCELERATED_3D)==SDL_PHOTON_ACCELERATED_3D)
+      {
+         _this->gl_config.accelerated=1;
+      }
+      else
+      {
+         _this->gl_config.accelerated=0;
+      }
+
+      /* Always clear stereo enable, since OpenGL ES do not supports stereo */
+      _this->gl_config.stereo=0;
+
+      /* Get back samples and samplebuffers configurations. Rest framebuffer */
+      /* parameters could be obtained through the OpenGL ES API              */
+      status=eglGetConfigAttrib(phdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_SAMPLES, &attr_value);
+      if (status==EGL_TRUE)
+      {
+         _this->gl_config.multisamplesamples=attr_value;
+      }
+      status=eglGetConfigAttrib(phdata->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(phdata->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(phdata->egldisplay, wdata->gles_configs[wdata->gles_config], EGL_STENCIL_SIZE, &attr_value);
+      if (status==EGL_TRUE)
+      {
+         _this->gl_config.stencil_size=attr_value;
+      }
+
+      /* Under Photon OpenGL ES output can't be double buffered */
+      _this->gl_config.double_buffer=0;
+
+      /* Check if current device is not the same as target */
+      if (phdata->current_device_id!=didata->device_id)
+      {
+         /* Set target device as default for Pd and Pg functions */
+         status=PdSetTargetDevice(NULL, phdata->rid[didata->device_id]);
+         if (status!=0)
+         {
+            /* Destroy OpenGL ES surface */
+            eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
+            gf_surface_free(wdata->gfsurface);
+            eglDestroyContext(phdata->egldisplay, wdata->gles_context);
+            wdata->gles_context=EGL_NO_CONTEXT;
+            SDL_SetError("Photon: Can't set default target device\n");
+            return NULL;
+         }
+         phdata->current_device_id=didata->device_id;
+      }
+
+      wdata->phsurface=PdCreateOffscreenContextGF(wdata->gfsurface);
+      if (wdata->phsurface==NULL)
+      {
+         /* Destroy OpenGL ES surface */
+         eglDestroySurface(phdata->egldisplay, wdata->gles_surface);
+         gf_surface_free(wdata->gfsurface);
+         eglDestroyContext(phdata->egldisplay, wdata->gles_context);
+         wdata->gles_context=EGL_NO_CONTEXT;
+         SDL_SetError("Photon: Can't bind GF surface to Photon\n");
+         return NULL;
+      }
+
+      /* GL ES context was successfully created */
+      return wdata->gles_context;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return NULL;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 int photon_gl_makecurrent(_THIS, SDL_Window* window, SDL_GLContext context)
 {
-   /* Failed to set current GL context */
-   return -1;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData*  phdata=(SDL_VideoData*)_this->driverdata;
+      SDL_WindowData* wdata;
+      EGLBoolean status;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return -1;
+      }
+
+      if ((window==NULL) && (context==NULL))
+      {
+         status=eglMakeCurrent(phdata->egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+         if (status!=EGL_TRUE)
+         {
+            /* Failed to set current GL ES context */
+            SDL_SetError("Photon: Can't set OpenGL ES context");
+            return -1;
+         }
+      }
+      else
+      {
+         wdata=(SDL_WindowData*)window->driverdata;
+         if (wdata->gles_surface==EGL_NO_SURFACE)
+         {
+            SDL_SetError("Photon: OpenGL ES surface is not initialized for this window");
+            return -1;
+         }
+         if (wdata->gles_context==EGL_NO_CONTEXT)
+         {
+            SDL_SetError("Photon: OpenGL ES context is not initialized for this window");
+            return -1;
+         }
+         if (wdata->gles_context!=context)
+         {
+            SDL_SetError("Photon: OpenGL ES context is not belong to this window");
+            return -1;
+         }
+         status=eglMakeCurrent(phdata->egldisplay, wdata->gles_surface, wdata->gles_surface, wdata->gles_context);
+         if (status!=EGL_TRUE)
+         {
+            /* Failed to set current GL ES context */
+            SDL_SetError("Photon: Can't set OpenGL ES context");
+            return -1;
+         }
+      }
+
+      return 0;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return -1;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 int photon_gl_setswapinterval(_THIS, int interval)
 {
-   /* Failed to set swap interval */
-   return -1;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+      EGLBoolean     status;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return -1;
+      }
+
+      /* Check if OpenGL ES connection has been initialized */
+      if (phdata->egldisplay!=EGL_NO_DISPLAY)
+      {
+         /* Set swap OpenGL ES interval */
+         status=eglSwapInterval(phdata->egldisplay, interval);
+         if (status==EGL_TRUE)
+         {
+            /* Return success to upper level */
+            phdata->swapinterval=interval;
+            return 0;
+         }
+      }
+
+      /* Failed to set swap interval */
+      SDL_SetError("Photon: Cannot set swap interval");
+      return -1;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return -1;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 int photon_gl_getswapinterval(_THIS)
 {
-   /* Failed to get default swap interval */
-   return -1;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return -1;
+      }
+
+      /* Return default swap interval value */
+      return phdata->swapinterval;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return -1;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 void photon_gl_swapwindow(_THIS, SDL_Window* window)
 {
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData*   phdata=(SDL_VideoData*)_this->driverdata;
+      SDL_WindowData*  wdata=(SDL_WindowData*)window->driverdata;
+      SDL_DisplayData* didata=(SDL_DisplayData*)SDL_CurrentDisplay.driverdata;
+      PhRect_t*        dst_rect;
+      PhRect_t         src_rect;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return;
+      }
+
+      /* Many applications do not uses glFinish(), so we call it for them */
+      glFinish();
+
+      /* Wait until OpenGL ES rendering is completed */
+      eglWaitGL();
+
+      /* Wait for VSYNC manually, if it was enabled */
+      if (phdata->swapinterval!=0)
+      {
+         /* Wait for VSYNC, we use GF function, since Photon requires */
+         /* to enter to the Direct mode to call PgWaitVSync()         */
+         gf_display_wait_vsync(didata->display);
+      }
+
+      /* Set blit area */
+      dst_rect=PtGetCanvas(wdata->window);
+      src_rect.ul.x=0;
+      src_rect.ul.y=0;
+      src_rect.lr.x=window->w-1;
+      src_rect.lr.y=window->h-1;
+
+      /* Blit OpenGL ES pixmap surface directly to window region */
+      PgFFlush(Ph_START_DRAW);
+      PgSetRegionCx(PhDCGetCurrent(), PtWidgetRid(wdata->window));
+      PgClearTranslationCx(PgGetGCCx(PhDCGetCurrent()));
+      PgContextBlit(wdata->phsurface, &src_rect, NULL, dst_rect);
+      PgFFlush(Ph_DONE_DRAW);
+      PgWaitHWIdle();
+
+      eglSwapBuffers(phdata->egldisplay, wdata->gles_surface);
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 void photon_gl_deletecontext(_THIS, SDL_GLContext context)
 {
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata;
+      EGLBoolean     status;
+
+      if (phdata->gfinitialized!=SDL_TRUE)
+      {
+         SDL_SetError("Photon: GF initialization failed, no OpenGL ES support");
+         return;
+      }
+
+      /* Check if OpenGL ES connection has been initialized */
+      if (phdata->egldisplay!=EGL_NO_DISPLAY)
+      {
+         if (context!=EGL_NO_CONTEXT)
+         {
+            status=eglDestroyContext(phdata->egldisplay, context);
+            if (status!=EGL_TRUE)
+            {
+               /* Error during OpenGL ES context destroying */
+               SDL_SetError("Photon: OpenGL ES context destroy error");
+               return;
+            }
+         }
+      }
+
+      return;
+   #else
+      SDL_SetError("Photon: OpenGL ES support is not compiled in");
+      return;
+   #endif /* SDL_VIDEO_OPENGL_ES */
 }
 
 /*****************************************************************************/
@@ -352,6 +1981,543 @@
 /*****************************************************************************/
 void photon_pumpevents(_THIS)
 {
+   uint8_t    eventbuffer[SDL_VIDEO_PHOTON_EVENT_SIZE];
+   PhEvent_t* event=(PhEvent_t*)eventbuffer;
+   int32_t    status;
+   uint32_t   finish=0;
+   uint32_t   it;
+   SDL_Window* window;
+   SDL_WindowData* wdata;
+
+   do {
+      status=PhEventPeek(event, SDL_VIDEO_PHOTON_EVENT_SIZE);
+      switch (status)
+      {
+         case Ph_RESIZE_MSG:
+              {
+                 SDL_SetError("Photon: Event size too much for buffer");
+                 return;
+              }
+              break;
+         case Ph_EVENT_MSG:
+              {
+                 /* Find a window, to which this handle destinated */
+                 status=0;
+                 for (it=0; it<SDL_CurrentDisplay.num_windows; it++)
+                 {
+                    wdata=(SDL_WindowData*)SDL_CurrentDisplay.windows[it].driverdata;
+
+                    /* Find the proper window */
+                    if (wdata->window!=NULL)
+                    {
+                       if (PtWidgetRid(wdata->window)==event->collector.rid)
+                       {
+                          window=(SDL_Window*)&SDL_CurrentDisplay.windows[it];
+                          status=1;
+                          break;
+                       }
+                    }
+                    else
+                    {
+                       continue;
+                    }
+                 }
+                 if (status==0)
+                 {
+                    window=NULL;
+                 }
+
+                 /* Event is ready */
+                 switch(event->type)
+                 {
+                    case Ph_EV_BOUNDARY:
+                         {
+                            switch(event->subtype)
+                            {
+                               case Ph_EV_PTR_ENTER:
+                                    {
+                                       /* Mouse cursor over handled window */
+                                       if (window!=NULL)
+                                       {
+                                          SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_ENTER, 0, 0);
+                                          SDL_SetMouseFocus(0, window->id);
+                                       }
+                                    }
+                                    break;
+                               case Ph_EV_PTR_LEAVE:
+                                    {
+                                       /* Mouse cursor out of handled window */
+                                       if (window!=NULL)
+                                       {
+                                          SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_LEAVE, 0, 0);
+                                       }
+                                    }
+                                    break;
+                            }
+                         }
+                         break;
+                    case Ph_EV_PTR_MOTION_BUTTON:
+                    case Ph_EV_PTR_MOTION_NOBUTTON:
+                         {
+                            PhPointerEvent_t* pevent=NULL;
+                            PhRect_t* prects=NULL;
+
+                            /* Get event data */
+                            pevent=PhGetData(event);
+                            /* Get associated event rectangles */
+                            prects=PhGetRects(event);
+                            if ((pevent!=NULL) && (prects!=NULL))
+                            {
+                               SDL_SendMouseMotion(0, 0, prects->ul.x, prects->ul.y, 0);
+                            }
+                         }
+                         break;
+                    case Ph_EV_BUT_PRESS:
+                         {
+                            /* Button press event */
+                            PhPointerEvent_t* pevent=NULL;
+                            uint32_t sdlbutton=0x00000000;
+
+                            /* Get event data */
+                            pevent=PhGetData(event);
+                            if (pevent!=NULL)
+                            {
+                               for (it=0; it<sizeof(pevent->buttons)*8; it++)
+                               {
+                                  if ((pevent->buttons&(0x0001<<it))==(0x0001<<it))
+                                  {
+                                     switch (it)
+                                     {
+                                        case 0:
+                                             {
+                                                sdlbutton=SDL_BUTTON_RIGHT;
+                                             }
+                                             break;
+                                        case 1:
+                                             {
+                                                sdlbutton=SDL_BUTTON_MIDDLE;
+                                             }
+                                             break;
+                                        case 2:
+                                             {
+                                                sdlbutton=SDL_BUTTON_LEFT;
+                                             }
+                                             break;
+                                        default:
+                                             {
+                                                sdlbutton=it+1;
+                                             }
+                                             break;
+                                     }
+                                     SDL_SendMouseButton(0, SDL_PRESSED, sdlbutton);
+                                  }
+                               }
+                            }
+                         }
+                         break;
+                    case Ph_EV_BUT_RELEASE:
+                         {
+                            /* Button press event */
+                            PhPointerEvent_t* pevent=NULL;
+                            uint32_t sdlbutton=0x00000000;
+
+                            /* Get event data */
+                            pevent=PhGetData(event);
+                            if (pevent!=NULL)
+                            {
+                               for (it=0; it<sizeof(pevent->buttons)*8; it++)
+                               {
+                                  if ((pevent->buttons&(0x0001<<it))==(0x0001<<it))
+                                  {
+                                     switch (it)
+                                     {
+                                        case 0:
+                                             {
+                                                sdlbutton=SDL_BUTTON_RIGHT;
+                                             }
+                                             break;
+                                        case 1:
+                                             {
+                                                sdlbutton=SDL_BUTTON_MIDDLE;
+                                             }
+                                             break;
+                                        case 2:
+                                             {
+                                                sdlbutton=SDL_BUTTON_LEFT;
+                                             }
+                                             break;
+                                        default:
+                                             {
+                                                sdlbutton=it+1;
+                                             }
+                                             break;
+                                     }
+                                  }
+                               }
+                            }
+
+                            switch(event->subtype)
+                            {
+                               case Ph_EV_RELEASE_REAL:
+                                    {
+                                       /* Real release button event */
+                                       SDL_SendMouseButton(0, SDL_RELEASED, sdlbutton);
+                                    }
+                                    break;
+                               case Ph_EV_RELEASE_PHANTOM:
+                                    {
+                                       /* We will get phantom button release */
+                                       /* event in case if it was unpressed  */
+                                       /* outside of window                  */
+                                       if (window!=NULL)
+                                       {
+                                          if ((window->flags & SDL_WINDOW_MOUSE_FOCUS)!=SDL_WINDOW_MOUSE_FOCUS)
+                                          {
+                                             /* Send phantom button release */
+                                             SDL_SendMouseButton(0, SDL_RELEASED, sdlbutton);
+                                          }
+                                       }
+                                    }
+                                    break;
+                            }
+                         }
+                         break;
+                    case Ph_EV_EXPOSE:
+                         {
+                            switch(event->subtype)
+                            {
+                               case Ph_NORMAL_EXPOSE:
+                                    {
+                                       PhRect_t* rects=NULL;
+
+                                       /* Get array of rectangles to be updated */
+                                       rects=PhGetRects(event);
+                                       if (rects==NULL)
+                                       {
+                                          break;
+                                       }
+
+                                       /* Cycle through each rectangle */
+                                       for (it=0; it<event->num_rects; it++)
+                                       {
+                                          /* TODO: update the damaged rectangles */
+                                       }
+
+                                       /* Flush all blittings */
+                                       PgFlush();
+                                    }
+                                    break;
+                               case Ph_CAPTURE_EXPOSE:
+                                    {
+                                       /* We need to redraw entire screen */
+                                       PgFFlush(Ph_START_DRAW);
+
+                                       /* TODO: redraw the whole screen */
+
+                                       PgFFlush(Ph_DONE_DRAW);
+                                    }
+                                    break;
+                               case Ph_GRAPHIC_EXPOSE:
+                                    {
+                                       /* TODO: What this event means ? */
+                                    }
+                                    break;
+                            }
+                         }
+                         break;
+                    case Ph_EV_INFO:
+                         {
+                         }
+                         break;
+                    case Ph_EV_KEY:
+                         {
+                            PhKeyEvent_t* keyevent=NULL;
+                            SDL_scancode scancode=SDL_SCANCODE_UNKNOWN;
+                            SDL_bool pressed=SDL_FALSE;
+
+                            keyevent=PhGetData(event);
+                            if (keyevent==NULL)
+                            {
+                               break;
+                            }
+
+                            /* Check if key is repeated */
+                            if ((keyevent->key_flags & Pk_KF_Key_Repeat)==Pk_KF_Key_Repeat)
+                            {
+                               /* Ignore such events */
+                               break;
+                            }
+
+                            /* Check if key has its own scancode */
+                            if ((keyevent->key_flags & Pk_KF_Scan_Valid)==Pk_KF_Scan_Valid)
+                            {
+                               if ((keyevent->key_flags & Pk_KF_Key_Down)==Pk_KF_Key_Down)
+                               {
+                                  pressed=SDL_TRUE;
+                               }
+                               else
+                               {
+                                  pressed=SDL_FALSE;
+                               }
+                               scancode=photon_to_sdl_keymap(keyevent->key_scan);
+
+                               /* Add details for the pressed key */
+                               if ((keyevent->key_flags & Pk_KF_Cap_Valid)==Pk_KF_Cap_Valid)
+                               {
+                                  switch(keyevent->key_cap)
+                                  {
+                                     case Pk_Hyper_R: /* Right windows flag key */
+                                          scancode=SDL_SCANCODE_RGUI;
+                                          break;
+                                     case Pk_Control_R: /* Right Ctrl key */
+                                          scancode=SDL_SCANCODE_RCTRL;
+                                          break;
+                                     case Pk_Alt_R: /* Right Alt key */
+                                          scancode=SDL_SCANCODE_RALT;
+                                          break;
+                                     case Pk_Up: /* Up key but with invalid scan */
+                                          if (scancode!=SDL_SCANCODE_UP)
+                                          {
+                                             /* This is a mouse wheel event */
+                                             SDL_SendMouseWheel(0, 0, 1);
+                                             return;
+                                          }
+                                          break;
+                                     case Pk_KP_8: /* Up arrow or 8 on keypad */
+                                          scancode=SDL_SCANCODE_KP_8;
+                                          break;
+                                     case Pk_Down: /* Down key but with invalid scan */
+                                          if (scancode!=SDL_SCANCODE_DOWN)
+                                          {
+                                             /* This is a mouse wheel event */
+                                             SDL_SendMouseWheel(0, 0, -1);
+                                             return;
+                                          }
+                                          break;
+                                     case Pk_KP_2: /* Down arrow or 2 on keypad */
+                                          scancode=SDL_SCANCODE_KP_2;
+                                          break;
+                                     case Pk_Left: /* Left arrow key */
+                                          scancode=SDL_SCANCODE_LEFT;
+                                          break;
+                                     case Pk_KP_4: /* Left arrow or 4 on keypad */
+                                          scancode=SDL_SCANCODE_KP_4;
+                                          break;
+                                     case Pk_Right: /* Right arrow key */
+                                          scancode=SDL_SCANCODE_RIGHT;
+                                          break;
+                                     case Pk_KP_6: /* Right arrow or 6 on keypad */
+                                          scancode=SDL_SCANCODE_KP_6;
+                                          break;
+                                     case Pk_Insert: /* Insert key */
+                                          scancode=SDL_SCANCODE_INSERT;
+                                          break;
+                                     case Pk_KP_0: /* Insert or 0 on keypad */
+                                          scancode=SDL_SCANCODE_KP_0;
+                                          break;
+                                     case Pk_Home: /* Home key */
+                                          scancode=SDL_SCANCODE_HOME;
+                                          break;
+                                     case Pk_KP_7: /* Home or 7 on keypad */
+                                          scancode=SDL_SCANCODE_KP_7;
+                                          break;
+                                     case Pk_Pg_Up: /* PageUp key */
+                                          scancode=SDL_SCANCODE_PAGEUP;
+                                          break;
+                                     case Pk_KP_9: /* PgUp or 9 on keypad */
+                                          scancode=SDL_SCANCODE_KP_9;
+                                          break;
+                                     case Pk_Delete: /* Delete key */
+                                          scancode=SDL_SCANCODE_DELETE;
+                                          break;
+                                     case Pk_KP_Decimal: /* Del or . on keypad */
+                                          scancode=SDL_SCANCODE_KP_PERIOD;
+                                          break;
+                                     case Pk_End: /* End key */
+                                          scancode=SDL_SCANCODE_END;
+                                          break;
+                                     case Pk_KP_1: /* End or 1 on keypad */
+                                          scancode=SDL_SCANCODE_KP_1;
+                                          break;
+                                     case Pk_Pg_Down: /* PageDown key */
+                                          scancode=SDL_SCANCODE_PAGEDOWN;
+                                          break;
+                                     case Pk_KP_3: /* PgDn or 3 on keypad */
+                                          scancode=SDL_SCANCODE_KP_3;
+                                          break;
+                                     case Pk_KP_5: /* 5 on keypad */
+                                          scancode=SDL_SCANCODE_KP_5;
+                                          break;
+                                     case Pk_KP_Enter:
+                                          scancode=SDL_SCANCODE_KP_ENTER;
+                                          break;
+                                     case Pk_KP_Add:
+                                          scancode=SDL_SCANCODE_KP_PLUS;
+                                          break;
+                                     case Pk_KP_Subtract:
+                                          scancode=SDL_SCANCODE_KP_MINUS;
+                                          break;
+                                     case Pk_KP_Multiply:
+                                          scancode=SDL_SCANCODE_KP_MULTIPLY;
+                                          break;
+                                     case Pk_KP_Divide:
+                                          scancode=SDL_SCANCODE_KP_DIVIDE;
+                                          break;
+                                     case Pk_Pause:
+                                          scancode=SDL_SCANCODE_PAUSE;
+                                          break;
+                                  }
+                               }
+
+                               /* Finally check if scancode has been decoded */
+                               if (scancode==SDL_SCANCODE_UNKNOWN)
+                               {
+                                  /* Something was pressed, which is not supported */
+                                  break;
+                               }
+
+                               /* Report pressed/released key to SDL */
+                               if (pressed==SDL_TRUE)
+                               {
+                                  SDL_SendKeyboardKey(0, SDL_PRESSED, scancode);
+                               }
+                               else
+                               {
+                                  SDL_SendKeyboardKey(0, SDL_RELEASED, scancode);
+                               }
+
+                               /* Photon doesn't send a release event for PrnScr key */
+                               if ((scancode==SDL_SCANCODE_PRINTSCREEN) && (pressed))
+                               {
+                                  SDL_SendKeyboardKey(0, SDL_RELEASED, scancode);
+                               }
+                            }
+                         }
+                         break;
+                    case Ph_EV_SERVICE:
+                         {
+                         }
+                         break;
+                    case Ph_EV_SYSTEM:
+                         {
+                         }
+                         break;
+                    case Ph_EV_WM:
+                         {
+                            PhWindowEvent_t* wmevent=NULL;
+
+                            /* Get associated event data */
+                            wmevent=PhGetData(event);
+                            if (wmevent==NULL)
+                            {
+                               break;
+                            }
+
+                            switch(wmevent->event_f)
+                            {
+                               case Ph_WM_CLOSE:
+                                    {
+                                       if (window!=NULL)
+                                       {
+                                          SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_CLOSE, 0, 0);
+                                       }
+                                    }
+                                    break;
+                               case Ph_WM_FOCUS:
+                                    {
+                                       if (wmevent->event_state==Ph_WM_EVSTATE_FOCUS)
+                                       {
+                                          if (window!=NULL)
+                                          {
+                                             PhRegion_t wregion;
+
+                                             SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
+                                             SDL_SetKeyboardFocus(0, window->id);
+
+                                             /* Set window region sensible to mouse motion events */
+                                             PhRegionQuery(PtWidgetRid(wdata->window), &wregion, NULL, NULL, 0);
+                                             wregion.events_sense|=Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON;
+                                             PhRegionChange(Ph_REGION_EV_SENSE, 0, &wregion, NULL, NULL);
+                                          }
+                                       }
+                                       if (wmevent->event_state==Ph_WM_EVSTATE_FOCUSLOST)
+                                       {
+                                          if (window!=NULL)
+                                          {
+                                             PhRegion_t wregion;
+
+                                             SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
+
+                                             /* Set window region ignore mouse motion events */
+                                             PhRegionQuery(PtWidgetRid(wdata->window), &wregion, NULL, NULL, 0);
+                                             wregion.events_sense&=~(Ph_EV_PTR_MOTION_BUTTON | Ph_EV_PTR_MOTION_NOBUTTON);
+                                             PhRegionChange(Ph_REGION_EV_SENSE, 0, &wregion, NULL, NULL);
+                                          }
+                                       }
+                                    }
+                                    break;
+                               case Ph_WM_MOVE:
+                                    {
+                                       if (window!=NULL)
+                                       {
+                                          SDL_SendWindowEvent(window->id, SDL_WINDOWEVENT_MOVED, wmevent->pos.x, wmevent->pos.y);
+                                       }
+                                    }
+                                    break;
+                               case Ph_WM_RESIZE:
+                                    {
+                                       if (window!=NULL)
+                                       {
+                                       }
+                                    }
+                                    break;
+                               case Ph_WM_HIDE:
+                                    {
+                                       if (window!=NULL)
+                                       {
+                                       }
+                                    }
+                                    break;
+                               case Ph_WM_MAX:
+                                    {
+                                       if (window!=NULL)
+                                       {
+                                       }
+                                    }
+                                    break;
+                               case Ph_WM_RESTORE:
+                                    {
+                                       if (window!=NULL)
+                                       {
+                                       }
+                                    }
+                                    break;
+                            }
+                         }
+                         break;
+                 }
+                 PtEventHandler(event);
+              }
+              break;
+         case 0:
+              {
+                 /* All events are read */
+                 finish=1;
+                 break;
+              }
+         case -1:
+              {
+                 /* Error occured in event reading */
+                 SDL_SetError("Photon: Can't read event");
+                 return;
+              }
+              break;
+      }
+      if (finish!=0)
+      {
+         break;
+      }
+   } while(1);
 }
 
 /*****************************************************************************/
--- a/src/video/photon/SDL_photon.h	Fri Apr 24 03:46:54 2009 +0000
+++ b/src/video/photon/SDL_photon.h	Tue Apr 28 04:30:52 2009 +0000
@@ -27,28 +27,78 @@
 #ifndef __SDL_PHOTON_H__
 #define __SDL_PHOTON_H__
 
+/* GF headers must be included first for the Photon GF functions */
+#if defined(SDL_VIDEO_OPENGL_ES)
+   #include <gf/gf.h>
+   #include <GLES/egl.h>
+#endif /* SDL_VIDEO_OPENGL_ES */
+
+#include "SDL_config.h"
 #include "../SDL_sysvideo.h"
 
 #include <Ph.h>
+#include <Pt.h>
+#include <photon/PkKeyDef.h>
+
+/* Maximum display devices, which can handle SDL Photon driver */
+#define SDL_VIDEO_PHOTON_MAX_RIDS 16
 
 typedef struct SDL_VideoData
 {
+   PhRid_t  rid[SDL_VIDEO_PHOTON_MAX_RIDS];
+   uint32_t avail_rids;
+   uint32_t current_device_id;
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      gf_dev_t      gfdev;           /* GF device handle                     */
+      gf_dev_info_t gfdev_info;      /* GF device information                */
+      SDL_bool      gfinitialized;   /* GF device initialization status      */
+      EGLDisplay    egldisplay;      /* OpenGL ES display connection         */
+      uint32_t      egl_refcount;    /* OpenGL ES reference count            */
+      uint32_t      swapinterval;    /* OpenGL ES default swap interval      */
+   #endif /* SDL_VIDEO_OPENGL_ES */
 } SDL_VideoData;
 
-#define SDL_VIDEO_PHOTON_DEVICENAME_MAX 257
+/* This is hardcoded value in photon/Pg.h */
+#define SDL_VIDEO_PHOTON_DEVICENAME_MAX  41
+#define SDL_VIDEO_PHOTON_MAX_CURSOR_SIZE 128
+
+/* Maximum event message size with data payload */
+#define SDL_VIDEO_PHOTON_EVENT_SIZE 8192
 
 typedef struct SDL_DisplayData
 {
+   uint32_t          device_id;
    uint32_t          custom_refresh;   /* Custom refresh rate for all modes  */
    SDL_DisplayMode   current_mode;     /* Current video mode                 */
    uint8_t           description[SDL_VIDEO_PHOTON_DEVICENAME_MAX];
                                        /* Device description                 */
    uint32_t          caps;             /* Device capabilities                */
+   PhCursorDef_t*    cursor;           /* Global cursor settings             */
+   SDL_bool          cursor_visible;   /* SDL_TRUE if cursor visible         */
+   uint32_t          cursor_size;      /* Cursor size in memory w/ structure */
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      gf_display_t      display;       /* GF display handle                  */
+      gf_display_info_t display_info;  /* GF display information             */
+   #endif /* SDL_VIDEO_OPENGL_ES */
 } SDL_DisplayData;
 
+/* Maximum amount of OpenGL ES framebuffer configurations */
+#define SDL_VIDEO_GF_OPENGLES_CONFS 32
+
 typedef struct SDL_WindowData
 {
-   SDL_bool     uses_gles;           /* if true window must support OpenGL ES*/
+   SDL_bool       uses_gles;           /* if true window must support OpenGL ES*/
+   PtWidget_t*    window;              /* window handle                        */
+   #if defined(SDL_VIDEO_OPENGL_ES)
+      EGLConfig    gles_configs[SDL_VIDEO_GF_OPENGLES_CONFS];
+                                         /* OpenGL ES framebuffer confs        */
+      EGLint       gles_config;          /* OpenGL ES configuration index      */
+      EGLContext   gles_context;         /* OpenGL ES context                  */
+      EGLint       gles_attributes[256]; /* OpenGL ES attributes for context   */
+      EGLSurface   gles_surface;         /* OpenGL ES target rendering surface */
+      gf_surface_t gfsurface;            /* OpenGL ES GF's surface             */
+      PdOffscreenContext_t* phsurface;   /* OpenGL ES Photon's surface         */
+   #endif /* SDL_VIDEO_OPENGL_ES */
 } SDL_WindowData;
 
 /****************************************************************************/
@@ -62,22 +112,24 @@
 
 #define SDL_PHOTON_UNACCELERATED         0x00000000
 #define SDL_PHOTON_ACCELERATED           0x00000001
+#define SDL_PHOTON_UNACCELERATED_3D      0x00000000
+#define SDL_PHOTON_ACCELERATED_3D        0x00000004
 
 /****************************************************************************/
 /* SDL_VideoDevice functions declaration                                    */
 /****************************************************************************/
 
 /* Display and window functions */
-int photon_videoinit(_THIS);
+int  photon_videoinit(_THIS);
 void photon_videoquit(_THIS);
 void photon_getdisplaymodes(_THIS);
-int photon_setdisplaymode(_THIS, SDL_DisplayMode* mode);
-int photon_setdisplaypalette(_THIS, SDL_Palette* palette);
-int photon_getdisplaypalette(_THIS, SDL_Palette* palette);
-int photon_setdisplaygammaramp(_THIS, Uint16* ramp);
-int photon_getdisplaygammaramp(_THIS, Uint16* ramp);
-int photon_createwindow(_THIS, SDL_Window* window);
-int photon_createwindowfrom(_THIS, SDL_Window* window, const void* data);
+int  photon_setdisplaymode(_THIS, SDL_DisplayMode* mode);
+int  photon_setdisplaypalette(_THIS, SDL_Palette* palette);
+int  photon_getdisplaypalette(_THIS, SDL_Palette* palette);
+int  photon_setdisplaygammaramp(_THIS, Uint16* ramp);
+int  photon_getdisplaygammaramp(_THIS, Uint16* ramp);
+int  photon_createwindow(_THIS, SDL_Window* window);
+int  photon_createwindowfrom(_THIS, SDL_Window* window, const void* data);
 void photon_setwindowtitle(_THIS, SDL_Window* window);
 void photon_setwindowicon(_THIS, SDL_Window* window, SDL_Surface* icon);
 void photon_setwindowposition(_THIS, SDL_Window* window);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/photon/SDL_photon_input.c	Tue Apr 28 04:30:52 2009 +0000
@@ -0,0 +1,735 @@
+/*
+    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 Photon GUI SDL driver
+    Copyright (C) 2009 Mike Gorchak
+    (mike@malva.ua, lestat@i.com.ua)
+*/
+
+#include "SDL_photon_input.h"
+
+#include "SDL_config.h"
+#include "SDL_events.h"
+#include "../../events/SDL_mouse_c.h"
+#include "../../events/SDL_keyboard_c.h"
+
+#include "SDL_photon_keycodes.h"
+
+/* Mouse related functions */
+SDL_Cursor* photon_createcursor(SDL_Surface* surface, int hot_x, int hot_y);
+int  photon_showcursor(SDL_Cursor* cursor);
+void photon_movecursor(SDL_Cursor* cursor);
+void photon_freecursor(SDL_Cursor* cursor);
+void photon_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y);
+void photon_freemouse(SDL_Mouse* mouse);
+
+int32_t photon_addinputdevices(_THIS)
+{
+   SDL_VideoData*    phdata=(SDL_VideoData*)_this->driverdata;
+   SDL_DisplayData*  didata=NULL;
+   struct SDL_Mouse  photon_mouse;
+   SDL_MouseData*    mdata=NULL;
+   SDL_Keyboard      photon_keyboard;
+   SDLKey   keymap[SDL_NUM_SCANCODES];
+   uint32_t it;
+
+   for (it=0; it<_this->num_displays; it++)
+   {
+      /* Clear SDL mouse structure */
+      SDL_memset(&photon_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 */
+      photon_mouse.id=it;
+      photon_mouse.driverdata=(void*)mdata;
+      photon_mouse.CreateCursor=photon_createcursor;
+      photon_mouse.ShowCursor=photon_showcursor;
+      photon_mouse.MoveCursor=photon_movecursor;
+      photon_mouse.FreeCursor=photon_freecursor;
+      photon_mouse.WarpMouse=photon_warpmouse;
+      photon_mouse.FreeMouse=photon_freemouse;
+
+      /* Get display data */
+      didata=(SDL_DisplayData*)_this->displays[it].driverdata;
+
+      /* Store SDL_DisplayData pointer in the mouse driver internals */
+      mdata->didata=didata;
+
+      /* Register mouse cursor in SDL */
+      SDL_AddMouse(&photon_mouse, "Photon mouse cursor", 0, 0, 1);
+   }
+
+   /* Photon maps all keyboards to one */
+   SDL_zero(photon_keyboard);
+   SDL_AddKeyboard(&photon_keyboard, -1);
+
+   /* Add default scancode to key mapping */
+   SDL_GetDefaultKeymap(keymap);
+   SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
+
+   return 0;
+}
+
+int32_t photon_delinputdevices(_THIS)
+{
+   /* Destroy all of the mice */
+   SDL_MouseQuit();
+}
+
+/*****************************************************************************/
+/* Photon mouse related functions                                            */
+/*****************************************************************************/
+SDL_Cursor* photon_createcursor(SDL_Surface* surface, int hot_x, int hot_y)
+{
+   PhCursorDef_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("Photon: Cursor shape is not 24/32bpp.");
+      return NULL;
+   }
+
+   /* Checking data parameters */
+   if ((surface->w==0) || (surface->h==0))
+   {
+      SDL_SetError("Photon: Cursor shape dimensions are zero");
+      return NULL;
+   }
+
+   /* Allocate memory for the internal cursor format */
+   internal_cursor=(PhCursorDef_t*)SDL_calloc(1, sizeof(PhCursorDef_t)+
+      ((((surface->w+7)>>3)*surface->h)*2)-1);
+   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;
+   }
+
+   /* Set driverdata as photon cursor format */
+   image0=(uint8_t*)internal_cursor;
+   image0+=sizeof(PhCursorDef_t)-1;
+   image1=image0;
+   image1+=((surface->w+7)>>3)*surface->h;
+   sdl_cursor->driverdata=(void*)internal_cursor;
+   internal_cursor->hdr.len=(sizeof(PhCursorDef_t)-sizeof(PhRegionDataHdr_t))+
+                            ((((surface->w+7)>>3)*surface->h)*2)-1;
+   internal_cursor->hdr.type=Ph_RDATA_CURSOR;
+   internal_cursor->size1.x=surface->w;
+   internal_cursor->size1.y=surface->h;
+   internal_cursor->size2.x=surface->w;
+   internal_cursor->size2.y=surface->h;
+   internal_cursor->offset1.x=hot_x;
+   internal_cursor->offset1.y=hot_y;
+   internal_cursor->offset2.x=hot_x;
+   internal_cursor->offset2.y=hot_y;
+   internal_cursor->bytesperline1=((surface->w+7)>>3);
+   internal_cursor->bytesperline2=((surface->w+7)>>3);
+   internal_cursor->color1=(SDL_PHOTON_MOUSE_COLOR_BLACK) & 0x00FFFFFF;
+   internal_cursor->color2=(SDL_PHOTON_MOUSE_COLOR_WHITE) & 0x00FFFFFF;
+
+   /* 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_PHOTON_MOUSE_COLOR_BLACK:
+                 {
+                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))|=0x80>>(it%8);
+                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))&=~(0x80>>(it%8));
+                 }
+                 break;
+            case SDL_PHOTON_MOUSE_COLOR_WHITE:
+                 {
+                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))&=~(0x80>>(it%8));
+                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))|=0x80>>(it%8);
+                 }
+                 break;
+            case SDL_PHOTON_MOUSE_COLOR_TRANS:
+                 {
+                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))&=~(0x80>>(it%8));
+                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))&=~(0x80>>(it%8));
+                 }
+                 break;
+            default:
+                 {
+                    /* The same as transparent color, must not happen */
+                    *(image0+jt*(internal_cursor->bytesperline1)+(it>>3))&=~(0x80>>(it%8));
+                    *(image1+jt*(internal_cursor->bytesperline2)+(it>>3))&=~(0x80>>(it%8));
+                 }
+                 break;
+         }
+      }
+   }
+
+   return sdl_cursor;
+}
+
+int photon_showcursor(SDL_Cursor* cursor)
+{
+   SDL_VideoDisplay* display;
+   SDL_DisplayData*  didata;
+   SDL_Window*       window;
+   SDL_WindowData*   wdata;
+   SDL_WindowID      window_id;
+   PhCursorDef_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)
+      {
+         /* Store cursor for future usage */
+         mdata=(SDL_MouseData*)cursor->mouse->driverdata;
+         didata=(SDL_DisplayData*)mdata->didata;
+         internal_cursor=(PhCursorDef_t*)cursor->driverdata;
+
+         if (didata->cursor_size>=(internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t)))
+         {
+            SDL_memcpy(didata->cursor, internal_cursor, internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t));
+         }
+         else
+         {
+            /* Partitial cursor image */
+            SDL_memcpy(didata->cursor, internal_cursor, didata->cursor_size);
+         }
+
+         didata->cursor_visible=SDL_TRUE;
+         return 0;
+      }
+      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)
+            {
+               wdata=(SDL_WindowData*)window->driverdata;
+               if (wdata==NULL)
+               {
+                  return -1;
+               }
+            }
+            else
+            {
+               return -1;
+            }
+         }
+         else
+         {
+            return -1;
+         }
+      }
+      else
+      {
+         return -1;
+      }
+   }
+
+   /* return if window widget has been destroyed already */
+   if (wdata->window==NULL)
+   {
+      return;
+   }
+
+   /* Check if we need to set new shape or disable cursor shape */
+   if (cursor!=NULL)
+   {
+      /* Retrieve photon cursor shape */
+      internal_cursor=(PhCursorDef_t*)cursor->driverdata;
+      if (internal_cursor==NULL)
+      {
+         SDL_SetError("Photon: Internal cursor data is absent");
+         return -1;
+      }
+
+      /* Setup cursor type */
+      status=PtSetResource(wdata->window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_BITMAP, 0);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Failed to set cursor type to bitmap");
+         return -1;
+      }
+
+      /* Setup cursor color to default */
+      status=PtSetResource(wdata->window, Pt_ARG_CURSOR_COLOR, Ph_CURSOR_DEFAULT_COLOR, 0);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Failed to set cursor color");
+         return -1;
+      }
+
+      /* Setup cursor shape */
+      status=PtSetResource(wdata->window, Pt_ARG_BITMAP_CURSOR, internal_cursor,
+                           internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t));
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Failed to set cursor color");
+         return -1;
+      }
+
+      /* Store current cursor for future usage */
+      if (didata->cursor_size>=(internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t)))
+      {
+         SDL_memcpy(didata->cursor, internal_cursor, internal_cursor->hdr.len+sizeof(PhRegionDataHdr_t));
+      }
+      else
+      {
+         /* Partitial cursor image */
+         SDL_memcpy(didata->cursor, internal_cursor, didata->cursor_size);
+      }
+
+      /* Set cursor visible */
+      didata->cursor_visible=SDL_TRUE;
+   }
+   else
+   {
+      /* SDL requests to disable cursor */
+      status=PtSetResource(wdata->window, Pt_ARG_CURSOR_TYPE, Ph_CURSOR_NONE, 0);
+      if (status!=0)
+      {
+         SDL_SetError("Photon: Can't disable cursor");
+         return -1;
+      }
+
+      /* Set cursor invisible */
+      didata->cursor_visible=SDL_FALSE;
+   }
+
+   /* Flush all pending widget data */
+   PtFlush();
+
+   /* New cursor shape is set */
+   return 0;
+}
+
+void photon_movecursor(SDL_Cursor* cursor)
+{
+   SDL_VideoDisplay* display;
+   SDL_DisplayData*  didata;
+   SDL_Window*  window;
+   SDL_WindowID window_id;
+   int32_t status;
+
+   /* 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;
+      }
+   }
+
+/*   cursor->mouse->x, cursor->mouse->y */
+}
+
+void photon_freecursor(SDL_Cursor* cursor)
+{
+   PhCursorDef_t* internal_cursor=NULL;
+
+   if (cursor!=NULL)
+   {
+      internal_cursor=(PhCursorDef_t*)cursor->driverdata;
+      if (internal_cursor!=NULL)
+      {
+         SDL_free(internal_cursor);
+         cursor->driverdata=NULL;
+      }
+   }
+}
+
+void photon_warpmouse(SDL_Mouse* mouse, SDL_WindowID windowID, int x, int y)
+{
+   SDL_VideoDisplay* display;
+   SDL_DisplayData*  didata;
+   SDL_Window* window;
+   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;
+   }
+
+}
+
+void photon_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;
+}
+
+SDL_scancode photon_to_sdl_keymap(uint32_t key)
+{
+   SDL_scancode scancode=SDL_SCANCODE_UNKNOWN;
+
+   switch(key & 0x0000007F)
+   {
+      case PHOTON_SCANCODE_ESCAPE:
+           scancode=SDL_SCANCODE_ESCAPE;
+           break;
+      case PHOTON_SCANCODE_F1:
+           scancode=SDL_SCANCODE_F1;
+           break;
+      case PHOTON_SCANCODE_F2:
+           scancode=SDL_SCANCODE_F2;
+           break;
+      case PHOTON_SCANCODE_F3:
+           scancode=SDL_SCANCODE_F3;
+           break;
+      case PHOTON_SCANCODE_F4:
+           scancode=SDL_SCANCODE_F4;
+           break;
+      case PHOTON_SCANCODE_F5:
+           scancode=SDL_SCANCODE_F5;
+           break;
+      case PHOTON_SCANCODE_F6:
+           scancode=SDL_SCANCODE_F6;
+           break;
+      case PHOTON_SCANCODE_F7:
+           scancode=SDL_SCANCODE_F7;
+           break;
+      case PHOTON_SCANCODE_F8:
+           scancode=SDL_SCANCODE_F8;
+           break;
+      case PHOTON_SCANCODE_F9:
+           scancode=SDL_SCANCODE_F9;
+           break;
+      case PHOTON_SCANCODE_F10:
+           scancode=SDL_SCANCODE_F10;
+           break;
+      case PHOTON_SCANCODE_F11:
+           scancode=SDL_SCANCODE_F11;
+           break;
+      case PHOTON_SCANCODE_F12:
+           scancode=SDL_SCANCODE_F12;
+           break;
+      case PHOTON_SCANCODE_BACKQOUTE:
+           scancode=SDL_SCANCODE_GRAVE;
+           break;
+      case PHOTON_SCANCODE_1:
+           scancode=SDL_SCANCODE_1;
+           break;
+      case PHOTON_SCANCODE_2:
+           scancode=SDL_SCANCODE_2;
+           break;
+      case PHOTON_SCANCODE_3:
+           scancode=SDL_SCANCODE_3;
+           break;
+      case PHOTON_SCANCODE_4:
+           scancode=SDL_SCANCODE_4;
+           break;
+      case PHOTON_SCANCODE_5:
+           scancode=SDL_SCANCODE_5;
+           break;
+      case PHOTON_SCANCODE_6:
+           scancode=SDL_SCANCODE_6;
+           break;
+      case PHOTON_SCANCODE_7:
+           scancode=SDL_SCANCODE_7;
+           break;
+      case PHOTON_SCANCODE_8:
+           scancode=SDL_SCANCODE_8;
+           break;
+      case PHOTON_SCANCODE_9:
+           scancode=SDL_SCANCODE_9;
+           break;
+      case PHOTON_SCANCODE_0:
+           scancode=SDL_SCANCODE_0;
+           break;
+      case PHOTON_SCANCODE_MINUS:
+           scancode=SDL_SCANCODE_MINUS;
+           break;
+      case PHOTON_SCANCODE_EQUAL:
+           scancode=SDL_SCANCODE_EQUALS;
+           break;
+      case PHOTON_SCANCODE_BACKSPACE:
+           scancode=SDL_SCANCODE_BACKSPACE;
+           break;
+      case PHOTON_SCANCODE_TAB:
+           scancode=SDL_SCANCODE_TAB;
+           break;
+      case PHOTON_SCANCODE_Q:
+           scancode=SDL_SCANCODE_Q;
+           break;
+      case PHOTON_SCANCODE_W:
+           scancode=SDL_SCANCODE_W;
+           break;
+      case PHOTON_SCANCODE_E:
+           scancode=SDL_SCANCODE_E;
+           break;
+      case PHOTON_SCANCODE_R:
+           scancode=SDL_SCANCODE_R;
+           break;
+      case PHOTON_SCANCODE_T:
+           scancode=SDL_SCANCODE_T;
+           break;
+      case PHOTON_SCANCODE_Y:
+           scancode=SDL_SCANCODE_Y;
+           break;
+      case PHOTON_SCANCODE_U:
+           scancode=SDL_SCANCODE_U;
+           break;
+      case PHOTON_SCANCODE_I:
+           scancode=SDL_SCANCODE_I;
+           break;
+      case PHOTON_SCANCODE_O:
+           scancode=SDL_SCANCODE_O;
+           break;
+      case PHOTON_SCANCODE_P:
+           scancode=SDL_SCANCODE_P;
+           break;
+      case PHOTON_SCANCODE_LEFT_SQ_BR:
+           scancode=SDL_SCANCODE_LEFTBRACKET;
+           break;
+      case PHOTON_SCANCODE_RIGHT_SQ_BR:
+           scancode=SDL_SCANCODE_RIGHTBRACKET;
+           break;
+      case PHOTON_SCANCODE_ENTER:
+           scancode=SDL_SCANCODE_RETURN;
+           break;
+      case PHOTON_SCANCODE_CAPSLOCK:
+           scancode=SDL_SCANCODE_CAPSLOCK;
+           break;
+      case PHOTON_SCANCODE_A:
+           scancode=SDL_SCANCODE_A;
+           break;
+      case PHOTON_SCANCODE_S:
+           scancode=SDL_SCANCODE_S;
+           break;
+      case PHOTON_SCANCODE_D:
+           scancode=SDL_SCANCODE_D;
+           break;
+      case PHOTON_SCANCODE_F:
+           scancode=SDL_SCANCODE_F;
+           break;
+      case PHOTON_SCANCODE_G:
+           scancode=SDL_SCANCODE_G;
+           break;
+      case PHOTON_SCANCODE_H:
+           scancode=SDL_SCANCODE_H;
+           break;
+      case PHOTON_SCANCODE_J:
+           scancode=SDL_SCANCODE_J;
+           break;
+      case PHOTON_SCANCODE_K:
+           scancode=SDL_SCANCODE_K;
+           break;
+      case PHOTON_SCANCODE_L:
+           scancode=SDL_SCANCODE_L;
+           break;
+      case PHOTON_SCANCODE_SEMICOLON:
+           scancode=SDL_SCANCODE_SEMICOLON;
+           break;
+      case PHOTON_SCANCODE_QUOTE:
+           scancode=SDL_SCANCODE_APOSTROPHE;
+           break;
+      case PHOTON_SCANCODE_BACKSLASH:
+           scancode=SDL_SCANCODE_BACKSLASH;
+           break;
+      case PHOTON_SCANCODE_LEFT_SHIFT:
+           scancode=SDL_SCANCODE_LSHIFT;
+           break;
+      case PHOTON_SCANCODE_Z:
+           scancode=SDL_SCANCODE_Z;
+           break;
+      case PHOTON_SCANCODE_X:
+           scancode=SDL_SCANCODE_X;
+           break;
+      case PHOTON_SCANCODE_C:
+           scancode=SDL_SCANCODE_C;
+           break;
+      case PHOTON_SCANCODE_V:
+           scancode=SDL_SCANCODE_V;
+           break;
+      case PHOTON_SCANCODE_B:
+           scancode=SDL_SCANCODE_B;
+           break;
+      case PHOTON_SCANCODE_N:
+           scancode=SDL_SCANCODE_N;
+           break;
+      case PHOTON_SCANCODE_M:
+           scancode=SDL_SCANCODE_M;
+           break;
+      case PHOTON_SCANCODE_COMMA:
+           scancode=SDL_SCANCODE_COMMA;
+           break;
+      case PHOTON_SCANCODE_POINT:
+           scancode=SDL_SCANCODE_PERIOD;
+           break;
+      case PHOTON_SCANCODE_SLASH:
+           scancode=SDL_SCANCODE_SLASH;
+           break;
+      case PHOTON_SCANCODE_RIGHT_SHIFT:
+           scancode=SDL_SCANCODE_RSHIFT;
+           break;
+      case PHOTON_SCANCODE_CTRL:
+           scancode=SDL_SCANCODE_LCTRL;
+           break;
+      case PHOTON_SCANCODE_WFLAG:
+           scancode=SDL_SCANCODE_LGUI;
+           break;
+      case PHOTON_SCANCODE_ALT:
+           scancode=SDL_SCANCODE_LALT;
+           break;
+      case PHOTON_SCANCODE_SPACE:
+           scancode=SDL_SCANCODE_SPACE;
+           break;
+      case PHOTON_SCANCODE_MENU:
+           scancode=SDL_SCANCODE_MENU;
+           break;
+      case PHOTON_SCANCODE_PRNSCR:
+           scancode=SDL_SCANCODE_PRINTSCREEN;
+           break;
+      case PHOTON_SCANCODE_SCROLLLOCK:
+           scancode=SDL_SCANCODE_SCROLLLOCK;
+           break;
+      case PHOTON_SCANCODE_INSERT:
+           scancode=SDL_SCANCODE_INSERT;
+           break;
+      case PHOTON_SCANCODE_HOME:
+           scancode=SDL_SCANCODE_HOME;
+           break;
+      case PHOTON_SCANCODE_PAGEUP:
+           scancode=SDL_SCANCODE_PAGEUP;
+           break;
+      case PHOTON_SCANCODE_DELETE:
+           scancode=SDL_SCANCODE_DELETE;
+           break;
+      case PHOTON_SCANCODE_END:
+           scancode=SDL_SCANCODE_END;
+           break;
+      case PHOTON_SCANCODE_PAGEDOWN:
+           scancode=SDL_SCANCODE_PAGEDOWN;
+           break;
+      case PHOTON_SCANCODE_UP:
+           scancode=SDL_SCANCODE_UP;
+           break;
+      case PHOTON_SCANCODE_DOWN:
+           scancode=SDL_SCANCODE_DOWN;
+           break;
+      case PHOTON_SCANCODE_LEFT:
+           scancode=SDL_SCANCODE_LEFT;
+           break;
+      case PHOTON_SCANCODE_RIGHT:
+           scancode=SDL_SCANCODE_RIGHT;
+           break;
+      case PHOTON_SCANCODE_NUMLOCK:
+           scancode=SDL_SCANCODE_NUMLOCKCLEAR;
+           break;
+      default:
+           break;
+   }
+
+   return scancode;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/photon/SDL_photon_input.h	Tue Apr 28 04:30:52 2009 +0000
@@ -0,0 +1,50 @@
+/*
+    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 Photon GUI SDL driver
+    Copyright (C) 2009 Mike Gorchak
+    (mike@malva.ua, lestat@i.com.ua)
+*/
+
+#ifndef __SDL_PHOTON_INPUT_H__
+#define __SDL_PHOTON_INPUT_H__
+
+#include "SDL_config.h"
+#include "SDL_video.h"
+#include "../SDL_sysvideo.h"
+
+#include "SDL_photon.h"
+
+typedef struct SDL_MouseData
+{
+   SDL_DisplayData* didata;
+} SDL_MouseData;
+
+int32_t photon_addinputdevices(_THIS);
+int32_t photon_delinputdevices(_THIS);
+
+#define SDL_PHOTON_MOUSE_COLOR_BLACK 0xFF000000
+#define SDL_PHOTON_MOUSE_COLOR_WHITE 0xFFFFFFFF
+#define SDL_PHOTON_MOUSE_COLOR_TRANS 0x00000000
+
+SDL_scancode photon_to_sdl_keymap(uint32_t key);
+
+#endif /* __SDL_GF_INPUT_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/photon/SDL_photon_keycodes.h	Tue Apr 28 04:30:52 2009 +0000
@@ -0,0 +1,123 @@
+/*
+    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 Photon GUI SDL driver
+    Copyright (C) 2009 Mike Gorchak
+    (mike@malva.ua, lestat@i.com.ua)
+*/
+
+#ifndef __SDL_PHOTON_KEYCODES_H__
+#define __SDL_PHOTON_KEYCODES_H__
+
+#define PHOTON_SCANCODE_ESCAPE      0x01
+#define PHOTON_SCANCODE_F1          0x3B
+#define PHOTON_SCANCODE_F2          0x3C
+#define PHOTON_SCANCODE_F3          0x3D
+#define PHOTON_SCANCODE_F4          0x3E
+#define PHOTON_SCANCODE_F5          0x3F
+#define PHOTON_SCANCODE_F6          0x40
+#define PHOTON_SCANCODE_F7          0x41
+#define PHOTON_SCANCODE_F8          0x42
+#define PHOTON_SCANCODE_F9          0x43
+#define PHOTON_SCANCODE_F10         0x44
+#define PHOTON_SCANCODE_F11         0x57
+#define PHOTON_SCANCODE_F12         0x58
+
+#define PHOTON_SCANCODE_BACKQOUTE   0x29
+#define PHOTON_SCANCODE_1           0x02
+#define PHOTON_SCANCODE_2           0x03
+#define PHOTON_SCANCODE_3           0x04
+#define PHOTON_SCANCODE_4           0x05
+#define PHOTON_SCANCODE_5           0x06
+#define PHOTON_SCANCODE_6           0x07
+#define PHOTON_SCANCODE_7           0x08
+#define PHOTON_SCANCODE_8           0x09
+#define PHOTON_SCANCODE_9           0x0A
+#define PHOTON_SCANCODE_0           0x0B
+#define PHOTON_SCANCODE_MINUS       0x0C
+#define PHOTON_SCANCODE_EQUAL       0x0D
+#define PHOTON_SCANCODE_BACKSPACE   0x0E
+
+#define PHOTON_SCANCODE_TAB         0x0F
+#define PHOTON_SCANCODE_Q           0x10
+#define PHOTON_SCANCODE_W           0x11
+#define PHOTON_SCANCODE_E           0x12
+#define PHOTON_SCANCODE_R           0x13
+#define PHOTON_SCANCODE_T           0x14
+#define PHOTON_SCANCODE_Y           0x15
+#define PHOTON_SCANCODE_U           0x16
+#define PHOTON_SCANCODE_I           0x17
+#define PHOTON_SCANCODE_O           0x18
+#define PHOTON_SCANCODE_P           0x19
+#define PHOTON_SCANCODE_LEFT_SQ_BR  0x1A
+#define PHOTON_SCANCODE_RIGHT_SQ_BR 0x1B
+#define PHOTON_SCANCODE_ENTER       0x1C
+
+#define PHOTON_SCANCODE_CAPSLOCK    0x3A
+#define PHOTON_SCANCODE_A           0x1E
+#define PHOTON_SCANCODE_S           0x1F
+#define PHOTON_SCANCODE_D           0x20
+#define PHOTON_SCANCODE_F           0x21
+#define PHOTON_SCANCODE_G           0x22
+#define PHOTON_SCANCODE_H           0x23
+#define PHOTON_SCANCODE_J           0x24
+#define PHOTON_SCANCODE_K           0x25
+#define PHOTON_SCANCODE_L           0x26
+#define PHOTON_SCANCODE_SEMICOLON   0x27
+#define PHOTON_SCANCODE_QUOTE       0x28
+#define PHOTON_SCANCODE_BACKSLASH   0x2B
+
+#define PHOTON_SCANCODE_LEFT_SHIFT  0x2A
+#define PHOTON_SCANCODE_Z           0x2C
+#define PHOTON_SCANCODE_X           0x2D
+#define PHOTON_SCANCODE_C           0x2E
+#define PHOTON_SCANCODE_V           0x2F
+#define PHOTON_SCANCODE_B           0x30
+#define PHOTON_SCANCODE_N           0x31
+#define PHOTON_SCANCODE_M           0x32
+#define PHOTON_SCANCODE_COMMA       0x33
+#define PHOTON_SCANCODE_POINT       0x34
+#define PHOTON_SCANCODE_SLASH       0x35
+#define PHOTON_SCANCODE_RIGHT_SHIFT 0x36
+
+#define PHOTON_SCANCODE_CTRL        0x1D
+#define PHOTON_SCANCODE_WFLAG       0x5B
+#define PHOTON_SCANCODE_ALT         0x38
+#define PHOTON_SCANCODE_SPACE       0x39
+#define PHOTON_SCANCODE_MENU        0x5D
+
+#define PHOTON_SCANCODE_PRNSCR      0x54   /* only key pressed event, no release */
+#define PHOTON_SCANCODE_SCROLLLOCK  0x46
+/* #define PHOTON_SCANCODE_PAUSE 0x?? */   /* pause doesn't generates a scancode */
+#define PHOTON_SCANCODE_INSERT      0x52
+#define PHOTON_SCANCODE_HOME        0x47
+#define PHOTON_SCANCODE_PAGEUP      0x49
+#define PHOTON_SCANCODE_DELETE      0x53
+#define PHOTON_SCANCODE_END         0x4F
+#define PHOTON_SCANCODE_PAGEDOWN    0x51
+#define PHOTON_SCANCODE_UP          0x48
+#define PHOTON_SCANCODE_DOWN        0x50
+#define PHOTON_SCANCODE_LEFT        0x4B
+#define PHOTON_SCANCODE_RIGHT       0x4D
+
+#define PHOTON_SCANCODE_NUMLOCK     0x45
+
+#endif /* __SDL_PHOTON_KEYCODES_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/photon/SDL_photon_pixelfmt.c	Tue Apr 28 04:30:52 2009 +0000
@@ -0,0 +1,198 @@
+/*
+    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 Photon GUI SDL driver
+    Copyright (C) 2009 Mike Gorchak
+    (mike@malva.ua, lestat@i.com.ua)
+*/
+
+#include "SDL_photon_pixelfmt.h"
+
+uint32_t photon_bits_to_sdl_pixelformat(uint32_t pixelfmt)
+{
+   switch(pixelfmt)
+   {
+      case 8:
+           {
+              return SDL_PIXELFORMAT_INDEX8;
+           }
+           break;
+      case 15:
+           {
+              return SDL_PIXELFORMAT_ARGB1555;
+           }
+           break;
+      case 16:
+           {
+              return SDL_PIXELFORMAT_RGB565;
+           }
+           break;
+      case 24:
+           {
+              return SDL_PIXELFORMAT_RGB888;
+           }
+           break;
+      case 32:
+           {
+              return SDL_PIXELFORMAT_ARGB8888;
+           }
+           break;
+   }
+}
+
+uint32_t photon_sdl_to_bits_pixelformat(uint32_t pixelfmt)
+{
+   switch(pixelfmt)
+   {
+      case SDL_PIXELFORMAT_INDEX8:
+           {
+              return 8;
+           }
+           break;
+      case SDL_PIXELFORMAT_ARGB1555:
+           {
+              return 15;
+           }
+           break;
+      case SDL_PIXELFORMAT_ABGR1555:
+           {
+              return 15;
+           }
+           break;
+      case SDL_PIXELFORMAT_RGB565:
+           {
+              return 16;
+           }
+           break;
+      case SDL_PIXELFORMAT_RGB888:
+           {
+              return 24;
+           }
+           break;
+      case SDL_PIXELFORMAT_BGRA8888:
+           {
+              return 32;
+           }
+           break;
+      case SDL_PIXELFORMAT_ARGB8888:
+           {
+              return 32;
+           }
+           break;
+      case SDL_PIXELFORMAT_YV12:
+           {
+              return 8;
+           }
+           break;
+      case SDL_PIXELFORMAT_YUY2:
+           {
+              return 16;
+           }
+           break;
+      case SDL_PIXELFORMAT_UYVY:
+           {
+              return 16;
+           }
+           break;
+      case SDL_PIXELFORMAT_YVYU:
+           {
+              return 16;
+           }
+           break;
+   }
+
+   return 0;
+}
+
+uint32_t photon_image_to_sdl_pixelformat(uint32_t pixelfmt)
+{
+   switch(pixelfmt)
+   {
+      case Pg_IMAGE_PALETTE_BYTE:
+           {
+              return SDL_PIXELFORMAT_INDEX8;
+           }
+           break;
+      case Pg_IMAGE_DIRECT_8888:
+           {
+              return SDL_PIXELFORMAT_BGRA8888;
+           }
+           break;
+      case Pg_IMAGE_DIRECT_888:
+           {
+              return SDL_PIXELFORMAT_RGB888;
+           }
+           break;
+      case Pg_IMAGE_DIRECT_565:
+           {
+              return SDL_PIXELFORMAT_RGB565;
+           }
+           break;
+      case Pg_IMAGE_DIRECT_555:
+           {
+              return SDL_PIXELFORMAT_RGB555;
+           }
+           break;
+      case Pg_IMAGE_DIRECT_1555:
+           {
+              return SDL_PIXELFORMAT_ARGB1555;
+           }
+           break;
+   }
+
+   return 0;
+}
+
+uint32_t photon_sdl_to_image_pixelformat(uint32_t pixelfmt)
+{
+   switch(pixelfmt)
+   {
+      case SDL_PIXELFORMAT_INDEX8:
+           {
+              return Pg_IMAGE_PALETTE_BYTE;
+           }
+           break;
+      case SDL_PIXELFORMAT_BGRA8888:
+           {
+              return Pg_IMAGE_DIRECT_8888;
+           }
+           break;
+      case SDL_PIXELFORMAT_RGB888:
+           {
+              return Pg_IMAGE_DIRECT_888;
+           }
+           break;
+      case SDL_PIXELFORMAT_RGB565:
+           {
+              return Pg_IMAGE_DIRECT_565;
+           }
+           break;
+      case SDL_PIXELFORMAT_ARGB1555:
+           {
+              return Pg_IMAGE_DIRECT_1555;
+           }
+           break;
+   }
+
+   return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/photon/SDL_photon_pixelfmt.h	Tue Apr 28 04:30:52 2009 +0000
@@ -0,0 +1,42 @@
+/*
+    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 Photon GUI SDL driver
+    Copyright (C) 2009 Mike Gorchak
+    (mike@malva.ua, lestat@i.com.ua)
+*/
+
+#include "SDL_config.h"
+#include "../SDL_sysvideo.h"
+
+#include <Ph.h>
+
+#ifndef __SDL_PHOTON_PIXELFMT_H__
+#define __SDL_PHOTON_PIXELFMT_H__
+
+uint32_t photon_bits_to_sdl_pixelformat(uint32_t pixelfmt);
+uint32_t photon_sdl_to_bits_pixelformat(uint32_t pixelfmt);
+uint32_t photon_image_to_sdl_pixelformat(uint32_t pixelfmt);
+uint32_t photon_sdl_to_image_pixelformat(uint32_t pixelfmt);
+
+#endif /* __SDL_PHOTON_PIXELFMT_H__ */
+
+/* vi: set ts=4 sw=4 expandtab: */
--- a/src/video/photon/SDL_photon_render.c	Fri Apr 24 03:46:54 2009 +0000
+++ b/src/video/photon/SDL_photon_render.c	Tue Apr 28 04:30:52 2009 +0000
@@ -35,24 +35,24 @@
 #include "SDL_photon.h"
 
 static SDL_Renderer* photon_createrenderer(SDL_Window* window, Uint32 flags);
-static int photon_displaymodechanged(SDL_Renderer* renderer);
-static int photon_activaterenderer(SDL_Renderer* renderer);
-static int photon_createtexture(SDL_Renderer* renderer, SDL_Texture* texture);
-static int photon_querytexturepixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch);
-static int photon_settexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Color* colors, int firstcolor, int ncolors);
-static int photon_gettexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Color* colors, int firstcolor, int ncolors);
-static int photon_settexturecolormod(SDL_Renderer* renderer, SDL_Texture* texture);
-static int photon_settexturealphamod(SDL_Renderer* renderer, SDL_Texture* texture);
-static int photon_settextureblendmode(SDL_Renderer* renderer, SDL_Texture* texture);
-static int photon_settexturescalemode(SDL_Renderer* renderer, SDL_Texture* texture);
-static int photon_updatetexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, const void* pixels, int pitch);
-static int photon_locktexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, int markDirty, void** pixels, int* pitch);
+static int  photon_displaymodechanged(SDL_Renderer* renderer);
+static int  photon_activaterenderer(SDL_Renderer* renderer);
+static int  photon_createtexture(SDL_Renderer* renderer, SDL_Texture* texture);
+static int  photon_querytexturepixels(SDL_Renderer* renderer, SDL_Texture* texture, void** pixels, int* pitch);
+static int  photon_settexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Color* colors, int firstcolor, int ncolors);
+static int  photon_gettexturepalette(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Color* colors, int firstcolor, int ncolors);
+static int  photon_settexturecolormod(SDL_Renderer* renderer, SDL_Texture* texture);
+static int  photon_settexturealphamod(SDL_Renderer* renderer, SDL_Texture* texture);
+static int  photon_settextureblendmode(SDL_Renderer* renderer, SDL_Texture* texture);
+static int  photon_settexturescalemode(SDL_Renderer* renderer, SDL_Texture* texture);
+static int  photon_updatetexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, const void* pixels, int pitch);
+static int  photon_locktexture(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* rect, int markDirty, void** pixels, int* pitch);
 static void photon_unlocktexture(SDL_Renderer* renderer, SDL_Texture* texture);
 static void photon_dirtytexture(SDL_Renderer* renderer, SDL_Texture* texture, int numrects, const SDL_Rect* rects);
-static int photon_renderpoint(SDL_Renderer* renderer, int x, int y);
-static int photon_renderline(SDL_Renderer* renderer, int x1, int y1, int x2, int y2);
-static int photon_renderfill(SDL_Renderer* renderer, const SDL_Rect* rect);
-static int photon_rendercopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect);
+static int  photon_renderpoint(SDL_Renderer* renderer, int x, int y);
+static int  photon_renderline(SDL_Renderer* renderer, int x1, int y1, int x2, int y2);
+static int  photon_renderfill(SDL_Renderer* renderer, const SDL_Rect* rect);
+static int  photon_rendercopy(SDL_Renderer* renderer, SDL_Texture* texture, const SDL_Rect* srcrect, const SDL_Rect* dstrect);
 static void photon_renderpresent(SDL_Renderer* renderer);
 static void photon_destroytexture(SDL_Renderer* renderer, SDL_Texture* texture);
 static void photon_destroyrenderer(SDL_Renderer* renderer);