Merge pull request #53 from derhass/unification/syncgl

cleaned-up syncgl patch for unification
This commit is contained in:
Christian 2015-03-24 12:37:55 +01:00
commit 97fc714970
9 changed files with 367 additions and 1 deletions

View file

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

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

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

View file

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

View 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
View 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();
};

View file

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

View file

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

View file

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