Merge remote-tracking branch 'opengles/master'

This integrates the backends for the pandora, gcw and gph written by
Scott "Pickle" Smith. Only the code itself is supplied, but no build
system integration.
This commit is contained in:
Yamagi Burmeister 2014-06-09 14:37:09 +02:00
commit 6c3fb38721
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