View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0004820 | The Dark Mod | Coding | public | 04.06.2018 04:00 | 16.05.2019 16:05 |
Reporter | stgatilov | Assigned To | stgatilov | ||
Priority | low | Severity | tweak | Reproducibility | N/A |
Status | resolved | Resolution | fixed | ||
Product Version | TDM 2.06 | ||||
Target Version | TDM 2.08 | Fixed in Version | TDM 2.08 | ||
Summary | 0004820: Remove M4 from Linux build | GL linking system | ||||
Description | For some incomprehensible reason Linux build uses ugly M4 macros for generating some OpenGL stubs. The M4 macro-generator is AWFUL, and it is much less usable that ordinary Python code which can be written directly in Scons script. I'd like to remove this dependency on M4, rewrite corresponding code generating with Python. P.S. I recall having some problems with these M4 scripts when duzenko changed the set of OpenGL functions. So this work is even useful =) | ||||
Additional Information | Gradually, this task turned into revising GL linking system (GL loader, qgl, glimp). | ||||
Tags | No tags attached. | ||||
Attached Files | gl_desc.txt (9,349 bytes)
renderer\qgl.h: #include <gl/gl.h> #include "glext.h" GLExtension_t GLimp_ExtensionPointer( const char *name ); extensions declarations: // ARB_vertex_buffer_object extern PFNGLBINDBUFFERARBPROC qglBindBuffer; extern PFNGLDELETEBUFFERSARBPROC qglDeleteBuffers; ... // GL fence sync extern PFNGLFENCESYNCPROC qglFenceSync; ... // non-windows systems will just redefine qgl* to gl* #if defined( ID_GL_HARDLINK ) #include "qgl_linked.h" #else // windows systems use a function pointer for each call so we can do our log file intercepts extern void ( APIENTRY * qglAccum )(GLenum op, GLfloat value); extern void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref); ... #if defined( _WIN32 ) extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); extern int ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR); ... #endif #if defined( __linux__ ) extern XVisualInfo * (*qglXChooseVisual)( Display *dpy, int screen, int *attribList ); extern GLXContext (*qglXCreateContext)( Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct ); ... #endif #endif renderer\qgl_linked.h: for every GL function: #define qglBegin glBegin #ifdef GLX_VERSION_1_1 // catch all for any GLX-aware situation #define qglXChooseVisual glXChooseVisual #define qglXCreateContext glXCreateContext #define qglXDestroyContext glXDestroyContext #define qglXMakeCurrent glXMakeCurrent #define qglXSwapBuffers glXSwapBuffers #define qglXGetProcAddressARB glXGetProcAddressARB #endif //=================================================================================== win32\gl_logfuncs.cpp: for every GL function: static void APIENTRY logAlphaFunc(GLenum func, GLclampf ref) { fprintf( tr.logFile, "glAlphaFunc %s %g\n", EnumString(func), ref ); dllAlphaFunc(func, ref); } linux-only: logChooseVisual(Display *dpy, int screen, int *attribList) {...} logCreateContext(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct) {...} logDestroyContext(Display *dpy, GLXContext ctx) {...} logMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx) {...} logSwapBuffers(Display *dpy, GLXDrawable drawable) {...} win32\win_glimp.cpp: wgl extensions gamma settings create window + setup GL on it frontend/backend threads swap buffers, GLimp_ExtensionPointer bool GLimp_Init( glimpParms_t parms ) { ... driverName = r_glDriver.GetString()[0] ? r_glDriver.GetString() : "opengl32"; if ( !QGL_Init( driverName ) ) { ... GLimp_EnableLogging( ( r_logFile.GetInteger() != 0 ) ); } void GLimp_Shutdown( void ) { ... QGL_Shutdown(); } win32\win_qgl.cpp: for every WGL function: int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *); for every GL function: void ( APIENTRY * qglBegin )(GLenum mode); static void ( APIENTRY * dllBegin )(GLenum mode); GL enums: typedef struct { GLenum e; const char *name; } glEnumName_t; #define DEF(x) { x, #x }, glEnumName_t glEnumNames[] = { DEF(GL_FALSE) DEF(GL_TRUE) { GL_BYTE, "GL_BYTE" }, { GL_UNSIGNED_BYTE, "GL_UNSIGNED_BYTE" }, ... static const char *EnumString( GLenum t ); #include "gl_logfuncs.cpp" void QGL_Shutdown( void ) { //for every GL function: qglAccum = NULL; //for every WGL function: qwglCopyContext = NULL; } bool QGL_Init( const char *dllname ) { ... if ( ( win32.hinstOpenGL = LoadLibrary( dllname ) ) == 0 ) ... //for every GL function: qglAccum = dllAccum = glAccum; //for every WGL function: qwglChoosePixelFormat = ChoosePixelFormat; } void GLimp_EnableLogging( bool enable ) { if ( enable ) { ... tr.logFile = fopen( ospath, "wt" ); ... //for every GL function: qglAccum = logAccum; } else { //for every GL function: qglAccum = dllAccum; } } //=================================================================================== linux\glimp.cpp: gamma settings create window + setup GL on it frontend/backend threads GLimp_SwapBuffers #ifdef ID_GL_HARDLINK void GLimp_EnableLogging(bool log) { static bool logging; if (log != logging) { common->DPrintf("GLimp_EnableLogging - disabled at compile time (ID_GL_HARDLINK)\n"); logging = log; } } #endif void GLimp_Shutdown() { ... #if !defined( ID_GL_HARDLINK ) GLimp_dlclose(); #endif ... } bool GLimp_Init( glimpParms_t a ) { ... #ifndef ID_GL_HARDLINK if ( !GLimp_dlopen() ) { return false; } #endif ... } linux\glimp_glenum.h: DEF(GL_FALSE) DEF(GL_TRUE) DEF(GL_BYTE) DEF(GL_UNSIGNED_BYTE) ... DEF(GL_TEXTURE_CUBE_MAP_EXT) DEF(GL_TEXTURE_3D) DEF(GL_TEXTURE_2D) DEF(GL_BLEND) ... [generated]\linux\glimp_dlopen.cpp: for every GL function: void ( APIENTRY * qglAccum )(GLenum op, GLfloat value); void ( * dllAccum )(GLenum op, GLfloat value); for every GLX function (6 items): XVisualInfo * ( * qglXChooseVisual )(Display *dpy, int screen, int *attribList); XVisualInfo * ( * dllChooseVisual )(Display *dpy, int screen, int *attribList); void GLimp_BindNative() { //for every GL function: qglAccum = dllAccum; //for every GLX function: qglXChooseVisual = dllChooseVisual; } bool GLimp_dlopen() { const char *driverName = r_glDriver.GetString()[0] ? r_glDriver.GetString() : "libGL.so.1"; if ( !( glHandle = dlopen( driverName, RTLD_NOW | RTLD_GLOBAL ) ) ) { ... //for every GL function: dllAccum = ( void ( APIENTRY *)(GLenum op, GLfloat value) ) dlsym( glHandle, "glAccum" ); if (!dllAccum) { GLimp_dlsym_failed("glAccum"); return false; } //for every GLX function: dllChooseVisual = ( XVisualInfo * ( APIENTRY *)(Display *dpy, int screen, int *attribList) ) dlsym( glHandle, "glXChooseVisual" ); if (!dllChooseVisual) { GLimp_dlsym_failed("glXChooseVisual"); return false; } ... // make the initial binding GLimp_BindNative(); } void GLimp_dlclose() { if (glHandle) dlclose( glHandle ); ... //for every GL function: qglAccum = NULL; //for every GLX function: qglXChooseVisual = NULL; } [generated]\linux\glimp_logfuncs.cpp: empty with some ifdefs... [generated]\linux\glimp_logging.cpp: GL enums: typedef struct { GLenum e; const char *name; } glEnumName_t; #define DEF(x) { x, #x }, glEnumName_t glEnumNames[] = { #include "sys/linux/glimp_glenum.h" { 0, NULL } }; static const char *EnumString( GLenum t ) #include "glimp_logfuncs.cpp" void GLimp_BindLogging() {/*empty*/} void GLimp_EnableLogging(bool enable) { ... if ( enable ) { ... tr.logFile = fopen( ospath, "wt" ); GLimp_BindLogging(); } else { GLimp_BindNative(); } } [generated]\linux\glimp_stub.cpp: //for every GL function: void glAccum(GLenum op, GLfloat value){} //for every GLX function: XVisualInfo * glXChooseVisual(Display *dpy, int screen, int *attribList){} GLenum glGetError(void){return 0;} GLuint glGenLists(GLsizei range){return 0;} void glGetIntegerv(GLenum pname, GLint *params){ ... } const GLubyte * glGetString(GLenum name){ switch( name ) { case GL_EXTENSIONS: return (GLubyte *)"GL_ARB_multitexture GL_ARB_texture_env_combine GL_ARB_texture_cube_map GL_ARB_texture_env_dot3"; } return (const GLubyte *)""; } [generated]\gllog\gl_extensions.cpp: GLExtension_t GLimp_ExtensionPointer( const char *name ) { if ( strstr( name, "wgl" ) == name ) { common->DPrintf( "WARNING: GLimp_ExtensionPointer for '%s'\n", name ); } #ifdef ID_DEDICATED common->Printf("GLimp_ExtensionPointer %s\n", name); return StubFunction; #else ... ret = qglXGetProcAddressARB((const GLubyte *) name); return res; ... #endif } | ||||
Having had a brief encounter with M4 I can't help but agree I'm sure M4 is great and powerful but having to learn it in order to do maintenance on the qgl stuff feels like an overkill Also, the way it's been used is very awkward and painful to maintain (I mean the hardcoded def sequence in gl_def.m4) |
|
I have uploaded brief description of GL trash code. Opened discussion here: forums.thedarkmod.com/topic/19961-gl-linking-system/ |
|
Branch glimp_4820 has been created for GL linking refactoring. | |
Merged in svn rev 8222 and 8223. | |
Date Modified | Username | Field | Change |
---|---|---|---|
04.06.2018 04:00 | stgatilov | New Issue | |
04.06.2018 04:00 | stgatilov | Status | new => assigned |
04.06.2018 04:00 | stgatilov | Assigned To | => stgatilov |
11.06.2018 09:41 | stgatilov | Target Version | TDM 2.07 => |
13.12.2018 10:35 | duzenko | Note Added: 0010900 | |
20.01.2019 07:20 | stgatilov | Target Version | => TDM 2.08 |
17.04.2019 14:56 | stgatilov | File Added: gl_desc.txt | |
17.04.2019 15:14 | stgatilov | Note Added: 0011746 | |
17.04.2019 15:14 | stgatilov | Note Edited: 0011746 | |
04.05.2019 07:57 | stgatilov | Summary | Remove M4 from Linux build => Remove M4 from Linux build | GL linking system |
04.05.2019 07:57 | stgatilov | Additional Information Updated | |
04.05.2019 09:09 | stgatilov | Note Added: 0011778 | |
16.05.2019 16:04 | stgatilov | Note Added: 0011807 | |
16.05.2019 16:05 | stgatilov | Status | assigned => resolved |
16.05.2019 16:05 | stgatilov | Fixed in Version | => TDM 2.08 |
16.05.2019 16:05 | stgatilov | Resolution | open => fixed |