From 758f2d64f8e21d40dd2062e10a3748a103780656 Mon Sep 17 00:00:00 2001 From: zico Date: Mon, 8 Apr 2013 12:54:02 +0200 Subject: [PATCH] Support for Raspberry Pi - patch by derhass --- CHANGELOG.txt | 4 + README.RPi | 72 ++++++++++ SConstruct | 17 ++- arch/ogl/gr.c | 378 +++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 422 insertions(+), 49 deletions(-) create mode 100644 README.RPi diff --git a/CHANGELOG.txt b/CHANGELOG.txt index cf722ced8..76f4ebfe2 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -10,6 +10,10 @@ d1x-rebirth.xcodeproj/project.pbxproj, editor/ehostage.c, main/custom.c: Updated SConstruct: For the assembler build, make sure platform_settings is accessed from self, likely preventing a compiling error SConstruct: Changes towards building using SCons on Mac OS X +20130122 +-------- +README.RPi, SConstruct, arch/ogl/gr.c: Support for Raspberry Pi - patch by derhass + 20130119 -------- main/gamerend.c, main/menu.c, main/multi.c, main/multi.h, main/net_udp.c, main/playsave.c, main/playsave.h: Added Rankings functionality like in D2X-Rebirth while still utilizing eff file from original D1X source diff --git a/README.RPi b/README.RPi new file mode 100644 index 000000000..ca159b909 --- /dev/null +++ b/README.RPi @@ -0,0 +1,72 @@ +DXX-Rebirth for the Raspberry Pi + +BUILDING: +========= +Make sure you have installed (the development packages of) all of the required +libraries (libsdl, libphysfs, ...). For building, you will also need scons (and +for that, python). Most linux distributions should contain all the required +packages, debain/raspbian do so for sure. Using a distribution with hardfp ABI +is recommended for optimal performance. I developed/tested this on a raspbian +wheezy. + +To build directly on the device, just run: + +scons raspberrypi=1 [... other options (see scons -h)...] + +This assumes that the development files (libs/headers) for the VideoCore APIs +are located in /opt/vc. You can use rpi_vc_path to specify another location. + +Currently, there is no direct support for crosscompiling. + +RUNNING: +======== +The game should run with X11 or directly on the console (libsdl with fbcon/ +directfb driver). + +NOTE: *** PLEASE USE THE 128/128MB MEMORY SPLIT *** + +The game might completely freeze or diplay messed up graphics in +out-of-(GPU)-memory situations. If you want to run it with the 192/64MB memory +split, you might be able to do so by setting the texture filter to "NONE" in +the graphics options. (This disables mip mapping and reduces the memory +requirements of the textures. Note that the "BILINEAR" filter still uses +mipmapping). + +If the game freezes during the "Prepare for Descent" phase when loading a +level, you probably do not have enough GPU memory. + +RUNNING ON X11: +=============== +Recommendation is to use fullscreen mode. However, you can run in "windowed" +mode, too. The game will open an X11 window in that case, and the actual game +output will be an overlay of the same size, but not at the same position, and +always on top (and completely out of control of the X Server). Game input is +still handled via the X11 window, so make sure it has the focus. + +RUNNING ON THE CONSOLE: +======================= +libsdl supports running directly on the Linux console. While the SDL Video mode +is technically not required on the RPi, we still have to use it to get all the +input events we need. libsdl seems to have problems on the RPi, I always get a +crash in libsdl when trying to change the resolution. To avoid such crashes, +the code will try to detect if it is running on the console and activate a hack +to prevent switching the resolution. Note that the in-game framebuffer +resolution can still be changed, the RPi will just scale the output to the +initial resolution (in "fullscreen" mode). "Windowed" mode will just result in +unscaled output. As libsdl creates a black screen, you will not be able to have +the "Window" on top of the linux console output :( + +NOTE: You might need root privileges to use the libsdl fbcon/directfb drivers. + +BUGS, SUGGESTIONS AND FEEDBACK: +=============================== + +The RPi patch was written by: + Marcel Heinz + +Send bug reports, suggestions and other feedback regarding the operation +on the RPi to me via email, or post to the official dxx-rebirth forum at: + http://www.dxx-rebirth.com/frm/index.php + + -- derhass, 2012-08-09 + diff --git a/SConstruct b/SConstruct index 205bdc7b1..64cc7e6ff 100644 --- a/SConstruct +++ b/SConstruct @@ -37,12 +37,15 @@ class DXXProgram: PREFIX = str(ARGUMENTS.get('prefix', '/usr/local')) self.BIN_DIR = PREFIX + '/bin' self.DATA_DIR = PREFIX + '/share/games/' + target + + # Paths for the Videocore libs/includes on the Raspberry Pi + self.RPI_DEFAULT_VC_PATH='/opt/vc' + # command-line parms self.sharepath = str(ARGUMENTS.get('sharepath', self.DATA_DIR)) self.debug = int(ARGUMENTS.get('debug', 0)) self.profiler = int(ARGUMENTS.get('profiler', 0)) self.opengl = int(ARGUMENTS.get('opengl', 1)) - self.opengles = int(ARGUMENTS.get('opengles', 0)) self.asm = int(ARGUMENTS.get('asm', 0)) self.editor = int(ARGUMENTS.get('editor', 0)) self.extra_version = ARGUMENTS.get('extra_version', None) @@ -51,6 +54,16 @@ class DXXProgram: self.use_udp = int(ARGUMENTS.get('use_udp', 1)) self.use_tracker = int(ARGUMENTS.get('use_tracker', 1)) self.verbosebuild = int(ARGUMENTS.get('verbosebuild', 0)) + self.raspberrypi = int(ARGUMENTS.get('raspberrypi', 0)) + self.rpi_vc_path = str(ARGUMENTS.get('rpi_vc_path', self.RPI_DEFAULT_VC_PATH)) + self.default_opengles = 0 + self.default_OGLES_LIB = 'GLES_CM' + # automatic setup for raspberrypi + if (self.raspberrypi == 1): + self.default_opengles=1 + self.default_OGLES_LIB='GLESv2' + self.opengles = int(ARGUMENTS.get('opengles', self.default_opengles)) + self.opengles_lib = str(ARGUMENTS.get('opengles_lib', self.default_OGLES_LIB)) builddir_prefix = ARGUMENTS.get('builddir_prefix', None) builddir_suffix = ARGUMENTS.get('builddir_suffix', None) default_builddir = builddir_prefix or '' @@ -546,6 +559,8 @@ Help(program.PROGRAM_NAME + ', SConstruct file help:' + 'use_udp=[0/1]' enable UDP support [default: 1] 'use_tracker=[0/1]' enable Tracker support (requires udp) [default :1] 'verbosebuild=[0/1]' print out all compiler/linker messages during building [default: 0] + 'raspberrypi=[0/1]' build for Raspberry Pi (automatically sets opengles and opengles_lib) [default: 0] + 'rpi_vc_path=[DIR]' use [DIR] to look for VideoCore libraries/header files (RPi only) Default values: """ + ' sharepath = ' + program.user_settings.DATA_DIR + """ diff --git a/arch/ogl/gr.c b/arch/ogl/gr.c index 1ce4d56dc..275e8cf5a 100644 --- a/arch/ogl/gr.c +++ b/arch/ogl/gr.c @@ -6,6 +6,11 @@ #define DECLARE_VARS +#ifdef RPI +// extra libraries for the Raspberry Pi +#include "bcm_host.h" +#endif + #include #include #include @@ -51,7 +56,7 @@ #include #else #ifdef OGLES -#include +#include #include #include #include @@ -62,18 +67,26 @@ #ifdef OGLES int sdl_video_flags = 0; + +#ifdef RPI +static EGL_DISPMANX_WINDOW_T nativewindow; +static DISPMANX_ELEMENT_HANDLE_T dispman_element=DISPMANX_NO_HANDLE; +static DISPMANX_DISPLAY_HANDLE_T dispman_display=DISPMANX_NO_HANDLE; +#endif + #else int sdl_video_flags = SDL_OPENGL; #endif int gr_installed = 0; int gl_initialized=0; int linedotscale=1; // scalar of glLinewidth and glPointSize - only calculated once when resolution changes +int sdl_no_modeswitch=0; #ifdef OGLES -EGLDisplay eglDisplay; +EGLDisplay eglDisplay=EGL_NO_DISPLAY; EGLConfig eglConfig; -EGLSurface eglSurface; -EGLContext eglContext; +EGLSurface eglSurface=EGL_NO_SURFACE; +EGLContext eglContext=EGL_NO_CONTEXT; bool TestEGLError(char* pszLocation) { @@ -102,8 +115,176 @@ void ogl_swap_buffers_internal(void) #endif } +#ifdef RPI + +// MH: I got the following constants for vc_dispmanx_element_change_attributes() from: +// http://qt.gitorious.org/qt/qtbase/commit/5933205cfcd73481cb0645fa6183103063fe3e0d +// I do not know where they got them from, but OTOH, they are quite obvious. + +// these constants are not in any headers (yet) +#define ELEMENT_CHANGE_LAYER (1<<0) +#define ELEMENT_CHANGE_OPACITY (1<<1) +#define ELEMENT_CHANGE_DEST_RECT (1<<2) +#define ELEMENT_CHANGE_SRC_RECT (1<<3) +#define ELEMENT_CHANGE_MASK_RESOURCE (1<<4) +#define ELEMENT_CHANGE_TRANSFORM (1<<5) + +void rpi_destroy_element(void) +{ + if (dispman_element != DISPMANX_NO_HANDLE) { + DISPMANX_UPDATE_HANDLE_T dispman_update; + con_printf(CON_DEBUG, "RPi: destroying display manager element\n"); + dispman_update = vc_dispmanx_update_start( 0 ); + if (vc_dispmanx_element_remove( dispman_update, dispman_element)) { + con_printf(CON_URGENT, "RPi: failed to remove dispmanx element!\n"); + } + vc_dispmanx_update_submit_sync( dispman_update ); + dispman_element = DISPMANX_NO_HANDLE; + } +} + +int rpi_setup_element(int x, int y, Uint32 video_flags, int update) +{ + // this code is based on the work of Ben O'Steen + // http://benosteen.wordpress.com/2012/04/27/using-opengl-es-2-0-on-the-raspberry-pi-without-x-windows/ + // https://github.com/benosteen/opengles-book-samples/tree/master/Raspi + DISPMANX_UPDATE_HANDLE_T dispman_update; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + VC_DISPMANX_ALPHA_T alpha_descriptor; + + uint32_t rpi_display_device=DISPMANX_ID_MAIN_LCD; + uint32_t display_width; + uint32_t display_height; + int success; + + success = graphics_get_display_size(rpi_display_device, &display_width, &display_height); + if ( success < 0 ) { + con_printf(CON_URGENT, "Could not get RPi display size, assuming 640x480\n"); + display_width=640; + display_height=480; + } + + if ((uint32_t)x > display_width) { + con_printf(CON_URGENT, "RPi: Requested width %d exceeds display width %u, scaling down!\n", + x,display_width); + x=(int)display_width; + } + if ((uint32_t)y > display_height) { + con_printf(CON_URGENT, "RPi: Requested height %d exceeds display height %u, scaling down!\n", + y,display_height); + y=(int)display_height; + } + + con_printf(CON_DEBUG, "RPi: display resolution %ux%u, game resolution: %dx%d (%s)\n", display_width, display_height, x, y, (video_flags & SDL_FULLSCREEN)?"fullscreen":"windowed"); + if (video_flags & SDL_FULLSCREEN) { + /* scale to the full display size... */ + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = display_width; + dst_rect.height= display_height; + } else { + /* TODO: we could query the position of the X11 window here + and try to place the ovelray exactly above that..., + we would have to track window movements, though ... */ + dst_rect.x = 0; + dst_rect.y = 0; + dst_rect.width = (uint32_t)x; + dst_rect.height= (uint32_t)y; + } + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = ((uint32_t)x)<< 16; + src_rect.height =((uint32_t)y)<< 16; + + /* we do not want our overlay to be blended against the background */ + alpha_descriptor.flags=DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS; + alpha_descriptor.opacity=0xffffffff; + alpha_descriptor.mask=0; + + // open display, if we do not already have one ... + if (dispman_display == DISPMANX_NO_HANDLE) { + con_printf(CON_DEBUG, "RPi: opening display: %u\n",rpi_display_device); + dispman_display = vc_dispmanx_display_open(rpi_display_device); + if (dispman_display == DISPMANX_NO_HANDLE) { + con_printf(CON_URGENT,"RPi: failed to open display: %u\n",rpi_display_device); + } + } + + if (dispman_element != DISPMANX_NO_HANDLE) { + if (!update) { + // if the element already exists, and we cannot update it, so recreate it + rpi_destroy_element(); + } + } else { + // if the element does not exist, we cannot do an update + update=0; + } + + dispman_update = vc_dispmanx_update_start( 0 ); + + if (update) { + con_printf(CON_DEBUG, "RPi: updating display manager element\n"); + vc_dispmanx_element_change_attributes ( dispman_update, nativewindow.element, + ELEMENT_CHANGE_DEST_RECT | ELEMENT_CHANGE_SRC_RECT, + 0 /*layer*/, 0 /*opacity*/, + &dst_rect, &src_rect, + 0 /*mask*/, VC_IMAGE_ROT0 /*transform*/); + } else { + // create a new element + con_printf(CON_DEBUG, "RPi: creating display manager element\n"); + dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, + 0 /*layer*/, &dst_rect, 0 /*src*/, + &src_rect, DISPMANX_PROTECTION_NONE, + &alpha_descriptor, NULL /*clamp*/, + VC_IMAGE_ROT0 /*transform*/); + if (dispman_element == DISPMANX_NO_HANDLE) { + con_printf(CON_URGENT,"RPi: failed to creat display manager elemenr\n"); + } + nativewindow.element = dispman_element; + } + nativewindow.width = display_width; + nativewindow.height = display_height; + vc_dispmanx_update_submit_sync( dispman_update ); + + return 0; +} + +#endif // RPI + +#ifdef OGLES +void ogles_destroy(void) +{ + if( eglDisplay != EGL_NO_DISPLAY ) { + eglMakeCurrent(eglDisplay, NULL, NULL, EGL_NO_CONTEXT); + } + + if (eglContext != EGL_NO_CONTEXT) { + con_printf(CON_DEBUG, "EGL: destroyig context\n"); + eglDestroyContext(eglDisplay, eglContext); + eglContext = EGL_NO_CONTEXT; + } + + if (eglSurface != EGL_NO_SURFACE) { + con_printf(CON_DEBUG, "EGL: destroyig surface\n"); + eglDestroySurface(eglDisplay, eglSurface); + eglSurface = EGL_NO_SURFACE; + } + + if (eglDisplay != EGL_NO_DISPLAY) { + con_printf(CON_DEBUG, "EGL: terminating\n"); + eglTerminate(eglDisplay); + eglDisplay = EGL_NO_DISPLAY; + } +} +#endif + int ogl_init_window(int x, int y) { + int use_x,use_y,use_bpp; + Uint32 use_flags; + #ifdef OGLES SDL_SysWMinfo info; Window x11Window = 0; @@ -117,10 +298,16 @@ int ogl_init_window(int x, int y) EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, - EGL_NONE + EGL_NONE, EGL_NONE }; + + // explicitely request an OpenGL ES 1.x context + EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE, EGL_NONE }; + // explicitely request a doublebuffering window + EGLint winAttribs[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE, EGL_NONE }; + int iConfigs; -#endif +#endif // OGLES if (gl_initialized) ogl_smash_texture_list_internal();//if we are or were fullscreen, changing vid mode will invalidate current textures @@ -128,18 +315,38 @@ int ogl_init_window(int x, int y) SDL_WM_SetCaption(DESCENT_VERSION, "Descent"); SDL_WM_SetIcon( SDL_LoadBMP( "d1x-rebirth.bmp" ), NULL ); - if (!SDL_SetVideoMode(x, y, GameArg.DbgBpp, sdl_video_flags)) + use_x=x; + use_y=y; + use_bpp=GameArg.DbgBpp; + use_flags=sdl_video_flags; + if (sdl_no_modeswitch) { + const SDL_VideoInfo *vinfo=SDL_GetVideoInfo(); + if (vinfo) { + use_x=vinfo->current_w; + use_y=vinfo->current_h; + use_bpp=vinfo->vfmt->BitsPerPixel; + use_flags=SDL_SWSURFACE | SDL_ANYFORMAT; + } else { + con_printf(CON_URGENT, "Could not query video info\n"); + } + } + + if (!SDL_SetVideoMode(use_x, use_y, use_bpp, use_flags)) { +#ifdef RPI + con_printf(CON_URGENT, "Could not set %dx%dx%d opengl video mode: %s\n (Ignored for RPI)", + x, y, GameArg.DbgBpp, SDL_GetError()); +#else Error("Could not set %dx%dx%d opengl video mode: %s\n", x, y, GameArg.DbgBpp, SDL_GetError()); +#endif } #ifdef OGLES - if( eglSurface || eglContext || eglDisplay ) - { - eglMakeCurrent(eglDisplay, NULL, NULL, EGL_NO_CONTEXT); - eglDestroyContext(eglDisplay, eglContext); - eglDestroySurface(eglDisplay, eglSurface); - } +#ifndef RPI + // NOTE: on the RPi, the EGL stuff is not connected to the X11 window, + // so there is no need to destroy and recreate this + ogles_destroy(); +#endif SDL_VERSION(&info.version); @@ -147,42 +354,67 @@ int ogl_init_window(int x, int y) if (info.subsystem == SDL_SYSWM_X11) { x11Display = info.info.x11.display; x11Window = info.info.x11.window; - printf ("Display: %p, Window: %i ===\n", x11Display, x11Window); + con_printf (CON_DEBUG, "Display: %p, Window: %i ===\n", (void*)x11Display, (int)x11Window); + } + } + + if (eglDisplay == EGL_NO_DISPLAY) { +#ifdef RPI + eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY); +#else + eglDisplay = eglGetDisplay((EGLNativeDisplayType)x11Display); +#endif + if (eglDisplay == EGL_NO_DISPLAY) { + con_printf(CON_URGENT, "EGL: Error querying EGL Display\n"); + } + + if (!eglInitialize(eglDisplay, &ver_maj, &ver_min)) { + con_printf(CON_URGENT, "EGL: Error initializing EGL\n"); + } else { + con_printf(CON_DEBUG, "EGL: Initialized, version: major %i minor %i\n", ver_maj, ver_min); + } + } + + +#ifdef RPI + if (rpi_setup_element(x,y,sdl_video_flags,1)) { + Error("RPi: Could not set up a %dx%d element\n", x, y); + } +#endif + + if (eglSurface == EGL_NO_SURFACE) { + if (!eglChooseConfig(eglDisplay, configAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) { + con_printf(CON_URGENT, "EGL: Error choosing config\n"); + } else { + con_printf(CON_DEBUG, "EGL: config chosen\n"); + } + +#ifdef RPI + eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)&nativewindow, winAttribs); +#else + eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)x11Window, winAttribs); +#endif + if ((!TestEGLError("eglCreateWindowSurface")) || eglSurface == EGL_NO_SURFACE) { + con_printf(CON_URGENT, "EGL: Error creating window surface\n"); + } else { + con_printf(CON_DEBUG, "EGL: Created window surface\n"); } } - eglDisplay = eglGetDisplay((NativeDisplayType)x11Display); - if (!eglInitialize(eglDisplay, &ver_maj, &ver_min)) { - con_printf(CON_URGENT, "EGL: Error initializing EGL\n"); - } else { - con_printf(CON_URGENT, "EGL: Initialized, version: major %i minor %i\n", ver_maj, ver_min); - } - - if (!eglChooseConfig(eglDisplay, configAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) { - con_printf(CON_URGENT, "EGL: Error choosing config\n"); - } else { - con_printf(CON_URGENT, "EGL: Choosed config\n", ver_maj, ver_min); - } - - eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (NativeWindowType)x11Window, NULL); - if (!TestEGLError("eglCreateWindowSurface")) { - con_printf(CON_URGENT, "EGL: Error creating window surface\n"); - } else { - con_printf(CON_URGENT, "EGL: Created window surface\n"); - } - - eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL); - if (!TestEGLError("eglCreateContext")) { - con_printf(CON_URGENT, "EGL: Error creating context\n"); - } else { - con_printf(CON_URGENT, "EGL: Created context\n"); + if (eglContext == EGL_NO_CONTEXT) { + eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs); + if ((!TestEGLError("eglCreateContext")) || eglContext == EGL_NO_CONTEXT) { + con_printf(CON_URGENT, "EGL: Error creating context\n"); + } else { + con_printf(CON_DEBUG, "EGL: Created context\n"); + } } eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); if (!TestEGLError("eglMakeCurrent")) { con_printf(CON_URGENT, "EGL: Error making current\n"); } else { - con_printf(CON_URGENT, "EGL: Created current\n"); + con_printf(CON_DEBUG, "EGL: made context current\n"); } #endif @@ -206,15 +438,22 @@ int gr_toggle_fullscreen(void) if (gl_initialized) { - if (!SDL_VideoModeOK(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) - { - con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480\n",SM_W(Game_screen_mode), SM_H(Game_screen_mode)); - Game_screen_mode=SM(640,480); + if (sdl_no_modeswitch == 0) { + if (!SDL_VideoModeOK(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) + { + con_printf(CON_URGENT,"Cannot set %ix%i. Fallback to 640x480\n",SM_W(Game_screen_mode), SM_H(Game_screen_mode)); + Game_screen_mode=SM(640,480); + } + if (!SDL_SetVideoMode(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) + { + Error("Could not set %dx%dx%d opengl video mode: %s\n", SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, SDL_GetError()); + } } - if (!SDL_SetVideoMode(SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, sdl_video_flags)) - { - Error("Could not set %dx%dx%d opengl video mode: %s\n", SM_W(Game_screen_mode), SM_H(Game_screen_mode), GameArg.DbgBpp, SDL_GetError()); +#ifdef RPI + if (rpi_setup_element(SM_W(Game_screen_mode), SM_H(Game_screen_mode), sdl_video_flags, 1)) { + Error("RPi: Could not set up %dx%d element\n", SM_W(Game_screen_mode), SM_H(Game_screen_mode)); } +#endif } if (gl_initialized) // update viewing values for menus @@ -328,6 +567,11 @@ int gr_list_modes( u_int32_t gsmodes[] ) int sdl_check_flags = SDL_OPENGL | SDL_FULLSCREEN; // always use Fullscreen as lead. #endif + if (sdl_no_modeswitch) { + /* TODO: we could use the tvservice to list resolutions on the RPi */ + return 0; + } + modes = SDL_ListModes(NULL, sdl_check_flags); if (modes == (SDL_Rect**)0) // check if we get any modes - if not, return 0 @@ -361,7 +605,12 @@ int gr_check_mode(u_int32_t mode) w=SM_W(mode); h=SM_H(mode); - return SDL_VideoModeOK(w, h, GameArg.DbgBpp, sdl_video_flags); + if (sdl_no_modeswitch == 0) { + return SDL_VideoModeOK(w, h, GameArg.DbgBpp, sdl_video_flags); + } else { + // just tell the caller that any mode is valid... + return 32; + } } int gr_set_mode(u_int32_t mode) @@ -470,12 +719,32 @@ void gr_set_attributes(void) int gr_init(int mode) { +#ifdef RPI + char sdl_driver[32]; + char *sdl_driver_ret; +#endif + int retcode; // Only do this function once! if (gr_installed==1) return -1; +#ifdef RPI + // Initialize the broadcom host library + // we have to call this before we can create an OpenGL ES context + bcm_host_init(); + + // Check if we are running with SDL directfb driver ... + sdl_driver_ret=SDL_VideoDriverName(sdl_driver,32); + if (sdl_driver_ret) { + if (strcmp(sdl_driver_ret,"x11")) { + con_printf(CON_URGENT,"RPi: activating hack for console driver\n"); + sdl_no_modeswitch=1; + } + } +#endif + #ifdef _WIN32 ogl_init_load_library(); #endif @@ -534,6 +803,19 @@ void gr_close() if (ogl_rt_loaded) OpenGL_LoadLibrary(false); #endif + +#ifdef OGLES + ogles_destroy(); +#ifdef RPI + con_printf(CON_DEBUG, "RPi: cleanuing up\n"); + if (dispman_display != DISPMANX_NO_HANDLE) { + rpi_destroy_element(); + con_printf(CON_DEBUG, "RPi: closing display\n"); + vc_dispmanx_display_close(dispman_display); + dispman_display = DISPMANX_NO_HANDLE; + } +#endif +#endif } extern int r_upixelc;