From 5ccd5e63c829a7b36be7f5a21e4d63cbfc24de4a Mon Sep 17 00:00:00 2001 From: Mike Gorchak Date: Tue, 28 Apr 2009 04:30:52 +0000 Subject: [PATCH] Continue working on QNX Photon with OpenGL ES support --- src/video/photon/SDL_photon.c | 2234 +++++++++++++++++++++++- src/video/photon/SDL_photon.h | 72 +- src/video/photon/SDL_photon_input.c | 735 ++++++++ src/video/photon/SDL_photon_input.h | 50 + src/video/photon/SDL_photon_keycodes.h | 123 ++ src/video/photon/SDL_photon_pixelfmt.c | 198 +++ src/video/photon/SDL_photon_pixelfmt.h | 42 + src/video/photon/SDL_photon_render.c | 32 +- 8 files changed, 3426 insertions(+), 60 deletions(-) create mode 100644 src/video/photon/SDL_photon_input.c create mode 100644 src/video/photon/SDL_photon_input.h create mode 100644 src/video/photon/SDL_photon_keycodes.h create mode 100644 src/video/photon/SDL_photon_pixelfmt.c create mode 100644 src/video/photon/SDL_photon_pixelfmt.h diff --git a/src/video/photon/SDL_photon.c b/src/video/photon/SDL_photon.c index ec647d02d..84525738c 100644 --- a/src/video/photon/SDL_photon.c +++ b/src/video/photon/SDL_photon.c @@ -24,16 +24,105 @@ (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 */ + +/* 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; static int photon_available(void) @@ -62,13 +151,26 @@ static int photon_available(void) 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 @@ static SDL_VideoDevice* photon_create(int devindex) 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 @@ static SDL_VideoDevice* photon_create(int devindex) } 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 @@ VideoBootStrap photon_bootstrap= /*****************************************************************************/ 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; itavail_rids; it++) + { + didata=(SDL_DisplayData*)SDL_calloc(1, sizeof(SDL_DisplayData)); + if (didata==NULL) + { + /* memory allocation error */ + SDL_OutOfMemory(); + return -1; + } - /* 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; -// } -// } + /* 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; + + /* 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 @@ int photon_videoinit(_THIS) void photon_videoquit(_THIS) { + SDL_VideoData* phdata=(SDL_VideoData*)_this->driverdata; SDL_DisplayData* didata; uint32_t it; @@ -143,19 +458,270 @@ void photon_videoquit(_THIS) 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; itcurrent_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; itw) && + (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; itw) && + (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; itw) && (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_getdisplaygammaramp(_THIS, Uint16* ramp) 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 @@ int photon_createwindow(_THIS, SDL_Window* window) /* 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 @@ SDL_bool photon_getwindowwminfo(_THIS, SDL_Window* window, struct SDL_SysWMinfo* /*****************************************************************************/ 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; citgl_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_gl_deletecontext(_THIS, SDL_GLContext context) /*****************************************************************************/ 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; itwindow!=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; itbuttons)*8; it++) + { + if ((pevent->buttons&(0x0001<buttons)*8; it++) + { + if ((pevent->buttons&(0x0001<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; itnum_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); } /*****************************************************************************/ diff --git a/src/video/photon/SDL_photon.h b/src/video/photon/SDL_photon.h index e76692c07..319173117 100644 --- a/src/video/photon/SDL_photon.h +++ b/src/video/photon/SDL_photon.h @@ -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 + #include +#endif /* SDL_VIDEO_OPENGL_ES */ + +#include "SDL_config.h" #include "../SDL_sysvideo.h" #include +#include +#include + +/* 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 @@ typedef struct Photon_DeviceCaps #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); diff --git a/src/video/photon/SDL_photon_input.c b/src/video/photon/SDL_photon_input.c new file mode 100644 index 000000000..0729523e6 --- /dev/null +++ b/src/video/photon/SDL_photon_input.c @@ -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; jth; jt++) + { + for (it=0; itw; it++) + { + shape_color=*((uint32_t*)((uint8_t*)surface->pixels+jt*surface->pitch+it*surface->format->BytesPerPixel)); + switch(shape_color) + { + case SDL_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; +} diff --git a/src/video/photon/SDL_photon_input.h b/src/video/photon/SDL_photon_input.h new file mode 100644 index 000000000..72caf978e --- /dev/null +++ b/src/video/photon/SDL_photon_input.h @@ -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__ */ diff --git a/src/video/photon/SDL_photon_keycodes.h b/src/video/photon/SDL_photon_keycodes.h new file mode 100644 index 000000000..c798f689f --- /dev/null +++ b/src/video/photon/SDL_photon_keycodes.h @@ -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__ */ diff --git a/src/video/photon/SDL_photon_pixelfmt.c b/src/video/photon/SDL_photon_pixelfmt.c new file mode 100644 index 000000000..2ba1de353 --- /dev/null +++ b/src/video/photon/SDL_photon_pixelfmt.c @@ -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: */ diff --git a/src/video/photon/SDL_photon_pixelfmt.h b/src/video/photon/SDL_photon_pixelfmt.h new file mode 100644 index 000000000..1bf494862 --- /dev/null +++ b/src/video/photon/SDL_photon_pixelfmt.h @@ -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 + +#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: */ diff --git a/src/video/photon/SDL_photon_render.c b/src/video/photon/SDL_photon_render.c index e15215295..feb7814c5 100644 --- a/src/video/photon/SDL_photon_render.c +++ b/src/video/photon/SDL_photon_render.c @@ -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);