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.
This commit is contained in:
Bill Currie 2019-07-09 01:00:47 +09:00
parent 53a62e4d62
commit 8ee06d75a9
41 changed files with 1576 additions and 980 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -29,7 +29,6 @@
#include <vulkan/vulkan.h>
#include "QF/qtypes.h"
#include "QF/Vulkan/funcs.h"
typedef struct {
VkDevice device;

View file

@ -30,7 +30,19 @@
#ifndef __context_sdl_h_
#define __context_sdl_h_
#include <SDL.h>
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_

View file

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

View file

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

20
include/vid_gl.h Normal file
View file

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

View file

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

18
include/vid_sw.h Normal file
View file

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

29
include/vid_vulkan.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef __vid_vulkan_h
#define __vid_vulkan_h
#ifndef VK_NO_PROTOTYPES
#define VK_NO_PROTOTYPES
#endif
#include <vulkan/vulkan.h>
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

View file

@ -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 ();

View file

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

View file

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

View file

@ -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 ();

View file

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

View file

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

View file

@ -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);
}

View file

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

View file

@ -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);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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");
}

View file

@ -1,6 +0,0 @@
#include <vulkan/vulkan.h>
#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname;
#include "QF/Vulkan/funclist.h"

View file

@ -39,8 +39,6 @@
# include <strings.h>
#endif
#include <dlfcn.h>
#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);
}

View file

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

View file

@ -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);
}

View file

@ -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 <windows.h>
# 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

View file

@ -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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <SDL.h>
#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 <windows.h>
# 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)");
}

View file

@ -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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <SDL.h>
#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 <windows.h>
#include <SDL_syswm.h>
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 <windows.h>
# 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 ()
{
}

View file

@ -44,21 +44,10 @@
# include <unistd.h>
#endif
#include <ctype.h>
#include <dlfcn.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <sys/types.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
#ifdef HAVE_VIDMODE
# include <X11/extensions/xf86vmode.h>
@ -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 <windows.h>
# 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 <id#>");
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)

View file

@ -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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <dlfcn.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#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 <windows.h>
# 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)");
}

View file

@ -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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/time.h>
#include <sys/types.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#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 <id#>");
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)
{
}

View file

@ -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 <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <dlfcn.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#define VK_NO_PROTOTYPES
#define VK_USE_PLATFORM_XLIB_KHR
#include <vulkan/vulkan.h>
#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");
}