aboutsummaryrefslogtreecommitdiff
path: root/src/parsec/vsdl_ogl.cpp
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /src/parsec/vsdl_ogl.cpp
downloadopenparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz
openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip
initial importHEADmain
Diffstat (limited to 'src/parsec/vsdl_ogl.cpp')
-rw-r--r--src/parsec/vsdl_ogl.cpp864
1 files changed, 864 insertions, 0 deletions
diff --git a/src/parsec/vsdl_ogl.cpp b/src/parsec/vsdl_ogl.cpp
new file mode 100644
index 0000000..bb03523
--- /dev/null
+++ b/src/parsec/vsdl_ogl.cpp
@@ -0,0 +1,864 @@
+/*
+ * PARSEC - SDL OpenGL Video Wrapper
+ *
+ * $Author: uberlinuxguy $ - $Date: 2004/09/15 12:25:37 $
+ *
+ * Orginally written by:
+ * Copyright (c) Andreas Varga <sid@parsec.org> 1999
+ * Copyright (c) Markus Hadwiger <msh@parsec.org> 1999
+ *
+ * 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 the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "config.h"
+
+// C library
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// compilation flags/debug support
+#include "config.h"
+#include "debug.h"
+
+// general definitions
+#include "general.h"
+#include "objstruc.h"
+
+// global externals
+#include "globals.h"
+
+// subsystem headers
+#include "vid_defs.h"
+
+// rendering subsystem
+#include "r_patch.h"
+
+// opengl headers
+#include "r_gl.h"
+#include "ro_api.h"
+
+// local module header
+#include "vsdl_ogl.h"
+
+// proprietary module headers
+#include "con_aux.h"
+#include "con_int.h"
+#include "e_supp.h"
+
+
+
+// flags
+//#define DEBUG_640x480_WINDOWED
+#define EXPLICIT_GL_ORTHO
+//#define LIST_ONLY_SAFE_MODES
+//#define REVERSED_DEPTH_RANGE
+
+
+//NOTE:
+// if REVERSED_DEPTH_RANGE is set, glDepthRange() will be used to reverse
+// the depth range. otherwise, it will be reversed in the projection matrices.
+// this is a work-around for the DRI drivers, since they have problems with a
+// reversed depth range. for them, REVERSED_DEPTH_RANGE should not be set.
+// currently, this is only an issue under Linux. for consistency and testing,
+// this flag has also been added here.
+
+
+// globally usable orthogonal projection-matrix (with glLoadMatrixf()) --------
+//
+GLfloat gl_orthogonal_matrix[] = {
+
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+};
+
+GLfloat gl_orthogonal_params[ 6 ];
+
+
+// special opengl flag values -------------------------------------------------
+//
+enum {
+
+ GL_FLAG_EXTCTRL_GLEXTS_OFF = 0, // don't use extensions
+ GL_FLAG_EXTCTRL_GLEXTS_ON = 1, // use available extensions
+
+ GL_FLAG_SWAPCTRL_NONE = 0, // no explicit synchronization
+ GL_FLAG_SWAPCTRL_GLFLUSH = 1, // glFlush() prior to SwapBuffers()
+ GL_FLAG_SWAPCTRL_GLFINISH = 2, // glFinish() prior to SwapBuffers()
+
+ GL_FLAG_BPPCTRL_OFF = 0, // never switch colordepth
+ GL_FLAG_BPPCTRL_ON = 1 // colordepth switching allowed
+};
+
+
+// user-specifiable opengl flags (will be registered as int commands) ---------
+//
+int gl_flag_swapctrl = GL_FLAG_SWAPCTRL_NONE;
+int gl_flag_bppctrl = GL_FLAG_BPPCTRL_ON;
+
+
+int oldpixdepth = 0;
+
+int sdl_win_width;
+int sdl_win_height;
+int sdl_win_bpp;
+
+GLint sdl_wsz_x;
+GLint sdl_wsz_y;
+GLsizei sdl_wsz_w;
+GLsizei sdl_wsz_h;
+
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+
+SDL_Window * curwindow = NULL;
+SDL_GLContext curcontext = NULL;
+
+#endif
+
+
+// display next opengl buffer -------------------------------------------------
+//
+void VSDL_CommitOGLBuff()
+{
+ // Tell SDL to swap the GL Buffers
+#if SDL_VERSION_ATLEAST(2,0,0)
+ SDL_GL_SwapWindow(curwindow);
+#else
+ SDL_GL_SwapBuffers(); // calls glFlush() internally
+#endif
+}
+
+
+// init interface code to GL functions ---------------------------------------
+//
+int VSDL_InitOGLInterface( int printmodelistflags )
+{
+ MSGOUT( "Using the OpenGL subsystem as rendering device." );
+
+ int v_init = SDL_Init(SDL_INIT_VIDEO);
+
+ if ( v_init < 0 ) {
+ MSGOUT("ERROR: Trouble initializing video subsystem.");
+ return FALSE;
+ }
+
+ Resolutions.clear();
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+
+ SDL_DisplayMode curmode;
+ SDL_GetDesktopDisplayMode(0, &curmode);
+
+ MaxScreenBPP = SDL_BITSPERPIXEL(curmode.format);
+
+ for (int i = 0; i < SDL_GetNumDisplayModes(0); i++) {
+
+ if (SDL_GetDisplayMode(0, i, &curmode) < 0) {
+ MSGOUT("Could not get info for SDL display mode #%d: %s\n", i, SDL_GetError());
+ continue;
+ }
+
+ int xres = curmode.w;
+ int yres = curmode.h;
+
+ int bpp = SDL_BITSPERPIXEL(curmode.format);
+
+ // we don't support resolutions below 640x480, or uneven ones
+ if (xres < 640 || yres < 480 || xres % 2 != 0 || yres % 2 != 0)
+ continue;
+
+ // we don't support non-standard screen formats
+ if (bpp != 32 && bpp != 16)
+ continue;
+
+ // TODO: look into supporting resolution-based BPP (if it's used at all anymore)
+ // for now, we can't use any screen mode that doesn't support the max known BPP
+ if (bpp < MaxScreenBPP)
+ continue;
+
+ // make sure we don't already have this resolution in our list
+ if (GetResolutionIndex(xres, yres) < 0) {
+ Resolutions.push_back(resinfo_s(xres, yres));
+ }
+ }
+
+#else
+
+ // fetch the display mode list of the selected screen
+ SDL_Rect ** mode_list = SDL_ListModes(NULL, SDL_OPENGL | SDL_FULLSCREEN);
+
+ const SDL_VideoInfo* v_info = SDL_GetVideoInfo();
+
+
+ // SDL_GetVideoInfo() should really never return null, but just in case, we check it here.
+ if (v_info == NULL) {
+ MSGOUT("ERROR: Trouble enumerating video modes in VSDL_InitGLInterface()");
+ return FALSE;
+ }
+
+ // mode_list contains w x h sizes based on the current video context's bpp, so let's grab out current bpp and save it
+ dword bpp = v_info->vfmt->BitsPerPixel;
+
+ if (bpp < 16) {
+ MSGOUT("ERROR: System doesn't have enough color depth!");
+ return FALSE;
+ }
+
+ MaxScreenBPP = bpp;
+
+ // enumerate available modes into the video system
+ for (int i = 0; mode_list[i]; ++i) {
+
+ int xres = mode_list[i]->w;
+ int yres = mode_list[i]->h;
+
+ // we don't support resolutions below 640x480, or uneven ones
+ if (xres < 640 || yres < 480 || xres % 2 != 0 || yres % 2 != 0)
+ continue;
+
+ // add resolution to the global list
+ resinfo_s resolution(xres, yres);
+ Resolutions.push_back(resolution);
+ }
+
+#endif
+
+ ASSERT(Resolutions.size() > 0);
+
+ // sort resolution list, putting the smallest at the front
+ std::sort(Resolutions.begin(), Resolutions.end());
+
+ return TRUE;
+}
+
+
+// globally usable projective projection-matrix (with glLoadMatrixf()) --------
+//
+GLfloat gl_projective_matrix[] = {
+
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 1.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f
+};
+
+
+// calculate the global projective projection-matrix --------------------------
+//
+void VSDL_CalcProjectiveMatrix()
+{
+ //NOTE:
+ // this matrix is equivalent to the following:
+ // - glLoadIdentity();
+ // - glFrustum( left, right, bottom, top, znear, zfar );
+ // - glMultMatrixf( { 1,0,0,0, 0,1,0,0, 0,0,-1,0, 0,0,0,1 } );
+
+ float crit_x = Criterion_X * Near_View_Plane;
+ float crit_y = Criterion_Y * Near_View_Plane;
+
+ float left = -crit_x;
+ float right = crit_x;
+ float bottom = crit_y;
+ float top = -crit_y;
+ float znear = Near_View_Plane;
+ float zfar = Far_View_Plane;
+
+ float r_min_l = right - left;
+ float t_min_b = top - bottom;
+ float f_min_n = zfar - znear;
+ float n2 = znear * 2;
+
+ gl_projective_matrix[ 0 ] = n2 / r_min_l;
+ gl_projective_matrix[ 5 ] = n2 / t_min_b;
+ gl_projective_matrix[ 8 ] = -( right + left ) / r_min_l;
+ gl_projective_matrix[ 9 ] = -( top + bottom ) / t_min_b;
+ gl_projective_matrix[ 10 ] = ( zfar + znear ) / f_min_n;
+ gl_projective_matrix[ 14 ] = -( zfar * n2 ) / f_min_n;
+}
+
+
+
+// calculate the global orthographic projection-matrix ------------------------
+//
+void VSDL_CalcOrthographicMatrix()
+{
+ //NOTE:
+ // this matrix is equivalent to the following:
+ // - glLoadIdentity();
+ // - glOrtho( wgl_wsz_x, wgl_wsz_x + wgl_wsz_w,
+ // wgl_wsz_y + wgl_wsz_h, wgl_wsz_y,
+ // -1.0, 0.0 );
+
+ float left = sdl_wsz_x;
+ float right = sdl_wsz_x + sdl_wsz_w;
+ float bottom = sdl_wsz_y + sdl_wsz_h;
+ float top = sdl_wsz_y;
+ float znear = 1.0f;
+ float zfar = 0.0f;
+
+ // make the parameters accessible separately
+ // to enable use of glOrtho()
+ gl_orthogonal_params[ 0 ] = left;
+ gl_orthogonal_params[ 1 ] = right;
+ gl_orthogonal_params[ 2 ] = bottom;
+ gl_orthogonal_params[ 3 ] = top;
+ gl_orthogonal_params[ 4 ] = -znear;
+ gl_orthogonal_params[ 5 ] = -zfar;
+
+ float r_min_l = right - left;
+ float t_min_b = top - bottom;
+ float f_min_n = zfar - znear;
+
+ gl_orthogonal_matrix[ 0 ] = 2.0f / r_min_l;
+ gl_orthogonal_matrix[ 5 ] = 2.0f / t_min_b;
+ gl_orthogonal_matrix[ 10 ] = 2.0f / f_min_n;
+ gl_orthogonal_matrix[ 12 ] = -( right + left ) / r_min_l;
+ gl_orthogonal_matrix[ 13 ] = -( top + bottom ) / t_min_b;
+ gl_orthogonal_matrix[ 14 ] = -( zfar + znear ) / f_min_n;
+}
+
+
+// configure opengl projection matrix and viewport ----------------------------
+//
+PRIVATE
+void SDL_ConfigureProjection()
+{
+
+}
+
+
+// query available extensions -------------------------------------------------
+//
+PRIVATE
+void SDL_RCQueryExtensions()
+{
+ const char * extliststr = (const char *) glGetString(GL_EXTENSIONS);
+
+ if (!extliststr || !extliststr[0])
+ return;
+
+ MSGOUT("Extensions:\n");
+
+ size_t extliststrlen = strlen(extliststr);
+ int extlen = 0, startindex = -1;
+
+ // extensions are separated by a single space, so we need to iterate over the string to find extension names
+ for (size_t i = 0; i < extliststrlen; i++) {
+ // print current extension if we encounter a space or we're at the end of the string
+ if (extliststr[i] == ' ' || i == extliststrlen-1) {
+ if (i == extliststrlen-1)
+ extlen++;
+
+ if (extlen > 0) // extension has been found, lets print it
+ MSGOUT("\t%.*s\n", extlen, extliststr + startindex);
+
+ // reset counters
+ extlen = 0;
+ startindex = -1;
+ } else {
+ // keep track of the length of the current extension we're traversing
+ extlen++;
+ if (startindex == -1) // keep track of the start index as well
+ startindex = i;
+ }
+ }
+}
+
+
+// display current rendering context info -------------------------------------
+//
+void SDL_RCDisplayInfo()
+{
+ MSGOUT( "--OpenGL driver info--\n" );
+
+ MSGOUT( "Vendor:\n" );
+ MSGOUT( " %s\n", glGetString( GL_VENDOR ) );
+ MSGOUT( "Renderer:\n" );
+ MSGOUT( " %s\n", glGetString( GL_RENDERER ) );
+ MSGOUT( "Version:\n" );
+ MSGOUT( " %s\n", glGetString( GL_VERSION ) );
+
+ // query extensions string
+ //SDL_RCQueryExtensions();
+}
+
+
+// initialize OpenGL extensions via GLEW --------------------------------------
+//
+PRIVATE
+void VSDL_InitGLExtensions()
+{
+ // don't rely purely on extension string list to determine capabilities
+ glewExperimental = GL_TRUE;
+
+ // initialize extensions from GLEW
+ if (glewInit() != GLEW_OK) {
+ MSGOUT("Warning: failed to initialize GLEW\n");
+ return;
+ }
+
+ // some drivers support core GL occlusion querying but not the ARB extension
+ // so we just use the core GL function pointers for the ARB functions since the interface is the same
+ if (GLEW_VERSION_1_5 && !GLEW_ARB_occlusion_query) {
+ glBeginQueryARB = glBeginQuery;
+ glDeleteQueriesARB = glDeleteQueries;
+ glEndQueryARB = glEndQuery;
+ glGenQueriesARB = glGenQueries;
+ glGetQueryObjectivARB = glGetQueryObjectiv;
+ glGetQueryObjectuivARB = glGetQueryObjectuiv;
+ glGetQueryivARB = glGetQueryiv;
+ glIsQueryARB = glIsQuery;
+ }
+
+ // same deal with vertex buffers
+ if (GLEW_VERSION_1_5 && !GLEW_ARB_vertex_buffer_object) {
+ glBindBufferARB = glBindBuffer;
+ glBufferDataARB = glBufferData;
+ glBufferSubDataARB = glBufferSubData;
+ glDeleteBuffersARB = glDeleteBuffers;
+ glGenBuffersARB = glGenBuffers;
+ glGetBufferParameterivARB = glGetBufferParameteriv;
+ glGetBufferPointervARB = glGetBufferPointerv;
+ glGetBufferSubDataARB = glGetBufferSubData;
+ glIsBufferARB = glIsBuffer;
+ glMapBufferARB = glMapBuffer;
+ glUnmapBufferARB = glUnmapBuffer;
+ }
+
+ // if available, use apple vertex array object functions instead of ARB versions, even if both exist
+ // ARB versions seem to break in OSX without a 3.2+ core context...?
+ if (GLEW_APPLE_vertex_array_object) {
+ glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) glGenVertexArraysAPPLE;
+ glDeleteVertexArrays = glDeleteVertexArraysAPPLE;
+ glBindVertexArray = glBindVertexArrayAPPLE;
+ glIsVertexArray = glIsVertexArrayAPPLE;
+ }
+}
+
+
+// setup current rendering context --------------------------------------------
+//
+PRIVATE
+void SDL_RCSetup()
+{
+ VSDL_InitGLExtensions();
+
+ // attempt to enable MSAA if set
+ if (AUX_MSAA > 0 && (GLEW_VERSION_1_3 || GLEW_ARB_multisample)) {
+ glEnable(GL_MULTISAMPLE);
+
+ GLint buffers;
+ GLint samples;
+
+ glGetIntegerv(GL_SAMPLE_BUFFERS, &buffers);
+ glGetIntegerv(GL_SAMPLES, &samples);
+
+ if ((AUX_MSAA && !buffers) || (AUX_MSAA != samples)) {
+ // OpenGL multisampling values different than expected
+ MSGOUT("MSAA warning: expected 1 buffer and %d samples, got %d buffer(s) and %d sample(s)\n", AUX_MSAA, buffers, samples);
+ if (samples > 0 && buffers > 0) {
+ AUX_MSAA = samples;
+ } else {
+ // clean up
+ glDisable(GL_MULTISAMPLE);
+ AUX_MSAA = 0;
+ }
+ }
+ } else {
+ // MSAA is 0 or multisampling isn't supported
+ AUX_MSAA = 0;
+ }
+
+
+ // calculate projection matrix, setup projection
+ // calc projection matrices
+ VSDL_CalcProjectiveMatrix();
+ VSDL_CalcOrthographicMatrix();
+
+ // set projection to screen coordinate identity
+ glMatrixMode( GL_PROJECTION );
+ GLint rc = glGetError();
+ /*
+ glLoadIdentity();
+ glOrtho( sdl_wsz_x, sdl_wsz_x + sdl_wsz_w,
+ sdl_wsz_y + sdl_wsz_h, sdl_wsz_y,
+ -1.0, 0.0 );
+ */
+
+#ifdef EXPLICIT_GL_ORTHO
+ glLoadIdentity();
+ rc = glGetError();
+ if(rc == GL_INVALID_VALUE) {
+ MSGOUT("Error: Invalid GL Viewport values");
+ exit(1);
+ }
+ //glOrtho( sdl_wsz_x, sdl_wsz_x + sdl_wsz_w,
+ // sdl_wsz_y + sdl_wsz_h, sdl_wsz_y,
+ // -1.0, 0.0 );
+ glOrtho( gl_orthogonal_params[ 0 ], gl_orthogonal_params[ 1 ],
+ gl_orthogonal_params[ 2 ], gl_orthogonal_params[ 3 ],
+ gl_orthogonal_params[ 4 ], gl_orthogonal_params[ 5 ] );
+ rc = glGetError();
+ if(rc == GL_INVALID_VALUE) {
+ MSGOUT("Error: Invalid GL Viewport values");
+ exit(1);
+ }
+#else
+ glLoadMatrixf( gl_orthogonal_matrix );
+#endif
+
+ // select reversed depth range
+ glDepthRange( 1.0, 0.0 );
+ rc = glGetError();
+ if(rc == GL_INVALID_VALUE) {
+ MSGOUT("Error: Invalid GL Viewport values");
+ exit(1);
+ }
+ // no transformation
+ glMatrixMode( GL_MODELVIEW );
+ rc = glGetError();
+ if(rc == GL_INVALID_VALUE) {
+ MSGOUT("Error: Invalid GL Viewport values");
+ exit(1);
+ }
+ glLoadIdentity();
+ rc = glGetError();
+ if(rc == GL_INVALID_VALUE) {
+ MSGOUT("Error: Invalid GL Viewport values");
+ exit(1);
+ }
+ // set viewport
+ glViewport( sdl_wsz_x, sdl_wsz_y, sdl_wsz_w, sdl_wsz_h );
+ rc = glGetError();
+ if(rc == GL_INVALID_VALUE) {
+ MSGOUT("Error: Invalid GL Viewport values");
+ exit(1);
+ }
+ if(rc == GL_INVALID_OPERATION){
+ MSGOUT("Error: Inavlid GL Operation: glViewport()");
+ }
+
+ //glFrontFace( GL_CW ); //FIXME: ?? why was this labelled FIXME?
+
+ // initial clear
+ glClearColor( 0, 0, 0, 1 );
+ glClearDepth( 0 );
+
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+
+ // disable dithering
+ glDisable( GL_DITHER );
+
+ // prettiest possible mipmaps, please
+ if (GLEW_VERSION_1_4 || GLEW_SGIS_generate_mipmap)
+ glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
+
+ // same with texture compression
+ if (GLEW_VERSION_1_3 || GLEW_ARB_texture_compression)
+ glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST);
+
+ // limit maximum texture size
+ int maxgltexsize = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxgltexsize);
+
+ if (maxgltexsize < VidInfo_MaxTextureSize) {
+ VidInfo_MaxTextureSize = maxgltexsize;
+ VidInfo_MaxTextureLod = CeilPow2Exp(maxgltexsize);
+ }
+
+ // determine maximum number of active texture units
+ if (GLEW_VERSION_1_3 || GLEW_ARB_multitexture) {
+ GLint maxtextureunits;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxtextureunits);
+
+ // GL 2.0 / shaders introduce texture image units, max tex units is the greater of the above and below
+ if (GLEW_VERSION_2_0 || GLEW_ARB_vertex_shader) {
+ GLint maxteximageunits;
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxteximageunits);
+ maxtextureunits = max(maxtextureunits, maxteximageunits);
+ }
+
+ VidInfo_NumTextureUnits = max(maxtextureunits, 1);
+ } else {
+ VidInfo_NumTextureUnits = 1;
+ }
+
+ // initialize GL state tracking
+ RO_InitializeState();
+}
+
+
+// ----------------------------------------------------------------------------
+//
+static int fullscreen_mode = TRUE;
+
+
+// flag whether old mode must be restored before initing new one --------------
+//
+static int must_restore_mode = FALSE;
+
+
+// restore previous mode by destroying context --------------------------------
+//
+void SDL_RestoreMode()
+{
+ static bool recursive_panic = false;
+ if ( recursive_panic )
+ return;
+
+ // safeguard on
+ recursive_panic = true;
+
+
+ // safeguard off
+ recursive_panic = false;
+
+ must_restore_mode = FALSE;
+}
+
+
+// set opengl graphics mode ---------------------------------------------------
+//
+int VSDL_InitOGLMode()
+{
+ if ( must_restore_mode )
+ SDL_RestoreMode();
+
+ // set our mode index
+ ASSERT(VID_MODE_AVAILABLE(GetResolutionIndex(GameScreenRes.width, GameScreenRes.height)));
+
+ fullscreen_mode = !Op_WindowedMode;
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+ Uint32 mode_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_MOUSE_FOCUS;
+#else
+ Uint32 mode_flags = SDL_OPENGL;
+#endif
+
+ sdl_win_bpp = GameScreenBPP;
+
+ sdl_win_width = GameScreenRes.width;
+ sdl_win_height = GameScreenRes.height;
+
+ if ( fullscreen_mode ) {
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+ mode_flags |= SDL_WINDOW_FULLSCREEN;
+#else
+ mode_flags |= SDL_FULLSCREEN;
+#endif
+
+ }
+
+ // disable system cursor inside the SDL window
+ SDL_ShowCursor(SDL_DISABLE);
+
+
+ sdl_wsz_x = 0;
+ sdl_wsz_y = 0;
+ sdl_wsz_w = sdl_win_width;
+ sdl_wsz_h = sdl_win_height;
+
+
+ // set the SDL GL Attributes
+
+ if ( sdl_win_bpp == 32 ) {
+
+ 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_ALPHA_SIZE, 0);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+
+ } else if ( sdl_win_bpp == 16 ) {
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
+
+ } else {
+
+ ASSERT( 0 );
+ PANIC( 0 );
+ }
+
+ // set vertical synchronization (set further down in SDL2)
+#if !(SDL_VERSION_ATLEAST(2,0,0))
+ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, FlipSynched ? 1 : 0);
+#endif
+
+ // use double buffering if possible
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ // set antialiasing
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, AUX_MSAA > 0 ? 1 : 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, AUX_MSAA);
+
+ // set window title (not needed here in 2.0)
+#if !SDL_VERSION_ATLEAST(2,0,0)
+ SDL_WM_SetCaption("Parsec", 0);
+#endif
+
+
+ // change the video mode.
+ printf("Changing vid mode to %ix%i, bpp: %i, vsync: %d, aa: %dx\n", sdl_win_width, sdl_win_height, sdl_win_bpp, FlipSynched, AUX_MSAA);
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+
+ if (curwindow != NULL) {
+
+ if (fullscreen_mode) {
+
+ SDL_DisplayMode mode;
+
+ mode.format = SDL_PIXELFORMAT_RGB888; // is this necessary?
+ mode.refresh_rate = 0;
+ mode.w = sdl_win_width;
+ mode.h = sdl_win_height;
+
+ // set fullscreen mode
+ if (SDL_SetWindowDisplayMode(curwindow, &mode) < 0) {
+ MSGOUT("Could not set display mode: %s\n", SDL_GetError());
+ return FALSE;
+ }
+
+ // if we were previously in fullscreen then we need to force the mode to properly set,
+ // by quickly toggling fullscreen
+ if ((SDL_SetWindowFullscreen(curwindow, SDL_FALSE) < 0) || (SDL_SetWindowFullscreen(curwindow, SDL_TRUE) < 0)) {
+ MSGOUT("Could not make window fullscreen: %s\n", SDL_GetError());
+ }
+
+ } else {
+ // windowed mode
+ SDL_SetWindowFullscreen(curwindow, SDL_FALSE);
+ SDL_SetWindowSize(curwindow, sdl_win_width, sdl_win_height);
+ SDL_SetWindowPosition(curwindow, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+ }
+
+ } else {
+
+ // window doesn't exist, so we have to make a new one
+ curwindow = SDL_CreateWindow("Parsec", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_UNDEFINED, sdl_win_width, sdl_win_height, mode_flags);
+
+ if (curwindow == NULL) {
+ MSGOUT("Could not create SDL window: %s\n", SDL_GetError());
+ return FALSE;
+ }
+ }
+
+ // TODO: check bpp and MSAA, and remake context if they've changed
+
+ if (curcontext == NULL) {
+
+ curcontext = SDL_GL_CreateContext(curwindow);
+ if (curcontext == NULL) {
+ MSGOUT("Could not create OpenGL context: %s\n", SDL_GetError());
+ return FALSE;
+ }
+ } else {
+ SDL_GL_MakeCurrent(curwindow, curcontext);
+ }
+
+
+ // set vertical synchronization
+ SDL_GL_SetSwapInterval(FlipSynched ? 1 : 0);
+
+ SDL_ShowWindow(curwindow);
+
+#else
+
+ if ( SDL_SetVideoMode(sdl_win_width, sdl_win_height, sdl_win_bpp, mode_flags) == NULL ) {
+ bool failed = true;
+
+ if ( AUX_MSAA > 0 ) {
+ // try disabling MSAA
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+
+ failed = SDL_SetVideoMode(sdl_win_width, sdl_win_height, sdl_win_bpp, mode_flags) == NULL;
+ }
+
+ if ( failed ) {
+ MSGOUT("Could not set Video Mode!\n");
+ return FALSE;
+ }
+ }
+
+#endif
+
+ // setup current rendering context
+ SDL_RCSetup();
+
+ // display current rendering context info
+ SDL_RCDisplayInfo();
+
+ must_restore_mode = TRUE;
+ return TRUE;
+}
+
+
+// shut down rendering canvas -------------------------------------------------
+//
+void VSDL_ShutDownOGL()
+{
+ // invalidate texture cache
+ R_InvalidateCachedTexture( NULL );
+
+ SDL_ShowCursor(SDL_ENABLE);
+
+#if SDL_VERSION_ATLEAST(2,0,0)
+
+ /*if (curwindow != NULL) {
+ SDL_DestroyWindow(curwindow);
+ curwindow = NULL;
+ }
+
+ if (curcontext != NULL) {
+ SDL_GL_DeleteContext(curcontext);
+ curcontext = NULL;
+ }*/
+
+#endif
+
+ // simply restore mode XXX: SDL should take care of restoring everything to pre-game state
+ SDL_RestoreMode();
+}
+
+
+// registration table for opengl int commands (user-specifiable flags) --------
+//
+int_command_s gl_int_commands[] = {
+ { 0x00, "gl.swapctrl", 0, 2, &gl_flag_swapctrl, NULL, NULL },
+ { 0x00, "gl.bppctrl", 0, 1, &gl_flag_bppctrl, NULL, NULL },
+};
+
+#define NUM_GL_INT_COMMANDS CALC_NUM_ARRAY_ENTRIES( gl_int_commands )
+
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( VSDL_OGL )
+{
+ // register opengl int commands (flags)
+ for ( int curcmd = 0; curcmd < NUM_GL_INT_COMMANDS; curcmd++ ) {
+ CON_RegisterIntCommand( &gl_int_commands[ curcmd ] );
+ }
+}