From f13e15e56172f7588834294706795395b7456de9 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Sun, 2 Oct 2016 00:40:52 +0200 Subject: [PATCH] ref_gl.so builds and works (on Linux, with Makefile) still dirty, seems to use some symbols from client directly, which will not work on Windows. --- Makefile | 136 ++++++-- src/backends/generic/vid.c | 289 +++++++++++++++-- src/backends/sdl/refresh.c | 485 +++-------------------------- src/client/cl_screen.c | 6 +- src/client/header/ref.h | 134 +++++++- src/client/menu/menu.c | 4 +- src/client/refresh/gl/r_draw.c | 45 +-- src/client/refresh/gl/r_image.c | 4 +- src/client/refresh/gl/r_light.c | 2 +- src/client/refresh/gl/r_lightmap.c | 2 +- src/client/refresh/gl/r_main.c | 118 ++++++- src/client/refresh/gl/r_mesh.c | 6 +- src/client/refresh/gl/r_misc.c | 2 +- src/client/refresh/gl/r_model.c | 8 +- src/client/refresh/gl/r_scrap.c | 2 +- src/client/refresh/gl/r_sdl.c | 449 ++++++++++++++++++++++++++ src/client/refresh/gl/r_surf.c | 2 +- src/client/refresh/gl/r_warp.c | 6 +- src/client/refresh/header/local.h | 10 +- 19 files changed, 1138 insertions(+), 572 deletions(-) create mode 100644 src/client/refresh/gl/r_sdl.c diff --git a/Makefile b/Makefile index 13fdeecd..5fd2da3e 100755 --- a/Makefile +++ b/Makefile @@ -302,12 +302,12 @@ endif # ---------- # Phony targets -.PHONY : all client game icon server +.PHONY : all client game icon server ref_gl # ---------- # Builds everything -all: config client server game +all: config client server game ref_gl # Print config values config: @@ -344,6 +344,10 @@ endif # Cleanup clean: + @echo "===> CLEAN" + ${Q}rm -Rf build release/* + +cleanall: @echo "===> CLEAN" ${Q}rm -Rf build release @@ -384,7 +388,9 @@ release/quake2.exe : CFLAGS += -DSDL2 endif release/quake2.exe : LDFLAGS += -mwindows -lopengl32 + else # not Windows + client: @echo "===> Building quake2" ${Q}mkdir -p release @@ -393,7 +399,7 @@ client: build/client/%.o: %.c @echo "===> CC $<" ${Q}mkdir -p $(@D) - ${Q}$(CC) -c $(CFLAGS) $(SDLCFLAGS) $(X11CFLAGS) $(INCLUDE) -o $@ $< + ${Q}$(CC) -c $(CFLAGS) $(SDLCFLAGS) $(INCLUDE) -o $@ $< ifeq ($(OSTYPE), Darwin) build/client/%.o : %.m @@ -439,9 +445,9 @@ endif ifeq ($(WITH_SDL2),yes) release/quake2 : CFLAGS += -DSDL2 endif - + ifneq ($(OSTYPE), Darwin) -release/quake2 : LDFLAGS += -lGL +release/ref_gl.so : LDFLAGS += -lGL endif ifeq ($(OSTYPE), FreeBSD) @@ -507,6 +513,53 @@ release/q2ded : LDFLAGS += -lz endif endif +# ---------- + +# The renderer lib + +ifeq ($(OSTYPE), Windows) + +ref_gl: + @echo "===> Building ref_gl.dll" + $(MAKE) release/ref_gl.dll + +ifeq ($(WITH_SDL2),yes) +release/ref_gl.dll : CFLAGS += -DSDL2 +endif + +else ifeq ($(OSTYPE), Darwin) + +ref_gl: + @echo "===> Building ref_gl.dylib" + $(MAKE) release/ref_gl.dylib + + +ifeq ($(WITH_SDL2),yes) +release/ref_gl.dylib : CFLAGS += -DSDL2 +endif + +else # not Windows or Darwin + +ref_gl: + @echo "===> Building ref_gl.so" + $(MAKE) release/ref_gl.so + + +release/ref_gl.so : CFLAGS += -fPIC +release/ref_gl.so : LDFLAGS += -shared + +ifeq ($(WITH_SDL2),yes) +release/ref_gl.so : CFLAGS += -DSDL2 +endif + +endif # OS specific ref_gl shit + +build/ref_gl/%.o: %.c + @echo "===> CC $<" + ${Q}mkdir -p $(@D) + ${Q}$(CC) -c $(CFLAGS) $(SDLCFLAGS) $(X11CFLAGS) $(INCLUDE) -o $@ $< + + # ---------- # The baseq2 game @@ -610,7 +663,6 @@ CLIENT_OBJS_ := \ src/backends/generic/misc.o \ src/backends/generic/qal.o \ src/backends/generic/vid.o \ - src/backends/generic/qgl.o \ src/backends/sdl/cd.o \ src/backends/sdl/input.o \ src/backends/sdl/refresh.o \ @@ -632,22 +684,6 @@ CLIENT_OBJS_ := \ src/client/cl_screen.o \ src/client/cl_tempentities.o \ src/client/cl_view.o \ - src/client/refresh/r_draw.o \ - src/client/refresh/r_image.o \ - src/client/refresh/r_light.o \ - src/client/refresh/r_lightmap.o \ - src/client/refresh/r_main.o \ - src/client/refresh/r_mesh.o \ - src/client/refresh/r_misc.o \ - src/client/refresh/r_model.o \ - src/client/refresh/r_scrap.o \ - src/client/refresh/r_surf.o \ - src/client/refresh/r_warp.o \ - src/client/refresh/files/md2.o \ - src/client/refresh/files/pcx.o \ - src/client/refresh/files/sp2.o \ - src/client/refresh/files/stb.o \ - src/client/refresh/files/wal.o \ src/client/menu/menu.o \ src/client/menu/qmenu.o \ src/client/menu/videomenu.o \ @@ -684,7 +720,7 @@ CLIENT_OBJS_ := \ src/server/sv_save.o \ src/server/sv_send.o \ src/server/sv_user.o \ - src/server/sv_world.o + src/server/sv_world.o ifeq ($(OSTYPE), Windows) CLIENT_OBJS_ += \ @@ -702,6 +738,41 @@ endif # ---------- +# TODO: move qgl.c to refresh/gl/ (and probably the header as well) + +REFGL_OBJS_ := \ + src/backends/generic/qgl.o \ + src/client/refresh/gl/r_draw.o \ + src/client/refresh/gl/r_image.o \ + src/client/refresh/gl/r_light.o \ + src/client/refresh/gl/r_lightmap.o \ + src/client/refresh/gl/r_main.o \ + src/client/refresh/gl/r_mesh.o \ + src/client/refresh/gl/r_misc.o \ + src/client/refresh/gl/r_model.o \ + src/client/refresh/gl/r_scrap.o \ + src/client/refresh/gl/r_surf.o \ + src/client/refresh/gl/r_warp.o \ + src/client/refresh/gl/r_sdl.o \ + src/client/refresh/files/md2.o \ + src/client/refresh/files/pcx.o \ + src/client/refresh/files/sp2.o \ + src/client/refresh/files/stb.o \ + src/client/refresh/files/wal.o \ + src/common/shared/flash.o \ + src/common/shared/rand.o \ + src/common/shared/shared.o + +ifeq ($(OSTYPE), Windows) +REFGL_OBJS_ += \ + src/backends/windows/shared/mem.o +else # not Windows +REFGL_OBJS_ += \ + src/backends/unix/shared/hunk.o +endif + +# ---------- + # Used by the server SERVER_OBJS_ := \ src/common/argproc.o \ @@ -753,6 +824,7 @@ endif # Rewrite pathes to our object directory CLIENT_OBJS = $(patsubst %,build/client/%,$(CLIENT_OBJS_)) +REFGL_OBJS = $(patsubst %,build/ref_gl/%,$(REFGL_OBJS_)) SERVER_OBJS = $(patsubst %,build/server/%,$(SERVER_OBJS_)) GAME_OBJS = $(patsubst %,build/baseq2/%,$(GAME_OBJS_)) @@ -760,6 +832,7 @@ GAME_OBJS = $(patsubst %,build/baseq2/%,$(GAME_OBJS_)) # Generate header dependencies CLIENT_DEPS= $(CLIENT_OBJS:.o=.d) +REFGL_DEPS= $(REFGL_OBJS:.o=.d) SERVER_DEPS= $(SERVER_OBJS:.o=.d) GAME_DEPS= $(GAME_OBJS:.o=.d) @@ -767,6 +840,7 @@ GAME_DEPS= $(GAME_OBJS:.o=.d) # Suck header dependencies in -include $(CLIENT_DEPS) +-include $(REFGL_DEPS) -include $(SERVER_DEPS) -include $(GAME_DEPS) @@ -796,6 +870,22 @@ release/q2ded : $(SERVER_OBJS) ${Q}$(CC) $(SERVER_OBJS) $(LDFLAGS) -o $@ endif +# release/ref_gl.so +ifeq ($(OSTYPE), Windows) +release/ref_gl.dll : $(REFGL_OBJS) + @echo "===> LD $@" + ${Q}$(CC) $(REFGL_OBJS) $(LDFLAGS) $(SDLLDFLAGS) -o $@ + $(Q)strip $@ +else ifeq ($(OSTYPE), Darwin) +release/ref_gl.dylib : $(REFGL_OBJS) + @echo "===> LD $@" + ${Q}$(CC) $(GAME_OBJS) $(LDFLAGS) $(SDLLDFLAGS) -o $@ +else +release/ref_gl.so : $(REFGL_OBJS) + @echo "===> LD $@" + ${Q}$(CC) $(REFGL_OBJS) $(LDFLAGS) $(SDLLDFLAGS) -o $@ +endif + # release/baseq2/game.so ifeq ($(OSTYPE), Windows) release/baseq2/game.dll : $(GAME_OBJS) diff --git a/src/backends/generic/vid.c b/src/backends/generic/vid.c index 27d8dc50..a638dc3e 100644 --- a/src/backends/generic/vid.c +++ b/src/backends/generic/vid.c @@ -41,6 +41,8 @@ #include "../../client/header/client.h" #include "../../client/header/keyboard.h" +qboolean VID_LoadRefresh(void); + typedef struct vidmode_s { const char *description; @@ -82,7 +84,6 @@ cvar_t *vid_fullscreen; /* Global variables used internally by this module */ viddef_t viddef; /* global video state; used by other modules */ -qboolean ref_active = false; /* Is the refresher being used? */ #define VID_NUM_MODES (sizeof(vid_modes) / sizeof(vid_modes[0])) #define MAXPRINTMSG 4096 @@ -152,33 +153,6 @@ VID_NewWindow(int width, int height) viddef.height = height; } -qboolean -VID_LoadRefresh(void) -{ - // If the refresher is already active - // we'll shut it down - VID_Shutdown(); - - // Log it! - Com_Printf("----- refresher initialization -----\n"); - - // Declare the refresher as active - ref_active = true; - - // Initiate the refresher - if (R_Init(0, 0) == -1) - { - VID_Shutdown(); // Isn't that just too bad? :( - return false; - } - - /* Ensure that all key states are cleared */ - Key_MarkAllUp(); - - Com_Printf("------------------------------------\n\n"); - return true; -} - /* * This function gets called once just before drawing each frame, and * it's sole purpose in life is to check to see if any of the video mode @@ -217,15 +191,272 @@ VID_Init(void) VID_CheckChanges(); } +// Structure containing functions exported from refresh DLL +refexport_t re; +void *reflib_handle = NULL; // Handle to refresh DLL +qboolean ref_active = false; /* Is the refresher being used? */ + +void Key_MarkAllUp(void); + +extern qboolean GLimp_InitGraphics(qboolean fullscreen, int *pwidth, int *pheight); +extern void VID_ShutdownWindow(void); + +qboolean +VID_LoadRefresh(void) +{ + refimport_t ri; + GetRefAPI_t GetRefAPI; + +#ifdef __APPLE__ + const char* lib_ext = "dylib"; +#elif defined(_WIN32) + const char* lib_ext = "dll"; +#else + const char* lib_ext = "so"; +#endif + char reflib_path[MAX_OSPATH] = {0}; + + // If the refresher is already active + // we'll shut it down + VID_Shutdown(); + + // Log it! + Com_Printf("----- refresher initialization -----\n"); + + snprintf(reflib_path, sizeof(reflib_path), "./ref_gl.%s", lib_ext); // TODO: name from cvar + + GetRefAPI = Sys_LoadLibrary(reflib_path, "GetRefAPI", &reflib_handle); + if(GetRefAPI == NULL) + { + Com_Error( ERR_FATAL, "Loading %s as renderer lib failed!", reflib_path ); + return false; + } + + ri.Cmd_AddCommand = Cmd_AddCommand; + ri.Cmd_RemoveCommand = Cmd_RemoveCommand; + ri.Cmd_Argc = Cmd_Argc; + ri.Cmd_Argv = Cmd_Argv; + ri.Cmd_ExecuteText = Cbuf_ExecuteText; + ri.Con_Printf = VID_Printf; + ri.Sys_Error = VID_Error; + ri.FS_LoadFile = FS_LoadFile; + ri.FS_FreeFile = FS_FreeFile; + ri.FS_Gamedir = FS_Gamedir; + ri.Cvar_Get = Cvar_Get; + ri.Cvar_Set = Cvar_Set; + ri.Cvar_SetValue = Cvar_SetValue; + ri.Vid_GetModeInfo = VID_GetModeInfo; + ri.Vid_MenuInit = VID_MenuInit; + ri.Vid_NewWindow = VID_NewWindow; + + ri.Vid_ShutdownWindow = VID_ShutdownWindow; + ri.GLimp_InitGraphics = GLimp_InitGraphics; + + re = GetRefAPI( ri ); + + // Declare the refresher as active + ref_active = true; + + if (re.api_version != API_VERSION) + { + VID_Shutdown(); + Com_Error (ERR_FATAL, "%s has incompatible api_version %d", reflib_path, re.api_version); + } + + // Initiate the refresher + if (re.Init(0, 0) == -1) + { + VID_Shutdown(); // Isn't that just too bad? :( + return false; + } + + /* Ensure that all key states are cleared */ + Key_MarkAllUp(); + + Com_Printf("------------------------------------\n\n"); + return true; +} + void VID_Shutdown(void) { if (ref_active) { /* Shut down the renderer */ - R_Shutdown(); + re.Shutdown(); + Sys_FreeLibrary(reflib_handle); + reflib_handle = NULL; + memset(&re, 0, sizeof(re)); } // Declare the refresher as inactive ref_active = false; } + +// ======== wrappers for functions from refresh lib ======== + +void +R_BeginRegistration(char *map) +{ + if(ref_active) + { + re.BeginRegistration(map); + } +} + +struct model_s* +R_RegisterModel(char *name) +{ + if(ref_active) + { + return re.RegisterModel(name); + } + return NULL; +} + +struct image_s* +R_RegisterSkin(char *name) +{ + if(ref_active) + { + return re.RegisterSkin(name); + } + return NULL; +} + +void +R_SetSky(char *name, float rotate, vec3_t axis) +{ + if(ref_active) + { + re.SetSky(name, rotate, axis); + } +} + +void +R_EndRegistration(void) +{ + if(ref_active) + { + re.EndRegistration(); + } +} + +void +R_RenderFrame(refdef_t *fd) +{ + if(ref_active) + { + re.RenderFrame(fd); + } +} + +struct image_s* +Draw_FindPic(char *name) +{ + if(ref_active) + { + return re.DrawFindPic(name); + } + return NULL; +} + + +void +Draw_GetPicSize(int *w, int *h, char *name) +{ + if(ref_active) + { + re.DrawGetPicSize(w, h, name); + } +} + +void +Draw_StretchPic(int x, int y, int w, int h, char *name) +{ + if(ref_active) + { + re.DrawStretchPic(x, y, w, h, name); + } +} + +void +Draw_PicScaled(int x, int y, char *pic, float factor) +{ + if(ref_active) + { + re.DrawPicScaled(x, y, pic, factor); + } +} + +void +Draw_CharScaled(int x, int y, int num, float scale) +{ + if(ref_active) + { + re.DrawCharScaled(x, y, num, scale); + } +} + +void +Draw_TileClear(int x, int y, int w, int h, char *name) +{ + if(ref_active) + { + re.DrawTileClear(x, y, w, h, name); + } +} + +void +Draw_Fill(int x, int y, int w, int h, int c) +{ + if(ref_active) + { + re.DrawFill(x, y, w, h, c); + } +} + +void +Draw_FadeScreen(void) +{ + if(ref_active) + { + re.DrawFadeScreen(); + } +} + +void +Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data) +{ + if(ref_active) + { + re.DrawStretchRaw(x, y, w, h, cols, rows, data); + } +} + +void +R_SetPalette(const unsigned char *palette) +{ + if(ref_active) + { + re.SetPalette(palette); + } +} + +void +R_BeginFrame(float camera_separation) +{ + if(ref_active) + { + re.BeginFrame(camera_separation); + } +} + +void +R_EndFrame(void) +{ + if(ref_active) + { + re.EndFrame(); + } +} diff --git a/src/backends/sdl/refresh.c b/src/backends/sdl/refresh.c index 169e1117..a914065c 100644 --- a/src/backends/sdl/refresh.c +++ b/src/backends/sdl/refresh.c @@ -35,11 +35,7 @@ */ #include "../../client/refresh/header/local.h" -#if defined(__APPLE__) -#include -#else -#include -#endif + #ifdef SDL2 #include @@ -49,42 +45,24 @@ #include #endif //SDL2 -/* X.org stuff */ -#ifdef X11GAMMA - #include - #include - #include - #include - #include - - #include -#endif - #if SDL_VERSION_ATLEAST(2, 0, 0) -SDL_Window* window = NULL; -SDL_GLContext context = NULL; +static SDL_Window* window = NULL; #else -SDL_Surface* window = NULL; +static SDL_Surface* window = NULL; #endif -qboolean have_stencil = false; + qboolean vsync_active; -#ifdef X11GAMMA -XRRCrtcGamma** gammaRamps = NULL; -int noGammaRamps = 0; -#endif - #if SDL_VERSION_ATLEAST(2, 0, 0) // some compatibility defines #define SDL_SRCCOLORKEY SDL_TRUE #define SDL_FULLSCREEN SDL_WINDOW_FULLSCREEN -#define SDL_OPENGL SDL_WINDOW_OPENGL #endif /* - * Initialzes the SDL OpenGL context + * Initializes the SDL video subsystem */ int GLimp_Init(void) @@ -110,15 +88,6 @@ GLimp_Init(void) return true; } -/* - * Returns the adress of a GL function - */ -void * -GLimp_GetProcAddress (const char* proc) -{ - return SDL_GL_GetProcAddress ( proc ); -} - /* * Sets the window icon */ @@ -208,127 +177,6 @@ SetSDLIcon() } #endif /* SDL 1.2 */ -/* - * from SDL2 SDL_CalculateGammaRamp, adjusted for arbitrary ramp sizes - * because xrandr seems to support ramp sizes != 256 (in theory at least) - */ -void CalculateGammaRamp(float gamma, Uint16* ramp, int len) -{ - int i; - - /* Input validation */ - if (gamma < 0.0f ) { - return; - } - if (ramp == NULL) { - return; - } - - /* 0.0 gamma is all black */ - if (gamma == 0.0f) { - for (i = 0; i < len; ++i) { - ramp[i] = 0; - } - return; - } else if (gamma == 1.0f) { - /* 1.0 gamma is identity */ - for (i = 0; i < len; ++i) { - ramp[i] = (i << 8) | i; - } - return; - } else { - /* Calculate a real gamma ramp */ - int value; - gamma = 1.0f / gamma; - for (i = 0; i < len; ++i) { - value = (int) (pow((double) i / (double) len, gamma) * 65535.0 + 0.5); - if (value > 65535) { - value = 65535; - } - ramp[i] = (Uint16) value; - } - } -} - -/* - * Sets the hardware gamma - */ -#ifdef X11GAMMA -void -UpdateHardwareGamma(void) -{ - float gamma = (vid_gamma->value); - int i; - - Display* dpy = NULL; - SDL_SysWMinfo info; - -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_VERSION(&info.version); - if(!SDL_GetWindowWMInfo(window, &info)) -#else - if(SDL_GetWMInfo(&info) != 1) -#endif - { - VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n"); - return; - } - - dpy = info.info.x11.display; - - XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window); - if(res == NULL) - { - VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n"); - return; - } - - for(i=0; i < res->ncrtc; ++i) - { - int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); - size_t rampSize = len*sizeof(Uint16); - Uint16* ramp = malloc(rampSize); // TODO: check for NULL - if(ramp == NULL) - { - VID_Printf(PRINT_ALL, "Couldn't allocate &zd byte of memory for gamma ramp - OOM?!\n", rampSize); - return; - } - - CalculateGammaRamp(gamma, ramp, len); - - XRRCrtcGamma* gamma = XRRAllocGamma(len); - - memcpy(gamma->red, ramp, rampSize); - memcpy(gamma->green, ramp, rampSize); - memcpy(gamma->blue, ramp, rampSize); - - free(ramp); - - XRRSetCrtcGamma(dpy, res->crtcs[i], gamma); - - XRRFreeGamma(gamma); - } - - XRRFreeScreenResources(res); -} -#else // no X11GAMMA -void -UpdateHardwareGamma(void) -{ - float gamma = (vid_gamma->value); - - Uint16 ramp[256]; - CalculateGammaRamp(gamma, ramp, 256); -#if SDL_VERSION_ATLEAST(2, 0, 0) - if(SDL_SetWindowGammaRamp(window, ramp, ramp, ramp) != 0) { -#else - if(SDL_SetGammaRamp(ramp, ramp, ramp) < 0) { -#endif - VID_Printf(PRINT_ALL, "Setting gamma failed: %s\n", SDL_GetError()); - } -} -#endif // X11GAMMA - static qboolean IsFullscreen() { #if SDL_VERSION_ATLEAST(2, 0, 0) @@ -338,30 +186,16 @@ static qboolean IsFullscreen() #endif } -static qboolean CreateSDLWindow(int flags) +static qboolean CreateSDLWindow(int flags, int w, int h) { #if SDL_VERSION_ATLEAST(2, 0, 0) int windowPos = SDL_WINDOWPOS_UNDEFINED; // TODO: support fullscreen on different displays with SDL_WINDOWPOS_UNDEFINED_DISPLAY(displaynum) - window = SDL_CreateWindow("Yamagi Quake II", windowPos, windowPos, - vid.width, vid.height, flags); + window = SDL_CreateWindow("Yamagi Quake II", windowPos, windowPos, w, h, flags); - if(window == NULL) - { - return false; - } - - context = SDL_GL_CreateContext(window); - if(context == NULL) - { - SDL_DestroyWindow(window); - window = NULL; - return false; - } - - return true; + return window != NULL; #else - window = SDL_SetVideoMode(vid.width, vid.height, 0, flags); + window = SDL_SetVideoMode(w, h, 0, flags); SDL_EnableUNICODE(SDL_TRUE); return window != NULL; #endif @@ -389,145 +223,20 @@ static qboolean GetWindowSize(int* w, int* h) return true; } -static void InitGamma() -{ -#ifdef X11GAMMA - int i=0; - SDL_SysWMinfo info; - Display* dpy = NULL; - - if(gammaRamps != NULL) // already saved gamma - return; - -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_VERSION(&info.version); - if(!SDL_GetWindowWMInfo(window, &info)) -#else - if(SDL_GetWMInfo(&info) != 1) -#endif - { - VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n"); - return; - } - - dpy = info.info.x11.display; - - XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window); - if(res == NULL) - { - VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n"); - return; - } - - noGammaRamps = res->ncrtc; - gammaRamps = calloc(noGammaRamps, sizeof(XRRCrtcGamma*)); - if(gammaRamps == NULL) { - VID_Printf(PRINT_ALL, "Couldn't allocate memory for %d gamma ramps - OOM?!\n", noGammaRamps); - return; - } - - for(i=0; i < noGammaRamps; ++i) - { - int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); - size_t rampSize = len*sizeof(Uint16); - - XRRCrtcGamma* origGamma = XRRGetCrtcGamma(dpy, res->crtcs[i]); - - XRRCrtcGamma* gammaCopy = XRRAllocGamma(len); - - memcpy(gammaCopy->red, origGamma->red, rampSize); - memcpy(gammaCopy->green, origGamma->green, rampSize); - memcpy(gammaCopy->blue, origGamma->blue, rampSize); - - gammaRamps[i] = gammaCopy; - } - - XRRFreeScreenResources(res); - - VID_Printf(PRINT_ALL, "Using hardware gamma via X11/xRandR.\n"); -#elif __APPLE__ - gl_state.hwgamma = false; - VID_Printf(PRINT_ALL, "Using software gamma (needs vid_restart after changes)\n"); - return; -#else - VID_Printf(PRINT_ALL, "Using hardware gamma via SDL.\n"); -#endif - gl_state.hwgamma = true; - vid_gamma->modified = true; -} - -#ifdef X11GAMMA -static void RestoreGamma() -{ - int i=0; - SDL_SysWMinfo info; - Display* dpy = NULL; - - if(gammaRamps == NULL) - return; - -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_VERSION(&info.version); - if(!SDL_GetWindowWMInfo(window, &info)) -#else - if(SDL_GetWMInfo(&info) != 1) -#endif - { - VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n"); - return; - } - - dpy = info.info.x11.display; - - XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window); - if(res == NULL) - { - VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n"); - return; - } - - for(i=0; i < noGammaRamps; ++i) - { - // in case a display was unplugged or something, noGammaRamps may be > res->ncrtc - if(i < res->ncrtc) - { - int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); - if(len != gammaRamps[i]->size) { - VID_Printf(PRINT_ALL, "WTF, gamma ramp size for display %d has changed from %d to %d!\n", - i, gammaRamps[i]->size, len); - - continue; - } - - XRRSetCrtcGamma(dpy, res->crtcs[i], gammaRamps[i]); - } - - // the ramp needs to be free()d either way - XRRFreeGamma(gammaRamps[i]); - gammaRamps[i] = NULL; - - } - XRRFreeScreenResources(res); - free(gammaRamps); - gammaRamps = NULL; - - VID_Printf(PRINT_ALL, "Restored original Gamma\n"); -} -#endif // X11GAMMA /* * Initializes the OpenGL window */ -static qboolean -GLimp_InitGraphics(qboolean fullscreen) +qboolean +GLimp_InitGraphics(qboolean fullscreen, int *pwidth, int *pheight) { int flags; - int msaa_samples; - int stencil_bits; - int width, height; + int curWidth, curHeight; char title[24]; + int width = *pwidth; + int height = *pheight; - if (GetWindowSize(&width, &height) && (width == vid.width) && (height == vid.height)) + if (GetWindowSize(&curWidth, &curHeight) && (curWidth == width) && (curHeight == height)) { /* If we want fullscreen, but aren't */ if (fullscreen != IsFullscreen()) @@ -552,45 +261,21 @@ GLimp_InitGraphics(qboolean fullscreen) if (window) { #if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_GL_DeleteContext(context); + + re.ShutdownWindow(true); + SDL_DestroyWindow(window); #else SDL_FreeSurface(window); #endif + window = NULL; } /* Create the window */ - VID_NewWindow(vid.width, vid.height); + VID_NewWindow(width, height); - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - - if (gl_msaa_samples->value) - { - msaa_samples = gl_msaa_samples->value; - - if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) < 0) - { - Com_Printf("MSAA is unsupported: %s\n", SDL_GetError()); - Cvar_SetValue ("gl_msaa_samples", 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); - } - else if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_samples) < 0) - { - Com_Printf("MSAA %ix is unsupported: %s\n", msaa_samples, SDL_GetError()); - Cvar_SetValue("gl_msaa_samples", 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); - } - } - - /* Initiate the flags */ - flags = SDL_OPENGL; + // let renderer prepare things (set OpenGL attributes) + flags = re.PrepareForWindow(); if (fullscreen) { @@ -598,34 +283,31 @@ GLimp_InitGraphics(qboolean fullscreen) } #if !SDL_VERSION_ATLEAST(2, 0, 0) - /* For SDL1.2, these things must be done before creating the window */ - - /* Set the icon */ + /* Set window icon - For SDL1.2, this must be done before creating the window */ SetSDLIcon(); - - /* Set vsync */ - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, gl_swapinterval->value ? 1 : 0); - vsync_active = gl_swapinterval->value ? true : false; #endif while (1) { - if (!CreateSDLWindow(flags)) + if (!CreateSDLWindow(flags, width, height)) { +#if 0 // DG: do we really need to do this? it makes things complicated and belongs into ref dll if (gl_msaa_samples->value) { VID_Printf(PRINT_ALL, "SDL SetVideoMode failed: %s\n", SDL_GetError()); VID_Printf(PRINT_ALL, "Reverting to %s gl_mode %i (%ix%i) without MSAA.\n", (flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed", - (int)Cvar_VariableValue("gl_mode"), vid.width, vid.height); + (int)Cvar_VariableValue("gl_mode"), width, height); /* Try to recover */ Cvar_SetValue("gl_msaa_samples", 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); } - else if (vid.width != 640 || vid.height != 480 || (flags & SDL_FULLSCREEN)) + else +#endif // 0 + if (width != 640 || height != 480 || (flags & SDL_FULLSCREEN)) { VID_Printf(PRINT_ALL, "SDL SetVideoMode failed: %s\n", SDL_GetError()); @@ -634,8 +316,9 @@ GLimp_InitGraphics(qboolean fullscreen) /* Try to recover */ Cvar_SetValue("gl_mode", 4); Cvar_SetValue("vid_fullscreen", 0); - vid.width = 640; - vid.height = 480; + VID_NewWindow(width, height); + *pwidth = width = 640; + *pheight = height = 480; flags &= ~SDL_FULLSCREEN; } else @@ -649,43 +332,25 @@ GLimp_InitGraphics(qboolean fullscreen) break; } } - if (gl_msaa_samples->value) + + if(!re.InitContext(window)) { - if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples) == 0) - { - Cvar_SetValue("gl_msaa_samples", msaa_samples); - } + // InitContext() should have logged an error + return false; } -#if SDL_VERSION_ATLEAST(2, 0, 0) - /* For SDL2, these things must be done after creating the window */ - - /* Set the icon */ - SetSDLIcon(); - - /* Set vsync - TODO: -1 could be set for "late swap tearing" */ - SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0); + // VSync is really set in the renderer dll, but we want vsync_active here + // so just get it from the Cvar here, even though it's a bit ugly + cvar_t* gl_swapinterval = Cvar_Get("gl_swapinterval", "1", CVAR_ARCHIVE); vsync_active = gl_swapinterval->value ? true : false; -#endif - - /* Initialize the stencil buffer */ - if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_bits)) - { - VID_Printf(PRINT_ALL, "Got %d bits of stencil.\n", stencil_bits); - - if (stencil_bits >= 1) - { - have_stencil = true; - } - } - - /* Initialize hardware gamma */ - InitGamma(); /* Window title */ snprintf(title, sizeof(title), "Yamagi Quake II %s", YQ2VERSION); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetWindowTitle(window, title); + + /* Also set the window icon - For SDL2, this must be done after creating the window */ + SetSDLIcon(); #else SDL_WM_SetCaption(title, title); #endif @@ -696,45 +361,6 @@ GLimp_InitGraphics(qboolean fullscreen) return true; } -/* - * Swaps the buffers to show the new frame - */ -void -GLimp_EndFrame(void) -{ -#if SDL_VERSION_ATLEAST(2, 0, 0) - SDL_GL_SwapWindow(window); -#else - SDL_GL_SwapBuffers(); -#endif -} - -/* - * Changes the video mode - */ -int -GLimp_SetMode(int *pwidth, int *pheight, int mode, qboolean fullscreen) -{ - VID_Printf(PRINT_ALL, "setting mode %d:", mode); - - /* mode -1 is not in the vid mode table - so we keep the values in pwidth - and pheight and don't even try to look up the mode info */ - if ((mode != -1) && !VID_GetModeInfo(pwidth, pheight, mode)) - { - VID_Printf(PRINT_ALL, " invalid mode\n"); - return rserr_invalid_mode; - } - - VID_Printf(PRINT_ALL, " %d %d\n", *pwidth, *pheight); - - if (!GLimp_InitGraphics(fullscreen)) - { - return rserr_invalid_mode; - } - - return rserr_ok; -} - /* * (Un)grab Input */ @@ -790,36 +416,14 @@ int GLimp_GetRefreshRate(void) * Shuts the SDL render backend down */ void -GLimp_Shutdown(void) +VID_ShutdownWindow(void) { - /* Clear the backbuffer and make it - current. This may help some broken - video drivers like the AMD Catalyst - to avoid artifacts in unused screen - areas. */ - if (SDL_WasInit(SDL_INIT_VIDEO)) - { - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - GLimp_EndFrame(); - } - -#ifdef X11GAMMA - RestoreGamma(); -#endif - if (window) { /* cleanly ungrab input (needs window) */ GLimp_GrabInput(false); #if SDL_VERSION_ATLEAST(2, 0, 0) - if(context) - { - SDL_GL_DeleteContext(context); - context = NULL; - } - SDL_DestroyWindow(window); #else SDL_FreeSurface(window); @@ -836,7 +440,4 @@ GLimp_Shutdown(void) { SDL_QuitSubSystem(SDL_INIT_VIDEO); } - - gl_state.hwgamma = false; } - diff --git a/src/client/cl_screen.c b/src/client/cl_screen.c index 5b8eb7bb..38136094 100644 --- a/src/client/cl_screen.c +++ b/src/client/cl_screen.c @@ -658,7 +658,7 @@ SCR_TimeRefresh_f(void) R_RenderFrame(&cl.refdef); } - GLimp_EndFrame(); + R_EndFrame(); } } else @@ -669,7 +669,7 @@ SCR_TimeRefresh_f(void) R_BeginFrame(0); R_RenderFrame(&cl.refdef); - GLimp_EndFrame(); + R_EndFrame(); } } @@ -1566,7 +1566,7 @@ SCR_UpdateScreen(void) } } - GLimp_EndFrame(); + R_EndFrame(); } static float diff --git a/src/client/header/ref.h b/src/client/header/ref.h index a6a911c9..d0600f3b 100644 --- a/src/client/header/ref.h +++ b/src/client/header/ref.h @@ -52,7 +52,6 @@ #define SHELL_WHITE_COLOR 0xD7 #define ENTITY_FLAGS 68 -#define API_VERSION 3 typedef struct entity_s { struct model_s *model; /* opaque type outside refresh */ @@ -117,8 +116,127 @@ typedef struct { particle_t *particles; } refdef_t; -// Soon to be deleted -//void R_GetRefAPI(void); +// FIXME: bump API_VERSION? +#define API_VERSION 4 +#define EXPORT +#define IMPORT + +// +// these are the functions exported by the refresh module +// +typedef struct +{ + // if api_version is different, the dll cannot be used + int api_version; + + // called when the library is loaded - FIXME: remove arguments, not used anyway + int (EXPORT *Init) ( void *hinstance, void *wndproc ); + + // called before the library is unloaded + void (EXPORT *Shutdown) (void); + + // called by GLimp_InitGraphics() before creating window, + // returns flags for SDL window creation + int (EXPORT *PrepareForWindow)(void); + + // called by GLimp_InitGraphics() *after* creating window, + // passing the SDL_Window* (void* so we don't spill SDL.h here) + // returns true (1) on success + int (EXPORT *InitContext)(void* window); + + // shuts down rendering (OpenGL) context, calls + // VID_ShutdownWindow() to shut down window as well, if !contextOnly + void (EXPORT *ShutdownWindow)(qboolean contextOnly); + + // All data that will be used in a level should be + // registered before rendering any frames to prevent disk hits, + // but they can still be registered at a later time + // if necessary. + // + // EndRegistration will free any remaining data that wasn't registered. + // Any model_s or skin_s pointers from before the BeginRegistration + // are no longer valid after EndRegistration. + // + // Skins and images need to be differentiated, because skins + // are flood filled to eliminate mip map edge errors, and pics have + // an implicit "pics/" prepended to the name. (a pic name that starts with a + // slash will not use the "pics/" prefix or the ".pcx" postfix) + void (EXPORT *BeginRegistration) (char *map); + struct model_s * (EXPORT *RegisterModel) (char *name); + struct image_s * (EXPORT *RegisterSkin) (char *name); + + void (EXPORT *SetSky) (char *name, float rotate, vec3_t axis); + void (EXPORT *EndRegistration) (void); + + void (EXPORT *RenderFrame) (refdef_t *fd); + + struct image_s * (EXPORT *DrawFindPic)(char *name); + + void (EXPORT *DrawGetPicSize) (int *w, int *h, char *name); // will return 0 0 if not found + //void (EXPORT *DrawPic) (int x, int y, char *name); - apparently not used anymore + void (EXPORT *DrawPicScaled) (int x, int y, char *pic, float factor); + void (EXPORT *DrawStretchPic) (int x, int y, int w, int h, char *name); + void (EXPORT *DrawChar) (int x, int y, int c); + void (EXPORT *DrawCharScaled)(int x, int y, int num, float scale); + void (EXPORT *DrawTileClear) (int x, int y, int w, int h, char *name); + void (EXPORT *DrawFill) (int x, int y, int w, int h, int c); + void (EXPORT *DrawFadeScreen) (void); + + // Draw images for cinematic rendering (which can have a different palette). Note that calls + void (EXPORT *DrawStretchRaw) (int x, int y, int w, int h, int cols, int rows, byte *data); + + /* + ** video mode and refresh state management entry points + */ + void (EXPORT *SetPalette)( const unsigned char *palette); // NULL = game palette + void (EXPORT *BeginFrame)( float camera_separation ); + void (EXPORT *EndFrame) (void); + + //void (EXPORT *AppActivate)( qboolean activate ); +} refexport_t; + +typedef struct +{ + void (IMPORT *Sys_Error) (int err_level, char *str, ...) __attribute__ ((format (printf, 2, 3))); + + void (IMPORT *Cmd_AddCommand) (char *name, void(*cmd)(void)); + void (IMPORT *Cmd_RemoveCommand) (char *name); + int (IMPORT *Cmd_Argc) (void); + char *(IMPORT *Cmd_Argv) (int i); + void (IMPORT *Cmd_ExecuteText) (int exec_when, char *text); + + void (IMPORT *Con_Printf) (int print_level, char *str, ...) __attribute__ ((format (printf, 2, 3))); + + // files will be memory mapped read only + // the returned buffer may be part of a larger pak file, + // or a discrete file from anywhere in the quake search path + // a -1 return means the file does not exist + // NULL can be passed for buf to just determine existance + int (IMPORT *FS_LoadFile) (char *name, void **buf); + void (IMPORT *FS_FreeFile) (void *buf); + + // gamedir will be the current directory that generated + // files should be stored to, ie: "f:\quake\id1" + char *(IMPORT *FS_Gamedir) (void); + + cvar_t *(IMPORT *Cvar_Get) (char *name, char *value, int flags); + cvar_t *(IMPORT *Cvar_Set) (char *name, char *value); + void (IMPORT *Cvar_SetValue) (char *name, float value); + + qboolean (IMPORT *Vid_GetModeInfo)(int *width, int *height, int mode); + void (IMPORT *Vid_MenuInit)( void ); + void (IMPORT *Vid_NewWindow)( int width, int height ); + + void (IMPORT *Vid_ShutdownWindow)(void); + qboolean (IMPORT *GLimp_InitGraphics)(qboolean fullscreen, int *pwidth, int *pheight); +} refimport_t; + +// this is the only function actually exported at the linker level +typedef refexport_t (EXPORT *GetRefAPI_t) (refimport_t); + +// FIXME: #ifdef client/ref around this +extern refexport_t re; +extern refimport_t ri; /* * Refresh API @@ -132,19 +250,19 @@ void R_EndRegistration(void); struct image_s *Draw_FindPic(char *name); void R_RenderFrame(refdef_t *fd); void Draw_GetPicSize(int *w, int *h, char *name); -void Draw_Pic(int x, int y, char *name); + void Draw_StretchPic(int x, int y, int w, int h, char *name); void Draw_PicScaled(int x, int y, char *pic, float factor); -void Draw_Char(int x, int y, int c); + void Draw_CharScaled(int x, int y, int num, float scale); void Draw_TileClear(int x, int y, int w, int h, char *name); void Draw_Fill(int x, int y, int w, int h, int c); void Draw_FadeScreen(void); void Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data); -int R_Init(void *hinstance, void *hWnd); -void R_Shutdown(void); +//int R_Init(void *hinstance, void *hWnd); +//void R_Shutdown(void); void R_SetPalette(const unsigned char *palette); void R_BeginFrame(float camera_separation); -void GLimp_EndFrame(void); +void R_EndFrame(void); #endif diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index b53db9f8..dc2ddaa9 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -1251,7 +1251,7 @@ UpdateSoundQualityFunc(void *unused) M_Popup(); /* the text box won't show up unless we do a buffer swap */ - GLimp_EndFrame(); + R_EndFrame(); CL_Snd_Restart_f(); } @@ -2566,7 +2566,7 @@ SearchLocalGames(void) M_Popup(); /* the text box won't show up unless we do a buffer swap */ - GLimp_EndFrame(); + R_EndFrame(); /* send out info packets */ CL_PingServers_f(); diff --git a/src/client/refresh/gl/r_draw.c b/src/client/refresh/gl/r_draw.c index 7e4598a7..7d646630 100644 --- a/src/client/refresh/gl/r_draw.c +++ b/src/client/refresh/gl/r_draw.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" image_t *draw_chars; @@ -51,18 +51,7 @@ Draw_InitLocal(void) * smoothly scrolled off. */ void -Draw_Char(int x, int y, int num) -{ - Draw_CharScaled(x, y, num, 1.0f); -} - -/* - * Draws one 8*8 graphics character with 0 being transparent. - * It can be clipped to the top of the screen to allow the console to be - * smoothly scrolled off. - */ -void -Draw_CharScaled(int x, int y, int num, float scale) +RDraw_CharScaled(int x, int y, int num, float scale) { int row, col; float frow, fcol, size, scaledSize; @@ -116,7 +105,7 @@ Draw_CharScaled(int x, int y, int num, float scale) } image_t * -Draw_FindPic(char *name) +RDraw_FindPic(char *name) { image_t *gl; char fullname[MAX_QPATH]; @@ -135,11 +124,11 @@ Draw_FindPic(char *name) } void -Draw_GetPicSize(int *w, int *h, char *pic) +RDraw_GetPicSize(int *w, int *h, char *pic) { image_t *gl; - gl = Draw_FindPic(pic); + gl = RDraw_FindPic(pic); if (!gl) { @@ -152,11 +141,11 @@ Draw_GetPicSize(int *w, int *h, char *pic) } void -Draw_StretchPic(int x, int y, int w, int h, char *pic) +RDraw_StretchPic(int x, int y, int w, int h, char *pic) { image_t *gl; - gl = Draw_FindPic(pic); + gl = RDraw_FindPic(pic); if (!gl) { @@ -197,17 +186,11 @@ Draw_StretchPic(int x, int y, int w, int h, char *pic) } void -Draw_Pic(int x, int y, char *pic) -{ - Draw_PicScaled(x, y, pic, 1.0f); -} - -void -Draw_PicScaled(int x, int y, char *pic, float factor) +RDraw_PicScaled(int x, int y, char *pic, float factor) { image_t *gl; - gl = Draw_FindPic(pic); + gl = RDraw_FindPic(pic); if (!gl) { @@ -253,11 +236,11 @@ Draw_PicScaled(int x, int y, char *pic, float factor) * refresh window. */ void -Draw_TileClear(int x, int y, int w, int h, char *pic) +RDraw_TileClear(int x, int y, int w, int h, char *pic) { image_t *image; - image = Draw_FindPic(pic); + image = RDraw_FindPic(pic); if (!image) { @@ -296,7 +279,7 @@ Draw_TileClear(int x, int y, int w, int h, char *pic) * Fills a box of pixels with a single color */ void -Draw_Fill(int x, int y, int w, int h, int c) +RDraw_Fill(int x, int y, int w, int h, int c) { union { @@ -334,7 +317,7 @@ Draw_Fill(int x, int y, int w, int h, int c) } void -Draw_FadeScreen(void) +RDraw_FadeScreen(void) { glEnable(GL_BLEND); glDisable(GL_TEXTURE_2D); @@ -360,7 +343,7 @@ Draw_FadeScreen(void) } void -Draw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data) +RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data) { GLfloat tex[8]; byte *source; diff --git a/src/client/refresh/gl/r_image.c b/src/client/refresh/gl/r_image.c index 40a85417..753626b7 100644 --- a/src/client/refresh/gl/r_image.c +++ b/src/client/refresh/gl/r_image.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" image_t gltextures[MAX_GLTEXTURES]; int numgltextures; @@ -1201,7 +1201,7 @@ R_FindImage(char *name, imagetype_t type) } struct image_s * -R_RegisterSkin(char *name) +RI_RegisterSkin(char *name) { return R_FindImage(name, it_skin); } diff --git a/src/client/refresh/gl/r_light.c b/src/client/refresh/gl/r_light.c index e4da73e7..2b9fabc2 100644 --- a/src/client/refresh/gl/r_light.c +++ b/src/client/refresh/gl/r_light.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" #define DLIGHT_CUTOFF 64 diff --git a/src/client/refresh/gl/r_lightmap.c b/src/client/refresh/gl/r_lightmap.c index 960a3aca..86b1c980 100644 --- a/src/client/refresh/gl/r_lightmap.c +++ b/src/client/refresh/gl/r_lightmap.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" extern gllightmapstate_t gl_lms; diff --git a/src/client/refresh/gl/r_main.c b/src/client/refresh/gl/r_main.c index 9637e04f..b1733d83 100644 --- a/src/client/refresh/gl/r_main.c +++ b/src/client/refresh/gl/r_main.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" #define NUM_BEAM_SEGS 6 @@ -134,6 +134,9 @@ cvar_t *gl_stereo_separation; cvar_t *gl_stereo_anaglyph_colors; cvar_t *gl_stereo_convergence; + +refimport_t ri; // TODO: put this in some header ? + /* * Returns true if the box is completely outside the frustom */ @@ -1179,7 +1182,7 @@ R_SetLightLevel(void) } void -R_RenderFrame(refdef_t *fd) +RI_RenderFrame(refdef_t *fd) { R_RenderView(fd); R_SetLightLevel(); @@ -1263,6 +1266,32 @@ R_Register(void) Cmd_AddCommand("gl_strings", R_Strings); } +/* + * Changes the video mode + */ +static int +SetMode_impl(int *pwidth, int *pheight, int mode, qboolean fullscreen) +{ + VID_Printf(PRINT_ALL, "setting mode %d:", mode); + + /* mode -1 is not in the vid mode table - so we keep the values in pwidth + and pheight and don't even try to look up the mode info */ + if ((mode != -1) && !VID_GetModeInfo(pwidth, pheight, mode)) + { + VID_Printf(PRINT_ALL, " invalid mode\n"); + return rserr_invalid_mode; + } + + VID_Printf(PRINT_ALL, " %d %d\n", *pwidth, *pheight); + + if (!ri.GLimp_InitGraphics(fullscreen, pwidth, pheight)) + { + return rserr_invalid_mode; + } + + return rserr_ok; +} + qboolean R_SetMode(void) { @@ -1279,7 +1308,7 @@ R_SetMode(void) vid.width = gl_customwidth->value; vid.height = gl_customheight->value; - if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, + if ((err = SetMode_impl(&vid.width, &vid.height, gl_mode->value, fullscreen)) == rserr_ok) { if (gl_mode->value == -1) @@ -1299,7 +1328,7 @@ R_SetMode(void) vid_fullscreen->modified = false; VID_Printf(PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n"); - if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, false)) == rserr_ok) + if ((err = SetMode_impl(&vid.width, &vid.height, gl_mode->value, false)) == rserr_ok) { return true; } @@ -1312,7 +1341,7 @@ R_SetMode(void) } /* try setting it back to something safe */ - if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_state.prev_mode, false)) != rserr_ok) + if ((err = SetMode_impl(&vid.width, &vid.height, gl_state.prev_mode, false)) != rserr_ok) { VID_Printf(PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n"); return false; @@ -1323,7 +1352,7 @@ R_SetMode(void) } int -R_Init(void *hinstance, void *hWnd) +RI_Init(void *hinstance, void *hWnd) { int j; extern float r_turbsin[256]; @@ -1518,7 +1547,7 @@ R_Init(void *hinstance, void *hWnd) } void -R_Shutdown(void) +RI_Shutdown(void) { Cmd_RemoveCommand("modellist"); Cmd_RemoveCommand("screenshot"); @@ -1530,7 +1559,7 @@ R_Shutdown(void) R_ShutdownImages(); /* shutdown OS specific OpenGL stuff like contexts, etc. */ - GLimp_Shutdown(); + RI_ShutdownWindow(false); /* shutdown our QGL subsystem */ QGL_Shutdown(); @@ -1539,7 +1568,7 @@ R_Shutdown(void) extern void UpdateHardwareGamma(); void -R_BeginFrame(float camera_separation) +RI_BeginFrame(float camera_separation) { gl_state.camera_separation = camera_separation; @@ -1666,7 +1695,7 @@ R_BeginFrame(float camera_separation) } void -R_SetPalette(const unsigned char *palette) +RI_SetPalette(const unsigned char *palette) { int i; @@ -1790,3 +1819,72 @@ R_DrawBeam(entity_t *e) glDepthMask(GL_TRUE); } +extern int RI_PrepareForWindow(void); +extern int RI_InitContext(void* win); + +extern void RI_BeginRegistration(char *model); +extern struct model_s * RI_RegisterModel(char *name); +extern struct image_s * RI_RegisterSkin(char *name); + +extern void RI_SetSky(char *name, float rotate, vec3_t axis); +extern void RI_EndRegistration(void); + +extern void RI_RenderFrame(refdef_t *fd); + +extern image_t * RDraw_FindPic(char *name); +extern void RDraw_GetPicSize(int *w, int *h, char *pic); +extern void RDraw_PicScaled(int x, int y, char *pic, float factor); +extern void RDraw_StretchPic(int x, int y, int w, int h, char *pic); +extern void RDraw_CharScaled(int x, int y, int num, float scale); +extern void RDraw_TileClear(int x, int y, int w, int h, char *pic); +extern void RDraw_Fill(int x, int y, int w, int h, int c); +extern void RDraw_FadeScreen(void); +extern void RDraw_StretchRaw(int x, int y, int w, int h, int cols, int rows, byte *data); + +extern void RI_SetPalette(const unsigned char *palette); +extern void RI_EndFrame(void); + +refexport_t +GetRefAPI(refimport_t imp) +{ + refexport_t re = {0}; + + ri = imp; + + re.api_version = API_VERSION; + + re.Init = RI_Init; + re.Shutdown = RI_Shutdown; + re.PrepareForWindow = RI_PrepareForWindow; + re.InitContext = RI_InitContext; + re.ShutdownWindow = RI_ShutdownWindow; + re.BeginRegistration = RI_BeginRegistration; + re.RegisterModel = RI_RegisterModel; + re.RegisterSkin = RI_RegisterSkin; + + re.SetSky = RI_SetSky; + re.EndRegistration = RI_EndRegistration; + + re.RenderFrame = RI_RenderFrame; + + re.DrawFindPic = RDraw_FindPic; + + re.DrawGetPicSize = RDraw_GetPicSize; + //re.DrawPic = Draw_Pic; + re.DrawPicScaled = RDraw_PicScaled; + re.DrawStretchPic = RDraw_StretchPic; + //re.DrawChar = Draw_Char; + re.DrawCharScaled = RDraw_CharScaled; + re.DrawTileClear = RDraw_TileClear; + re.DrawFill = RDraw_Fill; + re.DrawFadeScreen = RDraw_FadeScreen; + + re.DrawStretchRaw = RDraw_StretchRaw; + + re.SetPalette = RI_SetPalette; + re.BeginFrame = RI_BeginFrame; + re.EndFrame = RI_EndFrame; + + return re; +} + diff --git a/src/client/refresh/gl/r_mesh.c b/src/client/refresh/gl/r_mesh.c index 28064fb4..5a67662e 100644 --- a/src/client/refresh/gl/r_mesh.c +++ b/src/client/refresh/gl/r_mesh.c @@ -24,18 +24,18 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" #define NUMVERTEXNORMALS 162 #define SHADEDOT_QUANT 16 float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#include "constants/anorms.h" +#include "../constants/anorms.h" }; /* precalculated dot products for quantized angles */ float r_avertexnormal_dots[SHADEDOT_QUANT][256] = -#include "constants/anormtab.h" +#include "../constants/anormtab.h" ; typedef float vec4_t[4]; diff --git a/src/client/refresh/gl/r_misc.c b/src/client/refresh/gl/r_misc.c index a07d0c51..a4a21cdc 100644 --- a/src/client/refresh/gl/r_misc.c +++ b/src/client/refresh/gl/r_misc.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" byte dottexture[8][8] = { {0, 0, 0, 0, 0, 0, 0, 0}, diff --git a/src/client/refresh/gl/r_model.c b/src/client/refresh/gl/r_model.c index cb220153..3e0753c9 100644 --- a/src/client/refresh/gl/r_model.c +++ b/src/client/refresh/gl/r_model.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" #define MAX_MOD_KNOWN 512 @@ -980,7 +980,7 @@ Mod_FreeAll(void) * Specifies the model that will be used as the world */ void -R_BeginRegistration(char *model) +RI_BeginRegistration(char *model) { char fullname[MAX_QPATH]; cvar_t *flushmap; @@ -1006,7 +1006,7 @@ R_BeginRegistration(char *model) } struct model_s * -R_RegisterModel(char *name) +RI_RegisterModel(char *name) { model_t *mod; int i; @@ -1055,7 +1055,7 @@ R_RegisterModel(char *name) } void -R_EndRegistration(void) +RI_EndRegistration(void) { int i; model_t *mod; diff --git a/src/client/refresh/gl/r_scrap.c b/src/client/refresh/gl/r_scrap.c index 5cd4e6e6..7503f145 100644 --- a/src/client/refresh/gl/r_scrap.c +++ b/src/client/refresh/gl/r_scrap.c @@ -25,7 +25,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" int scrap_allocated[MAX_SCRAPS][BLOCK_WIDTH]; byte scrap_texels[MAX_SCRAPS][BLOCK_WIDTH * BLOCK_HEIGHT]; diff --git a/src/client/refresh/gl/r_sdl.c b/src/client/refresh/gl/r_sdl.c new file mode 100644 index 00000000..76844942 --- /dev/null +++ b/src/client/refresh/gl/r_sdl.c @@ -0,0 +1,449 @@ +// SDL-specific OpenGL shit formerly in refresh.c + +#include "../header/local.h" + +#ifdef SDL2 +#include +#else // SDL1.2 +#include +#endif //SDL2 + +#if defined(__APPLE__) +#include +#else +#include +#endif + +/* X.org stuff - put this here as more modern renderers wouldn't need it + * e.g. an OpenGL3 renderer could just apply gamma through a shader */ +#ifdef X11GAMMA + #include + #include + #include + #include + #include + + #include + + XRRCrtcGamma** gammaRamps = NULL; + int noGammaRamps = 0; +#endif + + +#if SDL_VERSION_ATLEAST(2, 0, 0) + static SDL_Window* window = NULL; + static SDL_GLContext context = NULL; +#else +static SDL_Surface* window = NULL; +#endif + +qboolean have_stencil = false; + +/* + * Returns the adress of a GL function + */ +void * +GLimp_GetProcAddress (const char* proc) +{ + return SDL_GL_GetProcAddress ( proc ); +} + +/* + * from SDL2 SDL_CalculateGammaRamp, adjusted for arbitrary ramp sizes + * because xrandr seems to support ramp sizes != 256 (in theory at least) + */ +void CalculateGammaRamp(float gamma, Uint16* ramp, int len) +{ + int i; + + /* Input validation */ + if (gamma < 0.0f ) { + return; + } + if (ramp == NULL) { + return; + } + + /* 0.0 gamma is all black */ + if (gamma == 0.0f) { + for (i = 0; i < len; ++i) { + ramp[i] = 0; + } + return; + } else if (gamma == 1.0f) { + /* 1.0 gamma is identity */ + for (i = 0; i < len; ++i) { + ramp[i] = (i << 8) | i; + } + return; + } else { + /* Calculate a real gamma ramp */ + int value; + gamma = 1.0f / gamma; + for (i = 0; i < len; ++i) { + value = (int) (pow((double) i / (double) len, gamma) * 65535.0 + 0.5); + if (value > 65535) { + value = 65535; + } + ramp[i] = (Uint16) value; + } + } +} + +/* + * Sets the hardware gamma + */ +#ifdef X11GAMMA +void +UpdateHardwareGamma(void) +{ + float gamma = (vid_gamma->value); + int i; + + Display* dpy = NULL; + SDL_SysWMinfo info; + +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_VERSION(&info.version); + if(!SDL_GetWindowWMInfo(window, &info)) +#else + if(SDL_GetWMInfo(&info) != 1) +#endif + { + VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n"); + return; + } + + dpy = info.info.x11.display; + + XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window); + if(res == NULL) + { + VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n"); + return; + } + + for(i=0; i < res->ncrtc; ++i) + { + int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); + size_t rampSize = len*sizeof(Uint16); + Uint16* ramp = malloc(rampSize); // TODO: check for NULL + if(ramp == NULL) + { + VID_Printf(PRINT_ALL, "Couldn't allocate &zd byte of memory for gamma ramp - OOM?!\n", rampSize); + return; + } + + CalculateGammaRamp(gamma, ramp, len); + + XRRCrtcGamma* gamma = XRRAllocGamma(len); + + memcpy(gamma->red, ramp, rampSize); + memcpy(gamma->green, ramp, rampSize); + memcpy(gamma->blue, ramp, rampSize); + + free(ramp); + + XRRSetCrtcGamma(dpy, res->crtcs[i], gamma); + + XRRFreeGamma(gamma); + } + + XRRFreeScreenResources(res); +} +#else // no X11GAMMA +void +UpdateHardwareGamma(void) +{ + float gamma = (vid_gamma->value); + + Uint16 ramp[256]; + CalculateGammaRamp(gamma, ramp, 256); +#if SDL_VERSION_ATLEAST(2, 0, 0) + if(SDL_SetWindowGammaRamp(window, ramp, ramp, ramp) != 0) { +#else + if(SDL_SetGammaRamp(ramp, ramp, ramp) < 0) { +#endif + VID_Printf(PRINT_ALL, "Setting gamma failed: %s\n", SDL_GetError()); + } +} +#endif // X11GAMMA + +static void InitGamma() +{ +#ifdef X11GAMMA + int i=0; + SDL_SysWMinfo info; + Display* dpy = NULL; + + if(gammaRamps != NULL) // already saved gamma + return; + +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_VERSION(&info.version); + if(!SDL_GetWindowWMInfo(window, &info)) +#else + if(SDL_GetWMInfo(&info) != 1) +#endif + { + VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n"); + return; + } + + dpy = info.info.x11.display; + + XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window); + if(res == NULL) + { + VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n"); + return; + } + + noGammaRamps = res->ncrtc; + gammaRamps = calloc(noGammaRamps, sizeof(XRRCrtcGamma*)); + if(gammaRamps == NULL) { + VID_Printf(PRINT_ALL, "Couldn't allocate memory for %d gamma ramps - OOM?!\n", noGammaRamps); + return; + } + + for(i=0; i < noGammaRamps; ++i) + { + int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); + size_t rampSize = len*sizeof(Uint16); + + XRRCrtcGamma* origGamma = XRRGetCrtcGamma(dpy, res->crtcs[i]); + + XRRCrtcGamma* gammaCopy = XRRAllocGamma(len); + + memcpy(gammaCopy->red, origGamma->red, rampSize); + memcpy(gammaCopy->green, origGamma->green, rampSize); + memcpy(gammaCopy->blue, origGamma->blue, rampSize); + + gammaRamps[i] = gammaCopy; + } + + XRRFreeScreenResources(res); + + VID_Printf(PRINT_ALL, "Using hardware gamma via X11/xRandR.\n"); +#elif __APPLE__ + gl_state.hwgamma = false; + VID_Printf(PRINT_ALL, "Using software gamma (needs vid_restart after changes)\n"); + return; +#else + VID_Printf(PRINT_ALL, "Using hardware gamma via SDL.\n"); +#endif + gl_state.hwgamma = true; + vid_gamma->modified = true; +} + +#ifdef X11GAMMA +static void RestoreGamma() +{ + int i=0; + SDL_SysWMinfo info; + Display* dpy = NULL; + + if(gammaRamps == NULL) + return; + +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_VERSION(&info.version); + if(!SDL_GetWindowWMInfo(window, &info)) +#else + if(SDL_GetWMInfo(&info) != 1) +#endif + { + VID_Printf(PRINT_ALL, "Couldn't get Window info from SDL\n"); + return; + } + + dpy = info.info.x11.display; + + XRRScreenResources* res = XRRGetScreenResources(dpy, info.info.x11.window); + if(res == NULL) + { + VID_Printf(PRINT_ALL, "Unable to get xrandr screen resources.\n"); + return; + } + + for(i=0; i < noGammaRamps; ++i) + { + // in case a display was unplugged or something, noGammaRamps may be > res->ncrtc + if(i < res->ncrtc) + { + int len = XRRGetCrtcGammaSize(dpy, res->crtcs[i]); + if(len != gammaRamps[i]->size) { + VID_Printf(PRINT_ALL, "WTF, gamma ramp size for display %d has changed from %d to %d!\n", + i, gammaRamps[i]->size, len); + + continue; + } + + XRRSetCrtcGamma(dpy, res->crtcs[i], gammaRamps[i]); + } + + // the ramp needs to be free()d either way + XRRFreeGamma(gammaRamps[i]); + gammaRamps[i] = NULL; + + } + XRRFreeScreenResources(res); + free(gammaRamps); + gammaRamps = NULL; + + VID_Printf(PRINT_ALL, "Restored original Gamma\n"); +} +#endif // X11GAMMA + + +// called by GLimp_InitGraphics() before creating window, +// returns flags for SDL window creation +int RI_PrepareForWindow(void) +{ + unsigned int flags = 0; + int msaa_samples = 0; + + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); + +#if !SDL_VERSION_ATLEAST(2, 0, 0) + /* Set vsync - For SDL1.2, this must be done before creating the window */ + SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, gl_swapinterval->value ? 1 : 0); +#endif + + if (gl_msaa_samples->value) + { + msaa_samples = gl_msaa_samples->value; + + if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) < 0) + { + Com_Printf("MSAA is unsupported: %s\n", SDL_GetError()); + Cvar_SetValue ("gl_msaa_samples", 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + } + else if (SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, msaa_samples) < 0) + { + Com_Printf("MSAA %ix is unsupported: %s\n", msaa_samples, SDL_GetError()); + Cvar_SetValue("gl_msaa_samples", 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + } + } + + /* Initiate the flags */ +#if SDL_VERSION_ATLEAST(2, 0, 0) + flags = SDL_WINDOW_OPENGL; +#else // SDL 1.2 + flags = SDL_OPENGL; +#endif + + return flags; +} + +int RI_InitContext(void* win) +{ + int msaa_samples = 0, stencil_bits = 0; + + if(win == NULL) + { + VID_Error(ERR_FATAL, "R_InitContext() must not be called with NULL argument!"); + return false; + } + + window = (SDL_Window*)win; + context = SDL_GL_CreateContext(window); + if(context == NULL) + { + VID_Printf(PRINT_ALL, "R_InitContext(): Creating OpenGL Context failed: %s\n", SDL_GetError()); + window = NULL; + return false; + } + + if (gl_msaa_samples->value) + { + if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa_samples) == 0) + { + Cvar_SetValue("gl_msaa_samples", msaa_samples); + } + } + +#if SDL_VERSION_ATLEAST(2, 0, 0) + /* For SDL2, this must be done after creating the window */ + /* Set vsync - TODO: -1 could be set for "late swap tearing" */ + SDL_GL_SetSwapInterval(gl_swapinterval->value ? 1 : 0); +#endif + + /* Initialize the stencil buffer */ + if (!SDL_GL_GetAttribute(SDL_GL_STENCIL_SIZE, &stencil_bits)) + { + VID_Printf(PRINT_ALL, "Got %d bits of stencil.\n", stencil_bits); + + if (stencil_bits >= 1) + { + have_stencil = true; + } + } + + /* Initialize hardware gamma */ + InitGamma(); + + return true; +} + +/* + * Swaps the buffers to show the new frame + */ +void +RI_EndFrame(void) +{ +#if SDL_VERSION_ATLEAST(2, 0, 0) + SDL_GL_SwapWindow(window); +#else + SDL_GL_SwapBuffers(); +#endif +} + +/* + * Shuts the SDL render backend down + */ +void +RI_ShutdownWindow(qboolean contextOnly) +{ +#ifdef X11GAMMA + RestoreGamma(); +#endif + + /* Clear the backbuffer and make it + current. This may help some broken + video drivers like the AMD Catalyst + to avoid artifacts in unused screen + areas. */ + if (window) + { + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + RI_EndFrame(); + +#if SDL_VERSION_ATLEAST(2, 0, 0) + if(context) + { + SDL_GL_DeleteContext(context); + context = NULL; + } +#endif + } + + window = NULL; + + gl_state.hwgamma = false; + + if(!contextOnly) + { + ri.Vid_ShutdownWindow(); + } +} diff --git a/src/client/refresh/gl/r_surf.c b/src/client/refresh/gl/r_surf.c index 588e611e..05cc1246 100644 --- a/src/client/refresh/gl/r_surf.c +++ b/src/client/refresh/gl/r_surf.c @@ -25,7 +25,7 @@ */ #include -#include "header/local.h" +#include "../header/local.h" int c_visible_lightmaps; int c_visible_textures; diff --git a/src/client/refresh/gl/r_warp.c b/src/client/refresh/gl/r_warp.c index 95a1b909..45747808 100644 --- a/src/client/refresh/gl/r_warp.c +++ b/src/client/refresh/gl/r_warp.c @@ -24,7 +24,7 @@ * ======================================================================= */ -#include "header/local.h" +#include "../header/local.h" #define TURBSCALE (256.0 / (2 * M_PI)) #define SUBDIVIDE_SIZE 64 @@ -48,7 +48,7 @@ unsigned int index_tex = 0; char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; float r_turbsin[] = { -#include "constants/warpsin.h" +#include "../constants/warpsin.h" }; vec3_t skyclip[6] = { @@ -724,7 +724,7 @@ R_DrawSkyBox(void) } void -R_SetSky(char *name, float rotate, vec3_t axis) +RI_SetSky(char *name, float rotate, vec3_t axis) { int i; char pathname[MAX_QPATH]; diff --git a/src/client/refresh/header/local.h b/src/client/refresh/header/local.h index bbb642c5..95850186 100644 --- a/src/client/refresh/header/local.h +++ b/src/client/refresh/header/local.h @@ -412,14 +412,10 @@ extern glstate_t gl_state; int GLimp_Init(void); /* - * Shuts the SDL render backend down + * Shuts the render context and SDL window down + * (if contextOnly, the window will not be shutdown) */ -void GLimp_Shutdown(void); - -/* - * Changes the video mode - */ -int GLimp_SetMode(int *pwidth, int *pheight, int mode, qboolean fullscreen); +void RI_ShutdownWindow(qboolean contextOnly); /* * Returns the address of the GL function proc,