Support for Raspberry Pi - patch by derhass

This commit is contained in:
zico 2013-04-08 12:54:02 +02:00
parent 3553ea3cf7
commit 758f2d64f8
4 changed files with 422 additions and 49 deletions

View file

@ -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

72
README.RPi Normal file
View file

@ -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 <derhass@arcor.de>
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

View file

@ -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 + """

View file

@ -6,6 +6,11 @@
#define DECLARE_VARS
#ifdef RPI
// extra libraries for the Raspberry Pi
#include "bcm_host.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -51,7 +56,7 @@
#include <OpenGL/glu.h>
#else
#ifdef OGLES
#include <GLES/egl.h>
#include <EGL/egl.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <SDL/SDL_syswm.h>
@ -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;