sdl: add OpenGL support

Issue #2507.
This commit is contained in:
Josef Söntgen 2017-08-18 14:50:12 +02:00 committed by Christian Helmuth
parent 0fa9a0dda7
commit bc0c78708c
6 changed files with 260 additions and 38 deletions

View File

@ -48,7 +48,7 @@
#define SDL_JOYSTICK_DISABLED 1
/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */
#define SDL_LOADSO_DISABLED 1
#define SDL_LOADSO_DISABLED 0
/* Enable thread support */
#define SDL_THREAD_PTHREAD 1
@ -59,6 +59,8 @@
/* Enable video drivers */
#define SDL_VIDEO_DRIVER_GENODE_FB 1
#define SDL_VIDEO_OPENGL 1
/* #define HAVE_MREMAP 0 */
#define HAVE_MALLOC
#define HAVE_CALLOC

View File

@ -74,7 +74,7 @@ SRC_C += cdrom/SDL_cdrom.c \
INC_DIR += $(SDL_DIR)/src/cdrom
# we need libc
LIBS = libc pthread
LIBS = libc pthread mesa_api
# backend path
vpath % $(REP_DIR)/src/lib/sdl

View File

@ -1 +1 @@
a792d3e8dcb7ffa33d4f9499cc91636dc2e01458
fd5b58f9ae4f2bfd52b7e33076449c66e9647264

View File

@ -31,3 +31,13 @@
#if SDL_VIDEO_DRIVER_DUMMY
extern VideoBootStrap DUMMY_bootstrap;
#endif
+++ src/lib/sdl/include/SDL_opengl.h
@@ -42,7 +42,7 @@
#include <glu.h> /* Header File For The GLU Library */
#else
#include <GL/gl.h> /* Header File For The OpenGL Library */
-#include <GL/glu.h> /* Header File For The GLU Library */
+//#include <GL/glu.h> /* Header File For The GLU Library */
#endif
#ifndef NO_SDL_GLEXT
#undef __glext_h_

View File

@ -28,12 +28,16 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/* Genode includes */
#include <base/log.h>
#include <base/env.h>
#include <framebuffer_session/connection.h>
extern "C" {
#include <dlfcn.h>
#include <SDL/SDL.h>
#include <SDL/SDL_video.h>
#include <SDL/SDL_mouse.h>
@ -48,40 +52,194 @@ extern "C" {
static SDL_Rect *modes[2];
static SDL_Rect df_mode;
/***************************************
* Genode_Fb driver bootstrap functions
**************************************/
#if defined(SDL_VIDEO_OPENGL)
/**
*
*/
static int Genode_Fb_Available(void) {
if(framebuffer == 0)
framebuffer = new(Genode::env()->heap()) Framebuffer::Connection();
if (!framebuffer->cap().valid())
{
Genode::error("couldn't obtain framebuffer session");
#define EGL_EGLEXT_PROTOTYPES
#include <EGL/eglplatform.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#define MAX_CONFIGS 10
#define MAX_MODES 100
/**********************************
** EGL/OpenGL backend functions **
**********************************/
static EGLDisplay display;
static EGLSurface screen_surf;
static EGLNativeWindowType native_window;
typedef EGLBoolean (*eglBindAPI_func) (EGLenum);
typedef EGLBoolean (*eglChooseConfig_func) (EGLDisplay, const EGLint *, EGLConfig *, EGLint , EGLint *);
typedef EGLContext (*eglCreateContext_func) (EGLDisplay, EGLConfig, EGLContext, const EGLint *);
typedef EGLSurface (*eglCreatePixmapSurface_func) (EGLDisplay, EGLConfig, EGLNativePixmapType, const EGLint *);
typedef EGLDisplay (*eglGetDisplay_func) (EGLNativeDisplayType);
typedef EGLBoolean (*eglInitialize_func) (EGLDisplay, EGLint *, EGLint *);
typedef EGLBoolean (*eglMakeCurrent_func) (EGLDisplay, EGLSurface, EGLSurface, EGLContext);
typedef EGLBoolean (*eglSwapBuffers_func) (EGLDisplay, EGLSurface);
typedef EGLBoolean (*eglWaitClient_func) (void);
typedef char const* (*eglQueryString_func) (EGLDisplay, EGLint);
static eglBindAPI_func __eglBindAPI;
static eglChooseConfig_func __eglChooseConfig;
static eglCreateContext_func __eglCreateContext;
static eglCreatePixmapSurface_func __eglCreatePixmapSurface;
static eglGetDisplay_func __eglGetDisplay;
static eglInitialize_func __eglInitialize;
static eglMakeCurrent_func __eglMakeCurrent;
static eglSwapBuffers_func __eglSwapBuffers;
static eglWaitClient_func __eglWaitClient;
static eglQueryString_func __eglQueryString;
static void *__mesa;
static bool init_egl()
{
void *egl = dlopen("egl.lib.so", 0);
if (!egl) {
Genode::error("could not open EGL library");
return false;
}
#define LOAD_GL_FUNC(lib, sym) \
__ ## sym = (sym ##_func) dlsym(lib, #sym); \
if (!__ ## sym) { return false; }
LOAD_GL_FUNC(egl, eglBindAPI)
LOAD_GL_FUNC(egl, eglChooseConfig)
LOAD_GL_FUNC(egl, eglCreateContext)
LOAD_GL_FUNC(egl, eglCreatePixmapSurface)
LOAD_GL_FUNC(egl, eglGetDisplay)
LOAD_GL_FUNC(egl, eglInitialize)
LOAD_GL_FUNC(egl, eglMakeCurrent)
LOAD_GL_FUNC(egl, eglQueryString)
LOAD_GL_FUNC(egl, eglSwapBuffers)
LOAD_GL_FUNC(egl, eglWaitClient)
LOAD_GL_FUNC(egl, eglWaitClient)
#undef LOAD_GL_FUNC
return true;
}
static bool init_opengl(SDL_VideoDevice *t)
{
__mesa = dlopen("mesa.lib.so", 0);
if (!__mesa) {
Genode::error("could not open mesa library");
return false;
}
if (!init_egl()) { return false; }
int maj, min;
EGLContext ctx;
EGLConfig configs[MAX_CONFIGS];
GLboolean printInfo = GL_FALSE;
display = __eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!display) {
Genode::error("eglGetDisplay failed\n");
return false;
}
if (!__eglInitialize(display, &maj, &min)) {
Genode::error("eglInitialize failed\n");
return false;
}
Genode::log("EGL version = ", maj, ".", min);
Genode::log("EGL_VENDOR = ", __eglQueryString(display, EGL_VENDOR));
EGLConfig config;
EGLint config_attribs[32];
EGLint renderable_type, num_configs, i;
i = 0;
config_attribs[i++] = EGL_RED_SIZE;
config_attribs[i++] = 1;
config_attribs[i++] = EGL_GREEN_SIZE;
config_attribs[i++] = 1;
config_attribs[i++] = EGL_BLUE_SIZE;
config_attribs[i++] = 1;
config_attribs[i++] = EGL_DEPTH_SIZE;
config_attribs[i++] = 1;
config_attribs[i++] = EGL_SURFACE_TYPE;
config_attribs[i++] = EGL_WINDOW_BIT;;
config_attribs[i++] = EGL_RENDERABLE_TYPE;
renderable_type = 0x0;
renderable_type |= EGL_OPENGL_BIT;
config_attribs[i++] = renderable_type;
config_attribs[i] = EGL_NONE;
if (!__eglChooseConfig(display, config_attribs, &config, 1, &num_configs)
|| !num_configs) {
Genode::error("eglChooseConfig failed");
return false;
}
__eglBindAPI(EGL_OPENGL_API);
EGLint context_attribs[4]; context_attribs[0] = EGL_NONE;
ctx = __eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs);
if (!ctx) {
Genode::error("eglCreateContext failed");
return false;
}
Genode_egl_window egl_window { scr_mode.width(), scr_mode.height(),
(unsigned char*)t->hidden->buffer };
screen_surf = __eglCreatePixmapSurface(display, config, &egl_window, NULL);
if (screen_surf == EGL_NO_SURFACE) {
Genode::error("eglCreatePixmapSurface failed");
return false;
}
if (!__eglMakeCurrent(display, screen_surf, screen_surf, ctx)) {
Genode::error("eglMakeCurrent failed");
return false;
}
t->gl_config.driver_loaded = 1;
return true;
}
#endif
/****************************************
* Genode_Fb driver bootstrap functions *
****************************************/
static int Genode_Fb_Available(void)
{
if (framebuffer == nullptr) {
framebuffer = new (Genode::env()->heap()) Framebuffer::Connection();
}
if (!framebuffer->cap().valid()) {
Genode::error("could not obtain framebuffer session");
return 0;
}
return 1;
}
/**
*
*/
static void Genode_Fb_DeleteDevice(SDL_VideoDevice *device)
{
Genode::log("free framebuffer session object");
if(framebuffer != 0)
if(framebuffer != nullptr) {
Genode::destroy(Genode::env()->heap(), framebuffer);
framebuffer = 0;
}
framebuffer = nullptr;
}
/**
*
*/
static SDL_VideoDevice *Genode_Fb_CreateDevice(int devindex)
{
SDL_VideoDevice *device;
@ -127,6 +285,11 @@ extern "C" {
device->IconifyWindow = 0;
device->GrabInput = 0;
device->GetWMInfo = 0;
device->GL_MakeCurrent = Genode_Fb_GL_MakeCurrent;
device->GL_SwapBuffers = Genode_Fb_GL_SwapBuffers;
device->GL_LoadLibrary = Genode_Fb_GL_LoadLibrary;
device->GL_GetProcAddress = Genode_Fb_GL_GetProcAddress;
return device;
}
@ -147,7 +310,7 @@ extern "C" {
*/
int Genode_Fb_VideoInit(SDL_VideoDevice *t, SDL_PixelFormat *vformat)
{
if(framebuffer == 0)
if (framebuffer == 0)
{
Genode::error("framebuffer isn't initialized");
return -1;
@ -189,7 +352,6 @@ extern "C" {
return -1;
}
t->hidden->buffer = Genode::env()->rm_session()->attach(fb_ds_cap);
return 0;
}
@ -202,8 +364,7 @@ extern "C" {
SDL_PixelFormat *format,
Uint32 flags)
{
if(format->BitsPerPixel != 16)
return (SDL_Rect **) 0;
if(format->BitsPerPixel != 16) { return (SDL_Rect **) 0; }
return modes;
}
@ -225,25 +386,35 @@ extern "C" {
Genode::log("Set video mode to: "
"width=", width, " " "height=", height, " " "bpp=", bpp);
if ( ! t->hidden->buffer ) {
if (!t->hidden->buffer) {
Genode::error("no buffer for requested mode");
return(0);
return nullptr;
}
SDL_memset(t->hidden->buffer, 0, width * height * (bpp / 8));
/* Allocate the new pixel format for the screen */
if ( ! SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
if (!SDL_ReallocFormat(current, bpp, 0, 0, 0, 0) ) {
Genode::error("couldn't allocate new pixel format for requested mode");
return(0);
return nullptr;
}
/* Set up the new mode framebuffer */
current->flags = flags & SDL_FULLSCREEN;
current->flags = flags | SDL_FULLSCREEN;
t->hidden->w = current->w = width;
t->hidden->h = current->h = height;
current->pitch = current->w * (bpp / 8);
#if defined(SDL_VIDEO_OPENGL)
if ((flags & SDL_OPENGL) && !init_opengl(t)) {
return nullptr;
}
#endif
/*
* XXX if SDL ever wants to free the pixels pointer,
* free() in the libc will trigger a page-fault
*/
current->pixels = t->hidden->buffer;
return(current);
return current;
}
@ -271,7 +442,7 @@ extern "C" {
static int Genode_Fb_LockHWSurface(SDL_VideoDevice *t,
SDL_Surface *surface)
{
Genode::log(__func__, " not supported yet ...");
/* Genode::log(__func__, " not supported yet ..."); */
return 0;
}
@ -279,7 +450,7 @@ extern "C" {
static void Genode_Fb_UnlockHWSurface(SDL_VideoDevice *t,
SDL_Surface *surface)
{
Genode::log(__func__, " not supported yet ...");
/* Genode::log(__func__, " not supported yet ..."); */
}
@ -287,8 +458,9 @@ extern "C" {
SDL_Rect *rects)
{
int i;
for(i=0;i<numrects;i++)
for(i=0;i<numrects;i++) {
framebuffer->refresh(rects[i].x, rects[i].y, rects[i].w, rects[i].h);
}
}
@ -304,7 +476,7 @@ extern "C" {
int Genode_Fb_SetColors(SDL_VideoDevice *t, int firstcolor,
int ncolors, SDL_Color *colors)
{
Genode::warning(__func__, " not implemented yet");
Genode::warning(__func__, " not yet implemented");
return 1;
}
@ -323,4 +495,33 @@ extern "C" {
}
}
int Genode_Fb_GL_MakeCurrent(SDL_VideoDevice *t)
{
Genode::warning(__func__, ": not yet implemented");
return 0;
}
void Genode_Fb_GL_SwapBuffers(SDL_VideoDevice *t)
{
#if defined(SDL_VIDEO_OPENGL)
__eglWaitClient();
__eglSwapBuffers(display, screen_surf);
framebuffer->refresh(0, 0, scr_mode.width(), scr_mode.height());
#endif
}
int Genode_Fb_GL_LoadLibrary(SDL_VideoDevice *t, const char *path)
{
Genode::warning(__func__, ": not yet implemented");
return 0;
}
void* Genode_Fb_GL_GetProcAddress(SDL_VideoDevice *t, const char *proc)
{
return !__mesa ? nullptr : dlsym(__mesa, proc);
}
} //extern "C"

View File

@ -65,4 +65,13 @@ static void Genode_Fb_FreeHWSurface(SDL_VideoDevice *t, SDL_Surface *surface);
*/
static void Genode_Fb_UpdateRects(SDL_VideoDevice *t, int numrects,
SDL_Rect *rects);
/**
* OpenGL functions
*/
static int Genode_Fb_GL_MakeCurrent(SDL_VideoDevice *t);
static void Genode_Fb_GL_SwapBuffers(SDL_VideoDevice *t);
static int Genode_Fb_GL_LoadLibrary(SDL_VideoDevice *t, const char *path);
static void* Genode_Fb_GL_GetProcAddress(SDL_VideoDevice *t, const char *proc);
#endif // _SDL_genode_fb_video_h