mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 04:21:51 +00:00
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:
parent
53a62e4d62
commit
8ee06d75a9
41 changed files with 1576 additions and 980 deletions
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -29,7 +29,6 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "QF/qtypes.h"
|
||||
#include "QF/Vulkan/funcs.h"
|
||||
|
||||
typedef struct {
|
||||
VkDevice device;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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
20
include/vid_gl.h
Normal 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
|
|
@ -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
18
include/vid_sw.h
Normal 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
29
include/vid_vulkan.h
Normal 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
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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@
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
178
libs/video/targets/vid_sdl_gl.c
Normal file
178
libs/video/targets/vid_sdl_gl.c
Normal 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)");
|
||||
}
|
183
libs/video/targets/vid_sdl_sw.c
Normal file
183
libs/video/targets/vid_sdl_sw.c
Normal 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 ()
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
|
|
209
libs/video/targets/vid_x11_gl.c
Normal file
209
libs/video/targets/vid_x11_gl.c
Normal 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)");
|
||||
}
|
542
libs/video/targets/vid_x11_sw.c
Normal file
542
libs/video/targets/vid_x11_sw.c
Normal 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)
|
||||
{
|
||||
}
|
169
libs/video/targets/vid_x11_vulkan.c
Normal file
169
libs/video/targets/vid_x11_vulkan.c
Normal 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");
|
||||
}
|
Loading…
Reference in a new issue