From 70eef55ab58313312d7f3468c6457b72f6694239 Mon Sep 17 00:00:00 2001 From: Scott Smith Date: Sat, 12 Oct 2013 12:31:20 -0400 Subject: [PATCH] OpenGL-ES converstion Specific device options for pandora, gcw, gph --- src/backends/egl/eglport.c | 701 +++++++++++++++++++++++++++++++++++++ src/backends/egl/eglport.h | 105 ++++++ src/backends/egl/in_gph.c | 359 +++++++++++++++++++ src/backends/egl/in_gph.h | 104 ++++++ 4 files changed, 1269 insertions(+) create mode 100644 src/backends/egl/eglport.c create mode 100644 src/backends/egl/eglport.h create mode 100755 src/backends/egl/in_gph.c create mode 100755 src/backends/egl/in_gph.h diff --git a/src/backends/egl/eglport.c b/src/backends/egl/eglport.c new file mode 100644 index 00000000..1cc2c87e --- /dev/null +++ b/src/backends/egl/eglport.c @@ -0,0 +1,701 @@ +/** + * + * EGLPORT.C + * Copyright (C) 2011-2013 Scott R. Smith + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "eglport.h" + +#include +#include +#include + +#if defined(USE_EGL_SDL) +#include "SDL.h" +#include "SDL_syswm.h" +SDL_SysWMinfo sysWmInfo; /** Holds our X Display/Window information */ +#endif /* USE_EGL_SDL */ + +#if defined(PANDORA) /* Pandora VSync Support */ +#include +#include +#include +#include + +#ifndef FBIO_WAITFORVSYNC +#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32) +#endif +int fbdev = -1; + +#elif defined(RPI) +#include "bcm_host.h" + +#endif + +enum EGL_RENDER_T { + RENDER_RAW=0, /** Sets render mode to raw or framebuffer mode. */ + RENDER_SDL, /** Sets render mode to X11/SDL mode. */ + RENDER_TOTAL +}; + +enum EGL_SETTINGS_T { + CFG_MODE=0, /** Render mode for EGL 0=RAW 1=SDL. */ + CFG_VSYNC, /** Controls system vsync if available. */ + CFG_FSAA, /** Number of samples for full screen AA. 0 is off, 2/4 samples. */ + CFG_FPS, /** Calculate and report frame per second. */ + CFG_RED_SIZE, /** Number of bits of Red in the color buffer. */ + CFG_GREEN_SIZE, /** Number of bits of Green in the color buffer. */ + CFG_BLUE_SIZE, /** Number of bits of Blue in the color buffer. */ + CFG_ALPHA_SIZE, /** Number of bits of Alpha in the color buffer. */ + CFG_DEPTH_SIZE, /** Number of bits of Z in the depth buffer. */ + CFG_BUFFER_SIZE, /** The total color component bits in the color buffer. */ + CFG_STENCIL_SIZE, /** Number of bits of Stencil in the stencil buffer. */ + CFG_TOTAL /** Total number of settings. */ +}; + +NativeDisplayType nativeDisplay = 0; /** Reference to the systems native display */ +NativeWindowType nativeWindow = 0; /** Reference to the systems native window */ +EGLint eglSettings[CFG_TOTAL]; /** Stores setting values. */ +EGLDisplay eglDisplay = NULL; /** Reference to the EGL display */ +EGLConfig eglConfig = NULL; /** Reference to the EGL config */ +EGLContext eglContext = NULL; /** Reference to the EGL context */ +EGLSurface eglSurface = NULL; /** Reference to the EGL surface */ + +#define totalConfigsIn 5 /** Total number of configurations to request */ +EGLint totalConfigsFound = 0; /** Total number of configurations matching attributes */ +EGLConfig eglConfigs[totalConfigsIn]; /** Structure containing references to matching configurations */ + +uint32_t fpsCount = 0; /** Total number of frames counted */ +uint32_t fpsTime = 0; /** Start time of frame count measurment */ + +/** Private API */ +void OpenCfg ( const char* file ); +int8_t ConfigureEGL ( EGLConfig config ); +int8_t FindEGLConfigs ( void ); +int8_t CheckEGLErrors ( const char* file, uint16_t line ); + +int8_t GetNativeDisplay ( void ); +int8_t GetNativeWindow ( uint16_t width, uint16_t height ); +void FreeNativeDisplay ( void ); +void FreeNativeWindow ( void ); + +void Platform_Open ( void ); +void Platform_Close ( void ); +void Platform_VSync ( void ); +uint32_t Platform_GetTicks ( void ); + +/** @brief Release all EGL and system resources + */ +void EGL_Close( void ) +{ + /* Release EGL resources */ + if (eglDisplay != NULL) + { + peglMakeCurrent( eglDisplay, NULL, NULL, EGL_NO_CONTEXT ); + if (eglContext != NULL) { + peglDestroyContext( eglDisplay, eglContext ); + } + if (eglSurface != NULL) { + peglDestroySurface( eglDisplay, eglSurface ); + } + peglTerminate( eglDisplay ); + } + + eglSurface = NULL; + eglContext = NULL; + eglDisplay = NULL; + + /* Release platform resources */ + FreeNativeWindow(); + FreeNativeDisplay(); + Platform_Close(); + + CheckEGLErrors( __FILE__, __LINE__ ); + + printf( "EGLport: Closed\n" ); +} + +/** @brief Swap the surface buffer onto the display + */ +void EGL_SwapBuffers( void ) +{ + if (eglSettings[CFG_VSYNC] != 0) { + Platform_VSync(); + } + + peglSwapBuffers( eglDisplay, eglSurface ); + + if (eglSettings[CFG_FPS] != 0) { + fpsCount++; + + if (fpsTime - Platform_GetTicks() >= 1000) + { + printf( "EGLport: %d fps\n", fpsCount ); + fpsTime = Platform_GetTicks(); + fpsCount = 0; + } + } +} + +/** @brief Obtain the system display and initialize EGL + * @param width : desired pixel width of the window (not used by all platforms) + * @param height : desired pixel height of the window (not used by all platforms) + * @return : 0 if the function passed, else 1 + */ +int8_t EGL_Open( uint16_t width, uint16_t height ) +{ + EGLint eglMajorVer, eglMinorVer; + EGLBoolean result; + uint32_t configIndex = 0; + const char* output; + + static const EGLint contextAttribs[] = + { +#if defined(USE_GLES2) + EGL_CONTEXT_CLIENT_VERSION, 2, +#endif + EGL_NONE + }; + +#if defined(DEBUG) + printf( "EGLport Warning: DEBUG is enabled which may effect performance\n" ); +#endif + + /* Check that system is not open */ + if (eglDisplay != NULL || eglContext != NULL || eglSurface != NULL) + { + printf( "EGLport Warning: EGL system is already open!\n" ); + peglMakeCurrent( eglDisplay, NULL, NULL, EGL_NO_CONTEXT ); + peglDestroyContext( eglDisplay, eglContext ); + peglDestroySurface( eglDisplay, eglSurface ); + peglTerminate( eglDisplay ); + + eglSurface = NULL; + eglContext = NULL; + eglDisplay = NULL; + } + else + { + /* Check for the cfg file to alternative settings */ + OpenCfg( "eglport.cfg" ); + + /* Setup any platform specific bits */ + Platform_Open(); + + printf( "EGLport: Opening EGL native splay\n" ); + if (GetNativeDisplay() != 0) + { + printf( "EGLport ERROR: Unable to obtain native display!\n" ); + return 1; + } + + printf( "EGLport: Opening native window surface\n" ); + if (GetNativeWindow( width, height ) != 0) + { + printf( "EGLport ERROR: Unable to obtain native window!\n" ); + return 1; + } + } + + printf( "EGLport: Opening EGL display\n" ); + eglDisplay = peglGetDisplay( nativeDisplay ); + if (eglDisplay == EGL_NO_DISPLAY) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Unable to create EGL display.\n" ); + return 1; + } + + printf( "EGLport: Initializing\n" ); + result = peglInitialize( eglDisplay, &eglMajorVer, &eglMinorVer ); + if (result != EGL_TRUE ) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Unable to initialize EGL display.\n" ); + return 1; + } + + /* Get EGL Library Information */ + printf( "EGL Implementation Version: Major %d Minor %d\n", eglMajorVer, eglMinorVer ); + output = peglQueryString( eglDisplay, EGL_VENDOR ); + printf( "EGL_VENDOR: %s\n", output ); + output = peglQueryString( eglDisplay, EGL_VERSION ); + printf( "EGL_VERSION: %s\n", output ); + output = peglQueryString( eglDisplay, EGL_EXTENSIONS ); + printf( "EGL_EXTENSIONS: %s\n", output ); + + if (FindEGLConfigs() != 0) + { + printf( "EGLport ERROR: Unable to configure EGL. See previous error.\n" ); + return 1; + } + + printf( "EGLport: Using Config %d\n", configIndex ); +#if defined(EGL_VERSION_1_2) + /* Bind GLES and create the context */ + printf( "EGLport: Binding API\n" ); + result = peglBindAPI( EGL_OPENGL_ES_API ); + if ( result == EGL_FALSE ) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Could not bind EGL API.\n" ); + return 1; + } +#endif /* EGL_VERSION_1_2 */ + + printf( "EGLport: Creating Context\n" ); + eglContext = peglCreateContext( eglDisplay, eglConfigs[configIndex], NULL, contextAttribs ); + if (eglContext == EGL_NO_CONTEXT) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Unable to create GLES context!\n"); + return 1; + } + + printf( "EGLport: Creating window surface\n" ); + eglSurface = peglCreateWindowSurface( eglDisplay, eglConfigs[configIndex], nativeWindow, 0 ); + if (eglSurface == EGL_NO_SURFACE) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Unable to create EGL surface!\n" ); + return 1; + } + + printf( "EGLport: Making Current\n" ); + result = peglMakeCurrent( eglDisplay, eglSurface, eglSurface, eglContext ); + if (result != EGL_TRUE) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Unable to make GLES context current\n" ); + return 1; + } + + printf( "EGLport: Setting swap interval\n" ); + peglSwapInterval( eglDisplay, (eglSettings[CFG_VSYNC] > 0) ? 1 : 0 ); + + printf( "EGLport: Complete\n" ); + + CheckEGLErrors( __FILE__, __LINE__ ); + + return 0; +} + +/** @brief Read settings that configure how to use EGL + * @param file : name of the config file + */ +void OpenCfg ( const char* file ) +{ + #define MAX_STRING 20 + #define MAX_SIZE 100 + uint8_t i; + FILE* fp = NULL; + char* location = NULL; + char eglStrings[CFG_TOTAL][MAX_STRING]; + char buffer[MAX_SIZE]; + + strncpy( eglStrings[CFG_MODE], "egl_mode=", MAX_STRING ); + strncpy( eglStrings[CFG_VSYNC], "use_vsync=", MAX_STRING ); + strncpy( eglStrings[CFG_FSAA], "use_fsaa=", MAX_STRING ); + strncpy( eglStrings[CFG_FPS], "use_fsp=", MAX_STRING ); + strncpy( eglStrings[CFG_RED_SIZE], "size_red=", MAX_STRING ); + strncpy( eglStrings[CFG_GREEN_SIZE], "size_green=", MAX_STRING ); + strncpy( eglStrings[CFG_BLUE_SIZE], "size_blue=", MAX_STRING ); + strncpy( eglStrings[CFG_ALPHA_SIZE], "size_alpha=", MAX_STRING ); + strncpy( eglStrings[CFG_DEPTH_SIZE], "size_depth=", MAX_STRING ); + strncpy( eglStrings[CFG_BUFFER_SIZE], "size_buffer=", MAX_STRING ); + strncpy( eglStrings[CFG_STENCIL_SIZE], "size_stencil=", MAX_STRING ); + + /* Set defaults */ +#if defined(USE_EGL_SDL) + eglSettings[CFG_MODE] = RENDER_SDL; +#else + eglSettings[CFG_MODE] = RENDER_RAW; +#endif + eglSettings[CFG_VSYNC] = 0; + eglSettings[CFG_FSAA] = 0; + eglSettings[CFG_FPS] = 0; + eglSettings[CFG_RED_SIZE] = 5; + eglSettings[CFG_GREEN_SIZE] = 6; + eglSettings[CFG_BLUE_SIZE] = 5; + eglSettings[CFG_ALPHA_SIZE] = 0; + eglSettings[CFG_DEPTH_SIZE] = 16; + eglSettings[CFG_BUFFER_SIZE] = 16; + eglSettings[CFG_STENCIL_SIZE] = 0; + + /* Parse INI file */ + fp = fopen( file, "r"); + if (fp != NULL) + { + while (fgets( buffer, MAX_SIZE, fp ) != NULL) + { + for (i=0; i 0) ? 1 : 0; /* 20 */ + ConfigAttribs[attrib++] = EGL_SAMPLES; /* 21 */ + ConfigAttribs[attrib++] = eglSettings[CFG_FSAA]; /* 22 */ + ConfigAttribs[attrib++] = EGL_NONE; /* 23 */ + + result = peglChooseConfig( eglDisplay, ConfigAttribs, eglConfigs, totalConfigsIn, &totalConfigsFound ); + if (result != EGL_TRUE || totalConfigsFound == 0) + { + CheckEGLErrors( __FILE__, __LINE__ ); + printf( "EGLport ERROR: Unable to query for available configs, found %d.\n", totalConfigsFound ); + return 1; + } + printf( "EGLport: Found %d available configs\n", totalConfigsFound ); + + return 0; +} + +/** @brief Error checking function + * @param file : string reference that contains the source file that the check is occuring in + * @param line : numeric reference that contains the line number that the check is occuring in + * @return : 0 if the function passed, else 1 + */ +int8_t CheckEGLErrors( const char* file, uint16_t line ) +{ + EGLenum error; + const char* errortext; + const char* description; + + error = eglGetError(); + + if (error != EGL_SUCCESS && error != 0) + { + switch (error) + { + case EGL_NOT_INITIALIZED: + errortext = "EGL_NOT_INITIALIZED."; + description = "EGL is not or could not be initialized, for the specified display."; + break; + case EGL_BAD_ACCESS: + errortext = "EGL_BAD_ACCESS EGL"; + description = "cannot access a requested resource (for example, a context is bound in another thread)."; + break; + case EGL_BAD_ALLOC: + errortext = "EGL_BAD_ALLOC EGL"; + description = "failed to allocate resources for the requested operation."; + break; + case EGL_BAD_ATTRIBUTE: + errortext = "EGL_BAD_ATTRIBUTE"; + description = "An unrecognized attribute or attribute value was passed in anattribute list."; + break; + case EGL_BAD_CONFIG: + errortext = "EGL_BAD_CONFIG"; + description = "An EGLConfig argument does not name a valid EGLConfig."; + break; + case EGL_BAD_CONTEXT: + errortext = "EGL_BAD_CONTEXT"; + description = "An EGLContext argument does not name a valid EGLContext."; + break; + case EGL_BAD_CURRENT_SURFACE: + errortext = "EGL_BAD_CURRENT_SURFACE"; + description = "The current surface of the calling thread is a window, pbuffer,or pixmap that is no longer valid."; + break; + case EGL_BAD_DISPLAY: + errortext = "EGL_BAD_DISPLAY"; + description = "An EGLDisplay argument does not name a valid EGLDisplay."; + break; + case EGL_BAD_MATCH: + errortext = "EGL_BAD_MATCH"; + description = "Arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface."; + break; + case EGL_BAD_NATIVE_PIXMAP: + errortext = "EGL_BAD_NATIVE_PIXMAP"; + description = "An EGLNativePixmapType argument does not refer to a validnative pixmap."; + break; + case EGL_BAD_NATIVE_WINDOW: + errortext = "EGL_BAD_NATIVE_WINDOW"; + description = "An EGLNativeWindowType argument does not refer to a validnative window."; + break; + case EGL_BAD_PARAMETER: + errortext = "EGL_BAD_PARAMETER"; + description = "One or more argument values are invalid."; + break; + case EGL_BAD_SURFACE: + errortext = "EGL_BAD_SURFACE"; + description = "An EGLSurface argument does not name a valid surface (window,pbuffer, or pixmap) configured for rendering"; + break; + case EGL_CONTEXT_LOST: + errortext = "EGL_CONTEXT_LOST"; + description = "A power management event has occurred. The application mustdestroy all contexts and reinitialise client API state and objects to continue rendering."; + break; + default: + errortext = "Unknown EGL Error"; + description = ""; + break; + } + + printf( "EGLport ERROR: EGL Error detected in file %s at line %d: %s (0x%X)\n Description: %s\n", file, line, errortext, error, description ); + return 1; + } + + return 0; +} + +/** @brief Obtain a reference to the system's native display + * @param window : pointer to save the display reference + * @return : 0 if the function passed, else 1 + */ +int8_t GetNativeDisplay( void ) +{ + if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */ + { + printf( "EGLport: Using EGL_DEFAULT_DISPLAY\n" ); + nativeDisplay = EGL_DEFAULT_DISPLAY; + } + else if (eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */ + { +#if defined(USE_EGL_SDL) + printf( "EGLport: Opening SDL/X11 display\n" ); + SDL_VERSION(&sysWmInfo.version); + SDL_GetWMInfo(&sysWmInfo); + nativeDisplay = (EGLNativeDisplayType)sysWmInfo.info.x11.display; + + if (nativeDisplay == 0) + { + printf( "EGLport ERROR: unable to get display!\n" ); + return 1; + } +#else + printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" ); +#endif + } + + return 0; +} + +/** @brief Obtain a reference to the system's native window + * @param width : desired pixel width of the window (not used by all platforms) + * @param height : desired pixel height of the window (not used by all platforms) + * @return : 0 if the function passed, else 1 + */ +int8_t GetNativeWindow( uint16_t width, uint16_t height ) +{ + nativeWindow = 0; + +#if defined(WIZ) || defined(CAANOO) + + printf( "EGLport: Allocating memory for CAANOO/WIZ\n" ); + nativeWindow = (NativeWindowType)malloc(16*1024); + + if(nativeWindow == NULL) { + printf( "EGLport ERROR: Memory for window Failed\n" ); + return 1; + } + +#elif defined(RPI) + + EGLBoolean result; + uint32_t screen_width, screen_height; + static EGL_DISPMANX_WINDOW_T nativewindow; + DISPMANX_ELEMENT_HANDLE_T dispman_element; + DISPMANX_DISPLAY_HANDLE_T dispman_display; + DISPMANX_UPDATE_HANDLE_T dispman_update; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + + VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE | DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS,255,0 }; + + /* create an EGL window surface */ + result = graphics_get_display_size(0 /* LCD */, &screen_width, &screen_height); + if(result < 0) { + printf( "EGLport ERROR: RPi graphicget_display_size failed\n" ); + return 1; + } + + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = screen_width; + dst_rect.height = screen_height; + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = width << 16; + src_rect.height = height << 16; + + dispman_display = vc_dispmanx_display_open( 0 /* LCD */); + dispman_update = vc_dispmanx_update_start( 0 ); + dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, + 0 /*layer*/, &dst_rect, 0 /*src*/, + &src_rect, DISPMANX_PROTECTION_NONE, &alpha /*alpha*/, (DISPMANX_CLAMP_T*)0 /*clamp*/, (DISPMANX_TRANSFORM_T)0 /*transform*/); + + nativewindow.element = dispman_element; + nativewindow.width = screen_width; + nativewindow.height = screen_height; + vc_dispmanx_update_submit_sync( dispman_update ); + + nativeWindow = (NativeWindowType)&nativewindow; + +#else /* default */ + + if (eglSettings[CFG_MODE] == RENDER_RAW) /* RAW FB mode */ + { + nativeWindow = 0; + } + else if(eglSettings[CFG_MODE] == RENDER_SDL) /* SDL/X11 mode */ + { +#if defined(USE_EGL_SDL) + /* SDL_GetWMInfo is populated when display was opened */ + nativeWindow = (NativeWindowType)sysWmInfo.info.x11.window; + + if (nativeWindow == 0) + { + printf( "EGLport ERROR: unable to get window!\n" ); + return 1; + } +#else + printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" ); +#endif + } + else + { + printf( "EGLport ERROR: Unknown EGL render mode %d!\n", eglSettings[CFG_MODE] ); + return 1; + } + +#endif /* WIZ / CAANOO */ + + return 0; +} + +/** @brief Release the system's native display + */ +void FreeNativeDisplay( void ) +{ +} + +/** @brief Release the system's native window + */ +void FreeNativeWindow( void ) +{ +#if defined(WIZ) || defined(CAANOO) + if (nativeWindow != NULL) { + free( nativeWindow ); + } + nativeWindow = NULL; +#endif /* WIZ / CAANOO */ +} + +/** @brief Open any system specific resources + */ +void Platform_Open( void ) +{ +#if defined(PANDORA) + /* Pandora VSync */ + fbdev = open( "/dev/fb0", O_RDONLY /* O_RDWR */ ); + if ( fbdev < 0 ) { + printf( "EGLport ERROR: Couldn't open /dev/fb0 for Pandora Vsync\n" ); + } +#elif defined(RPI) + bcm_host_init(); +#endif /* PANDORA */ +} + +/** @brief Release any system specific resources + */ +void Platform_Close( void ) +{ +#if defined(PANDORA) + /* Pandora VSync */ + close( fbdev ); + fbdev = -1; +#endif /* PANDORA */ +} + +/** @brief Check the systems vsync state + */ +void Platform_VSync( void ) +{ +#if defined(PANDORA) + /* Pandora VSync */ + if (fbdev >= 0) { + int arg = 0; + ioctl( fbdev, FBIO_WAITFORVSYNC, &arg ); + } +#endif /* PANDORA */ +} + +/** @brief Get the system tick time (ms) + */ +uint32_t Platform_GetTicks( void ) +{ + uint32_t ticks = 0; +#if defined(USE_EGL_SDL) + ticks = SDL_GetTicks(); +#else + printf( "EGLport ERROR: SDL mode was not enabled in this compile!\n" ); +#endif + return ticks; +} diff --git a/src/backends/egl/eglport.h b/src/backends/egl/eglport.h new file mode 100644 index 00000000..4b6c40bb --- /dev/null +++ b/src/backends/egl/eglport.h @@ -0,0 +1,105 @@ +/** + * + * EGLPORT.H + * Copyright (C) 2011-2013 Scott R. Smith + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef EGLPORT_H +#define EGLPORT_H + +#include +#include "EGL/egl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Defines (in every case choose only one) */ +/** Common: */ +/** DEBUG : enable additional error monitoring per EGL function call */ +/** Native display and window system for use with EGL */ +/** USE_EGL_SDL : used for access to a SDL X11 window */ +/** Platform: settings that are specific to that device */ +/** PANDORA (USE_GLES1 or USE_GLES2) */ +/** WIZ (USE_GLES1) */ +/** CAANOO (USE_GLES1) */ +/** RPI (USE_GLES1 or USE_GLES2) */ +/** GCW (USE_GLES1 or USE_GLES2) */ +/** GLES Version */ +/** USE_GLES1 : EGL for use with OpenGL-ES 1.X contexts */ +/** USE_GLES2 : EGL for use with OpenGL-ES 2.0 contexts */ + +/** Public API */ +void EGL_Close ( void ); +int8_t EGL_Open ( uint16_t width, uint16_t height ); +void EGL_SwapBuffers ( void ); + +/** Simple Examples */ +/** Raw mode: + EGL_Open( window_width, window_height ); + do while(!quit) { + ... run app + EGL_SwapBuffers(); + } + EGL_Close(); +*/ +/** X11/SDL mode: + SDL_Init( SDL_INIT_VIDEO ); + SDL_Surface* screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE|SDL_FULLSCREEN); + EGL_Open( window_width, window_height ); + do while(!quit) { + ... run app + EGL_SwapBuffers(); + } + EGL_Close(); + SDL_Quit(); +*/ + +#if defined(DEBUG) +#define GET_EGLERROR(FUNCTION) \ + FUNCTION; \ + { \ + CheckEGLErrors(__FILE__, __LINE__); \ + } +#else +#define GET_EGLERROR(FUNCTION) FUNCTION; +#endif + +#define peglQueryString(A,B) GET_EGLERROR(eglQueryString(A,B)) +#define peglDestroyContext(A,B) GET_EGLERROR(eglDestroyContext(A,B)) +#define peglDestroySurface(A,B) GET_EGLERROR(eglDestroySurface(A,B)) +#define peglTerminate(A) GET_EGLERROR(eglTerminate(A)) +#define peglSwapBuffers(A,B) GET_EGLERROR(eglSwapBuffers(A,B)) +#define peglGetDisplay(A) GET_EGLERROR(eglGetDisplay(A)) +#define peglBindAPI(A) GET_EGLERROR(eglBindAPI(A)) +#define peglCreateContext(A,B,C,D) GET_EGLERROR(eglCreateContext(A,B,C,D)) +#define peglCreateWindowSurface(A,B,C,D) GET_EGLERROR(eglCreateWindowSurface(A,B,C,D)) +#define peglInitialize(A,B,C) GET_EGLERROR(eglInitialize(A,B,C)) +#define peglMakeCurrent(A,B,C,D) GET_EGLERROR(eglMakeCurrent(A,B,C,D)) +#define peglChooseConfig(A,B,C,D,E) GET_EGLERROR(eglChooseConfig(A,B,C,D,E)) +#define peglSwapInterval(A,B) GET_EGLERROR(eglSwapInterval(A,B)) + +#ifdef __cplusplus +} +#endif + +#endif /* EGLPORT_H */ diff --git a/src/backends/egl/in_gph.c b/src/backends/egl/in_gph.c new file mode 100755 index 00000000..a04d6fcc --- /dev/null +++ b/src/backends/egl/in_gph.c @@ -0,0 +1,359 @@ +/** + * + * Copyright (C) 2011 Scott R. Smith + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "in_gph.h" + +int8_t Volume = 20; +uint8_t VolumeDirection = 0; +int32_t HandleStick = 0; +int32_t HandleGpio = 0; +uint32_t ButtonsCurrent = 0; +uint32_t ButtonsPrevious = 0; +uint32_t Ticksup = 0; +uint32_t Ticksdown = 0; + +SDLKey gph_map[GPH_MAX_BUTTONS] = { + SDLK_UP, // GPH_UP + 0, // GPH_UP_LEFT + SDLK_LEFT, // GPH_LEFT + 0, // GPH_DOWN_LEFT + SDLK_DOWN, // GPH_DOWN + 0, // GPH_DOWN_RIGHT + SDLK_RIGHT, // GPH_RIGHT + 0, // GPH_UP_RIGHT + SDLK_RETURN, // GPH_START + SDLK_ESCAPE, // GPH_SELECT + SDLK_l, // GPH_L + SDLK_r, // GPH_R + SDLK_a, // GPH_A + SDLK_b, // GPH_B` + SDLK_x, // GPH_Y + SDLK_y, // GPH_X + 0, // GPH_VOL_UP + 0, // GPH_VOL_DOWN + SDLK_p, // GPH_PUSH + SDLK_q, // GPH_HELP1 + SDLK_1, // AB + SDLK_F1, // AX + SDLK_2, // AY + SDLK_3, // BX + SDLK_4, // BY + SDLK_5, // XY + 0, + 0, + 0, + 0, + 0, + 0 +}; + +void GPH_Close( void ) +{ + close(HandleGpio); +#if defined(CAANOO) + close(HandleStick); +#endif +} + +int8_t GPH_Open( void ) +{ +#if defined(CAANOO) + HandleStick = open( "/dev/input/event1", O_RDONLY|O_NONBLOCK ); + if (HandleStick < 0) + { + printf( "GPH Input Analog stick OPEN FAIL\n"); + return 1; + } + else + { + printf("GPH Input Caanoo stick loaded\n"); + } +#endif + HandleGpio = open( "/dev/GPIO", O_RDWR|O_NDELAY ); + if (HandleGpio < 0) + { + printf( "GPH Input GPIO OPEN FAIL\n"); + return 1; + } + else + { + printf("GPH Input Wiz/Caanoo buttons loaded\n"); + } + + return 0; +} + +void GPH_Input( void ) +{ + ButtonsPrevious = ButtonsCurrent; + + GPH_ReadButtons(); +#if defined(CAANOO) + GPH_ReadAnalog(); +#endif + + return ButtonsCurrent; +} + +void GPH_ReadButtons( void ) +{ + uint8_t button; + uint16_t index; + + read( HandleGpio, &ButtonsCurrent, 4 ); + +#if defined(WIZ) + // Use diagonals + if ( (ButtonsCurrent&GPH_BUTTON(GPH_UP_LEFT)) && + !((ButtonsCurrent&GPH_BUTTON(GPH_UP)) || (ButtonsCurrent&GPH_BUTTON(GPH_LEFT)))) + { + ButtonsCurrent |= GPH_BUTTON(GPH_UP); + ButtonsCurrent |= GPH_BUTTON(GPH_LEFT); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_UP_RIGHT)) && + !((ButtonsCurrent&GPH_BUTTON(GPH_UP)) || (ButtonsCurrent&GPH_BUTTON(GPH_RIGHT)))) + { + ButtonsCurrent |= GPH_BUTTON(GPH_UP); + ButtonsCurrent |= GPH_BUTTON(GPH_RIGHT); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_DOWN_LEFT)) && + !((ButtonsCurrent&GPH_BUTTON(GPH_DOWN)) || (ButtonsCurrent&GPH_BUTTON(GPH_LEFT)))) + { + ButtonsCurrent |= GPH_BUTTON(GPH_DOWN); + ButtonsCurrent |= GPH_BUTTON(GPH_LEFT); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_DOWN_RIGHT)) && + !((ButtonsCurrent&GPH_BUTTON(GPH_DOWN)) || (ButtonsCurrent&GPH_BUTTON(GPH_RIGHT)))) + { + ButtonsCurrent |= GPH_BUTTON(GPH_DOWN); + ButtonsCurrent |= GPH_BUTTON(GPH_RIGHT); + } +#endif + + // Map combos + if ( (ButtonsCurrent&GPH_BUTTON(GPH_A)) && (ButtonsCurrent&GPH_BUTTON(GPH_B)) ) + { + ButtonsCurrent ^= GPH_BUTTON(GPH_A); + ButtonsCurrent ^= GPH_BUTTON(GPH_B); + ButtonsCurrent |= GPH_BUTTON(GPH_AB); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_A)) && (ButtonsCurrent&GPH_BUTTON(GPH_X)) ) + { + ButtonsCurrent ^= GPH_BUTTON(GPH_A); + ButtonsCurrent ^= GPH_BUTTON(GPH_X); + ButtonsCurrent |= GPH_BUTTON(GPH_AX); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_A)) && (ButtonsCurrent&GPH_BUTTON(GPH_Y)) ) + { + ButtonsCurrent ^= GPH_BUTTON(GPH_A); + ButtonsCurrent ^= GPH_BUTTON(GPH_Y); + ButtonsCurrent |= GPH_BUTTON(GPH_AY); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_B)) && (ButtonsCurrent&GPH_BUTTON(GPH_X)) ) + { + ButtonsCurrent ^= GPH_BUTTON(GPH_B); + ButtonsCurrent ^= GPH_BUTTON(GPH_X); + ButtonsCurrent |= GPH_BUTTON(GPH_BX); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_B)) && (ButtonsCurrent&GPH_BUTTON(GPH_Y)) ) + { + ButtonsCurrent ^= GPH_BUTTON(GPH_B); + ButtonsCurrent ^= GPH_BUTTON(GPH_Y); + ButtonsCurrent |= GPH_BUTTON(GPH_BY); + } + if ( (ButtonsCurrent&GPH_BUTTON(GPH_X)) && (ButtonsCurrent&GPH_BUTTON(GPH_Y)) ) + { + ButtonsCurrent ^= GPH_BUTTON(GPH_X); + ButtonsCurrent ^= GPH_BUTTON(GPH_Y); + ButtonsCurrent |= GPH_BUTTON(GPH_XY); + } + +#if defined(WIZ) + // Volume Up + if ((((ButtonsPrevious & GPH_BUTTON(GPH_VOL_UP)) == 0) && ((ButtonsCurrent & GPH_BUTTON(GPH_VOL_UP))> 0)) || + (((ButtonsPrevious & GPH_BUTTON(GPH_VOL_UP)) > 0) && ((ButtonsCurrent & GPH_BUTTON(GPH_VOL_UP))> 0) && ((SDL_GetTicks() - Ticksup) > VOLUME_TIME_RATE )) ) + { + Ticksup = SDL_GetTicks(); + GPH_AdjustVolume(VOLUME_UP); + } + // Volume Down + if ((((ButtonsPrevious & GPH_BUTTON(GPH_VOL_DOWN)) == 0) && ((ButtonsCurrent & GPH_BUTTON(GPH_VOL_DOWN))> 0)) || + (((ButtonsPrevious & GPH_BUTTON(GPH_VOL_DOWN)) > 0) && ((ButtonsCurrent & GPH_BUTTON(GPH_VOL_DOWN))> 0) && ((SDL_GetTicks() - Ticksdown) > VOLUME_TIME_RATE )) ) + { + Ticksdown = SDL_GetTicks(); + GPH_AdjustVolume(VOLUME_DOWN); + } +#endif +} + +#if defined(CAANOO) +#define ZERO_POINT 128 +#define OPT_DEADZONE 64 + +int8_t up, down, left, right = 0; + +void GPH_ReadAnalog( void ) +{ + struct input_event event[16]; + int32_t rbytes; + uint32_t i; + + rbytes = read( HandleStick, &event, sizeof(event) ); + if (rbytes > 0) + { + for (i=0; iZERO_POINT+OPT_DEADZONE) { + right = 1; + } else { + right = 0; + } + + if (event[i].valueZERO_POINT+OPT_DEADZONE) { + down = 1; + } else { + down = 0; + } + + //printf("y = 0x%x\n", event[i].value); + break; + default: + //printf("type = 0x%x, code = 0x%x\n", event[i].type, event[i].code); + break; + } + break; + default: + if (event[i].type) { + //printf("type = 0x%x, code = 0x%x\n", event[i].type, event[i].code); + } + break; + } + } + } + + if (right) + ButtonsCurrent |= GPH_BUTTON(GPH_RIGHT); + + if (left) + ButtonsCurrent |= GPH_BUTTON(GPH_LEFT); + + if (up) + ButtonsCurrent |= GPH_BUTTON(GPH_UP); + + if (down) + ButtonsCurrent |= GPH_BUTTON(GPH_DOWN); +} +#endif /* if defined(CAANOO) */ + +#if defined(WIZ) +void GPH_AdjustVolume( uint8_t direction ) +{ + if (direction != VOLUME_NOCHG) + { + if (Volume <= 10) + { + if (direction == VOLUME_UP) Volume += VOLUME_CHANGE_RATE/2; + if (direction == VOLUME_DOWN) Volume -= VOLUME_CHANGE_RATE/2; + } + else + { + if (direction == VOLUME_UP) Volume += VOLUME_CHANGE_RATE; + if (direction == VOLUME_DOWN) Volume -= VOLUME_CHANGE_RATE; + } + + if (Volume < VOLUME_MIN) Volume = VOLUME_MIN; + if (Volume > VOLUME_MAX) Volume = VOLUME_MAX; + + printf( "Volume Change: %i\n", Volume ); + + unsigned long soundDev = open("/dev/mixer", O_RDWR); + if (soundDev) + { + int vol = ((Volume << 8) | Volume); + ioctl(soundDev, SOUND_MIXER_WRITE_PCM, &vol); + close(soundDev); + } + } +} +#endif /* if defined(WIZ) */ + +int8_t GPH_GetButttonState( uint32_t button ) +{ + uint32_t current_state; + uint32_t previous_state; + + current_state = button & ButtonsCurrent; + previous_state = button & ButtonsPrevious; + + // Was released and now pressed + if (previous_state == 0 && current_state == button) + { + //printf ("GPH_RELEASED_TO_PRESSED %X\n", button ); + return GPH_RELEASED_TO_PRESSED; + } + else // Was pressed and still being pressed + if (previous_state == button && current_state == button) + { + //printf ("GPH_PRESSED %X\n", button ); + return GPH_PRESSED; + } + else // Was pressed and now released + if (previous_state == button && current_state == 0) + { + //printf ("GPH_PRESSED_TO_RELEASED %X\n", button ); + return GPH_PRESSED_TO_RELEASED; + } + else // Was released and still released + if (previous_state == 0 && current_state == 0) + { + //printf ("GPH_RELEASED %X\n", button ); + return GPH_RELEASED; + } + else // Shouldnt ever have this state + { + printf( "GPH Input Wiz/Caanoo detected unexpected button state: previous %X current %X\n", ButtonsPrevious, ButtonsCurrent ); + return GPH_NONE; + } +} diff --git a/src/backends/egl/in_gph.h b/src/backends/egl/in_gph.h new file mode 100755 index 00000000..e0cfb953 --- /dev/null +++ b/src/backends/egl/in_gph.h @@ -0,0 +1,104 @@ +/** + * + * Copyright (C) 2011 Scott R. Smith + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef CGPH_H +#define CGPH_H + +#include +#include +#include +#include +#include +#include + +enum { + GPH_NONE=0, + GPH_RELEASED_TO_PRESSED, + GPH_PRESSED, + GPH_PRESSED_TO_RELEASED, + GPH_RELEASED +}; + +#define GPH_MAX_BUTTONS 32 +#define GPH_BUTTON(X) (1< +#endif + +#define GPH_UP 0 +#define GPH_UP_LEFT 1 +#define GPH_LEFT 2 +#define GPH_DOWN_LEFT 3 +#define GPH_DOWN 4 +#define GPH_DOWN_RIGHT 5 +#define GPH_RIGHT 6 +#define GPH_UP_RIGHT 7 +#define GPH_START 8 // Caanoo HOME +#define GPH_SELECT 9 // Cannoo HELP2 +#define GPH_L 10 +#define GPH_R 11 +#define GPH_A 12 +#define GPH_B 13 +#define GPH_X 14 +#define GPH_Y 15 +#define GPH_VOL_UP 16 +#define GPH_VOL_DOWN 17 +#define GPH_PUSH 18 // Caanoo only +#define GPH_HELP1 19 // Caanoo only + +#define GPH_AB 20 +#define GPH_AX 21 +#define GPH_AY 22 +#define GPH_BX 23 +#define GPH_BY 24 +#define GPH_XY 25 + +#if defined(WIZ) +#define VOLUME_MIN 0 +#define VOLUME_MAX 100 +#define VOLUME_CHANGE_RATE 2 +#define VOLUME_NOCHG 0 +#define VOLUME_DOWN 1 +#define VOLUME_UP 2 +#define VOLUME_TIME_RATE 20 +#endif + +void GPH_Close ( void ); +int8_t GPH_Open ( void ); +void GPH_Input ( void ); + +void GPH_ReadButtons ( void ); +#if defined(CAANOO) +void GPH_ReadAnalog ( void ); +#endif +#if defined(WIZ) +void GPH_AdjustVolume ( uint8_t direction ); +#endif +int8_t GPH_GetButttonState ( uint32_t button ); + +extern SDLKey gph_map[GPH_MAX_BUTTONS]; + +#endif // CGPH_H +