diff --git a/repos/libports/include/SDL/SDL_config_genode.h b/repos/libports/include/SDL/SDL_config_genode.h index 069c2009e..d1d21fa82 100644 --- a/repos/libports/include/SDL/SDL_config_genode.h +++ b/repos/libports/include/SDL/SDL_config_genode.h @@ -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 diff --git a/repos/libports/lib/mk/sdl.mk b/repos/libports/lib/mk/sdl.mk index 50aec58c9..e4458ebf2 100644 --- a/repos/libports/lib/mk/sdl.mk +++ b/repos/libports/lib/mk/sdl.mk @@ -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 diff --git a/repos/libports/ports/sdl.hash b/repos/libports/ports/sdl.hash index c0f558c63..b02749d89 100644 --- a/repos/libports/ports/sdl.hash +++ b/repos/libports/ports/sdl.hash @@ -1 +1 @@ -a792d3e8dcb7ffa33d4f9499cc91636dc2e01458 +fd5b58f9ae4f2bfd52b7e33076449c66e9647264 diff --git a/repos/libports/src/lib/sdl/SDL_video.patch b/repos/libports/src/lib/sdl/SDL_video.patch index 16cad3b8a..d96620a80 100644 --- a/repos/libports/src/lib/sdl/SDL_video.patch +++ b/repos/libports/src/lib/sdl/SDL_video.patch @@ -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 /* Header File For The GLU Library */ + #else + #include /* Header File For The OpenGL Library */ +-#include /* Header File For The GLU Library */ ++//#include /* Header File For The GLU Library */ + #endif + #ifndef NO_SDL_GLEXT + #undef __glext_h_ diff --git a/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.cc b/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.cc index ba422995f..ff5ab5acc 100644 --- a/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.cc +++ b/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.cc @@ -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 #include #include extern "C" { +#include + #include #include #include @@ -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 +#include +#include + +#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;irefresh(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" diff --git a/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.h b/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.h index 7185325fe..72193d05b 100644 --- a/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.h +++ b/repos/libports/src/lib/sdl/video/SDL_genode_fb_video.h @@ -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