OpenGL-ES converstion

Specific device options for pandora, gcw, gph
This commit is contained in:
Scott Smith 2013-10-12 12:31:20 -04:00
parent 5e85fbc8b9
commit 70eef55ab5
4 changed files with 1269 additions and 0 deletions

701
src/backends/egl/eglport.c Normal file
View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#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<CFG_TOTAL; i++)
{
location = strstr( buffer, eglStrings[i] );
if (location != NULL)
{
eglSettings[i] = atol( location+strlen( eglStrings[i] ) );
printf( "EGLport: %s set to %d.\n", eglStrings[i], eglSettings[i] );
break;
}
}
}
fclose( fp );
}
else
{
printf( "EGL ERROR: Unable to read ini settings from file '%s'. Using defaults\n", file );
}
}
/** @brief Find a EGL configuration tht matches the defined attributes
* @return : 0 if the function passed, else 1
*/
int8_t FindEGLConfigs( void )
{
EGLBoolean result;
int attrib = 0;
EGLint ConfigAttribs[23];
ConfigAttribs[attrib++] = EGL_RED_SIZE; /* 1 */
ConfigAttribs[attrib++] = eglSettings[CFG_RED_SIZE]; /* 2 */
ConfigAttribs[attrib++] = EGL_GREEN_SIZE; /* 3 */
ConfigAttribs[attrib++] = eglSettings[CFG_GREEN_SIZE]; /* 4 */
ConfigAttribs[attrib++] = EGL_BLUE_SIZE; /* 5 */
ConfigAttribs[attrib++] = eglSettings[CFG_BLUE_SIZE]; /* 6 */
ConfigAttribs[attrib++] = EGL_ALPHA_SIZE; /* 7 */
ConfigAttribs[attrib++] = eglSettings[CFG_ALPHA_SIZE]; /* 8 */
ConfigAttribs[attrib++] = EGL_DEPTH_SIZE; /* 9 */
ConfigAttribs[attrib++] = eglSettings[CFG_DEPTH_SIZE]; /* 10 */
ConfigAttribs[attrib++] = EGL_BUFFER_SIZE; /* 11 */
ConfigAttribs[attrib++] = eglSettings[CFG_BUFFER_SIZE]; /* 12 */
ConfigAttribs[attrib++] = EGL_STENCIL_SIZE; /* 13 */
ConfigAttribs[attrib++] = eglSettings[CFG_STENCIL_SIZE]; /* 14 */
ConfigAttribs[attrib++] = EGL_SURFACE_TYPE; /* 15 */
ConfigAttribs[attrib++] = EGL_WINDOW_BIT; /* 16 */
#if defined(EGL_VERSION_1_2)
ConfigAttribs[attrib++] = EGL_RENDERABLE_TYPE; /* 17 */
#if defined(USE_GLES1)
ConfigAttribs[attrib++] = EGL_OPENGL_ES_BIT;
#elif defined(USE_GLES2)
ConfigAttribs[attrib++] = EGL_OPENGL_ES2_BIT; /* 18 */
#endif /* USE_GLES1 */
#endif /* EGL_VERSION_1_2 */
ConfigAttribs[attrib++] = EGL_SAMPLE_BUFFERS; /* 19 */
ConfigAttribs[attrib++] = (eglSettings[CFG_FSAA] > 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;
}

105
src/backends/egl/eglport.h Normal file
View File

@ -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 <stdint.h>
#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 */

359
src/backends/egl/in_gph.c Executable file
View File

@ -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; i<rbytes/sizeof(struct input_event); i++)
{
switch (event[i].type)
{
case EV_ABS:
switch (event[i].code)
{
case ABS_X:
if (event[i].value>ZERO_POINT+OPT_DEADZONE) {
right = 1;
} else {
right = 0;
}
if (event[i].value<ZERO_POINT-OPT_DEADZONE) {
left = 1;
} else {
left = 0;
}
//printf("x = 0x%x\n", event[i].value);
break;
case ABS_Y:
if (event[i].value<ZERO_POINT-OPT_DEADZONE) {
up = 1;
} else {
up = 0;
}
if (event[i].value>ZERO_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;
}
}

104
src/backends/egl/in_gph.h Executable file
View File

@ -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 <SDL.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
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<<X)
#if defined(CAANOO)
#include <linux/input.h>
#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