From 8ee06d75a9547a143c7054c1fb615a38a44c0f9b Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Tue, 9 Jul 2019 01:00:47 +0900 Subject: [PATCH] Separate render and presentation initialization This paves the way for clean initialization of the Vulkan renderer, and very much cleans up the older renderer initialization code as gl and sw are no longer intertwined. --- config.d/vulkan.m4 | 16 +- configure.ac | 2 +- include/QF/Vulkan/cvars.h | 1 - include/QF/Vulkan/funclist.h | 11 + include/QF/Vulkan/funcs.h | 9 - include/QF/Vulkan/init.h | 1 - include/context_sdl.h | 12 + include/context_x11.h | 9 + include/r_cvar.h | 1 - include/vid_gl.h | 20 + include/vid_internal.h | 13 +- include/vid_sw.h | 18 + include/vid_vulkan.h | 29 + libs/video/renderer/gl/gl_rmisc.c | 8 +- libs/video/renderer/gl/gl_screen.c | 6 +- libs/video/renderer/gl/qfgl_ext.c | 8 +- libs/video/renderer/glsl/glsl_main.c | 6 +- libs/video/renderer/glsl/glsl_screen.c | 4 +- libs/video/renderer/glsl/qfglsl.c | 6 +- libs/video/renderer/sw/screen.c | 3 +- libs/video/renderer/sw/sw_rmisc.c | 3 +- libs/video/renderer/sw32/screen.c | 3 +- libs/video/renderer/sw32/sw32_rmisc.c | 4 +- libs/video/renderer/vid_render_gl.c | 24 +- libs/video/renderer/vid_render_glsl.c | 23 +- libs/video/renderer/vid_render_sw.c | 24 +- libs/video/renderer/vid_render_sw32.c | 22 + libs/video/renderer/vid_render_vulkan.c | 9 +- libs/video/renderer/vulkan/Makefile.am | 3 +- libs/video/renderer/vulkan/init.c | 22 +- libs/video/renderer/vulkan/vulkan_funcs.c | 6 - .../video/renderer/vulkan/vulkan_vid_common.c | 39 +- libs/video/targets/Makefile.am | 14 +- libs/video/targets/context_sdl.c | 9 +- libs/video/targets/vid_sdl.c | 244 +------ libs/video/targets/vid_sdl_gl.c | 178 +++++ libs/video/targets/vid_sdl_sw.c | 183 +++++ libs/video/targets/vid_x11.c | 643 +----------------- libs/video/targets/vid_x11_gl.c | 209 ++++++ libs/video/targets/vid_x11_sw.c | 542 +++++++++++++++ libs/video/targets/vid_x11_vulkan.c | 169 +++++ 41 files changed, 1576 insertions(+), 980 deletions(-) delete mode 100644 include/QF/Vulkan/funcs.h create mode 100644 include/vid_gl.h create mode 100644 include/vid_sw.h create mode 100644 include/vid_vulkan.h delete mode 100644 libs/video/renderer/vulkan/vulkan_funcs.c create mode 100644 libs/video/targets/vid_sdl_gl.c create mode 100644 libs/video/targets/vid_sdl_sw.c create mode 100644 libs/video/targets/vid_x11_gl.c create mode 100644 libs/video/targets/vid_x11_sw.c create mode 100644 libs/video/targets/vid_x11_vulkan.c diff --git a/config.d/vulkan.m4 b/config.d/vulkan.m4 index c82900f58..4c9df43f4 100644 --- a/config.d/vulkan.m4 +++ b/config.d/vulkan.m4 @@ -9,16 +9,12 @@ if test "x$HAVE_VULKAN" != xno; then LDFLAGS="$LDFLAGS -L$VULKAN_SDK/lib" glslangvalidator="$VULKAN_SDK/bin/glslangValidator" ], [glslangvalidator="glslangValidator"]) - AC_CHECK_HEADER( - [vulkan/vulkan.h], - dnl Make sure the library "works" - [AC_CHECK_LIB([vulkan], [vkCreateInstance], - [AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) - VULKAN_LIBS=-lvulkan], - [AC_MSG_RESULT(no)]) - ], - [AC_MSG_RESULT(no)] - ) + AC_CHECK_HEADER([vulkan/vulkan.h], [HAVE_VULKAN=yes], [HAVE_VULKAN=no]) CPPFLAGS="$save_CPPFLAGS" fi +if test "x$HAVE_VULKAN" = xyes; then + AC_DEFINE([HAVE_VULKAN], [1], [Define if yhou have the Vulkan libs]) +fi AC_SUBST(VULKAN_LIBS) + +AM_CONDITIONAL(X11_VULKAN, test "x$HAVE_VULKAN" = "xyes") diff --git a/configure.ac b/configure.ac index aaf6492ea..fe398b273 100644 --- a/configure.ac +++ b/configure.ac @@ -63,8 +63,8 @@ m4_include(config.d/compression.m4) m4_include(config.d/mgl.m4) m4_include(config.d/fbdev.m4) m4_include(config.d/svga.m4) -m4_include(config.d/x11.m4) m4_include(config.d/vulkan.m4) +m4_include(config.d/x11.m4) m4_include(config.d/sdl.m4) m4_include(config.d/curses.m4) diff --git a/include/QF/Vulkan/cvars.h b/include/QF/Vulkan/cvars.h index 9f318b8f0..b6110e353 100644 --- a/include/QF/Vulkan/cvars.h +++ b/include/QF/Vulkan/cvars.h @@ -1,7 +1,6 @@ #ifndef __QF_Vulkan_cvars_h #define __QF_Vulkan_cvars_h -extern struct cvar_s *vulkan_library_name; extern struct cvar_s *vulkan_use_validation; #endif//__QF_Vulkan_cvars_h diff --git a/include/QF/Vulkan/funclist.h b/include/QF/Vulkan/funclist.h index 2b755889e..79af14277 100644 --- a/include/QF/Vulkan/funclist.h +++ b/include/QF/Vulkan/funclist.h @@ -21,6 +21,16 @@ GLOBAL_LEVEL_VULKAN_FUNCTION (vkCreateInstance) #define INSTANCE_LEVEL_VULKAN_FUNCTION(function) #endif +#if defined(VK_USE_PLATFORM_XLIB_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceXlibPresentationSupportKHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateXlibSurfaceKHR) +#elif defined(VK_USE_PLATFORM_WIN32_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceWin32PresentationSupportKHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateWin32SurfaceKHR) +#elif defined(VK_USE_PLATFORM_XCB_KHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceXcbPresentationSupportKHR) +INSTANCE_LEVEL_VULKAN_FUNCTION (vkCreateXcbSurfaceKHR) +#else INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumeratePhysicalDevices) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceFeatures) @@ -31,6 +41,7 @@ INSTANCE_LEVEL_VULKAN_FUNCTION (vkDestroyInstance) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceLayerProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkEnumerateDeviceExtensionProperties) INSTANCE_LEVEL_VULKAN_FUNCTION (vkGetPhysicalDeviceMemoryProperties) +#endif #undef INSTANCE_LEVEL_VULKAN_FUNCTION diff --git a/include/QF/Vulkan/funcs.h b/include/QF/Vulkan/funcs.h deleted file mode 100644 index 975f5485b..000000000 --- a/include/QF/Vulkan/funcs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __QF_Vulkan_funcs_h -#define __QF_Vulkan_funcs_h - -#define EXPORTED_VULKAN_FUNCTION(fname) extern PFN_##fname fname; -#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) extern PFN_##fname fname; - -#include "QF/Vulkan/funclist.h" - -#endif//__QF_Vulkan_funcs_h diff --git a/include/QF/Vulkan/init.h b/include/QF/Vulkan/init.h index 4a97b82f8..85efb44e1 100644 --- a/include/QF/Vulkan/init.h +++ b/include/QF/Vulkan/init.h @@ -29,7 +29,6 @@ #include #include "QF/qtypes.h" -#include "QF/Vulkan/funcs.h" typedef struct { VkDevice device; diff --git a/include/context_sdl.h b/include/context_sdl.h index b097587f1..f6f1dbbe7 100644 --- a/include/context_sdl.h +++ b/include/context_sdl.h @@ -30,7 +30,19 @@ #ifndef __context_sdl_h_ #define __context_sdl_h_ +#include + +extern SDL_Surface *sdl_screen; + void VID_SDL_GammaCheck (void); void SDL_Init_Cvars (void); +struct gl_ctx_s *SDL_GL_Context (void); +void SDL_GL_Init_Cvars (void); + +struct sw_ctx_s *SDL_SW_Context (void); +void SDL_SW_Init_Cvars (void); + +extern uint32_t sdl_flags; + #endif // __context_sdl_h_ diff --git a/include/context_x11.h b/include/context_x11.h index b513e587a..884fafe9e 100644 --- a/include/context_x11.h +++ b/include/context_x11.h @@ -77,4 +77,13 @@ void X11_SaveMouseAcceleration (void); void X11_RemoveMouseAcceleration (void); void X11_RestoreMouseAcceleration (void); +struct gl_ctx_s *X11_GL_Context (void); +void X11_GL_Init_Cvars (void); + +struct sw_ctx_s *X11_SW_Context (void); +void X11_SW_Init_Cvars (void); + +struct vulkan_ctx_s *X11_Vulkan_Context (void); +void X11_Vulkan_Init_Cvars (void); + #endif // __context_x11_h_ diff --git a/include/r_cvar.h b/include/r_cvar.h index 8383f4705..e8a85a679 100644 --- a/include/r_cvar.h +++ b/include/r_cvar.h @@ -16,7 +16,6 @@ extern quat_t crosshair_color; extern struct cvar_s *d_mipcap; extern struct cvar_s *d_mipscale; -extern struct cvar_s *gl_driver; extern struct cvar_s *gl_affinemodels; extern struct cvar_s *gl_anisotropy; extern struct cvar_s *gl_clear; diff --git a/include/vid_gl.h b/include/vid_gl.h new file mode 100644 index 000000000..2561af575 --- /dev/null +++ b/include/vid_gl.h @@ -0,0 +1,20 @@ +#ifndef __vid_gl_h +#define __vid_gl_h + +// GLXContext is a pointer to opaque data +typedef struct __GLXcontextRec *GLXContext; + +typedef struct gl_ctx_s { + GLXContext context; + void (*load_gl) (void); + void (*choose_visual) (struct gl_ctx_s *ctx); + void (*create_context) (struct gl_ctx_s *ctx); + void (*init_gl) (void); + void *(*get_proc_address) (const char *name, qboolean crit); + void (*end_rendering) (void); +} gl_ctx_t; + +extern gl_ctx_t *gl_ctx; +extern gl_ctx_t *glsl_ctx; + +#endif//__vid_gl_h diff --git a/include/vid_internal.h b/include/vid_internal.h index fc1538202..e922508a4 100644 --- a/include/vid_internal.h +++ b/include/vid_internal.h @@ -11,11 +11,12 @@ typedef struct vid_internal_s { void (*do_screen_buffer) (void); void (*set_palette) (const byte *palette); - // gl stuff - void (*load_gl) (void); - void (*init_gl) (void); - void *(*get_proc_address) (const char *name, qboolean crit); - void (*end_rendering) (void); + void (*choose_visual) (void); + void (*create_context) (void); + + struct gl_ctx_s *(*gl_context) (void); + struct sw_ctx_s *(*sw_context) (void); + struct vulkan_ctx_s *(*vulkan_context) (void); } vid_internal_t; extern struct cvar_s *vid_fullscreen; @@ -30,11 +31,9 @@ void VID_InitGamma (unsigned char *); qboolean VID_SetGamma (double); void VID_UpdateGamma (struct cvar_s *); -void VID_Update (vrect_t *rects); void VID_LockBuffer (void); void VID_UnlockBuffer (void); void VID_InitBuffers (void); void VID_MakeColormaps (void); - #endif//__vid_internal_h diff --git a/include/vid_sw.h b/include/vid_sw.h new file mode 100644 index 000000000..2a5ab20a5 --- /dev/null +++ b/include/vid_sw.h @@ -0,0 +1,18 @@ +#ifndef __vid_sw_h +#define __vid_sw_h + +// GLXContext is a pointer to opaque data +typedef struct __GLXcontextRec *GLXContext; +struct vrect_s; +typedef struct sw_ctx_s { + GLXContext context; + void (*choose_visual) (struct sw_ctx_s *ctx); + void (*create_context) (struct sw_ctx_s *ctx); + void (*set_palette) (const byte *palette); + void (*update) (struct vrect_s *rects); +} sw_ctx_t; + +extern sw_ctx_t *sw_ctx; +extern sw_ctx_t *sw32_ctx; + +#endif//__vid_sw_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h new file mode 100644 index 000000000..627269cdb --- /dev/null +++ b/include/vid_vulkan.h @@ -0,0 +1,29 @@ +#ifndef __vid_vulkan_h +#define __vid_vulkan_h + +#ifndef VK_NO_PROTOTYPES +#define VK_NO_PROTOTYPES +#endif +#include + +typedef struct vulkan_ctx_s { + void (*load_vulkan) (struct vulkan_ctx_s *ctx); + void (*unload_vulkan) (struct vulkan_ctx_s *ctx); + void (*init_vulkan) (void); + + const char * const *required_extensions; + struct vulkan_presentation_s *presentation; + int (*get_presentation_support) (struct vulkan_ctx_s *ctx, + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex); + VkSurfaceKHR (*create_surface) (struct vulkan_ctx_s *ctx); + VkInstance instance; + VkPhysicalDevice physicalDevice; +#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; +#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; +#include "QF/Vulkan/funclist.h" +} vulkan_ctx_t; + +extern vulkan_ctx_t *vulkan_ctx; + +#endif//__vid_vulkan_h diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index e054e37bf..a47e6ba42 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -64,7 +64,7 @@ #include "mod_internal.h" #include "r_internal.h" #include "varrays.h" -#include "vid_internal.h" +#include "vid_gl.h" /* R_Envmap_f @@ -122,7 +122,7 @@ R_Envmap_f (void) gl_envmap = false; qfglDrawBuffer (GL_BACK); qfglReadBuffer (GL_BACK); - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); } void @@ -250,13 +250,13 @@ gl_R_TimeRefresh_f (void) double start, stop, time; int i; - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i * (360.0 / 128.0); gl_R_RenderView (); - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); } stop = Sys_DoubleTime (); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 73674e70c..fbe47106f 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -59,7 +59,7 @@ #include "compat.h" #include "r_internal.h" #include "sbar.h" -#include "vid_internal.h" +#include "vid_gl.h" /* SCREEN SHOTS */ @@ -207,7 +207,7 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) return; if (begun) - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); vr_data.realtime = realtime; @@ -264,7 +264,7 @@ gl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) qfglFlush (); if (gl_finish->int_val) { - vid.vid_internal->end_rendering (); + gl_ctx->end_rendering (); begun = 0; } } diff --git a/libs/video/renderer/gl/qfgl_ext.c b/libs/video/renderer/gl/qfgl_ext.c index 41fe1f52b..f012726de 100644 --- a/libs/video/renderer/gl/qfgl_ext.c +++ b/libs/video/renderer/gl/qfgl_ext.c @@ -61,7 +61,7 @@ #include "QF/GL/funcs.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" // First we need to get all the function pointers declared. #define QFGL_WANT(ret, name, args) \ @@ -76,9 +76,9 @@ qboolean GLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ - qf##name = vid.vid_internal->get_proc_address (#name, false); + qf##name = gl_ctx->get_proc_address (#name, false); #define QFGL_NEED(ret, name, args) \ - qf##name = vid.vid_internal->get_proc_address (#name, true); + qf##name = gl_ctx->get_proc_address (#name, true); #include "QF/GL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT @@ -136,6 +136,6 @@ void * QFGL_ExtensionAddress (const char *name) { if (name) - return vid.vid_internal->get_proc_address (name, false); + return gl_ctx->get_proc_address (name, false); return NULL; } diff --git a/libs/video/renderer/glsl/glsl_main.c b/libs/video/renderer/glsl/glsl_main.c index 2bc60bdd4..32688b2ae 100644 --- a/libs/video/renderer/glsl/glsl_main.c +++ b/libs/video/renderer/glsl/glsl_main.c @@ -58,7 +58,7 @@ #include "mod_internal.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" mat4_t glsl_projection; mat4_t glsl_view; @@ -305,13 +305,13 @@ glsl_R_TimeRefresh_f (void) double start, stop, time; int i; - vid.vid_internal->end_rendering (); + glsl_ctx->end_rendering (); start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { r_refdef.viewangles[1] = i * (360.0 / 128.0); glsl_R_RenderView (); - vid.vid_internal->end_rendering (); + glsl_ctx->end_rendering (); } stop = Sys_DoubleTime (); diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c index ecdda6ec8..89276999d 100644 --- a/libs/video/renderer/glsl/glsl_screen.c +++ b/libs/video/renderer/glsl/glsl_screen.c @@ -60,7 +60,7 @@ #include "QF/GLSL/qf_vid.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" /* Unknown renamed to GLErr_Unknown to solve conflict with winioctl.h */ static unsigned int GLErr_InvalidEnum; @@ -166,7 +166,7 @@ glsl_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, if (begun) { begun = 0; - vid.vid_internal->end_rendering (); + glsl_ctx->end_rendering (); } vr_data.realtime = realtime; diff --git a/libs/video/renderer/glsl/qfglsl.c b/libs/video/renderer/glsl/qfglsl.c index b4fd25662..0e48e9354 100644 --- a/libs/video/renderer/glsl/qfglsl.c +++ b/libs/video/renderer/glsl/qfglsl.c @@ -60,7 +60,7 @@ #include "QF/GLSL/funcs.h" #include "r_internal.h" -#include "vid_internal.h" +#include "vid_gl.h" // First we need to get all the function pointers declared. #define QFGL_WANT(ret, name, args) \ @@ -75,9 +75,9 @@ qboolean EGLF_FindFunctions (void) { #define QFGL_WANT(ret, name, args) \ - qfe##name = vid.vid_internal->get_proc_address (#name, false); + qfe##name = glsl_ctx->get_proc_address (#name, false); #define QFGL_NEED(ret, name, args) \ - qfe##name = vid.vid_internal->get_proc_address (#name, true); + qfe##name = glsl_ctx->get_proc_address (#name, true); #include "QF/GLSL/qf_funcs_list.h" #undef QFGL_NEED #undef QFGL_WANT diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index d425f6549..5b69e7a0d 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -51,6 +51,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" /* SCREEN SHOTS */ @@ -263,5 +264,5 @@ SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vrect.height = scr_vrect.height; vrect.next = 0; } - VID_Update (&vrect); + sw_ctx->update (&vrect); } diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index f30200ffa..b2272ff14 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -37,6 +37,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" static void @@ -74,7 +75,7 @@ R_TimeRefresh_f (void) vr.width = r_refdef.vrect.width; vr.height = r_refdef.vrect.height; vr.next = NULL; - VID_Update (&vr); + sw_ctx->update (&vr); } stop = Sys_DoubleTime (); time = stop - start; diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c index bcadb5c9b..e4779d8da 100644 --- a/libs/video/renderer/sw32/screen.c +++ b/libs/video/renderer/sw32/screen.c @@ -54,6 +54,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_sw.h" /* SCREEN SHOTS */ @@ -221,5 +222,5 @@ sw32_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs vrect.height = scr_vrect.height; vrect.next = 0; } - VID_Update (&vrect); + sw32_ctx->update (&vrect); } diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c index cb12395d3..1b329b54f 100644 --- a/libs/video/renderer/sw32/sw32_rmisc.c +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -40,7 +40,7 @@ #include "compat.h" #include "r_internal.h" #include "vid_internal.h" - +#include "vid_sw.h" static void R_CheckVariables (void) @@ -77,7 +77,7 @@ sw32_R_TimeRefresh_f (void) vr.width = r_refdef.vrect.width; vr.height = r_refdef.vrect.height; vr.next = NULL; - VID_Update (&vr); + sw32_ctx->update (&vr); } stop = Sys_DoubleTime (); time = stop - start; diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 91f4178b5..9085e751d 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -39,9 +39,12 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_gl.h" #include "gl/namehack.h" +gl_ctx_t *gl_ctx; + static vid_model_funcs_t model_funcs = { gl_Mod_LoadExternalTextures, gl_Mod_LoadLighting, @@ -124,12 +127,29 @@ vid_render_funcs_t gl_vid_render_funcs = { &model_funcs }; +static void +gl_vid_render_choose_visual (void) +{ + gl_ctx->choose_visual (gl_ctx); +} + +static void +gl_vid_render_create_context (void) +{ + gl_ctx->create_context (gl_ctx); +} + static void gl_vid_render_init (void) { + gl_ctx = vr_data.vid->vid_internal->gl_context (); + gl_ctx->init_gl = GL_Init_Common; + gl_ctx->load_gl (); + vr_data.vid->vid_internal->set_palette = GL_SetPalette; - vr_data.vid->vid_internal->init_gl = GL_Init_Common; - vr_data.vid->vid_internal->load_gl (); + vr_data.vid->vid_internal->choose_visual = gl_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = gl_vid_render_create_context; + vr_funcs = &gl_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index d1f380ae5..22de04ea3 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -39,9 +39,12 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_gl.h" #include "glsl/namehack.h" +gl_ctx_t *glsl_ctx; + static vid_model_funcs_t model_funcs = { glsl_Mod_LoadExternalTextures, glsl_Mod_LoadLighting, @@ -124,12 +127,28 @@ vid_render_funcs_t glsl_vid_render_funcs = { &model_funcs }; +static void +glsl_vid_render_choose_visual (void) +{ + glsl_ctx->choose_visual (glsl_ctx); +} + +static void +glsl_vid_render_create_context (void) +{ + glsl_ctx->create_context (glsl_ctx); +} + static void glsl_vid_render_init (void) { + glsl_ctx = vr_data.vid->vid_internal->gl_context (); + glsl_ctx->init_gl = GLSL_Init_Common; + glsl_ctx->load_gl (); + vr_data.vid->vid_internal->set_palette = GLSL_SetPalette; - vr_data.vid->vid_internal->init_gl = GLSL_Init_Common; - vr_data.vid->vid_internal->load_gl (); + vr_data.vid->vid_internal->choose_visual = glsl_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = glsl_vid_render_create_context; vr_funcs = &glsl_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 7c2485911..dcfb4abc7 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -1,5 +1,5 @@ /* - vid_render_gl.c + vid_render_sw.c SW version of the renderer @@ -33,6 +33,10 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" + +sw_ctx_t *sw_ctx; static vid_model_funcs_t model_funcs = { sw_Mod_LoadExternalTextures, @@ -116,9 +120,27 @@ vid_render_funcs_t sw_vid_render_funcs = { &model_funcs }; +static void +sw_vid_render_choose_visual (void) +{ + sw_ctx->choose_visual (sw_ctx); +} + +static void +sw_vid_render_create_context (void) +{ + sw_ctx->create_context (sw_ctx); +} + static void sw_vid_render_init (void) { + sw_ctx = vr_data.vid->vid_internal->sw_context (); + + vr_data.vid->vid_internal->set_palette = sw_ctx->set_palette; + vr_data.vid->vid_internal->choose_visual = sw_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = sw_vid_render_create_context; + vr_funcs = &sw_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_sw32.c b/libs/video/renderer/vid_render_sw32.c index 40034c0dc..ed7414a85 100644 --- a/libs/video/renderer/vid_render_sw32.c +++ b/libs/video/renderer/vid_render_sw32.c @@ -36,9 +36,13 @@ #include "mod_internal.h" #include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" #include "sw32/namehack.h" +sw_ctx_t *sw32_ctx; + static vid_model_funcs_t model_funcs = { sw_Mod_LoadExternalTextures, sw_Mod_LoadLighting, @@ -121,9 +125,27 @@ vid_render_funcs_t sw32_vid_render_funcs = { &model_funcs }; +static void +sw32_vid_render_choose_visual (void) +{ + sw32_ctx->choose_visual (sw32_ctx); +} + +static void +sw32_vid_render_create_context (void) +{ + sw32_ctx->create_context (sw32_ctx); +} + static void sw32_vid_render_init (void) { + sw32_ctx = vr_data.vid->vid_internal->sw_context (); + + vr_data.vid->vid_internal->set_palette = sw32_ctx->set_palette; + vr_data.vid->vid_internal->choose_visual = sw32_vid_render_choose_visual; + vr_data.vid->vid_internal->create_context = sw32_vid_render_create_context; + vr_funcs = &sw32_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index c71264fcb..2a94f31cb 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -39,9 +39,12 @@ #include "mod_internal.h" #include "r_internal.h" #include "vid_internal.h" +#include "vid_vulkan.h" #include "vulkan/namehack.h" +vulkan_ctx_t *vulkan_ctx; + static vid_model_funcs_t model_funcs = { /* vulkan_Mod_LoadExternalTextures, vulkan_Mod_LoadLighting, @@ -135,9 +138,11 @@ set_palette (const byte *palette) static void vulkan_vid_render_init (void) { + vulkan_ctx = vr_data.vid->vid_internal->vulkan_context (); + vulkan_ctx->init_vulkan = Vulkan_Init_Common; + vulkan_ctx->load_vulkan (vulkan_ctx); + vr_data.vid->vid_internal->set_palette = set_palette; - vr_data.vid->vid_internal->init_gl = Vulkan_Init_Common; - vr_data.vid->vid_internal->load_gl (); vr_funcs = &vulkan_vid_render_funcs; m_funcs = &model_funcs; } diff --git a/libs/video/renderer/vulkan/Makefile.am b/libs/video/renderer/vulkan/Makefile.am index 5d2f65d8e..e4102ec9d 100644 --- a/libs/video/renderer/vulkan/Makefile.am +++ b/libs/video/renderer/vulkan/Makefile.am @@ -1,12 +1,11 @@ AUTOMAKE_OPTIONS= foreign AM_CFLAGS= @PREFER_PIC@ -AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES -DVK_USE_PLATFORM_XLIB_KHR +AM_CPPFLAGS= -I$(top_srcdir)/include -DVK_NO_PROTOTYPES vulkan_src = \ init.c \ vulkan_draw.c \ - vulkan_funcs.c \ vulkan_vid_common.c noinst_LTLIBRARIES= libvulkan.la diff --git a/libs/video/renderer/vulkan/init.c b/libs/video/renderer/vulkan/init.c index 2c4fb7ca1..e3181fc07 100644 --- a/libs/video/renderer/vulkan/init.c +++ b/libs/video/renderer/vulkan/init.c @@ -43,7 +43,8 @@ #include "QF/vid.h" #include "QF/Vulkan/init.h" -cvar_t *vulkan_library_name; +#include "vid_vulkan.h" + cvar_t *vulkan_use_validation; static uint32_t numLayers; @@ -78,9 +79,9 @@ get_instance_layers_and_extensions (void) VkLayerProperties *properties; VkExtensionProperties *extensions; - vkEnumerateInstanceLayerProperties (&numLayers, 0); + vulkan_ctx->vkEnumerateInstanceLayerProperties (&numLayers, 0); properties = malloc (numLayers * sizeof (VkLayerProperties)); - vkEnumerateInstanceLayerProperties (&numLayers, properties); + vulkan_ctx->vkEnumerateInstanceLayerProperties (&numLayers, properties); instanceLayerNames = (const char **) malloc ((numLayers + 1) * sizeof (const char **)); for (i = 0; i < numLayers; i++) { @@ -88,9 +89,10 @@ get_instance_layers_and_extensions (void) } instanceLayerNames[i] = 0; - vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); + vulkan_ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, 0); extensions = malloc (numExtensions * sizeof (VkLayerProperties)); - vkEnumerateInstanceExtensionProperties (0, &numExtensions, extensions); + vulkan_ctx->vkEnumerateInstanceExtensionProperties (0, &numExtensions, + extensions); instanceExtensionNames = (const char **) malloc ((numExtensions + 1) * sizeof (const char **)); for (i = 0; i < numExtensions; i++) { @@ -278,15 +280,15 @@ static void load_instance_funcs (VulkanInstance_t *instance) { #define INSTANCE_LEVEL_VULKAN_FUNCTION(name) \ - instance->name = (PFN_##name) vkGetInstanceProcAddr (instance->instance, \ - #name); \ + instance->name = (PFN_##name) \ + vulkan_ctx->vkGetInstanceProcAddr (instance->instance, #name); \ if (!instance->name) { \ Sys_Error ("Couldn't find instance level function %s", #name); \ } #define INSTANCE_LEVEL_VULKAN_FUNCTION_EXTENSION(name) \ - instance->name = (PFN_##name) vkGetInstanceProcAddr (instance->instance,\ - #name); \ + instance->name = (PFN_##name) \ + vulkan_ctx->vkGetInstanceProcAddr (instance->instance, #name); \ if (!instance->name) { \ Sys_Printf ("Couldn't find instance level function %s", #name); \ } @@ -344,7 +346,7 @@ Vulkan_CreateInstance (const char *appName, uint32_t appVersion, createInfo.ppEnabledLayerNames = lay; createInfo.ppEnabledExtensionNames = ext; - res = vkCreateInstance (&createInfo, 0, &instance); + res = vulkan_ctx->vkCreateInstance (&createInfo, 0, &instance); if (res != VK_SUCCESS) { Sys_Error ("unable to create vulkan instance\n"); } diff --git a/libs/video/renderer/vulkan/vulkan_funcs.c b/libs/video/renderer/vulkan/vulkan_funcs.c deleted file mode 100644 index 2d8f79c9a..000000000 --- a/libs/video/renderer/vulkan/vulkan_funcs.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname; -#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname; - -#include "QF/Vulkan/funclist.h" diff --git a/libs/video/renderer/vulkan/vulkan_vid_common.c b/libs/video/renderer/vulkan/vulkan_vid_common.c index 9366799cb..98a4d3dc3 100644 --- a/libs/video/renderer/vulkan/vulkan_vid_common.c +++ b/libs/video/renderer/vulkan/vulkan_vid_common.c @@ -39,8 +39,6 @@ # include #endif -#include - #include "QF/cvar.h" #include "QF/dstring.h" #include "QF/input.h" @@ -55,43 +53,14 @@ #include "compat.h" #include "d_iface.h" #include "r_internal.h" - -static void *vulkan_library; +#include "vid_vulkan.h" static VulkanInstance_t *vulkan_instance; static VulkanDevice_t *vulkan_device; -static void -load_vulkan_library (void) -{ - vulkan_library = dlopen (vulkan_library_name->string, - RTLD_DEEPBIND | RTLD_NOW); - if (!vulkan_library) { - Sys_Error ("Couldn't load vulkan library %s: %s", - vulkan_library_name->name, dlerror ()); - } - - #define EXPORTED_VULKAN_FUNCTION(name) \ - name = (PFN_##name) dlsym (vulkan_library, #name); \ - if (!name) { \ - Sys_Error ("Couldn't find exported vulkan function %s", #name); \ - } - - #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ - name = (PFN_##name) vkGetInstanceProcAddr (0, #name); \ - if (!name) { \ - Sys_Error ("Couldn't find global-level function %s", #name); \ - } - - #include "QF/Vulkan/funclist.h" -} - void Vulkan_Init_Cvars () { - vulkan_library_name = Cvar_Get ("vulkan_library", "libvulkan.so.1", - CVAR_ROM, 0, - "the name of the vulkan shared library"); vulkan_use_validation = Cvar_Get ("vulkan_use_validation", "1", CVAR_NONE, 0, "enable LunarG Standard Validation " @@ -101,7 +70,6 @@ Vulkan_Init_Cvars () static const char *instance_extensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, - VK_KHR_XLIB_SURFACE_EXTENSION_NAME, 0, }; @@ -203,8 +171,6 @@ Vulkan_Init_Common (void) Sys_Printf ("Vulkan_Init_Common\n"); Vulkan_Init_Cvars (); - load_vulkan_library (); - vulkan_instance = Vulkan_CreateInstance (PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version vulkan_device = create_suitable_device (vulkan_instance); if (!vulkan_device) { @@ -227,6 +193,5 @@ Vulkan_Shutdown_Common (void) } Vulkan_DestroyInstance (vulkan_instance); vulkan_instance = 0; - dlclose (vulkan_library); - vulkan_library = 0; + vulkan_ctx->unload_vulkan (vulkan_ctx); } diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index b883b676b..d7241f528 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -27,6 +27,15 @@ joy_src= $(joy_null_src) endif endif +x11_gl_src=vid_x11_gl.c +x11_sw_src=vid_x11_sw.c +x11_vulkan_src=vid_x11_vulkan.c +if X11_VULKAN +x11_src= $(x11_gl_src) $(x11_sw_src) $(x11_vulkan_src) +else +x11_src= $(x11_gl_src) $(x11_sw_src) +endif + js_libs=$(top_builddir)/libs/util/libQFutil.la libQFjs_la_LDFLAGS= $(lib_ldflags) @@ -41,15 +50,16 @@ libvid_common_la_SOURCES= \ libvid_common_la_CFLAGS= @PREFER_NON_PIC@ libvid_common_la_LDFLAGS= @STATIC@ -libvid_x11_la_SOURCES= in_x11.c context_x11.c dga_check.c +libvid_x11_la_SOURCES= in_x11.c context_x11.c dga_check.c $(x11_src) libvid_x11_la_CFLAGS= @PREFER_NON_PIC@ $(X_CFLAGS) libvid_x11_la_LDFLAGS= @STATIC@ +EXTRA_libvid_x11_la_SOURCES= $(x11_vulkan_src) libvid_svga_la_SOURCES= in_svgalib.c libvid_svga_la_CFLAGS= @PREFER_NON_PIC@ $(SVGA_CFLAGS) libvid_svga_la_LDFLAGS= @STATIC@ -libvid_sdl_la_SOURCES= in_sdl.c context_sdl.c +libvid_sdl_la_SOURCES= in_sdl.c context_sdl.c vid_sdl_gl.c vid_sdl_sw.c libvid_sdl_la_CFLAGS= @PREFER_NON_PIC@ $(SDL_CFLAGS) libvid_sdl_la_LDFLAGS= @STATIC@ diff --git a/libs/video/targets/context_sdl.c b/libs/video/targets/context_sdl.c index 105d7e1f6..7426ea8f8 100644 --- a/libs/video/targets/context_sdl.c +++ b/libs/video/targets/context_sdl.c @@ -23,9 +23,6 @@ cvar_t *vid_bitdepth; -extern SDL_Surface *screen; - - void VID_SDL_GammaCheck (void) { @@ -67,9 +64,9 @@ VID_UpdateFullscreen (cvar_t *vid_fullscreen) { if (!r_data || !viddef.initialized) return; - if ((vid_fullscreen->int_val && !(screen->flags & SDL_FULLSCREEN)) - || (!vid_fullscreen->int_val && screen->flags & SDL_FULLSCREEN)) - if (!SDL_WM_ToggleFullScreen (screen)) + if ((vid_fullscreen->int_val && !(sdl_screen->flags & SDL_FULLSCREEN)) + || (!vid_fullscreen->int_val && sdl_screen->flags & SDL_FULLSCREEN)) + if (!SDL_WM_ToggleFullScreen (sdl_screen)) Sys_Printf ("VID_UpdateFullscreen: error setting fullscreen\n"); IN_UpdateGrab (in_grab); } diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index 514b8020e..9b1938d30 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -58,190 +58,17 @@ HWND mainwindow; #define BASEWIDTH 320 #define BASEHEIGHT 200 -byte *VGA_pagebase; -int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; - -SDL_Surface *screen = NULL; - -// Define GLAPIENTRY to a useful value -#ifndef GLAPIENTRY -# ifdef _WIN32 -# include -# define GLAPIENTRY WINAPI -# undef LoadImage -# else -# ifdef APIENTRY -# define GLAPIENTRY APIENTRY -# else -# define GLAPIENTRY -# endif -# endif -#endif +SDL_Surface *sdl_screen = NULL; static vid_internal_t vid_internal; -static void (*set_vid_mode) (Uint32 flags); - -static void (GLAPIENTRY *qfglFinish) (void); -static int use_gl_procaddress = 0; -static cvar_t *gl_driver; - -static byte cached_palette[256 * 3]; -static int update_palette; - -static void * -QFGL_ProcAddress (const char *name, qboolean crit) -{ - void *glfunc = NULL; - - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); - - glfunc = SDL_GL_GetProcAddress (name); - if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); - return glfunc; - } - Sys_MaskPrintf (SYS_VID, "not found\n"); - - if (crit) { - if (strncmp ("fxMesa", name, 6) == 0) { - Sys_Printf ("This target requires a special version of Mesa with " - "support for Glide and SVGAlib.\n"); - Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); - } - Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", - name); - } - return NULL; -} - -static void -sdlgl_set_vid_mode (Uint32 flags) -{ - int i, j; - - flags |= SDL_OPENGL; - - // Setup GL Attributes - SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); -// SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 0); // Try for 0, 8 -// SDL_GL_SetAttribute (SDL_GL_STEREO, 1); // Someday... - - for (i = 0; i < 5; i++) { - int k; - int color[5] = {32, 24, 16, 15, 0}; - int rgba[5][4] = { - {8, 8, 8, 0}, - {8, 8, 8, 8}, - {5, 6, 5, 0}, - {5, 5, 5, 0}, - {5, 5, 5, 1}, - }; - - SDL_GL_SetAttribute (SDL_GL_RED_SIZE, rgba[i][0]); - SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgba[i][1]); - SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, rgba[i][2]); - SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, rgba[i][3]); - - for (j = 0; j < 5; j++) { - for (k = 32; k >= 16; k -= 8) { - SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, k); - if ((screen = SDL_SetVideoMode (viddef.width, viddef.height, - color[j], flags))) - goto success; - } - } - } - - Sys_Error ("Couldn't set video mode: %s", SDL_GetError ()); - SDL_Quit (); - -success: - viddef.numpages = 2; - - viddef.vid_internal->init_gl (); -} - -static void -sdlgl_end_rendering (void) -{ - qfglFinish (); - SDL_GL_SwapBuffers (); -} - -static void -sdl_load_gl (void) -{ - viddef.vid_internal->get_proc_address = QFGL_ProcAddress; - viddef.vid_internal->end_rendering = sdlgl_end_rendering; - set_vid_mode = sdlgl_set_vid_mode; - - if (SDL_GL_LoadLibrary (gl_driver->string) != 0) - Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); - - use_gl_procaddress = 1; - - qfglFinish = QFGL_ProcAddress ("glFinish", true); -} - -static void -sdl_update_palette (const byte *palette) -{ - SDL_Color colors[256]; - int i; - - for (i = 0; i < 256; ++i) { - colors[i].r = *palette++; - colors[i].g = *palette++; - colors[i].b = *palette++; - } - SDL_SetColors (screen, colors, 0, 256); -} - -static void -VID_SetPalette (const byte *palette) -{ - if (memcmp (cached_palette, palette, sizeof (cached_palette))) { - memcpy (cached_palette, palette, sizeof (cached_palette)); - update_palette = 1; - } -} - -static void -do_screen_buffer (void) -{ -} - -static void -sdl_set_vid_mode (Uint32 flags) -{ - // Initialize display - if (!(screen = SDL_SetVideoMode (viddef.width, viddef.height, 8, flags))) - Sys_Error ("VID: Couldn't set video mode: %s", SDL_GetError ()); - - // now know everything we need to know about the buffer - VGA_width = viddef.width; - VGA_height = viddef.height; - viddef.vid_internal->do_screen_buffer = do_screen_buffer; - VGA_pagebase = viddef.buffer = screen->pixels; - VGA_rowbytes = viddef.rowbytes = screen->pitch; - viddef.conbuffer = viddef.buffer; - viddef.conrowbytes = viddef.rowbytes; - viddef.direct = 0; - - VID_InitBuffers (); // allocate z buffer and surface cache -} +uint32_t sdl_flags; void VID_Init (byte *palette, byte *colormap) { - Uint32 flags; - - vid_internal.set_palette = VID_SetPalette; - vid_internal.load_gl = sdl_load_gl; - - set_vid_mode = sdl_set_vid_mode; - + vid_internal.gl_context = SDL_GL_Context; + vid_internal.sw_context = SDL_SW_Context; // Load the SDL library if (SDL_Init (SDL_INIT_VIDEO) < 0) Sys_Error ("VID: Couldn't load SDL: %s", SDL_GetError ()); @@ -256,9 +83,9 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (BASEWIDTH, BASEHEIGHT); // Set video width, height and flags - flags = (SDL_SWSURFACE | SDL_HWPALETTE); + sdl_flags = (SDL_SWSURFACE | SDL_HWPALETTE); if (vid_fullscreen->int_val) { - flags |= SDL_FULLSCREEN; + sdl_flags |= SDL_FULLSCREEN; #ifndef _WIN32 // Don't annoy Mesa/3dfx folks // doesn't hurt if not using a gl renderer // FIXME: Maybe this could be put in a different spot, but I don't @@ -270,11 +97,10 @@ VID_Init (byte *palette, byte *colormap) #endif } - set_vid_mode (flags); + vid_internal.create_context (); VID_SDL_GammaCheck (); VID_InitGamma (palette); - viddef.vid_internal->set_palette (viddef.palette); viddef.initialized = true; @@ -296,46 +122,8 @@ void VID_Init_Cvars () { SDL_Init_Cvars (); - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); -} - -void -VID_Update (vrect_t *rects) -{ - static SDL_Rect *sdlrects; - static int num_sdlrects; - int i, n; - vrect_t *rect; - - if (update_palette) { - update_palette = 0; - sdl_update_palette (cached_palette); - } - // Two-pass system, since Quake doesn't do it the SDL way... - - // First, count the number of rectangles - n = 0; - for (rect = rects; rect; rect = rect->next) - ++n; - - if (n > num_sdlrects) { - num_sdlrects = n; - sdlrects = realloc (sdlrects, n * sizeof (SDL_Rect)); - if (!sdlrects) - Sys_Error ("Out of memory!"); - } - - // Second, copy them to SDL rectangles and update - i = 0; - for (rect = rects; rect; rect = rect->next) { - sdlrects[i].x = rect->x; - sdlrects[i].y = rect->y; - sdlrects[i].w = rect->width; - sdlrects[i].h = rect->height; - ++i; - } - SDL_UpdateRects (screen, n, sdlrects); + SDL_GL_Init_Cvars (); + SDL_SW_Init_Cvars (); } void @@ -343,14 +131,14 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { Uint8 *offset; - if (!screen) + if (!sdl_screen) return; if (x < 0) - x = screen->w + x - 1; - offset = (Uint8 *) screen->pixels + y * screen->pitch + x; + x = sdl_screen->w + x - 1; + offset = (Uint8 *) sdl_screen->pixels + y * sdl_screen->pitch + x; while (height--) { memcpy (offset, pbitmap, width); - offset += screen->pitch; + offset += sdl_screen->pitch; pbitmap += width; } } @@ -358,11 +146,11 @@ D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) void D_EndDirectRect (int x, int y, int width, int height) { - if (!screen) + if (!sdl_screen) return; if (x < 0) - x = screen->w + x - 1; - SDL_UpdateRect (screen, x, y, width, height); + x = sdl_screen->w + x - 1; + SDL_UpdateRect (sdl_screen, x, y, width, height); } void diff --git a/libs/video/targets/vid_sdl_gl.c b/libs/video/targets/vid_sdl_gl.c new file mode 100644 index 000000000..829ca2860 --- /dev/null +++ b/libs/video/targets/vid_sdl_gl.c @@ -0,0 +1,178 @@ +/* + vid_sdl.c + + Video driver for Sam Lantinga's Simple DirectMedia Layer + + Copyright (C) 1996-1997 Id Software, Inc. + + This program 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 Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_sdl.h" +#include "d_iface.h" +#include "vid_internal.h" +#include "vid_gl.h" + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# ifdef _WIN32 +# include +# define GLAPIENTRY WINAPI +# undef LoadImage +# else +# ifdef APIENTRY +# define GLAPIENTRY APIENTRY +# else +# define GLAPIENTRY +# endif +# endif +#endif + +static void (GLAPIENTRY *qfglFinish) (void); +static int use_gl_procaddress = 0; +static cvar_t *gl_driver; + +static void * +QFGL_ProcAddress (const char *name, qboolean crit) +{ + void *glfunc = NULL; + + Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + + glfunc = SDL_GL_GetProcAddress (name); + if (glfunc) { + Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + return glfunc; + } + Sys_MaskPrintf (SYS_VID, "not found\n"); + + if (crit) { + if (strncmp ("fxMesa", name, 6) == 0) { + Sys_Printf ("This target requires a special version of Mesa with " + "support for Glide and SVGAlib.\n"); + Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); + } + Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", + name); + } + return NULL; +} + +static void +sdlgl_set_vid_mode (gl_ctx_t *ctx) +{ + int i, j; + + sdl_flags |= SDL_OPENGL; + + // Setup GL Attributes + SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1); +// SDL_GL_SetAttribute (SDL_GL_STENCIL_SIZE, 0); // Try for 0, 8 +// SDL_GL_SetAttribute (SDL_GL_STEREO, 1); // Someday... + + for (i = 0; i < 5; i++) { + int k; + int color[5] = {32, 24, 16, 15, 0}; + int rgba[5][4] = { + {8, 8, 8, 0}, + {8, 8, 8, 8}, + {5, 6, 5, 0}, + {5, 5, 5, 0}, + {5, 5, 5, 1}, + }; + + SDL_GL_SetAttribute (SDL_GL_RED_SIZE, rgba[i][0]); + SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, rgba[i][1]); + SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, rgba[i][2]); + SDL_GL_SetAttribute (SDL_GL_ALPHA_SIZE, rgba[i][3]); + + for (j = 0; j < 5; j++) { + for (k = 32; k >= 16; k -= 8) { + SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, k); + if ((sdl_screen = SDL_SetVideoMode (viddef.width, viddef.height, + color[j], sdl_flags))) + goto success; + } + } + } + + Sys_Error ("Couldn't set video mode: %s", SDL_GetError ()); + SDL_Quit (); + +success: + viddef.numpages = 2; + + ctx->init_gl (); +} + +static void +sdlgl_end_rendering (void) +{ + qfglFinish (); + SDL_GL_SwapBuffers (); +} + +static void +sdl_load_gl (void) +{ + if (SDL_GL_LoadLibrary (gl_driver->string) != 0) + Sys_Error ("Couldn't load OpenGL library %s!", gl_driver->string); + + use_gl_procaddress = 1; + + qfglFinish = QFGL_ProcAddress ("glFinish", true); +} + +gl_ctx_t * +SDL_GL_Context (void) +{ + gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); + ctx->load_gl = sdl_load_gl; + ctx->create_context = sdlgl_set_vid_mode; + ctx->get_proc_address = QFGL_ProcAddress; + ctx->end_rendering = sdlgl_end_rendering; + return ctx; +} + +void +SDL_GL_Init_Cvars () +{ + gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, + "The OpenGL library to use. (path optional)"); +} diff --git a/libs/video/targets/vid_sdl_sw.c b/libs/video/targets/vid_sdl_sw.c new file mode 100644 index 000000000..2d4f806d4 --- /dev/null +++ b/libs/video/targets/vid_sdl_sw.c @@ -0,0 +1,183 @@ +/* + vid_sdl.c + + Video driver for Sam Lantinga's Simple DirectMedia Layer + + Copyright (C) 1996-1997 Id Software, Inc. + + This program 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 Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qendian.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_sdl.h" +#include "d_iface.h" +#include "vid_internal.h" +#include "vid_sw.h" + +#ifdef _WIN32 // FIXME: evil hack to get full DirectSound support with SDL +#include +#include +HWND mainwindow; +#endif + +// The original defaults +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +byte *VGA_pagebase; +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# ifdef _WIN32 +# include +# define GLAPIENTRY WINAPI +# undef LoadImage +# else +# ifdef APIENTRY +# define GLAPIENTRY APIENTRY +# else +# define GLAPIENTRY +# endif +# endif +#endif + +static byte cached_palette[256 * 3]; +static int update_palette; + +static void +sdl_update_palette (const byte *palette) +{ + SDL_Color colors[256]; + int i; + + for (i = 0; i < 256; ++i) { + colors[i].r = *palette++; + colors[i].g = *palette++; + colors[i].b = *palette++; + } + SDL_SetColors (sdl_screen, colors, 0, 256); +} + +static void +VID_SetPalette (const byte *palette) +{ + if (memcmp (cached_palette, palette, sizeof (cached_palette))) { + memcpy (cached_palette, palette, sizeof (cached_palette)); + update_palette = 1; + } +} + +static void +do_screen_buffer (void) +{ +} + +static void +sdl_set_vid_mode (sw_ctx_t *ctx) +{ + // Initialize display + if (!(sdl_screen = SDL_SetVideoMode (viddef.width, viddef.height, 8, + sdl_flags))) + Sys_Error ("VID: Couldn't set video mode: %s", SDL_GetError ()); + + // now know everything we need to know about the buffer + VGA_width = viddef.width; + VGA_height = viddef.height; + viddef.vid_internal->do_screen_buffer = do_screen_buffer; + VGA_pagebase = viddef.buffer = sdl_screen->pixels; + VGA_rowbytes = viddef.rowbytes = sdl_screen->pitch; + viddef.conbuffer = viddef.buffer; + viddef.conrowbytes = viddef.rowbytes; + viddef.direct = 0; + + VID_InitBuffers (); // allocate z buffer and surface cache +} + +static void +sdl_sw_update (vrect_t *rects) +{ + static SDL_Rect *sdlrects; + static int num_sdlrects; + int i, n; + vrect_t *rect; + + if (update_palette) { + update_palette = 0; + sdl_update_palette (cached_palette); + } + // Two-pass system, since Quake doesn't do it the SDL way... + + // First, count the number of rectangles + n = 0; + for (rect = rects; rect; rect = rect->next) + ++n; + + if (n > num_sdlrects) { + num_sdlrects = n; + sdlrects = realloc (sdlrects, n * sizeof (SDL_Rect)); + if (!sdlrects) + Sys_Error ("Out of memory!"); + } + + // Second, copy them to SDL rectangles and update + i = 0; + for (rect = rects; rect; rect = rect->next) { + sdlrects[i].x = rect->x; + sdlrects[i].y = rect->y; + sdlrects[i].w = rect->width; + sdlrects[i].h = rect->height; + ++i; + } + SDL_UpdateRects (sdl_screen, n, sdlrects); +} + +sw_ctx_t * +SDL_SW_Context (void) +{ + sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->set_palette = VID_SetPalette; + ctx->create_context = sdl_set_vid_mode; + ctx->update = sdl_sw_update; + return ctx; +} + +void +SDL_SW_Init_Cvars () +{ +} diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index bc4b4b6dc..946824547 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -44,21 +44,10 @@ # include #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include #include -#include #ifdef HAVE_VIDMODE # include @@ -67,7 +56,6 @@ #include "QF/cmd.h" #include "QF/console.h" #include "QF/cvar.h" -#include "QF/qargs.h" #include "QF/qendian.h" #include "QF/screen.h" #include "QF/sys.h" @@ -80,339 +68,9 @@ #include "vid_internal.h" static vid_internal_t vid_internal; -int XShmGetEventBase (Display *x); // for broken X11 headers - -static GC x_gc; - -static qboolean doShm; -static XShmSegmentInfo x_shminfo[2]; - -static int current_framebuffer; -static XImage *x_framebuffer[2] = { 0, 0 }; int VID_options_items = 1; -static byte current_palette[768]; - -typedef unsigned char PIXEL8; -typedef unsigned short PIXEL16; -typedef unsigned int PIXEL24; - -static PIXEL16 st2d_8to16table[256]; -static PIXEL24 st2d_8to24table[256]; -static int shiftmask_fl = 0; -static long r_shift, g_shift, b_shift; -static unsigned long r_mask, g_mask, b_mask; - -#define GLX_RGBA 4 // true if RGBA mode -#define GLX_DOUBLEBUFFER 5 // double buffering supported -#define GLX_RED_SIZE 8 // number of red component bits -#define GLX_GREEN_SIZE 9 // number of green component bits -#define GLX_BLUE_SIZE 10 // number of blue component bits -#define GLX_DEPTH_SIZE 12 // number of depth bits - -// GLXContext is a pointer to opaque data -typedef struct __GLXcontextRec *GLXContext; -typedef XID GLXDrawable; - -// Define GLAPIENTRY to a useful value -#ifndef GLAPIENTRY -# ifdef _WIN32 -# include -# define GLAPIENTRY WINAPI -# undef LoadImage -# else -# ifdef APIENTRY -# define GLAPIENTRY APIENTRY -# else -# define GLAPIENTRY -# endif -# endif -#endif -static GLXContext ctx = NULL; -static void *libgl_handle; -static void (*qfglXSwapBuffers) (Display *dpy, GLXDrawable drawable); -static XVisualInfo* (*qfglXChooseVisual) (Display *dpy, int screen, - int *attribList); -static GLXContext (*qfglXCreateContext) (Display *dpy, XVisualInfo *vis, - GLXContext shareList, Bool direct); -static Bool (*qfglXMakeCurrent) (Display *dpy, GLXDrawable drawable, - GLXContext ctx); -static void (GLAPIENTRY *qfglFinish) (void); -static void *(*glGetProcAddress) (const char *symbol) = NULL; -static int use_gl_procaddress = 0; -static cvar_t *gl_driver; - -static void (*choose_visual) (void); -static void (*create_context) (void); - -static void * -QFGL_GetProcAddress (void *handle, const char *name) -{ - void *glfunc = NULL; - - if (use_gl_procaddress && glGetProcAddress) - glfunc = glGetProcAddress (name); - if (!glfunc) - glfunc = dlsym (handle, name); - return glfunc; -} - -static void * -QFGL_ProcAddress (const char *name, qboolean crit) -{ - void *glfunc = NULL; - - Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); - - glfunc = QFGL_GetProcAddress (libgl_handle, name); - if (glfunc) { - Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); - return glfunc; - } - Sys_MaskPrintf (SYS_VID, "not found\n"); - - if (crit) { - if (strncmp ("fxMesa", name, 6) == 0) { - Sys_Printf ("This target requires a special version of Mesa with " - "support for Glide and SVGAlib.\n"); - Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); - } - Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", - name); - } - return NULL; -} - -static void -glx_choose_visual (void) -{ - int attrib[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DOUBLEBUFFER, - GLX_DEPTH_SIZE, 1, - None - }; - - x_visinfo = qfglXChooseVisual (x_disp, x_screen, attrib); - if (!x_visinfo) { - Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); - } - x_vis = x_visinfo->visual; -} - -static void -glx_create_context (void) -{ - XSync (x_disp, 0); - ctx = qfglXCreateContext (x_disp, x_visinfo, NULL, True); - qfglXMakeCurrent (x_disp, x_win, ctx); - viddef.vid_internal->init_gl (); -} - -static void -glx_end_rendering (void) -{ - qfglFinish (); - qfglXSwapBuffers (x_disp, x_win); -} - -static void -glx_load_gl (void) -{ - int flags = RTLD_NOW; - - choose_visual = glx_choose_visual; - create_context = glx_create_context; - - viddef.vid_internal->get_proc_address = QFGL_ProcAddress; - viddef.vid_internal->end_rendering = glx_end_rendering; - -#ifdef RTLD_GLOBAL - flags |= RTLD_GLOBAL; -#endif - if (!(libgl_handle = dlopen (gl_driver->string, flags))) { - Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver->string, - dlerror ()); - } - glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddress"); - if (!glGetProcAddress) - glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddressARB"); - - qfglXSwapBuffers = QFGL_ProcAddress ("glXSwapBuffers", true); - qfglXChooseVisual = QFGL_ProcAddress ("glXChooseVisual", true); - qfglXCreateContext = QFGL_ProcAddress ("glXCreateContext", true); - qfglXMakeCurrent = QFGL_ProcAddress ("glXMakeCurrent", true); - - use_gl_procaddress = 1; - - qfglFinish = QFGL_ProcAddress ("glFinish", true); -} - -static void -shiftmask_init (void) -{ - unsigned long long x; - - r_mask = x_vis->red_mask; - g_mask = x_vis->green_mask; - b_mask = x_vis->blue_mask; - - for (r_shift = -8, x = 1; x < r_mask; x <<= 1) - r_shift++; - for (g_shift = -8, x = 1; x < g_mask; x <<= 1) - g_shift++; - for (b_shift = -8, x = 1; x < b_mask; x <<= 1) - b_shift++; - shiftmask_fl = 1; -} - -static PIXEL16 -xlib_rgb16 (int r, int g, int b) -{ - PIXEL16 p = 0; - - if (!shiftmask_fl) - shiftmask_init (); - - if (r_shift > 0) { - p = (r << (r_shift)) & r_mask; - } else { - if (r_shift < 0) { - p = (r >> (-r_shift)) & r_mask; - } else { - p |= (r & r_mask); - } - } - - if (g_shift > 0) { - p |= (g << (g_shift)) & g_mask; - } else { - if (g_shift < 0) { - p |= (g >> (-g_shift)) & g_mask; - } else { - p |= (g & g_mask); - } - } - - if (b_shift > 0) { - p |= (b << (b_shift)) & b_mask; - } else { - if (b_shift < 0) { - p |= (b >> (-b_shift)) & b_mask; - } else { - p |= (b & b_mask); - } - } - - return p; -} - -static PIXEL24 -xlib_rgb24 (int r, int g, int b) -{ - PIXEL24 p = 0; - - if (!shiftmask_fl) - shiftmask_init (); - - if (r_shift > 0) { - p = (r << (r_shift)) & r_mask; - } else { - if (r_shift < 0) { - p = (r >> (-r_shift)) & r_mask; - } else { - p |= (r & r_mask); - } - } - - if (g_shift > 0) { - p |= (g << (g_shift)) & g_mask; - } else { - if (g_shift < 0) { - p |= (g >> (-g_shift)) & g_mask; - } else { - p |= (g & g_mask); - } - } - - if (b_shift > 0) { - p |= (b << (b_shift)) & b_mask; - } else { - if (b_shift < 0) { - p |= (b >> (-b_shift)) & b_mask; - } else { - p |= (b & b_mask); - } - } - - return p; -} - -static void -st2_fixup (XImage *framebuf, int x, int y, int width, int height) -{ - int xi, yi; - unsigned char *src; - PIXEL16 *dest; - - if (x < 0 || y < 0) - return; - - for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width]; - dest = (PIXEL16 *) &framebuf->data[yi * framebuf->bytes_per_line]; - for (xi = x; xi < x + width; xi++) { - dest[xi] = st2d_8to16table[src[xi]]; - } - } -} - -static void -st3_fixup (XImage * framebuf, int x, int y, int width, int height) -{ - int yi; - unsigned char *src; - PIXEL24 *dest; - register int count, n; - - if (x < 0 || y < 0) - return; - - for (yi = y; yi < (y + height); yi++) { - src = &((byte *)viddef.buffer)[yi * viddef.width + x]; - dest = (PIXEL24 *) &framebuf->data[yi * framebuf->bytes_per_line + x]; - - // Duff's Device - count = width; - n = (count + 7) / 8; - - switch (count % 8) { - case 0: - do { - *dest++ = st2d_8to24table[*src++]; - case 7: - *dest++ = st2d_8to24table[*src++]; - case 6: - *dest++ = st2d_8to24table[*src++]; - case 5: - *dest++ = st2d_8to24table[*src++]; - case 4: - *dest++ = st2d_8to24table[*src++]; - case 3: - *dest++ = st2d_8to24table[*src++]; - case 2: - *dest++ = st2d_8to24table[*src++]; - case 1: - *dest++ = st2d_8to24table[*src++]; - } while (--n > 0); - } - } -} - void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { @@ -425,240 +83,6 @@ D_EndDirectRect (int x, int y, int width, int height) // direct drawing of the "accessing disk" icon isn't supported } -static void -ResetFrameBuffer (void) -{ - int mem, pwidth; - char *buf; - - if (x_framebuffer[0]) { - XDestroyImage (x_framebuffer[0]); - } - - pwidth = x_visinfo->depth / 8; - - if (pwidth == 3) - pwidth = 4; - mem = ((viddef.width * pwidth + 7) & ~7) * viddef.height; - buf = malloc (mem); - SYS_CHECKMEM (buf); - - // allocate new screen buffer - x_framebuffer[0] = XCreateImage (x_disp, x_vis, x_visinfo->depth, - ZPixmap, 0, buf, viddef.width, - viddef.height, 32, 0); - - if (!x_framebuffer[0]) { - Sys_Error ("VID: XCreateImage failed"); - } -} - -static void -ResetSharedFrameBuffers (void) -{ - int size; - int key; - int minsize = getpagesize (); - int frm; - - for (frm = 0; frm < 2; frm++) { - - // free up old frame buffer memory - if (x_framebuffer[frm]) { - XShmDetach (x_disp, &x_shminfo[frm]); - free (x_framebuffer[frm]); - shmdt (x_shminfo[frm].shmaddr); - } - // create the image - x_framebuffer[frm] = XShmCreateImage (x_disp, x_vis, x_visinfo->depth, - ZPixmap, 0, &x_shminfo[frm], - viddef.width, viddef.height); - - // grab shared memory - size = x_framebuffer[frm]->bytes_per_line * x_framebuffer[frm]->height; - - if (size < minsize) - Sys_Error ("VID: Window must use at least %d bytes", minsize); - - key = random (); - x_shminfo[frm].shmid = shmget ((key_t) key, size, IPC_CREAT | 0777); - if (x_shminfo[frm].shmid == -1) - Sys_Error ("VID: Could not get any shared memory (%s)", - strerror (errno)); - - // attach to the shared memory segment - x_shminfo[frm].shmaddr = (void *) shmat (x_shminfo[frm].shmid, 0, 0); - - Sys_MaskPrintf (SYS_VID, "VID: shared memory id=%d, addr=0x%lx\n", - x_shminfo[frm].shmid, (long) x_shminfo[frm].shmaddr); - - x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; - - // get the X server to attach to it - if (!XShmAttach (x_disp, &x_shminfo[frm])) - Sys_Error ("VID: XShmAttach() failed"); - XSync (x_disp, 0); - shmctl (x_shminfo[frm].shmid, IPC_RMID, 0); - - } -} - -static void -x11_init_buffers (void) -{ - if (doShm) - ResetSharedFrameBuffers (); - else - ResetFrameBuffer (); - - current_framebuffer = 0; - - viddef.direct = 0; - viddef.rowbytes = viddef.width; - if (x_visinfo->depth != 8) { - if (viddef.buffer) - free (viddef.buffer); - viddef.buffer = calloc (viddef.width, viddef.height); - if (!viddef.buffer) - Sys_Error ("Not enough memory for video mode"); - } else { - viddef.buffer = x_framebuffer[current_framebuffer]->data; - } - viddef.conbuffer = viddef.buffer; - - viddef.conrowbytes = viddef.rowbytes; -} - -static void -x11_choose_visual (void) -{ - int pnum, i; - XVisualInfo template; - int num_visuals; - int template_mask; - - // specify a visual id - if ((pnum = COM_CheckParm ("-visualid"))) { - if (pnum >= com_argc - 1) - Sys_Error ("VID: -visualid "); - template.visualid = atoi (com_argv[pnum + 1]); - template_mask = VisualIDMask; - } else { // If not specified, use default - // visual - template.visualid = - XVisualIDFromVisual (XDefaultVisual (x_disp, x_screen)); - template_mask = VisualIDMask; - } - - // pick a visual -- warn if more than one was available - x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, - &num_visuals); - - if (x_visinfo->depth == 8 && x_visinfo->class == PseudoColor) - x_cmap = XCreateColormap (x_disp, x_win, x_vis, AllocAll); - x_vis = x_visinfo->visual; - - if (num_visuals > 1) { - Sys_MaskPrintf (SYS_VID, - "Found more than one visual id at depth %d:\n", - template.depth); - for (i = 0; i < num_visuals; i++) - Sys_MaskPrintf (SYS_VID, " -visualid %d\n", - (int) x_visinfo[i].visualid); - } else { - if (num_visuals == 0) { - if (template_mask == VisualIDMask) { - Sys_Error ("VID: Bad visual ID %ld", template.visualid); - } else { - Sys_Error ("VID: No visuals at depth %d", template.depth); - } - } - } - - Sys_MaskPrintf (SYS_VID, "Using visualid %d:\n", - (int) x_visinfo->visualid); - Sys_MaskPrintf (SYS_VID, " class %d\n", x_visinfo->class); - Sys_MaskPrintf (SYS_VID, " screen %d\n", x_visinfo->screen); - Sys_MaskPrintf (SYS_VID, " depth %d\n", x_visinfo->depth); - Sys_MaskPrintf (SYS_VID, " red_mask 0x%x\n", - (int) x_visinfo->red_mask); - Sys_MaskPrintf (SYS_VID, " green_mask 0x%x\n", - (int) x_visinfo->green_mask); - Sys_MaskPrintf (SYS_VID, " blue_mask 0x%x\n", - (int) x_visinfo->blue_mask); - Sys_MaskPrintf (SYS_VID, " colormap_size %d\n", - x_visinfo->colormap_size); - Sys_MaskPrintf (SYS_VID, " bits_per_rgb %d\n", - x_visinfo->bits_per_rgb); -} - -static void -x11_create_context (void) -{ - // create the GC - { - XGCValues xgcvalues; - int valuemask = GCGraphicsExposures; - - xgcvalues.graphics_exposures = False; - x_gc = XCreateGC (x_disp, x_win, valuemask, &xgcvalues); - } - - // even if MITSHM is available, make sure it's a local connection - if (XShmQueryExtension (x_disp)) { - char *displayname; - char *d; - - doShm = true; - - if ((displayname = XDisplayName (NULL))) { - if ((d = strchr (displayname, ':'))) - *d = '\0'; - - if (!(!strcasecmp (displayname, "unix") || !*displayname)) - doShm = false; - } - } - - if (doShm) { - x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; - } - - viddef.vid_internal->do_screen_buffer = x11_init_buffers; - VID_InitBuffers (); - -// XSynchronize (x_disp, False); -// X11_AddEvent (x_shmeventtype, event_shm); -} - -static void -VID_SetPalette (const byte *palette) -{ - int i; - XColor colors[256]; - - for (i = 0; i < 256; i++) { - st2d_8to16table[i] = xlib_rgb16 (palette[i * 3], palette[i * 3 + 1], - palette[i * 3 + 2]); - st2d_8to24table[i] = xlib_rgb24 (palette[i * 3], palette[i * 3 + 1], - palette[i * 3 + 2]); - } - - if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) { - if (palette != current_palette) { - memcpy (current_palette, palette, 768); - } - for (i = 0; i < 256; i++) { - colors[i].pixel = i; - colors[i].flags = DoRed | DoGreen | DoBlue; - colors[i].red = palette[(i * 3)] << 8; - colors[i].green = palette[(i * 3) + 1] << 8; - colors[i].blue = palette[(i * 3) + 2] << 8; - } - XStoreColors (x_disp, x_cmap, colors, 256); - } -} - /* Set up color translation tables and the window. Takes a 256-color 8-bit palette. Palette data will go away after the call, so copy it if you'll @@ -667,11 +91,11 @@ VID_SetPalette (const byte *palette) void VID_Init (byte *palette, byte *colormap) { - vid_internal.load_gl = glx_load_gl; - vid_internal.set_palette = VID_SetPalette; - - choose_visual = x11_choose_visual; - create_context = x11_create_context; + vid_internal.gl_context = X11_GL_Context; + vid_internal.sw_context = X11_SW_Context; +#ifdef HAVE_VULKAN + vid_internal.vulkan_context = X11_Vulkan_Context; +#endif R_LoadModule (&vid_internal); @@ -683,11 +107,11 @@ VID_Init (byte *palette, byte *colormap) VID_GetWindowSize (320, 200); X11_OpenDisplay (); - choose_visual (); + vid_internal.choose_visual (); X11_SetVidMode (viddef.width, viddef.height); X11_CreateWindow (viddef.width, viddef.height); X11_CreateNullCursor (); // hide mouse pointer - create_context (); + vid_internal.create_context (); VID_InitGamma (palette); viddef.vid_internal->set_palette (viddef.palette); @@ -703,8 +127,10 @@ void VID_Init_Cvars () { X11_Init_Cvars (); - gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, - "The OpenGL library to use. (path optional)"); +#ifdef HAVE_VULKAN + X11_Vulkan_Init_Cvars (); +#endif + X11_GL_Init_Cvars (); } /* @@ -719,17 +145,13 @@ VID_Shutdown (void) X11_CloseDisplay (); } +#if 0 static int config_notify = 0; static int config_notify_width; static int config_notify_height; -/* - VID_Update - - Flush the given rectangles from the view buffer to the screen. -*/ -void -VID_Update (vrect_t *rects) +static void +update () { /* If the window changes dimension, skip this frame. */ if (config_notify) { @@ -744,43 +166,8 @@ VID_Update (vrect_t *rects) Con_CheckResize (); return; } - - while (rects) { - switch (x_visinfo->depth) { - case 16: - st2_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - case 24: - st3_fixup (x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->width, rects->height); - break; - } - if (doShm) { - if (!XShmPutImage (x_disp, x_win, x_gc, - x_framebuffer[current_framebuffer], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height, True)) { - Sys_Error ("VID_Update: XShmPutImage failed"); - } - oktodraw = false; - while (!oktodraw) - X11_ProcessEvent (); - rects = rects->next; - - current_framebuffer = !current_framebuffer; - } else { - if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], - rects->x, rects->y, rects->x, rects->y, - rects->width, rects->height)) { - Sys_Error ("VID_Update: XPutImage failed"); - } - rects = rects->next; - } - } - XSync (x_disp, False); - r_data->scr_fullupdate = 0; } +#endif void VID_LockBuffer (void) diff --git a/libs/video/targets/vid_x11_gl.c b/libs/video/targets/vid_x11_gl.c new file mode 100644 index 000000000..28b2f3294 --- /dev/null +++ b/libs/video/targets/vid_x11_gl.c @@ -0,0 +1,209 @@ +/* + vid_x11_gl.c + + GLX X11 video driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + This program 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 Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include + +#include "QF/cvar.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_x11.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_gl.h" + +#define GLX_RGBA 4 // true if RGBA mode +#define GLX_DOUBLEBUFFER 5 // double buffering supported +#define GLX_RED_SIZE 8 // number of red component bits +#define GLX_GREEN_SIZE 9 // number of green component bits +#define GLX_BLUE_SIZE 10 // number of blue component bits +#define GLX_DEPTH_SIZE 12 // number of depth bits + +typedef XID GLXDrawable; + +// Define GLAPIENTRY to a useful value +#ifndef GLAPIENTRY +# ifdef _WIN32 +# include +# define GLAPIENTRY WINAPI +# undef LoadImage +# else +# ifdef APIENTRY +# define GLAPIENTRY APIENTRY +# else +# define GLAPIENTRY +# endif +# endif +#endif +static void *libgl_handle; +static void (*qfglXSwapBuffers) (Display *dpy, GLXDrawable drawable); +static XVisualInfo* (*qfglXChooseVisual) (Display *dpy, int screen, + int *attribList); +static GLXContext (*qfglXCreateContext) (Display *dpy, XVisualInfo *vis, + GLXContext shareList, Bool direct); +static Bool (*qfglXMakeCurrent) (Display *dpy, GLXDrawable drawable, + GLXContext ctx); +static void (GLAPIENTRY *qfglFinish) (void); +static void *(*glGetProcAddress) (const char *symbol) = NULL; +static int use_gl_procaddress = 0; + +static cvar_t *gl_driver; + +static void * +QFGL_GetProcAddress (void *handle, const char *name) +{ + void *glfunc = NULL; + + if (use_gl_procaddress && glGetProcAddress) + glfunc = glGetProcAddress (name); + if (!glfunc) + glfunc = dlsym (handle, name); + return glfunc; +} + +static void * +QFGL_ProcAddress (const char *name, qboolean crit) +{ + void *glfunc = NULL; + + Sys_MaskPrintf (SYS_VID, "DEBUG: Finding symbol %s ... ", name); + + glfunc = QFGL_GetProcAddress (libgl_handle, name); + if (glfunc) { + Sys_MaskPrintf (SYS_VID, "found [%p]\n", glfunc); + return glfunc; + } + Sys_MaskPrintf (SYS_VID, "not found\n"); + + if (crit) { + if (strncmp ("fxMesa", name, 6) == 0) { + Sys_Printf ("This target requires a special version of Mesa with " + "support for Glide and SVGAlib.\n"); + Sys_Printf ("If you are in X, try using a GLX or SGL target.\n"); + } + Sys_Error ("Couldn't load critical OpenGL function %s, exiting...", + name); + } + return NULL; +} + +static void +glx_choose_visual (gl_ctx_t *ctx) +{ + int attrib[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DOUBLEBUFFER, + GLX_DEPTH_SIZE, 1, + None + }; + + x_visinfo = qfglXChooseVisual (x_disp, x_screen, attrib); + if (!x_visinfo) { + Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual"); + } + x_vis = x_visinfo->visual; +} + +static void +glx_create_context (gl_ctx_t *ctx) +{ + XSync (x_disp, 0); + ctx->context = qfglXCreateContext (x_disp, x_visinfo, NULL, True); + qfglXMakeCurrent (x_disp, x_win, ctx->context); + ctx->init_gl (); +} + +static void +glx_end_rendering (void) +{ + qfglFinish (); + qfglXSwapBuffers (x_disp, x_win); +} + +static void +glx_load_gl (void) +{ + libgl_handle = dlopen (gl_driver->string, RTLD_NOW); + if (!libgl_handle) { + Sys_Error ("Couldn't load OpenGL library %s: %s", gl_driver->string, + dlerror ()); + } + glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddress"); + if (!glGetProcAddress) + glGetProcAddress = dlsym (libgl_handle, "glXGetProcAddressARB"); + + qfglXSwapBuffers = QFGL_ProcAddress ("glXSwapBuffers", true); + qfglXChooseVisual = QFGL_ProcAddress ("glXChooseVisual", true); + qfglXCreateContext = QFGL_ProcAddress ("glXCreateContext", true); + qfglXMakeCurrent = QFGL_ProcAddress ("glXMakeCurrent", true); + + use_gl_procaddress = 1; + + qfglFinish = QFGL_ProcAddress ("glFinish", true); +} + +gl_ctx_t * +X11_GL_Context (void) +{ + gl_ctx_t *ctx = calloc (1, sizeof (gl_ctx_t)); + ctx->load_gl = glx_load_gl; + ctx->choose_visual = glx_choose_visual; + ctx->create_context = glx_create_context; + ctx->get_proc_address = QFGL_ProcAddress; + ctx->end_rendering = glx_end_rendering; + return ctx; +} + +void +X11_GL_Init_Cvars (void) +{ + gl_driver = Cvar_Get ("gl_driver", GL_DRIVER, CVAR_ROM, NULL, + "The OpenGL library to use. (path optional)"); +} diff --git a/libs/video/targets/vid_x11_sw.c b/libs/video/targets/vid_x11_sw.c new file mode 100644 index 000000000..9c734a635 --- /dev/null +++ b/libs/video/targets/vid_x11_sw.c @@ -0,0 +1,542 @@ +/* + vid_x11_sw.c + + Software X11 video driver (8/32 bit) + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + This program 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 Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "QF/cvar.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "QF/vid.h" + +#include "context_x11.h" +#include "r_internal.h" +#include "vid_internal.h" +#include "vid_sw.h" + +int XShmGetEventBase (Display *x); // for broken X11 headers + +static GC x_gc; + +static qboolean doShm; +static XShmSegmentInfo x_shminfo[2]; + +static int current_framebuffer; +static XImage *x_framebuffer[2] = { 0, 0 }; + +typedef unsigned char PIXEL8; +typedef unsigned short PIXEL16; +typedef unsigned int PIXEL24; + +static PIXEL16 st2d_8to16table[256]; +static PIXEL24 st2d_8to24table[256]; + +static byte current_palette[768]; +static int shiftmask_fl = 0; +static long r_shift, g_shift, b_shift; +static unsigned long r_mask, g_mask, b_mask; + +static void +shiftmask_init (void) +{ + unsigned long long x; + + r_mask = x_vis->red_mask; + g_mask = x_vis->green_mask; + b_mask = x_vis->blue_mask; + + for (r_shift = -8, x = 1; x < r_mask; x <<= 1) + r_shift++; + for (g_shift = -8, x = 1; x < g_mask; x <<= 1) + g_shift++; + for (b_shift = -8, x = 1; x < b_mask; x <<= 1) + b_shift++; + shiftmask_fl = 1; +} + +static PIXEL16 +xlib_rgb16 (int r, int g, int b) +{ + PIXEL16 p = 0; + + if (!shiftmask_fl) + shiftmask_init (); + + if (r_shift > 0) { + p = (r << (r_shift)) & r_mask; + } else { + if (r_shift < 0) { + p = (r >> (-r_shift)) & r_mask; + } else { + p |= (r & r_mask); + } + } + + if (g_shift > 0) { + p |= (g << (g_shift)) & g_mask; + } else { + if (g_shift < 0) { + p |= (g >> (-g_shift)) & g_mask; + } else { + p |= (g & g_mask); + } + } + + if (b_shift > 0) { + p |= (b << (b_shift)) & b_mask; + } else { + if (b_shift < 0) { + p |= (b >> (-b_shift)) & b_mask; + } else { + p |= (b & b_mask); + } + } + + return p; +} + +static PIXEL24 +xlib_rgb24 (int r, int g, int b) +{ + PIXEL24 p = 0; + + if (!shiftmask_fl) + shiftmask_init (); + + if (r_shift > 0) { + p = (r << (r_shift)) & r_mask; + } else { + if (r_shift < 0) { + p = (r >> (-r_shift)) & r_mask; + } else { + p |= (r & r_mask); + } + } + + if (g_shift > 0) { + p |= (g << (g_shift)) & g_mask; + } else { + if (g_shift < 0) { + p |= (g >> (-g_shift)) & g_mask; + } else { + p |= (g & g_mask); + } + } + + if (b_shift > 0) { + p |= (b << (b_shift)) & b_mask; + } else { + if (b_shift < 0) { + p |= (b >> (-b_shift)) & b_mask; + } else { + p |= (b & b_mask); + } + } + + return p; +} + +static void +VID_SetPalette (const byte *palette) +{ + int i; + XColor colors[256]; + + for (i = 0; i < 256; i++) { + st2d_8to16table[i] = xlib_rgb16 (palette[i * 3], palette[i * 3 + 1], + palette[i * 3 + 2]); + st2d_8to24table[i] = xlib_rgb24 (palette[i * 3], palette[i * 3 + 1], + palette[i * 3 + 2]); + } + + if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8) { + if (palette != current_palette) { + memcpy (current_palette, palette, 768); + } + for (i = 0; i < 256; i++) { + colors[i].pixel = i; + colors[i].flags = DoRed | DoGreen | DoBlue; + colors[i].red = palette[(i * 3)] << 8; + colors[i].green = palette[(i * 3) + 1] << 8; + colors[i].blue = palette[(i * 3) + 2] << 8; + } + XStoreColors (x_disp, x_cmap, colors, 256); + } +} + +static void +st2_fixup (XImage *framebuf, int x, int y, int width, int height) +{ + int xi, yi; + unsigned char *src; + PIXEL16 *dest; + + if (x < 0 || y < 0) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &((byte *)viddef.buffer)[yi * viddef.width]; + dest = (PIXEL16 *) &framebuf->data[yi * framebuf->bytes_per_line]; + for (xi = x; xi < x + width; xi++) { + dest[xi] = st2d_8to16table[src[xi]]; + } + } +} + +static void +st3_fixup (XImage * framebuf, int x, int y, int width, int height) +{ + int yi; + unsigned char *src; + PIXEL24 *dest; + register int count, n; + + if (x < 0 || y < 0) + return; + + for (yi = y; yi < (y + height); yi++) { + src = &((byte *)viddef.buffer)[yi * viddef.width + x]; + dest = (PIXEL24 *) &framebuf->data[yi * framebuf->bytes_per_line + x]; + + // Duff's Device + count = width; + n = (count + 7) / 8; + + switch (count % 8) { + case 0: + do { + *dest++ = st2d_8to24table[*src++]; + case 7: + *dest++ = st2d_8to24table[*src++]; + case 6: + *dest++ = st2d_8to24table[*src++]; + case 5: + *dest++ = st2d_8to24table[*src++]; + case 4: + *dest++ = st2d_8to24table[*src++]; + case 3: + *dest++ = st2d_8to24table[*src++]; + case 2: + *dest++ = st2d_8to24table[*src++]; + case 1: + *dest++ = st2d_8to24table[*src++]; + } while (--n > 0); + } + } +} + +/* + Flush the given rectangles from the view buffer to the screen. +*/ +static void +x11_sw_update (vrect_t *rects) +{ + while (rects) { + switch (x_visinfo->depth) { + case 16: + st2_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + break; + case 24: + st3_fixup (x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->width, rects->height); + break; + } + if (doShm) { + if (!XShmPutImage (x_disp, x_win, x_gc, + x_framebuffer[current_framebuffer], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height, True)) { + Sys_Error ("VID_Update: XShmPutImage failed"); + } + oktodraw = false; + while (!oktodraw) + X11_ProcessEvent (); + rects = rects->next; + + current_framebuffer = !current_framebuffer; + } else { + if (XPutImage (x_disp, x_win, x_gc, x_framebuffer[0], + rects->x, rects->y, rects->x, rects->y, + rects->width, rects->height)) { + Sys_Error ("VID_Update: XPutImage failed"); + } + rects = rects->next; + } + } + XSync (x_disp, False); + r_data->scr_fullupdate = 0; +} + +static void +x11_choose_visual (sw_ctx_t *ctx) +{ + int pnum, i; + XVisualInfo template; + int num_visuals; + int template_mask; + + // specify a visual id + if ((pnum = COM_CheckParm ("-visualid"))) { + if (pnum >= com_argc - 1) + Sys_Error ("VID: -visualid "); + template.visualid = atoi (com_argv[pnum + 1]); + template_mask = VisualIDMask; + } else { // If not specified, use default + // visual + template.visualid = + XVisualIDFromVisual (XDefaultVisual (x_disp, x_screen)); + template_mask = VisualIDMask; + } + + // pick a visual -- warn if more than one was available + x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, + &num_visuals); + + if (x_visinfo->depth == 8 && x_visinfo->class == PseudoColor) + x_cmap = XCreateColormap (x_disp, x_win, x_vis, AllocAll); + x_vis = x_visinfo->visual; + + if (num_visuals > 1) { + Sys_MaskPrintf (SYS_VID, + "Found more than one visual id at depth %d:\n", + template.depth); + for (i = 0; i < num_visuals; i++) + Sys_MaskPrintf (SYS_VID, " -visualid %d\n", + (int) x_visinfo[i].visualid); + } else { + if (num_visuals == 0) { + if (template_mask == VisualIDMask) { + Sys_Error ("VID: Bad visual ID %ld", template.visualid); + } else { + Sys_Error ("VID: No visuals at depth %d", template.depth); + } + } + } + + Sys_MaskPrintf (SYS_VID, "Using visualid %d:\n", + (int) x_visinfo->visualid); + Sys_MaskPrintf (SYS_VID, " class %d\n", x_visinfo->class); + Sys_MaskPrintf (SYS_VID, " screen %d\n", x_visinfo->screen); + Sys_MaskPrintf (SYS_VID, " depth %d\n", x_visinfo->depth); + Sys_MaskPrintf (SYS_VID, " red_mask 0x%x\n", + (int) x_visinfo->red_mask); + Sys_MaskPrintf (SYS_VID, " green_mask 0x%x\n", + (int) x_visinfo->green_mask); + Sys_MaskPrintf (SYS_VID, " blue_mask 0x%x\n", + (int) x_visinfo->blue_mask); + Sys_MaskPrintf (SYS_VID, " colormap_size %d\n", + x_visinfo->colormap_size); + Sys_MaskPrintf (SYS_VID, " bits_per_rgb %d\n", + x_visinfo->bits_per_rgb); +} + +static void +ResetFrameBuffer (void) +{ + int mem, pwidth; + char *buf; + + if (x_framebuffer[0]) { + XDestroyImage (x_framebuffer[0]); + } + + pwidth = x_visinfo->depth / 8; + + if (pwidth == 3) + pwidth = 4; + mem = ((viddef.width * pwidth + 7) & ~7) * viddef.height; + buf = malloc (mem); + SYS_CHECKMEM (buf); + + // allocate new screen buffer + x_framebuffer[0] = XCreateImage (x_disp, x_vis, x_visinfo->depth, + ZPixmap, 0, buf, viddef.width, + viddef.height, 32, 0); + + if (!x_framebuffer[0]) { + Sys_Error ("VID: XCreateImage failed"); + } +} + +static void +ResetSharedFrameBuffers (void) +{ + int size; + int key; + int minsize = getpagesize (); + int frm; + + for (frm = 0; frm < 2; frm++) { + + // free up old frame buffer memory + if (x_framebuffer[frm]) { + XShmDetach (x_disp, &x_shminfo[frm]); + free (x_framebuffer[frm]); + shmdt (x_shminfo[frm].shmaddr); + } + // create the image + x_framebuffer[frm] = XShmCreateImage (x_disp, x_vis, x_visinfo->depth, + ZPixmap, 0, &x_shminfo[frm], + viddef.width, viddef.height); + + // grab shared memory + size = x_framebuffer[frm]->bytes_per_line * x_framebuffer[frm]->height; + + if (size < minsize) + Sys_Error ("VID: Window must use at least %d bytes", minsize); + + key = random (); + x_shminfo[frm].shmid = shmget ((key_t) key, size, IPC_CREAT | 0777); + if (x_shminfo[frm].shmid == -1) + Sys_Error ("VID: Could not get any shared memory (%s)", + strerror (errno)); + + // attach to the shared memory segment + x_shminfo[frm].shmaddr = (void *) shmat (x_shminfo[frm].shmid, 0, 0); + + Sys_MaskPrintf (SYS_VID, "VID: shared memory id=%d, addr=0x%lx\n", + x_shminfo[frm].shmid, (long) x_shminfo[frm].shmaddr); + + x_framebuffer[frm]->data = x_shminfo[frm].shmaddr; + + // get the X server to attach to it + if (!XShmAttach (x_disp, &x_shminfo[frm])) + Sys_Error ("VID: XShmAttach() failed"); + XSync (x_disp, 0); + shmctl (x_shminfo[frm].shmid, IPC_RMID, 0); + + } +} + +static void +x11_init_buffers (void) +{ + if (doShm) + ResetSharedFrameBuffers (); + else + ResetFrameBuffer (); + + current_framebuffer = 0; + + viddef.direct = 0; + viddef.rowbytes = viddef.width; + if (x_visinfo->depth != 8) { + if (viddef.buffer) + free (viddef.buffer); + viddef.buffer = calloc (viddef.width, viddef.height); + if (!viddef.buffer) + Sys_Error ("Not enough memory for video mode"); + } else { + viddef.buffer = x_framebuffer[current_framebuffer]->data; + } + viddef.conbuffer = viddef.buffer; + + viddef.conrowbytes = viddef.rowbytes; +} + +static void +x11_create_context (sw_ctx_t *ctx) +{ + // create the GC + { + XGCValues xgcvalues; + int valuemask = GCGraphicsExposures; + + xgcvalues.graphics_exposures = False; + x_gc = XCreateGC (x_disp, x_win, valuemask, &xgcvalues); + } + + // even if MITSHM is available, make sure it's a local connection + if (XShmQueryExtension (x_disp)) { + char *displayname; + char *d; + + doShm = true; + + if ((displayname = XDisplayName (NULL))) { + if ((d = strchr (displayname, ':'))) + *d = '\0'; + + if (!(!strcasecmp (displayname, "unix") || !*displayname)) + doShm = false; + } + } + + if (doShm) { + x_shmeventtype = XShmGetEventBase (x_disp) + ShmCompletion; + } + + viddef.vid_internal->do_screen_buffer = x11_init_buffers; + VID_InitBuffers (); + +// XSynchronize (x_disp, False); +// X11_AddEvent (x_shmeventtype, event_shm); +} + +sw_ctx_t * +X11_SW_Context (void) +{ + sw_ctx_t *ctx = calloc (1, sizeof (sw_ctx_t)); + ctx->set_palette = VID_SetPalette; + ctx->choose_visual = x11_choose_visual; + ctx->create_context = x11_create_context; + ctx->update = x11_sw_update; + return ctx; +} + +void +X11_SW_Init_Cvars (void) +{ +} diff --git a/libs/video/targets/vid_x11_vulkan.c b/libs/video/targets/vid_x11_vulkan.c new file mode 100644 index 000000000..e472c0c0e --- /dev/null +++ b/libs/video/targets/vid_x11_vulkan.c @@ -0,0 +1,169 @@ +/* + vid_x11_vulkan.c + + Vulkan X11 video driver + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 1999-2000 contributors of the QuakeForge project + Copyright (C) 2000 Marcus Sundberg [mackan@stacken.kth.se] + Copyright (C) 1999,2000 contributors of the QuakeForge project + Please see the file "AUTHORS" for a list of contributors + + This program 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 Foundation; either version 2 + of the License, or (at your option) any later version. + + This program 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 this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif + +#include +#include +#include +#include +#define VK_NO_PROTOTYPES +#define VK_USE_PLATFORM_XLIB_KHR +#include + +#include "QF/cvar.h" +#include "QF/set.h" +#include "QF/sys.h" + +#include "context_x11.h" +#include "vid_internal.h" +#include "vid_vulkan.h" + +static cvar_t *vulkan_library_name; + +typedef struct vulkan_presentation_s { +#define INSTANCE_LEVEL_VULKAN_FUNCTION(name) PFN_##name name; +#include "QF/Vulkan/funclist.h" + + Display *display; + Window window; + int num_visuals; + XVisualInfo *visinfo; + set_t *usable_visuals; +} vulkan_presentation_t; + +static const char *required_extensions[] = { + VK_KHR_XLIB_SURFACE_EXTENSION_NAME, + 0 +}; + +static void *vulkan_library; + +static void +load_vulkan_library (vulkan_ctx_t *ctx) +{ + vulkan_library = dlopen (vulkan_library_name->string, + RTLD_DEEPBIND | RTLD_NOW); + if (!vulkan_library) { + Sys_Error ("Couldn't load vulkan library %s: %s", + vulkan_library_name->name, dlerror ()); + } + + #define EXPORTED_VULKAN_FUNCTION(name) \ + ctx->name = (PFN_##name) dlsym (vulkan_library, #name); \ + if (!ctx->name) { \ + Sys_Error ("Couldn't find exported vulkan function %s", #name); \ + } + + #define GLOBAL_LEVEL_VULKAN_FUNCTION(name) \ + ctx->name = (PFN_##name) ctx->vkGetInstanceProcAddr (0, #name); \ + if (!ctx->name) { \ + Sys_Error ("Couldn't find global-level function %s", #name); \ + } + + #include "QF/Vulkan/funclist.h" +} + +static void +unload_vulkan_library (vulkan_ctx_t *ctx) +{ + dlclose (vulkan_library); + vulkan_library = 0; +} + +static int +x11_vulkan_get_presentation_support (vulkan_ctx_t *ctx, + VkPhysicalDevice physicalDevice, + uint32_t queueFamilyIndex) +{ + vulkan_presentation_t *pres = ctx->presentation; + + set_empty (pres->usable_visuals); + for (int i = 0; i < pres->num_visuals; i++) { + VisualID visID = pres->visinfo[i].visualid; + + if (pres->vkGetPhysicalDeviceXlibPresentationSupportKHR ( + physicalDevice, queueFamilyIndex, pres->display, visID)) { + set_add (pres->usable_visuals, i); + } + } + return !set_is_empty (pres->usable_visuals); +} + +static VkSurfaceKHR +x11_vulkan_create_surface (vulkan_ctx_t *ctx) +{ + vulkan_presentation_t *pres = ctx->presentation; + VkSurfaceKHR surface; + VkXlibSurfaceCreateInfoKHR createInfo = { + .sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + .flags = 0, + .dpy = pres->display, + .window = pres->window + }; + + if (pres->vkCreateXlibSurfaceKHR (ctx->instance, &createInfo, 0, &surface) + != VK_SUCCESS) { + return 0; + } + return surface; +} + +vulkan_ctx_t * +X11_Vulkan_Context (void) +{ + vulkan_ctx_t *ctx = calloc (1, sizeof (vulkan_ctx_t)); + ctx->load_vulkan = load_vulkan_library; + ctx->unload_vulkan = unload_vulkan_library; + ctx->get_presentation_support = x11_vulkan_get_presentation_support; + ctx->create_surface = x11_vulkan_create_surface; + ctx->required_extensions = required_extensions; + return ctx; +} + +void +X11_Vulkan_Init_Cvars (void) +{ + vulkan_library_name = Cvar_Get ("vulkan_library", "libvulkan.so.1", + CVAR_ROM, 0, + "the name of the vulkan shared library"); +}