Mercurial > sdl-ios-xcode
diff src/video/photon/SDL_photon.c @ 3108:aa1897bee1e9
Continue working on QNX Photon with OpenGL ES support
author | Mike Gorchak <lestat@i.com.ua> |
---|---|
date | Tue, 28 Apr 2009 04:30:52 +0000 |
parents | cad1aefa2ed9 |
children | 1102a3305928 |
line wrap: on
line diff
--- 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); } /*****************************************************************************/