Merge pull request #53 from derhass/unification/syncgl
cleaned-up syncgl patch for unification
This commit is contained in:
commit
97fc714970
|
@ -1620,6 +1620,12 @@ class DXXArchive(DXXCommon):
|
|||
'3d/clipper.cpp',
|
||||
'texmap/tmapflat.cpp'
|
||||
]
|
||||
])
|
||||
# for ogl
|
||||
objects_arch_ogl = DXXCommon.create_lazy_object_property([os.path.join(srcdir, f) for f in [
|
||||
'arch/ogl/ogl_extensions.cpp',
|
||||
'arch/ogl/ogl_sync.cpp'
|
||||
]
|
||||
])
|
||||
objects_arch_sdlmixer = DXXCommon.create_lazy_object_property([os.path.join(srcdir, f) for f in [
|
||||
'arch/sdl/digi_mixer_music.cpp',
|
||||
|
@ -2001,6 +2007,7 @@ class DXXProgram(DXXCommon):
|
|||
objects.extend(self.objects_similar_arch_sdlmixer)
|
||||
if (self.user_settings.opengl == 1) or (self.user_settings.opengles == 1):
|
||||
env.Append(LIBS = self.platform_settings.ogllibs)
|
||||
objects.extend(static_archive_construction.objects_arch_ogl)
|
||||
objects.extend(self.objects_similar_arch_ogl)
|
||||
else:
|
||||
message(self, "building with Software Renderer")
|
||||
|
|
97
common/arch/ogl/ogl_extensions.cpp
Normal file
97
common/arch/ogl/ogl_extensions.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
|
||||
/* OpenGL extensions:
|
||||
* We use global function pointer for any extension function we want to use.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include "ogl_extensions.h"
|
||||
#include "console.h"
|
||||
|
||||
/* GL_ARB_sync */
|
||||
bool ogl_have_ARB_sync = false;
|
||||
PFNGLFENCESYNCPROC glFenceSyncFunc = NULL;
|
||||
PFNGLDELETESYNCPROC glDeleteSyncFunc = NULL;
|
||||
PFNGLCLIENTWAITSYNCPROC glClientWaitSyncFunc = NULL;
|
||||
|
||||
static void parse_version_str(const char *v, long *version)
|
||||
{
|
||||
version[0]=1;
|
||||
version[1]=0;
|
||||
|
||||
if (v) {
|
||||
char *ptr;
|
||||
version[0]=strtol(v,&ptr,10);
|
||||
if (ptr[0])
|
||||
version[1]=strtol(ptr+1,NULL,10);
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_ext_supported(const char *extensions, const char *name)
|
||||
{
|
||||
if (extensions && name) {
|
||||
const char *found=strstr(extensions, name);
|
||||
if (found) {
|
||||
// check that the name is actually complete */
|
||||
char c = found[strlen(name)];
|
||||
if (c == ' ' || c == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum support_mode {
|
||||
NO_SUPPORT=0,
|
||||
SUPPORT_CORE=1,
|
||||
SUPPORT_EXT=2
|
||||
};
|
||||
|
||||
static support_mode is_supported(const char *extensions, const long version[2], const char *name, long major, long minor)
|
||||
{
|
||||
if ( (version[0] > major) || (version[0] == major && version[1] >= minor))
|
||||
return SUPPORT_CORE;
|
||||
|
||||
if (is_ext_supported(extensions, name))
|
||||
return SUPPORT_EXT;
|
||||
return NO_SUPPORT;
|
||||
}
|
||||
|
||||
bool ogl_extensions_init()
|
||||
{
|
||||
const char *version_str = reinterpret_cast<const char *>(glGetString(GL_VERSION));
|
||||
long version[2];
|
||||
|
||||
if (!version_str) {
|
||||
con_printf(CON_URGENT, "no valid OpenGL context when querying GL extensions!");
|
||||
return false;
|
||||
}
|
||||
parse_version_str(version_str, version);
|
||||
const char *extension_str = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
|
||||
|
||||
/* GL_ARB_sync */
|
||||
if (is_supported(extension_str, version, "GL_ARB_sync", 3, 2)) {
|
||||
glFenceSyncFunc = reinterpret_cast<PFNGLFENCESYNCPROC>(SDL_GL_GetProcAddress("glFenceSync"));
|
||||
glDeleteSyncFunc = reinterpret_cast<PFNGLDELETESYNCPROC>(SDL_GL_GetProcAddress("glDeleteSync"));
|
||||
glClientWaitSyncFunc = reinterpret_cast<PFNGLCLIENTWAITSYNCPROC>(SDL_GL_GetProcAddress("glClientWaitSync"));
|
||||
|
||||
}
|
||||
if (glFenceSyncFunc && glDeleteSyncFunc && glClientWaitSyncFunc) {
|
||||
con_printf(CON_VERBOSE, "GL_ARB_sync available");
|
||||
ogl_have_ARB_sync=true;
|
||||
} else {
|
||||
con_printf(CON_VERBOSE, "GL_ARB_sync not available");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
121
common/arch/ogl/ogl_sync.cpp
Normal file
121
common/arch/ogl/ogl_sync.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
|
||||
/* OpenGL Synchronization code:
|
||||
* either use fence sync objects or glFinish() to prevent the GPU from
|
||||
* lagging behind too much.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
|
||||
#include "args.h"
|
||||
#include "console.h"
|
||||
#include "maths.h"
|
||||
#include "ogl_sync.h"
|
||||
#include "timer.h"
|
||||
|
||||
ogl_sync::ogl_sync()
|
||||
{
|
||||
method=SYNC_GL_NONE;
|
||||
wait_timeout = 0;
|
||||
fence = NULL;
|
||||
}
|
||||
|
||||
ogl_sync::~ogl_sync()
|
||||
{
|
||||
if (fence)
|
||||
con_printf(CON_URGENT, "fence sync object was never destroyed!");
|
||||
}
|
||||
|
||||
void ogl_sync::before_swap()
|
||||
{
|
||||
if (fence) {
|
||||
/// use a fence sync object to prevent the GPU from queuing up more than one frame
|
||||
if (method == SYNC_GL_FENCE_SLEEP) {
|
||||
while(glClientWaitSyncFunc(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 0ULL) == GL_TIMEOUT_EXPIRED) {
|
||||
timer_delay(wait_timeout);
|
||||
}
|
||||
} else {
|
||||
glClientWaitSyncFunc(fence, GL_SYNC_FLUSH_COMMANDS_BIT, 34000000ULL);
|
||||
}
|
||||
glDeleteSyncFunc(fence);
|
||||
fence = NULL;
|
||||
} else if (method == SYNC_GL_FINISH_BEFORE_SWAP) {
|
||||
glFinish();
|
||||
}
|
||||
}
|
||||
void ogl_sync::after_swap()
|
||||
{
|
||||
if (method == SYNC_GL_FENCE || method == SYNC_GL_FENCE_SLEEP ) {
|
||||
fence=glFenceSyncFunc(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
} else if (method == SYNC_GL_FINISH_AFTER_SWAP) {
|
||||
glFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void ogl_sync::init(SyncGLMethod sync_method, int wait)
|
||||
{
|
||||
method = sync_method;
|
||||
fence = NULL;
|
||||
fix a = i2f(wait);
|
||||
fix b = i2f(1000);
|
||||
wait_timeout = fixdiv(a,b);
|
||||
|
||||
bool need_ARB_sync;
|
||||
|
||||
switch (method) {
|
||||
case SYNC_GL_FENCE:
|
||||
case SYNC_GL_FENCE_SLEEP:
|
||||
case SYNC_GL_AUTO:
|
||||
need_ARB_sync = true;
|
||||
break;
|
||||
default:
|
||||
need_ARB_sync = false;
|
||||
}
|
||||
|
||||
if (method == SYNC_GL_AUTO) {
|
||||
if (!ogl_have_ARB_sync) {
|
||||
con_printf(CON_NORMAL, "GL_ARB_sync not available, disabling sync");
|
||||
method = SYNC_GL_NONE;
|
||||
need_ARB_sync = false;
|
||||
} else {
|
||||
method = SYNC_GL_FENCE_SLEEP;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_ARB_sync && !ogl_have_ARB_sync) {
|
||||
con_printf(CON_URGENT, "GL_ARB_sync not available, using fallback");
|
||||
method = SYNC_GL_FINISH_BEFORE_SWAP;
|
||||
}
|
||||
switch(method) {
|
||||
case SYNC_GL_FENCE:
|
||||
con_printf(CON_VERBOSE, "using GL_ARB_sync for synchronization (direct)");
|
||||
break;
|
||||
case SYNC_GL_FENCE_SLEEP:
|
||||
con_printf(CON_VERBOSE, "using GL_ARB_sync for synchronization with interval %dms", wait);
|
||||
break;
|
||||
case SYNC_GL_FINISH_AFTER_SWAP:
|
||||
con_printf(CON_VERBOSE, "using glFinish synchronization (method 1)");
|
||||
break;
|
||||
case SYNC_GL_FINISH_BEFORE_SWAP:
|
||||
con_printf(CON_VERBOSE, "using glFinish synchronization (method 2)");
|
||||
break;
|
||||
default:
|
||||
con_printf(CON_VERBOSE, "using no explicit GPU synchronization");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ogl_sync::deinit()
|
||||
{
|
||||
if (fence) {
|
||||
glDeleteSyncFunc(fence);
|
||||
fence = NULL;
|
||||
}
|
||||
}
|
|
@ -30,6 +30,22 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
|
||||
bool InitArgs(int argc, char **argv);
|
||||
|
||||
#ifdef OGL
|
||||
// GL Sync methods
|
||||
typedef enum {
|
||||
SYNC_GL_NONE=0,
|
||||
SYNC_GL_FENCE,
|
||||
SYNC_GL_FENCE_SLEEP,
|
||||
SYNC_GL_FINISH_AFTER_SWAP,
|
||||
SYNC_GL_FINISH_BEFORE_SWAP,
|
||||
SYNC_GL_AUTO
|
||||
} SyncGLMethod;
|
||||
|
||||
#define OGL_SYNC_METHOD_DEFAULT SYNC_GL_AUTO
|
||||
#define OGL_SYNC_WAIT_DEFAULT 2 /* milliseconds */
|
||||
|
||||
#endif
|
||||
|
||||
// Struct that keeps all variables used by FindArg
|
||||
// Prefixes are:
|
||||
// Sys - System Options
|
||||
|
@ -85,6 +101,8 @@ struct Arg
|
|||
int GfxSkipHiresFNT;
|
||||
#ifdef OGL
|
||||
int OglFixedFont;
|
||||
SyncGLMethod OglSyncMethod;
|
||||
int OglSyncWait;
|
||||
#endif
|
||||
std::string MplUdpHostAddr;
|
||||
uint16_t MplUdpHostPort;
|
||||
|
|
57
common/include/ogl_extensions.h
Normal file
57
common/include/ogl_extensions.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
|
||||
/* OpenGL extensions:
|
||||
* We use global function pointer for any extension function we want to use.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <OpenGL/gl.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
/* global extension stuff (from glext.h)
|
||||
*/
|
||||
#ifndef APIENTRY
|
||||
#define APIENTRY
|
||||
#endif
|
||||
#ifndef APIENTRYP
|
||||
#define APIENTRYP APIENTRY *
|
||||
#endif
|
||||
#ifndef GLAPI
|
||||
#define GLAPI extern
|
||||
#endif
|
||||
|
||||
typedef int64_t GLint64;
|
||||
typedef uint64_t GLuint64;
|
||||
|
||||
/* GL_ARB_sync */
|
||||
typedef struct __GLsync *GLsync;
|
||||
|
||||
typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
|
||||
typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
|
||||
typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
|
||||
typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
|
||||
#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
|
||||
#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
|
||||
#define GL_TIMEOUT_EXPIRED 0x911B
|
||||
|
||||
extern bool ogl_have_ARB_sync;
|
||||
extern PFNGLFENCESYNCPROC glFenceSyncFunc;
|
||||
extern PFNGLDELETESYNCPROC glDeleteSyncFunc;
|
||||
extern PFNGLCLIENTWAITSYNCPROC glClientWaitSyncFunc;
|
||||
|
||||
/* Global initialization:
|
||||
* will need an OpenGL context and intialize all function pointers.
|
||||
*/
|
||||
extern bool ogl_extensions_init();
|
||||
|
31
common/include/ogl_sync.h
Normal file
31
common/include/ogl_sync.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
|
||||
/* OpenGL Synchronization code:
|
||||
* either use fence sync objects or glFinish() to prevent the GPU from
|
||||
* lagging behind too much.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "args.h"
|
||||
#include "ogl_extensions.h"
|
||||
|
||||
class ogl_sync {
|
||||
private:
|
||||
SyncGLMethod method;
|
||||
fix wait_timeout;
|
||||
GLsync fence;
|
||||
public:
|
||||
ogl_sync();
|
||||
~ogl_sync();
|
||||
|
||||
void before_swap();
|
||||
void after_swap();
|
||||
void init(SyncGLMethod sync_method, int wait);
|
||||
void deinit();
|
||||
};
|
|
@ -57,7 +57,6 @@
|
|||
#include "config.h"
|
||||
#include "playsave.h"
|
||||
#include "vers_id.h"
|
||||
#include "game.h"
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <OpenGL/glu.h>
|
||||
|
@ -72,6 +71,11 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef OGLES
|
||||
#include "ogl_extensions.h"
|
||||
#include "ogl_sync.h"
|
||||
#endif
|
||||
|
||||
#include "compiler-make_unique.h"
|
||||
|
||||
using std::max;
|
||||
|
@ -88,6 +92,7 @@ static DISPMANX_DISPLAY_HANDLE_T dispman_display=DISPMANX_NO_HANDLE;
|
|||
#endif
|
||||
|
||||
#else
|
||||
static ogl_sync sync_helper;
|
||||
static int sdl_video_flags = SDL_OPENGL;
|
||||
#endif
|
||||
static int gr_installed;
|
||||
|
@ -128,7 +133,9 @@ void ogl_swap_buffers_internal(void)
|
|||
#ifdef OGLES
|
||||
eglSwapBuffers(eglDisplay, eglSurface);
|
||||
#else
|
||||
sync_helper.before_swap();
|
||||
SDL_GL_SwapBuffers();
|
||||
sync_helper.after_swap();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -648,6 +655,12 @@ int gr_set_mode(u_int32_t mode)
|
|||
|
||||
ogl_init_window(w,h);//platform specific code
|
||||
ogl_get_verinfo();
|
||||
|
||||
#ifndef OGLES
|
||||
ogl_extensions_init();
|
||||
sync_helper.init(GameArg.OglSyncMethod, GameArg.OglSyncWait);
|
||||
#endif
|
||||
|
||||
OGL_VIEWPORT(0,0,w,h);
|
||||
ogl_init_state();
|
||||
gamefont_choose_game_font(w,h);
|
||||
|
@ -781,6 +794,9 @@ void gr_close()
|
|||
if (gl_initialized)
|
||||
{
|
||||
ogl_smash_texture_list_internal();
|
||||
#ifndef OGLES
|
||||
sync_helper.deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (grd_curscreen)
|
||||
|
|
|
@ -162,6 +162,14 @@ static void print_commandline_help()
|
|||
#endif
|
||||
#ifdef OGL
|
||||
printf( " -gl_fixedfont Do not scale fonts to current resolution\n");
|
||||
printf( " -gl_syncmethod <n> OpenGL sync method (default: %i)\n", OGL_SYNC_METHOD_DEFAULT);
|
||||
printf( " 0: disabled\n");
|
||||
printf( " 1: fence syncs, limit GPU latency to at most one frame\n");
|
||||
printf( " 2: like 1, but sleep during sync to reduce CPU load\n");
|
||||
printf( " 3: immedaitely sync after buffer swap\n");
|
||||
printf( " 4: immediately sync after buffer swap\n");
|
||||
printf( " 5: auto. use mode 2 if available, 0 otherwise\n");
|
||||
printf( " -gl_syncwait <n> wait interval (ms) for sync mode 2 (default: %i)\n", OGL_SYNC_WAIT_DEFAULT);
|
||||
#endif // OGL
|
||||
|
||||
#if defined(USE_UDP)
|
||||
|
|
|
@ -139,6 +139,11 @@ static long arg_integer(Arglist::iterator &pp, Arglist::const_iterator end)
|
|||
return i;
|
||||
}
|
||||
|
||||
template<typename E> E arg_enum(Arglist::iterator &pp, Arglist::const_iterator end)
|
||||
{
|
||||
return static_cast<E>(arg_integer(pp, end));
|
||||
}
|
||||
|
||||
static void arg_port_number(Arglist::iterator &pp, Arglist::const_iterator end, uint16_t &out, bool allow_privileged)
|
||||
{
|
||||
auto port = arg_integer(pp, end);
|
||||
|
@ -162,6 +167,8 @@ static void InitGameArg()
|
|||
GameArg.DbgVerbose = CON_NORMAL;
|
||||
GameArg.DbgBpp = 32;
|
||||
#ifdef OGL
|
||||
GameArg.OglSyncMethod = OGL_SYNC_METHOD_DEFAULT;
|
||||
GameArg.OglSyncWait = OGL_SYNC_WAIT_DEFAULT;
|
||||
GameArg.DbgGlIntensity4Ok = 1;
|
||||
GameArg.DbgGlLuminance4Alpha4Ok = 1;
|
||||
GameArg.DbgGlRGBA2Ok = 1;
|
||||
|
@ -261,6 +268,10 @@ static void ReadCmdArgs(Inilist &ini, Arglist &Args)
|
|||
|
||||
else if (!d_stricmp(p, "-gl_fixedfont"))
|
||||
GameArg.OglFixedFont = 1;
|
||||
else if (!d_stricmp(p, "-gl_syncmethod"))
|
||||
GameArg.OglSyncMethod = arg_enum<SyncGLMethod>(pp, end);
|
||||
else if (!d_stricmp(p, "-gl_syncwait"))
|
||||
GameArg.OglSyncWait = arg_integer(pp, end);
|
||||
#endif
|
||||
|
||||
// Multiplayer Options
|
||||
|
|
Loading…
Reference in a new issue