From d0e220bbf1c3e5b21e79ebed8019da0abe102d92 Mon Sep 17 00:00:00 2001 From: Themaister Date: Tue, 25 Sep 2012 01:26:22 +0200 Subject: [PATCH] Refactor all GL context handling code. --- Makefile | 45 ++++---- Makefile.win | 2 +- gfx/context/drm_egl_ctx.c | 212 +++++++++++++++++++------------------- gfx/context/ps3_ctx.c | 45 ++++++-- gfx/context/sdl_ctx.c | 98 ++++++++++-------- gfx/context/vc_egl_ctx.c | 78 ++++++++------ gfx/context/xegl_ctx.c | 64 +++++++++--- gfx/gfx_context.c | 66 ++++++++++++ gfx/gfx_context.h | 90 +++++++++++++--- gfx/gl.c | 107 +++++++++---------- gfx/gl_common.h | 17 +-- gfx/shader_glsl.c | 11 +- gfx/shader_glsl.h | 3 + input/dinput.c | 3 +- qb/config.libs.sh | 15 ++- qb/config.params.sh | 5 +- 16 files changed, 547 insertions(+), 314 deletions(-) create mode 100644 gfx/gfx_context.c diff --git a/Makefile b/Makefile index 43c968ec2f..277bfdbb5f 100644 --- a/Makefile +++ b/Makefile @@ -129,27 +129,27 @@ ifeq ($(HAVE_COREAUDIO), 1) LIBS += -framework CoreServices -framework CoreAudio -framework AudioUnit endif +ifeq ($(SCALER_NO_SIMD), 1) + DEFINES += -DSCALER_NO_SIMD +endif + +ifeq ($(SCALER_PERF), 1) + DEFINES += -DSCALER_PERF +endif + ifeq ($(HAVE_SDL), 1) OBJ += gfx/sdl_gfx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o DEFINES += $(SDL_CFLAGS) $(BSD_LOCAL_INC) LIBS += $(SDL_LIBS) - ifeq ($(SCALER_NO_SIMD), 1) - DEFINES += -DSCALER_NO_SIMD - endif - - ifeq ($(SCALER_PERF), 1) - DEFINES += -DSCALER_PERF - endif - ifeq ($(HAVE_X11), 1) LIBS += $(X11_LIBS) DEFINES += $(X11_CFLAGS) endif ifeq ($(HAVE_OPENGL), 1) - OBJ += gfx/gl.o gfx/fonts/freetype.o gfx/math/matrix.o + OBJ += gfx/gl.o gfx/gfx_context.o gfx/fonts/freetype.o gfx/math/matrix.o ifeq ($(OSX), 1) LIBS += -framework OpenGL @@ -158,24 +158,29 @@ ifeq ($(HAVE_SDL), 1) OBJ += gfx/context/drm_egl_ctx.o DEFINES += $(GBM_CFLAGS) $(DRM_CFLAGS) $(EGL_CFLAGS) LIBS += $(GBM_LIBS) $(DRM_LIBS) $(EGL_LIBS) - else ifeq ($(HAVE_VIDEOCORE), 1) + endif + ifeq ($(HAVE_VIDEOCORE), 1) OBJ += gfx/context/vc_egl_ctx.o # videocore's libs set later - else ifeq ($(HAVE_GLES), 1) + endif + + ifeq ($(HAVE_X11), 1) + ifeq ($(HAVE_EGL), 1) OBJ += gfx/context/xegl_ctx.o DEFINES += $(EGL_CFLAGS) LIBS += $(EGL_LIBS) - else - LIBS += -lGL - OBJ += gfx/context/sdl_ctx.o endif + endif + + endif - ifeq ($(HAVE_GLES), 1) - LIBS += -lGLESv2 - DEFINES += -DHAVE_OPENGLES -DHAVE_OPENGLES2 - else - LIBS += -lGL - endif + OBJ += gfx/context/sdl_ctx.o + + ifeq ($(HAVE_GLES), 1) + LIBS += -lGLESv2 + DEFINES += -DHAVE_OPENGLES -DHAVE_OPENGLES2 + else + LIBS += -lGL endif endif diff --git a/Makefile.win b/Makefile.win index 5e3931f634..879ee04cc3 100644 --- a/Makefile.win +++ b/Makefile.win @@ -61,7 +61,7 @@ ifeq ($(TDM_GCC),) endif ifeq ($(HAVE_SDL), 1) - OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o + OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/math/matrix.o gfx/fonts/freetype.o gfx/context/sdl_ctx.o gfx/gfx_context.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o OBJ += gfx/scaler/scaler.o gfx/scaler/pixconv.o gfx/scaler/scaler_int.o gfx/scaler/filter.o LIBS += -lSDL DEFINES += -ISDL -DHAVE_SDL diff --git a/gfx/context/drm_egl_ctx.c b/gfx/context/drm_egl_ctx.c index 84fb0b75fc..cf4980d420 100644 --- a/gfx/context/drm_egl_ctx.c +++ b/gfx/context/drm_egl_ctx.c @@ -54,6 +54,7 @@ static EGLConfig g_config; static volatile sig_atomic_t g_quit; static bool g_inited; static unsigned g_interval; +static enum gfx_ctx_api g_api; static struct gbm_device *g_gbm_dev; static struct gbm_surface *g_gbm_surface; @@ -81,6 +82,7 @@ struct drm_fb }; static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo); +static void gfx_ctx_destroy(void); static void sighandler(int sig) { @@ -88,12 +90,12 @@ static void sighandler(int sig) g_quit = 1; } -void gfx_ctx_set_swap_interval(unsigned interval, bool inited) +static void gfx_ctx_swap_interval(unsigned interval) { g_interval = interval; } -void gfx_ctx_check_window(bool *quit, +static void gfx_ctx_check_window(bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { (void)frame_count; @@ -204,7 +206,7 @@ static void queue_flip(void) waiting_for_flip = true; } -void gfx_ctx_swap_buffers(void) +static void gfx_ctx_swap_buffers(void) { eglSwapBuffers(g_egl_dpy, g_egl_surf); @@ -226,65 +228,28 @@ void gfx_ctx_swap_buffers(void) } } -void gfx_ctx_set_resize(unsigned width, unsigned height) +static void gfx_ctx_set_resize(unsigned width, unsigned height) { (void)width; (void)height; } -void gfx_ctx_update_window_title(bool reset) +static void gfx_ctx_update_window_title(bool reset) { (void)reset; } -void gfx_ctx_get_video_size(unsigned *width, unsigned *height) +static void gfx_ctx_get_video_size(unsigned *width, unsigned *height) { *width = g_fb_width; *height = g_fb_height; } -#if 0 -static void reschedule_process(void) -{ - struct sched_param param = {0}; - - // All-out real-time. Why not? :D - param.sched_priority = sched_get_priority_max(SCHED_FIFO); - if (sched_setscheduler(0, SCHED_FIFO, ¶m) < 0) - RARCH_ERR("[KMS/EGL]: Failed to set SCHED_FIFO priority.\n"); - - int sched = sched_getscheduler(getpid()); - - const char *scheduler; - switch (sched) - { - case SCHED_OTHER: - scheduler = "SCHED_OTHER"; - break; - - case SCHED_FIFO: - scheduler = "SCHED_FIFO"; - break; - - default: - scheduler = "Unrelated"; - } - - RARCH_LOG("[KMS/EGL]: Current scheduler: %s\n", scheduler); - if (sched == SCHED_FIFO) - RARCH_LOG("[KMS/EGL]: SCHED_FIFO prio: %d\n", param.sched_priority); -} -#endif - -bool gfx_ctx_init(void) +static bool gfx_ctx_init(void) { if (g_inited) return false; -#if 0 - reschedule_process(); -#endif - static const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", NULL }; @@ -367,8 +332,8 @@ bool gfx_ctx_init(void) goto error; } - g_crtc_id = g_encoder->crtc_id; - g_connector_id = g_connector->connector_id; + g_crtc_id = g_encoder->crtc_id; + g_connector_id = g_connector->connector_id; g_fb_width = g_drm_mode->hdisplay; g_fb_height = g_drm_mode->vdisplay; @@ -385,6 +350,64 @@ bool gfx_ctx_init(void) goto error; } + return true; + +error: + gfx_ctx_destroy(); + return false; +} + +static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data) +{ + struct drm_fb *fb = (struct drm_fb*)data; + + if (fb->fb_id) + drmModeRmFB(g_drm_fd, fb->fb_id); + + free(fb); +} + +static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo) +{ + struct drm_fb *fb = (struct drm_fb*)gbm_bo_get_user_data(bo); + if (fb) + return fb; + + fb = (struct drm_fb*)calloc(1, sizeof(*fb)); + fb->bo = bo; + + unsigned width = gbm_bo_get_width(bo); + unsigned height = gbm_bo_get_height(bo); + unsigned stride = gbm_bo_get_stride(bo); + unsigned handle = gbm_bo_get_handle(bo).u32; + + int ret = drmModeAddFB(g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id); + if (ret < 0) + { + RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno)); + free(fb); + return NULL; + } + + gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); + return fb; +} + +static bool gfx_ctx_set_video_mode( + unsigned width, unsigned height, + unsigned bits, bool fullscreen) +{ + (void)bits; + if (g_inited) + return false; + + struct sigaction sa = {{0}}; + sa.sa_handler = sighandler; + sa.sa_flags = SA_RESTART; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE @@ -430,64 +453,6 @@ bool gfx_ctx_init(void) if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx)) goto error; - return true; - -error: - gfx_ctx_destroy(); - return false; -} - -static void drm_fb_destroy_callback(struct gbm_bo *bo, void *data) -{ - struct drm_fb *fb = (struct drm_fb*)data; - - if (fb->fb_id) - drmModeRmFB(g_drm_fd, fb->fb_id); - - free(fb); -} - -static struct drm_fb *drm_fb_get_from_bo(struct gbm_bo *bo) -{ - struct drm_fb *fb = (struct drm_fb*)gbm_bo_get_user_data(bo); - if (fb) - return fb; - - fb = (struct drm_fb*)calloc(1, sizeof(*fb)); - fb->bo = bo; - - unsigned width = gbm_bo_get_width(bo); - unsigned height = gbm_bo_get_height(bo); - unsigned stride = gbm_bo_get_stride(bo); - unsigned handle = gbm_bo_get_handle(bo).u32; - - int ret = drmModeAddFB(g_drm_fd, width, height, 24, 32, stride, handle, &fb->fb_id); - if (ret < 0) - { - RARCH_ERR("[KMS/EGL]: Failed to create FB: %s\n", strerror(errno)); - free(fb); - return NULL; - } - - gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback); - return fb; -} - -bool gfx_ctx_set_video_mode( - unsigned width, unsigned height, - unsigned bits, bool fullscreen) -{ - (void)bits; - if (g_inited) - return false; - - struct sigaction sa = {{0}}; - sa.sa_handler = sighandler; - sa.sa_flags = SA_RESTART; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); - glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(g_egl_dpy, g_egl_surf); @@ -596,20 +561,53 @@ void gfx_ctx_destroy(void) g_inited = false; } -void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) +static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) { void *linuxinput = input_linuxraw.init(); *input = linuxinput ? &input_linuxraw : NULL; *input_data = linuxinput; } -bool gfx_ctx_window_has_focus(void) +static bool gfx_ctx_has_focus(void) { return g_inited; } -gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) +static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) { return eglGetProcAddress(symbol); } +static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +{ + g_api = api; + switch (api) + { + case GFX_CTX_OPENGL_API: + return eglBindAPI(EGL_OPENGL_API); + case GFX_CTX_OPENGL_ES_API: + return eglBindAPI(EGL_OPENGL_ES_API); + case GFX_CTX_OPENVG_API: + return eglBindAPI(EGL_OPENVG_API); + default: + return false; + } +} + +const gfx_ctx_driver_t gfx_ctx_drm_egl = { + gfx_ctx_init, + gfx_ctx_destroy, + gfx_ctx_bind_api, + gfx_ctx_swap_interval, + gfx_ctx_set_video_mode, + gfx_ctx_get_video_size, + gfx_ctx_update_window_title, + gfx_ctx_check_window, + gfx_ctx_set_resize, + gfx_ctx_has_focus, + gfx_ctx_swap_buffers, + gfx_ctx_input_driver, + gfx_ctx_get_proc_address, + "drm-egl", +}; + diff --git a/gfx/context/ps3_ctx.c b/gfx/context/ps3_ctx.c index 1d6a58a114..7fa4adc2d6 100644 --- a/gfx/context/ps3_ctx.c +++ b/gfx/context/ps3_ctx.c @@ -139,10 +139,8 @@ void gfx_ctx_get_available_resolutions (void) g_console.check_available_resolutions = true; } -void gfx_ctx_set_swap_interval(unsigned interval, bool inited) +void gfx_ctx_set_swap_interval(unsigned interval) { - (void)inited; - #if defined(HAVE_PSGL) if (gl_context) { @@ -172,12 +170,10 @@ void gfx_ctx_check_window(bool *quit, *resize = true; } -#ifndef HAVE_GRIFFIN -bool gfx_ctx_window_has_focus(void) +bool gfx_ctx_has_focus(void) { return true; } -#endif void gfx_ctx_swap_buffers(void) { @@ -413,3 +409,40 @@ void gfx_ctx_set_overscan(void) gl->should_resize = true; } + +static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +{ + return api == GFX_CTX_OPENGL_API || GFX_CTX_OPENGL_ES_API; +} + +const gfx_ctx_driver_t gfx_ctx_ps3 = { + gfx_ctx_init, + gfx_ctx_destroy, + gfx_ctx_bind_api, + gfx_ctx_set_swap_interval, + gfx_ctx_set_video_mode, + gfx_ctx_get_video_size, + gfx_ctx_update_window_title, + gfx_ctx_check_window, + gfx_ctx_set_resize, + gfx_ctx_has_focus, + gfx_ctx_swap_buffers, + gfx_ctx_input_driver, + gfx_ctx_get_proc_address, + "ps3", + + // RARCH_CONSOLE stuff. + gfx_set_filtering, + gfx_get_available_resolutions, + gfx_check_resolutions, + +#ifdef HAVE_CG_MENU + gfx_menu_init, +#else + NULL, +#endif + + gfx_set_fbo, + gfx_apply_fbo_state_changes, +}; + diff --git a/gfx/context/sdl_ctx.c b/gfx/context/sdl_ctx.c index 4cb7b2e67c..d2c44b0377 100644 --- a/gfx/context/sdl_ctx.c +++ b/gfx/context/sdl_ctx.c @@ -41,13 +41,16 @@ static bool g_fullscreen; static unsigned g_interval; +static bool g_inited; -void gfx_ctx_set_swap_interval(unsigned interval, bool inited) +static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol); + +static void gfx_ctx_swap_interval(unsigned interval) { g_interval = interval; bool success = true; - if (inited) + if (g_inited) { #if defined(_WIN32) static BOOL (APIENTRY *wgl_swap_interval)(int) = NULL; @@ -81,7 +84,7 @@ static void gfx_ctx_wm_set_caption(const char *str) SDL_WM_SetCaption(str, NULL); } -void gfx_ctx_update_window_title(bool reset) +static void gfx_ctx_update_window_title(bool reset) { if (reset) gfx_window_title_reset(); @@ -91,15 +94,15 @@ void gfx_ctx_update_window_title(bool reset) gfx_ctx_wm_set_caption(buf); } -void gfx_ctx_get_video_size(unsigned *width, unsigned *height) +static void gfx_ctx_get_video_size(unsigned *width, unsigned *height) { const SDL_VideoInfo *video_info = SDL_GetVideoInfo(); rarch_assert(video_info); - *width = video_info->current_w; + *width = video_info->current_w; *height = video_info->current_h; } -bool gfx_ctx_init(void) +static bool gfx_ctx_init(void) { if (SDL_WasInit(SDL_INIT_VIDEO)) return true; @@ -111,12 +114,13 @@ bool gfx_ctx_init(void) return ret; } -void gfx_ctx_destroy(void) +static void gfx_ctx_destroy(void) { SDL_QuitSubSystem(SDL_INIT_VIDEO); + g_inited = false; } -bool gfx_ctx_set_video_mode( +static bool gfx_ctx_set_video_mode( unsigned width, unsigned height, unsigned bits, bool fullscreen) { @@ -136,12 +140,14 @@ bool gfx_ctx_set_video_mode( return false; } + g_inited = true; + int attr = 0; SDL_GL_GetAttribute(SDL_GL_SWAP_CONTROL, &attr); if (attr <= 0 && g_interval) { RARCH_WARN("SDL failed to setup VSync, attempting to recover using native calls.\n"); - gfx_ctx_set_swap_interval(g_interval, true); + gfx_ctx_swap_interval(g_interval); } g_fullscreen = fullscreen; @@ -158,8 +164,9 @@ bool gfx_ctx_set_video_mode( #if defined(HAVE_X11) && !defined(__APPLE__) RARCH_LOG("Suspending screensaver (X11).\n"); SDL_SysWMinfo info; + SDL_VERSION(&info.version); - if (gfx_ctx_get_wm_info(&info)) + if (SDL_GetWMInfo(&info) == 1) gfx_suspend_screensaver(info.info.x11.window); else RARCH_ERR("Failed to get SDL WM info, cannot suspend screensaver.\n"); @@ -169,8 +176,7 @@ bool gfx_ctx_set_video_mode( } // SDL 1.2 has an awkward model where you need to "confirm" window resizing. -// SDL 1.3 luckily removes this quirk. -void gfx_ctx_set_resize(unsigned width, unsigned height) +static void gfx_ctx_set_resize(unsigned width, unsigned height) { #ifndef __APPLE__ // Resizing on OSX is broken in 1.2 it seems :) static const int resizable = SDL_RESIZABLE; @@ -180,14 +186,13 @@ void gfx_ctx_set_resize(unsigned width, unsigned height) SDL_SetVideoMode(width, height, 0, SDL_OPENGL | (g_fullscreen ? SDL_FULLSCREEN : resizable)); } -void gfx_ctx_swap_buffers(void) +static void gfx_ctx_swap_buffers(void) { SDL_GL_SwapBuffers(); } -// 1.2 specific workaround for tiling WMs. In 1.3 we call GetSize directly, so we don't need to rely on -// proper event handling (I hope). -#if !defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_X11) +// 1.2 specific workaround for tiling WMs. +#if defined(HAVE_X11) && !defined(__APPLE__) // This X11 is set on OSX for some reason. static bool gfx_ctx_get_window_size(unsigned *width, unsigned *height) { @@ -210,9 +215,12 @@ static bool gfx_ctx_get_window_size(unsigned *width, unsigned *height) } #endif -static void check_window(bool *quit, +static void gfx_ctx_check_window(bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { + *quit = false; + *resize = false; + SDL_Event event; while (SDL_PollEvent(&event)) { @@ -230,7 +238,7 @@ static void check_window(bool *quit, } } -#if defined(SDL_VIDEO_DRIVER_X11) && !defined(__APPLE__) +#if defined(HAVE_X11) && !defined(__APPLE__) if (!*resize && !g_fullscreen) { unsigned new_width, new_height; @@ -252,34 +260,12 @@ static void check_window(bool *quit, #endif } -void gfx_ctx_check_window(bool *quit, - bool *resize, unsigned *width, unsigned *height, unsigned frame_count) -{ - *quit = false; - *resize = false; - - check_window(quit, resize, width, height, frame_count); -} - -#ifndef __APPLE__ -bool gfx_ctx_get_wm_info(SDL_SysWMinfo *info) -{ -#ifdef XENON - (void)info; - return false; -#else - SDL_VERSION(&info->version); - return SDL_GetWMInfo(info) == 1; -#endif -} -#endif - -bool gfx_ctx_window_has_focus(void) +static bool gfx_ctx_has_focus(void) { return (SDL_GetAppState() & (SDL_APPINPUTFOCUS | SDL_APPACTIVE)) == (SDL_APPINPUTFOCUS | SDL_APPACTIVE); } -void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) +static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) { void *sdl_input = input_sdl.init(); if (sdl_input) @@ -291,12 +277,13 @@ void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) *input = NULL; } -#ifdef HAVE_OPENGL // Enforce void (*)(void) as it's not really legal to cast void* to fn-pointer. // POSIX allows this, but strict C99 doesn't. -gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) +static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) { + // This will not fail on any system RetroArch would run on, but let's just be defensive. rarch_assert(sizeof(void*) == sizeof(void (*)(void))); + gfx_ctx_proc_t ret; void *sym__ = SDL_GL_GetProcAddress(symbol); @@ -304,5 +291,26 @@ gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) return ret; } -#endif + +static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +{ + return api == GFX_CTX_OPENGL_API; +} + +const gfx_ctx_driver_t gfx_ctx_sdl_gl = { + gfx_ctx_init, + gfx_ctx_destroy, + gfx_ctx_bind_api, + gfx_ctx_swap_interval, + gfx_ctx_set_video_mode, + gfx_ctx_get_video_size, + gfx_ctx_update_window_title, + gfx_ctx_check_window, + gfx_ctx_set_resize, + gfx_ctx_has_focus, + gfx_ctx_swap_buffers, + gfx_ctx_input_driver, + gfx_ctx_get_proc_address, + "sdl-gl", +}; diff --git a/gfx/context/vc_egl_ctx.c b/gfx/context/vc_egl_ctx.c index e11ddc98a0..901b79b6d0 100644 --- a/gfx/context/vc_egl_ctx.c +++ b/gfx/context/vc_egl_ctx.c @@ -43,6 +43,7 @@ static EGLConfig g_config; static volatile sig_atomic_t g_quit; static bool g_inited; +static gfx_ctx_api g_api; static unsigned g_fb_width; // Just use something for now. static unsigned g_fb_height; @@ -59,12 +60,12 @@ static void sighandler(int sig) g_quit = 1; } -void gfx_ctx_set_swap_interval(unsigned interval, bool inited) +static void gfx_ctx_set_swap_interval(unsigned interval, bool inited) { eglSwapInterval(g_egl_dpy, interval); } -void gfx_ctx_check_window(bool *quit, +static void gfx_ctx_check_window(bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { (void)frame_count; @@ -75,29 +76,29 @@ void gfx_ctx_check_window(bool *quit, *quit = g_quit; } -void gfx_ctx_swap_buffers(void) +static void gfx_ctx_swap_buffers(void) { eglSwapBuffers(g_egl_dpy, g_egl_surf); } -void gfx_ctx_set_resize(unsigned width, unsigned height) +static void gfx_ctx_set_resize(unsigned width, unsigned height) { (void)width; (void)height; } -void gfx_ctx_update_window_title(bool reset) +static void gfx_ctx_update_window_title(bool reset) { (void)reset; } -void gfx_ctx_get_video_size(unsigned *width, unsigned *height) +static void gfx_ctx_get_video_size(unsigned *width, unsigned *height) { *width = g_fb_width; *height = g_fb_height; } -bool gfx_ctx_init(void) +static bool gfx_ctx_init(void) { if (g_inited) { @@ -189,7 +190,7 @@ bool gfx_ctx_init(void) return true; } -bool gfx_ctx_set_video_mode( +static bool gfx_ctx_set_video_mode( unsigned width, unsigned height, unsigned bits, bool fullscreen) { @@ -208,7 +209,7 @@ bool gfx_ctx_set_video_mode( return true; } -void gfx_ctx_destroy(void) +static void gfx_ctx_destroy(void) { if (g_egl_dpy) { @@ -227,39 +228,56 @@ void gfx_ctx_destroy(void) g_egl_surf = NULL; g_egl_dpy = NULL; g_config = 0; - g_inited = false; + g_inited = false; } -void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) +static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) { void *linuxinput = input_linuxraw.init(); *input = linuxinput ? &input_linuxraw : NULL; *input_data = linuxinput; } -void gfx_ctx_set_projection(gl_t *gl, const struct gl_ortho *ortho, bool allow_rotate) -{ - // Calculate projection. - math_matrix proj; - matrix_ortho(&proj, ortho->left, ortho->right, - ortho->bottom, ortho->top, ortho->znear, ortho->zfar); - - if (allow_rotate) - { - math_matrix rot; - matrix_rotate_z(&rot, M_PI * gl->rotation / 180.0f); - matrix_multiply(&proj, &rot, &proj); - } - - gl->mvp = proj; -} - -bool gfx_ctx_window_has_focus(void) +static bool gfx_ctx_window_has_focus(void) { return g_inited; } -gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) +static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) { return eglGetProcAddress(symbol); } + +static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +{ + g_api = api; + switch (api) + { + case GFX_CTX_OPENGL_API: + return eglBindAPI(EGL_OPENGL_API); + case GFX_CTX_OPENGL_ES_API: + return eglBindAPI(EGL_OPENGL_ES_API); + case GFX_CTX_OPENVG_API: + return eglBindAPI(EGL_OPENVG_API); + default: + return false; + } +} + +const gfx_ctx_driver_t gfx_ctx_videocore = { + gfx_ctx_init, + gfx_ctx_destroy, + gfx_ctx_bind_api, + gfx_ctx_swap_interval, + gfx_ctx_set_video_mode, + gfx_ctx_get_video_size, + gfx_ctx_update_window_title, + gfx_ctx_check_window, + gfx_ctx_set_resize, + gfx_ctx_has_focus, + gfx_ctx_swap_buffers, + gfx_ctx_input_driver, + gfx_ctx_get_proc_address, + "videocore", +}; + diff --git a/gfx/context/xegl_ctx.c b/gfx/context/xegl_ctx.c index 65b5f4da7a..5266cb7a92 100644 --- a/gfx/context/xegl_ctx.c +++ b/gfx/context/xegl_ctx.c @@ -44,6 +44,7 @@ static EGLConfig g_config; static volatile sig_atomic_t g_quit; static bool g_inited; static unsigned g_interval; +static enum gfx_ctx_api g_api; static void sighandler(int sig) { @@ -51,6 +52,9 @@ static void sighandler(int sig) g_quit = 1; } +static void gfx_ctx_get_video_size(unsigned *width, unsigned *height); +static void gfx_ctx_destroy(void); + static void hide_mouse(void) { Cursor no_ptr; @@ -110,10 +114,10 @@ static void set_windowed_fullscreen(void) &xev); } -void gfx_ctx_set_swap_interval(unsigned interval, bool inited) +static void gfx_ctx_swap_interval(unsigned interval) { g_interval = interval; - if (inited) + if (g_egl_dpy) { RARCH_LOG("[X/EGL]: eglSwapInterval(%u)\n", g_interval); if (!eglSwapInterval(g_egl_dpy, g_interval)) @@ -121,7 +125,7 @@ void gfx_ctx_set_swap_interval(unsigned interval, bool inited) } } -void gfx_ctx_check_window(bool *quit, +static void gfx_ctx_check_window(bool *quit, bool *resize, unsigned *width, unsigned *height, unsigned frame_count) { (void)frame_count; @@ -164,18 +168,18 @@ void gfx_ctx_check_window(bool *quit, *quit = g_quit; } -void gfx_ctx_swap_buffers(void) +static void gfx_ctx_swap_buffers(void) { eglSwapBuffers(g_egl_dpy, g_egl_surf); } -void gfx_ctx_set_resize(unsigned width, unsigned height) +static void gfx_ctx_set_resize(unsigned width, unsigned height) { (void)width; (void)height; } -void gfx_ctx_update_window_title(bool reset) +static void gfx_ctx_update_window_title(bool reset) { if (reset) gfx_window_title_reset(); @@ -185,7 +189,7 @@ void gfx_ctx_update_window_title(bool reset) XStoreName(g_dpy, g_win, buf); } -void gfx_ctx_get_video_size(unsigned *width, unsigned *height) +static void gfx_ctx_get_video_size(unsigned *width, unsigned *height) { if (!g_dpy || g_win == None) { @@ -213,7 +217,7 @@ void gfx_ctx_get_video_size(unsigned *width, unsigned *height) } } -bool gfx_ctx_init(void) +static bool gfx_ctx_init(void) { if (g_inited) return false; @@ -260,7 +264,7 @@ error: return false; } -bool gfx_ctx_set_video_mode( +static bool gfx_ctx_set_video_mode( unsigned width, unsigned height, unsigned bits, bool fullscreen) { @@ -326,6 +330,7 @@ bool gfx_ctx_set_video_mode( XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1); gfx_suspend_screensaver(g_win); + gfx_ctx_swap_interval(g_interval); XFree(vi); g_has_focus = true; @@ -341,7 +346,7 @@ error: return false; } -void gfx_ctx_destroy(void) +static void gfx_ctx_destroy(void) { if (g_egl_dpy) { @@ -383,7 +388,7 @@ void gfx_ctx_destroy(void) g_inited = false; } -void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) +static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) { void *xinput = input_x.init(); *input = xinput ? &input_x : NULL; @@ -393,7 +398,7 @@ void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) x_input_set_disp_win((x11_input_t*)xinput, g_dpy, g_win); } -bool gfx_ctx_window_has_focus(void) +static bool gfx_ctx_has_focus(void) { if (!g_inited) return false; @@ -405,8 +410,41 @@ bool gfx_ctx_window_has_focus(void) return win == g_win && g_has_focus; } -gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) +static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol) { return eglGetProcAddress(symbol); } +static bool gfx_ctx_bind_api(enum gfx_ctx_api api) +{ + g_api = api; + switch (api) + { + case GFX_CTX_OPENGL_API: + return eglBindAPI(EGL_OPENGL_API); + case GFX_CTX_OPENGL_ES_API: + return eglBindAPI(EGL_OPENGL_ES_API); + case GFX_CTX_OPENVG_API: + return eglBindAPI(EGL_OPENVG_API); + default: + return false; + } +} + +const gfx_ctx_driver_t gfx_ctx_x_egl = { + gfx_ctx_init, + gfx_ctx_destroy, + gfx_ctx_bind_api, + gfx_ctx_swap_interval, + gfx_ctx_set_video_mode, + gfx_ctx_get_video_size, + gfx_ctx_update_window_title, + gfx_ctx_check_window, + gfx_ctx_set_resize, + gfx_ctx_has_focus, + gfx_ctx_swap_buffers, + gfx_ctx_input_driver, + gfx_ctx_get_proc_address, + "x-egl", +}; + diff --git a/gfx/gfx_context.c b/gfx/gfx_context.c new file mode 100644 index 0000000000..0341e48a2c --- /dev/null +++ b/gfx/gfx_context.c @@ -0,0 +1,66 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2012 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "gfx_context.h" + +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +static const gfx_ctx_driver_t *gfx_ctx_drivers[] = { +#if defined(__CELLOS_LV2__) + &gfx_ctx_ps3, +#endif +#if defined(HAVE_VIDEOCORE) + &gfx_ctx_videocore, +#endif +#if defined(HAVE_SDL) && defined(HAVE_OPENGL) + &gfx_ctx_sdl_gl, +#endif +#if defined(HAVE_X11) && defined(HAVE_EGL) + &gfx_ctx_x_egl, +#endif +#if defined(HAVE_KMS) + &gfx_ctx_drm_egl, +#endif +}; + +const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident) +{ + for (unsigned i = 0; i < sizeof(gfx_ctx_drivers) / sizeof(gfx_ctx_drivers[0]); i++) + { + if (strcmp(gfx_ctx_drivers[i]->ident, ident) == 0) + return gfx_ctx_drivers[i]; + } + + return NULL; +} + +const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api) +{ + for (unsigned i = 0; i < sizeof(gfx_ctx_drivers) / sizeof(gfx_ctx_drivers[0]); i++) + { + if (gfx_ctx_drivers[i]->init()) + { + if (gfx_ctx_drivers[i]->bind_api(api)) + return gfx_ctx_drivers[i]; + else + gfx_ctx_drivers[i]->destroy(); + } + } + + return NULL; +} + diff --git a/gfx/gfx_context.h b/gfx/gfx_context.h index f4aa394996..326f97bdad 100644 --- a/gfx/gfx_context.h +++ b/gfx/gfx_context.h @@ -19,20 +19,88 @@ #include "../boolean.h" #include "../driver.h" - #ifdef HAVE_CONFIG_H #include "../config.h" #endif -#ifdef HAVE_OPENGL -#include "gl_common.h" -#define VID_HANDLE gl_t -#endif - #if defined(HAVE_SDL) && !defined(__APPLE__) #include "SDL_syswm.h" #endif +enum gfx_ctx_api +{ + GFX_CTX_OPENGL_API, + GFX_CTX_OPENGL_ES_API, + GFX_CTX_OPENVG_API +}; + +typedef void (*gfx_ctx_proc_t)(void); + +// Avoid breakage on XBox. TODO: Migrate to new context abstraction if it makes sense. +#if !defined(HAVE_D3D9) && !defined(HAVE_D3D8) +typedef struct gfx_ctx_driver +{ + bool (*init)(void); + void (*destroy)(void); + + bool (*bind_api)(enum gfx_ctx_api); // Which API to bind to. + + // Sets the swap interval. + void (*swap_interval)(unsigned); + + // Sets video mode. Creates a window, etc. + bool (*set_video_mode)(unsigned, unsigned, unsigned, bool); + + // Gets current window size. + // If not initialized yet, it returns current screen size. + void (*get_video_size)(unsigned*, unsigned*); + + // Asks driver to update window title (FPS, etc). + void (*update_window_title)(bool); + + // Queries for resize and quit events. + // Also processes events. + void (*check_window)(bool*, bool*, unsigned*, unsigned*, unsigned); + + // Acknowledge a resize event. This is needed for some APIs. Most backends will ignore this. + void (*set_resize)(unsigned, unsigned); + + // Checks if window has input focus. + bool (*has_focus)(void); + + // Swaps buffers. VBlank sync depends on earlier calls to swap_interval. + void (*swap_buffers)(void); + + // Most video backends will want to use a certain input driver. + // Checks for it here. + void (*input_driver)(const input_driver_t**, void**); + + // Wraps whatever gl_proc_address() there is. + gfx_ctx_proc_t (*get_proc_address)(const char*); + + // Human readable string. + const char *ident; + +#ifdef RARCH_CONSOLE + void (*set_filtering)(unsigned index, bool set_smooth); + void (*get_available_resolutions)(void); + int (*check_resolution)(unsigned resolution_id); + bool (*menu_init)(void); + void (*set_fbo)(bool); + void (*apply_fbo_state_changes)(unsigned); +#endif +} gfx_ctx_driver_t; + +extern const gfx_ctx_driver_t gfx_ctx_sdl_gl; +extern const gfx_ctx_driver_t gfx_ctx_x_egl; +extern const gfx_ctx_driver_t gfx_ctx_drm_egl; +extern const gfx_ctx_driver_t gfx_ctx_ps3; +extern const gfx_ctx_driver_t gfx_ctx_videocore; + +const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident); // Finds driver with ident. Does not initialize. +const gfx_ctx_driver_t *gfx_ctx_init_first(enum gfx_ctx_api api); // Finds first suitable driver and initializes. + +#else void gfx_ctx_set_swap_interval(unsigned interval, bool inited); bool gfx_ctx_set_video_mode( @@ -50,10 +118,6 @@ void gfx_ctx_check_window(bool *quit, void gfx_ctx_set_resize(unsigned width, unsigned height); -#if defined(HAVE_SDL) && !defined(__APPLE__) -bool gfx_ctx_get_wm_info(SDL_SysWMinfo *info); -#endif - #ifndef HAVE_GRIFFIN bool gfx_ctx_window_has_focus(void); #endif @@ -65,16 +129,10 @@ void gfx_ctx_input_driver(const input_driver_t **input, void **input_data); bool gfx_ctx_menu_init(void); #endif -#ifdef RARCH_CONSOLE void gfx_ctx_set_filtering(unsigned index, bool set_smooth); void gfx_ctx_get_available_resolutions(void); int gfx_ctx_check_resolution(unsigned resolution_id); -#endif -typedef void (*gfx_ctx_proc_t)(void); -gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *sym); - -#if defined(HAVE_D3D9) || defined(HAVE_D3D8) void gfx_ctx_set_projection(xdk_d3d_video_t *vid, const struct gl_ortho *ortho, bool allow_rotate); #endif diff --git a/gfx/gl.c b/gfx/gl.c index bdb152de80..546b34bc29 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -26,10 +26,6 @@ #include "config.h" #endif -#ifdef HAVE_EGL -#include -#endif - #include "gl_common.h" #include "gl_font.h" #include "gfx_common.h" @@ -94,7 +90,7 @@ const GLfloat *vertex_ptr = vertexes_flipped; const GLfloat *default_vertex_ptr = vertexes_flipped; #define LOAD_GL_SYM(SYM) if (!pgl##SYM) { \ - gfx_ctx_proc_t sym = gfx_ctx_get_proc_address("gl" #SYM); \ + gfx_ctx_proc_t sym = gl->driver->get_proc_address("gl" #SYM); \ memcpy(&(pgl##SYM), &sym, sizeof(sym)); \ } @@ -106,7 +102,7 @@ static PFNGLFRAMEBUFFERTEXTURE2DPROC pglFramebufferTexture2D = NULL; static PFNGLCHECKFRAMEBUFFERSTATUSPROC pglCheckFramebufferStatus = NULL; static PFNGLDELETEFRAMEBUFFERSPROC pglDeleteFramebuffers = NULL; -static bool load_fbo_proc(void) +static bool load_fbo_proc(gl_t *gl) { LOAD_GL_SYM(GenFramebuffers); LOAD_GL_SYM(BindFramebuffer); @@ -123,7 +119,7 @@ static bool load_fbo_proc(void) #define pglFramebufferTexture2D glFramebufferTexture2D #define pglCheckFramebufferStatus glCheckFramebufferStatus #define pglDeleteFramebuffers glDeleteFramebuffers -static bool load_fbo_proc(void) { return true; } +#define load_fbo_proc(gl) (true) #elif defined(HAVE_OPENGLES) #define pglGenFramebuffers glGenFramebuffersOES #define pglBindFramebuffer glBindFramebufferOES @@ -133,14 +129,14 @@ static bool load_fbo_proc(void) { return true; } #define GL_FRAMEBUFFER GL_FRAMEBUFFER_OES #define GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT #define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES -static bool load_fbo_proc(void) { return true; } +#define load_fbo_proc(gl) (true) #else #define pglGenFramebuffers glGenFramebuffers #define pglBindFramebuffer glBindFramebuffer #define pglFramebufferTexture2D glFramebufferTexture2D #define pglCheckFramebufferStatus glCheckFramebufferStatus #define pglDeleteFramebuffers glDeleteFramebuffers -static bool load_fbo_proc(void) { return true; } +#define load_fbo_proc(gl) (true) #endif #endif @@ -152,7 +148,7 @@ static PFNGLBUFFERSUBDATAPROC pglBufferSubData; static PFNGLBUFFERDATAPROC pglBufferData; static PFNGLMAPBUFFERPROC pglMapBuffer; static PFNGLUNMAPBUFFERPROC pglUnmapBuffer; -static inline bool load_gl_proc_win32(void) +static inline bool load_gl_proc_win32(gl_t *gl) { LOAD_GL_SYM(ClientActiveTexture); LOAD_GL_SYM(ActiveTexture); @@ -521,7 +517,7 @@ void gl_init_fbo(gl_t *gl, unsigned width, unsigned height) if (gl_shader_num() == 1 && !scale.valid && !g_settings.video.render_to_texture) return; - if (!load_fbo_proc()) + if (!load_fbo_proc(gl)) { RARCH_ERR("Failed to locate FBO functions. Won't be able to use render-to-texture.\n"); return; @@ -1102,7 +1098,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei if (gl->should_resize) { gl->should_resize = false; - gfx_ctx_set_resize(gl->win_width, gl->win_height); + gl->driver->set_resize(gl->win_width, gl->win_height); // On resize, we might have to recreate our FBOs due to "Viewport" scale, and set a new viewport. gl_update_resize(gl); @@ -1144,13 +1140,13 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei gl_render_msg(gl, msg); #ifndef RARCH_CONSOLE - gfx_ctx_update_window_title(false); + gl->driver->update_window_title(false); #endif #ifdef RARCH_CONSOLE if (!gl->block_swap) #endif - gfx_ctx_swap_buffers(); + gl->driver->swap_buffers(); #ifdef HAVE_CG_MENU if (gl->menu_render) @@ -1199,7 +1195,7 @@ static void gl_free(void *data) gl_deinit_fbo(gl); #endif - gfx_ctx_destroy(); + gl->driver->destroy(); free(gl->empty_buf); free(gl->conv_buffer); @@ -1209,10 +1205,10 @@ static void gl_free(void *data) static void gl_set_nonblock_state(void *data, bool state) { - (void)data; + gl_t *gl = (gl_t*)data; RARCH_LOG("GL VSync => %s\n", state ? "off" : "on"); - gfx_ctx_set_swap_interval(state ? 0 : 1, true); + gl->driver->swap_interval(state ? 0 : 1); } static bool resolve_extensions(gl_t *gl) @@ -1220,7 +1216,7 @@ static bool resolve_extensions(gl_t *gl) #ifdef _WIN32 // Win32 GL lib doesn't have some elementary functions needed. // Need to load dynamically :( - if (!load_gl_proc_win32()) + if (!load_gl_proc_win32(gl)) return false; #endif @@ -1265,26 +1261,23 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo if (!gl) return NULL; -#ifdef HAVE_EGL #ifdef HAVE_OPENGLES - if (!eglBindAPI(EGL_OPENGL_ES_API)) - return NULL; + gl->driver = gfx_ctx_init_first(GFX_CTX_OPENGL_ES_API); #else - if (!eglBindAPI(EGL_OPENGL_API)) - return NULL; + gl->driver = gfx_ctx_init_first(GFX_CTX_OPENGL_API); #endif -#endif - - if (!gfx_ctx_init()) + if (!gl->driver) { free(gl); return NULL; } - gfx_ctx_get_video_size(&gl->full_x, &gl->full_y); + RARCH_LOG("Found GL context: %s\n", gl->driver->ident); + + gl->driver->get_video_size(&gl->full_x, &gl->full_y); RARCH_LOG("Detecting screen resolution %ux%u.\n", gl->full_x, gl->full_y); - gfx_ctx_set_swap_interval(video->vsync ? 1 : 0, false); + gl->driver->swap_interval(video->vsync ? 1 : 0); unsigned win_width = video->width; unsigned win_height = video->height; @@ -1294,7 +1287,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo win_height = gl->full_y; } - if (!gfx_ctx_set_video_mode(win_width, win_height, + if (!gl->driver->set_video_mode(win_width, win_height, g_settings.video.force_16bit ? 15 : 0, video->fullscreen)) { free(gl); @@ -1302,13 +1295,13 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo } #ifndef RARCH_CONSOLE - gfx_ctx_update_window_title(true); + gl->driver->update_window_title(true); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); #endif if (!resolve_extensions(gl)) { - gfx_ctx_destroy(); + gl->driver->destroy(); free(gl); return NULL; } @@ -1317,7 +1310,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo gl->fullscreen = video->fullscreen; // Get real known video size, which might have been altered by context. - gfx_ctx_get_video_size(&gl->win_width, &gl->win_height); + gl->driver->get_video_size(&gl->win_width, &gl->win_height); RARCH_LOG("GL: Using resolution %ux%u\n", gl->win_width, gl->win_height); if (gl->full_x || gl->full_y) // We got bogus from gfx_ctx_get_video_size. Replace. @@ -1331,10 +1324,14 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo gl_cg_set_menu_shader(default_paths.menu_shader_file); #endif +#ifdef HAVE_XML + gl_glsl_set_get_proc_address(gl->driver->get_proc_address); +#endif + if (!gl_shader_init()) { RARCH_ERR("Shader init failed.\n"); - gfx_ctx_destroy(); + gl->driver->destroy(); free(gl); return NULL; } @@ -1402,7 +1399,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo gl->conv_buffer = calloc(gl->tex_w * gl->tex_h, gl->base_size); if (!gl->conv_buffer) { - gfx_ctx_destroy(); + gl->driver->destroy(); free(gl); return NULL; } @@ -1426,12 +1423,12 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords)); } - gfx_ctx_input_driver(input, input_data); + gl->driver->input_driver(input, input_data); gl_init_font(gl, g_settings.video.font_path, g_settings.video.font_size); if (!gl_check_error()) { - gfx_ctx_destroy(); + gl->driver->destroy(); free(gl); return NULL; } @@ -1444,7 +1441,7 @@ static bool gl_alive(void *data) gl_t *gl = (gl_t*)data; bool quit, resize; - gfx_ctx_check_window(&quit, + gl->driver->check_window(&quit, &resize, &gl->win_width, &gl->win_height, gl->frame_count); @@ -1458,8 +1455,8 @@ static bool gl_alive(void *data) static bool gl_focus(void *data) { - (void)data; - return gfx_ctx_window_has_focus(); + gl_t *gl = (gl_t*)data; + return gl->driver->has_focus(); } #if defined(HAVE_XML) || defined(HAVE_CG) @@ -1553,29 +1550,25 @@ static void gl_start(void) video_info.fullscreen = true; if (g_console.aspect_ratio_index == ASPECT_RATIO_CUSTOM) { - video_info.width = g_console.viewports.custom_vp.width; + video_info.width = g_console.viewports.custom_vp.width; video_info.height = g_console.viewports.custom_vp.height; } driver.video_data = gl_init(&video_info, NULL, NULL); -#ifdef HAVE_FBO - gfx_ctx_set_fbo(g_console.fbo_enabled); -#endif - - gfx_ctx_get_available_resolutions(); - -#ifdef HAVE_CG_MENU - gfx_ctx_menu_init(); -#endif + if (gl->driver->set_fbo) + gl->driver->set_fbo(g_console.fbo_enabled); + gl->driver->get_available_resolutions(); + if (gl->driver->menu_init) + gl->driver->menu_init(); #ifdef HAVE_FBO // FBO mode has to be enabled once even if FBO mode has to be // turned off if (!g_console.fbo_enabled) { - gfx_ctx_apply_fbo_state_changes(FBO_DEINIT); - gfx_ctx_apply_fbo_state_changes(FBO_INIT); - gfx_ctx_apply_fbo_state_changes(FBO_DEINIT); + gl->driver->apply_fbo_state_changes(FBO_DEINIT); + gl->driver->apply_fbo_state_changes(FBO_INIT); + gl->driver->apply_fbo_state_changes(FBO_DEINIT); } #endif } @@ -1589,22 +1582,16 @@ static void gl_stop(void) static void gl_restart(void) { -#ifdef HAVE_CG_MENU - bool should_menu_render; -#endif -#ifdef RARCH_CONSOLE - bool should_block_swap; -#endif gl_t *gl = driver.video_data; if (!gl) return; #ifdef RARCH_CONSOLE - should_block_swap = gl->block_swap; + bool should_block_swap = gl->block_swap; #endif #ifdef HAVE_CG_MENU - should_menu_render = gl->menu_render; + bool should_menu_render = gl->menu_render; #endif gl_stop(); diff --git a/gfx/gl_common.h b/gfx/gl_common.h index 40b383a512..5b66c9b352 100644 --- a/gfx/gl_common.h +++ b/gfx/gl_common.h @@ -19,6 +19,7 @@ #include "../general.h" #include "fonts/fonts.h" #include "math/matrix.h" +#include "gfx_context.h" #ifdef HAVE_CONFIG_H #include "../config.h" @@ -161,13 +162,7 @@ struct gl_coords typedef struct gl { -#ifdef RARCH_CONSOLE - bool block_swap; -#endif -#ifdef HAVE_CG_MENU - bool menu_render; - GLuint menu_texture_id; -#endif + const gfx_ctx_driver_t *driver; bool vsync; GLuint texture[TEXTURES]; unsigned tex_index; // For use with PREV. @@ -226,6 +221,14 @@ typedef struct gl GLfloat font_color[16]; GLfloat font_color_dark[16]; #endif + +#ifdef RARCH_CONSOLE + bool block_swap; +#endif +#ifdef HAVE_CG_MENU + bool menu_render; + GLuint menu_texture_id; +#endif } gl_t; // Windows ... <_< diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index a5d480a715..9a119b5115 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -154,6 +154,8 @@ static char *gl_script_program = NULL; static GLint gl_attribs[PREV_TEXTURES + 1 + 4 + MAX_PROGRAMS]; static unsigned gl_attrib_index = 0; +static gfx_ctx_proc_t (*glsl_get_proc_address)(const char*); + struct shader_program { char *vertex; @@ -928,13 +930,14 @@ static void gl_glsl_reset_attrib(void) // Platforms with broken get_proc_address. // Assume functions are available without proc_address. #define LOAD_GL_SYM(SYM) if (!pgl##SYM) { \ - gfx_ctx_proc_t sym = gfx_ctx_get_proc_address("gl" #SYM); \ + gfx_ctx_proc_t sym = glsl_get_proc_address("gl" #SYM); \ memcpy(&(pgl##SYM), &sym, sizeof(sym)); \ } bool gl_glsl_init(const char *path) { #if !defined(HAVE_OPENGLES2) && !defined(HAVE_OPENGL_MODERN) + // Load shader functions. LOAD_GL_SYM(CreateProgram); LOAD_GL_SYM(UseProgram); @@ -1427,3 +1430,9 @@ void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale) else scale->valid = false; } + +void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*)) +{ + glsl_get_proc_address = proc; +} + diff --git a/gfx/shader_glsl.h b/gfx/shader_glsl.h index 3176f72f9a..93fe0accf8 100644 --- a/gfx/shader_glsl.h +++ b/gfx/shader_glsl.h @@ -19,6 +19,7 @@ #include "../boolean.h" #include "gl_common.h" +#include "gfx_context.h" #include "math/matrix.h" bool gl_glsl_init(const char *path); @@ -43,4 +44,6 @@ void gl_glsl_shader_scale(unsigned index, struct gl_fbo_scale *scale); bool gl_glsl_set_coords(const struct gl_coords *coords); bool gl_glsl_set_mvp(const math_matrix *mat); +void gl_glsl_set_get_proc_address(gfx_ctx_proc_t (*proc)(const char*)); + #endif diff --git a/input/dinput.c b/input/dinput.c index d3376a06e5..9ec9bf8a2a 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -106,7 +106,8 @@ sdl_dinput_t* sdl_dinput_init(void) CoInitialize(NULL); SDL_SysWMinfo info; - if (!gfx_ctx_get_wm_info(&info)) + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info) != 1) { RARCH_ERR("Failed to get SysWM info.\n"); goto error; diff --git a/qb/config.libs.sh b/qb/config.libs.sh index 6130d177f3..8b1ac3d10e 100644 --- a/qb/config.libs.sh +++ b/qb/config.libs.sh @@ -127,18 +127,23 @@ fi check_lib DYNAMIC "$DYLIB" dlopen -if [ "$HAVE_KMS" = "yes" ]; then - check_pkgconf GBM gbm - check_pkgconf DRM libdrm - +check_pkgconf GBM gbm 9.1.0 +check_pkgconf DRM libdrm +if [ "$HAVE_KMS" != "no" ]; then if [ "$HAVE_GBM" = "yes" ] && [ "$HAVE_DRM" = "yes" ]; then HAVE_KMS=yes - HAVE_EGL=yes + HAVE_EGL=yes # Required + elif [ "$HAVE_KMS" = "yes" ]; then + echo "Cannot find libgbm and/or libdrm libraries required." + exit 1 + else + HAVE_KMS=no fi fi [ "$HAVE_GLES" = "yes" ] && HAVE_EGL=yes && HAVE_XML=yes [ "$HAVE_VG" = "yes" ] && HAVE_EGL=yes + if [ "$HAVE_VIDEOCORE" != "yes" ]; then check_pkgconf EGL egl check_pkgconf GLES glesv2 diff --git a/qb/config.params.sh b/qb/config.params.sh index f89c26c656..ee9a54d661 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -6,8 +6,9 @@ HAVE_DYLIB=auto # Enable dynamic loading support HAVE_NETPLAY=auto # Enable netplay support HAVE_CONFIGFILE=yes # Disable support for config file HAVE_OPENGL=yes # Disable OpenGL support -HAVE_GLES=no # Use X/EGL instead of desktop GL (experimental) -HAVE_KMS=no # Use KMS framebuffer EGL instead of desktop GL (experimental) +HAVE_GLES=no # Use GLESv2 instead of desktop GL +HAVE_KMS=auto # Enable KMS context support +HAVE_EGL=auto # Enable EGL context support HAVE_VG=no # Enable OpenVG support HAVE_CG=auto # Enable Cg shader support HAVE_XML=auto # Enable bSNES-style XML shader support