linux: clean up the GL & XIM init code a bit

This commit is contained in:
insofaras 2016-05-08 01:55:00 +01:00
parent ad6645295b
commit fd09ab2383
1 changed files with 137 additions and 129 deletions

View File

@ -1292,7 +1292,7 @@ LinuxResizeTarget(i32 width, i32 height){
// NOTE(allen): Thanks to Casey for providing the linux OpenGL launcher.
static bool ctxErrorOccurred = false;
static int XInput2OpCode = 0;
internal int
ctxErrorHandler( Display *dpy, XErrorEvent *ev )
{
@ -1320,20 +1320,25 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
IsLegacy = false;
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
typedef PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXTProc;
typedef PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESAProc;
typedef PFNGLXGETSWAPINTERVALMESAPROC glXGetSwapIntervalMESAProc;
typedef PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGIProc;
const char *glxExts = glXQueryExtensionsString(XDisplay, DefaultScreen(XDisplay));
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
#define GLXLOAD(x) x ## Proc x = (x ## Proc) glXGetProcAddressARB( (const GLubyte*) #x);
GLXLOAD(glXCreateContextAttribsARB);
GLXContext ctx = 0;
ctxErrorOccurred = false;
int (*oldHandler)(Display*, XErrorEvent*) =
XSetErrorHandler(&ctxErrorHandler);
int (*oldHandler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctxErrorHandler);
if (!glXCreateContextAttribsARB)
{
fprintf(stderr, "glXCreateContextAttribsARB() not found"
" ... using old-style GLX context\n" );
fprintf(stderr, "glXCreateContextAttribsARB() not found, using old-style GLX context\n" );
ctx = glXCreateNewContext( XDisplay, bestFbc, GLX_RGBA_TYPE, 0, True );
}
else
@ -1357,8 +1362,7 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
context_attribs[4]);
fprintf(stderr, "Creating context\n");
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
True, context_attribs );
ctx = glXCreateContextAttribsARB(XDisplay, bestFbc, 0, True, context_attribs);
XSync( XDisplay, False );
if (!ctxErrorOccurred && ctx)
@ -1373,8 +1377,7 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
context_attribs[3] = 2;
fprintf(stderr, "Creating context\n" );
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
True, context_attribs );
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0, True, context_attribs );
XSync(XDisplay, False);
@ -1389,10 +1392,8 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
ctxErrorOccurred = false;
fprintf(stderr, "Failed to create GL 3.2 context"
" ... using old-style GLX context\n" );
ctx = glXCreateContextAttribsARB( XDisplay, bestFbc, 0,
True, context_attribs );
fprintf(stderr, "Failed to create GL 3.2 context, using old-style GLX context\n");
ctx = glXCreateContextAttribsARB(XDisplay, bestFbc, 0, True, context_attribs);
IsLegacy = true;
}
@ -1420,7 +1421,6 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
fprintf(stderr, "Making context current\n");
glXMakeCurrent( XDisplay, XWindow, ctx );
GLint n;
char *Vendor = (char *)glGetString(GL_VENDOR);
char *Renderer = (char *)glGetString(GL_RENDERER);
char *Version = (char *)glGetString(GL_VERSION);
@ -1435,28 +1435,29 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
//NOTE(inso): enable vsync if available. this should probably be optional
if(strstr(glxExts, "GLX_EXT_swap_control ")){
PFNGLXSWAPINTERVALEXTPROC glx_swap_interval_ext =
(PFNGLXSWAPINTERVALEXTPROC) glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalEXT");
if(glx_swap_interval_ext){
glx_swap_interval_ext(XDisplay, XWindow, 1);
GLXLOAD(glXSwapIntervalEXT);
if(glXSwapIntervalEXT){
glXSwapIntervalEXT(XDisplay, XWindow, 1);
unsigned int swap_val = 0;
glXQueryDrawable(XDisplay, XWindow, GLX_SWAP_INTERVAL_EXT, &swap_val);
linuxvars.vsync = swap_val == 1;
fprintf(stderr, "VSync enabled? %s.\n", linuxvars.vsync ? "Yes" : "No");
}
} else if(strstr(glxExts, "GLX_MESA_swap_control ")){
PFNGLXSWAPINTERVALMESAPROC glx_swap_interval_mesa =
(PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalMESA");
PFNGLXGETSWAPINTERVALMESAPROC glx_get_swap_interval_mesa =
(PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB((const GLubyte*)"glXGetSwapIntervalMESA");
GLXLOAD(glXSwapIntervalMESA);
GLXLOAD(glXGetSwapIntervalMESA);
if(glx_swap_interval_mesa){
glx_swap_interval_mesa(1);
if(glx_get_swap_interval_mesa){
linuxvars.vsync = glx_get_swap_interval_mesa();
if(glXSwapIntervalMESA){
glXSwapIntervalMESA(1);
if(glXGetSwapIntervalMESA){
linuxvars.vsync = glXGetSwapIntervalMESA();
fprintf(stderr, "VSync enabled? %s (MESA)\n", linuxvars.vsync ? "Yes" : "No");
} else {
// NOTE(inso): assume it worked?
@ -1464,25 +1465,31 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
fputs("VSync enabled? possibly (MESA)", stderr);
}
}
} else if(strstr(glxExts, "GLX_SGI_swap_control ")){
PFNGLXSWAPINTERVALSGIPROC glx_swap_interval_sgi =
(PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddressARB((const GLubyte*)"glXSwapIntervalSGI");
if(glx_swap_interval_sgi){
glx_swap_interval_sgi(1);
} else if(strstr(glxExts, "GLX_SGI_swap_control ")){
GLXLOAD(glXSwapIntervalSGI);
if(glXSwapIntervalSGI){
glXSwapIntervalSGI(1);
//NOTE(inso): The SGI one doesn't seem to have a way to confirm we got it...
linuxvars.vsync = 1;
fputs("VSync enabled? hopefully (SGI)", stderr);
}
} else {
fputs("VSync enabled? nope, no suitable extension", stderr);
}
#if FRED_INTERNAL
PFNGLDEBUGMESSAGECALLBACKARBPROC gl_dbg_callback = (PFNGLDEBUGMESSAGECALLBACKARBPROC)glXGetProcAddress((const GLubyte*)"glDebugMessageCallback");
if(gl_dbg_callback){
typedef PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackProc;
GLXLOAD(glDebugMessageCallback);
if(glDebugMessageCallback){
fputs("enabling gl debug\n", stderr);
gl_dbg_callback(&gl_log, 0);
glDebugMessageCallback(&gl_log, 0);
glEnable(GL_DEBUG_OUTPUT);
}
#endif
@ -1492,6 +1499,8 @@ InitializeOpenGLContext(Display *XDisplay, Window XWindow, GLXFBConfig &bestFbc,
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#undef GLXLOAD
return(ctx);
}
@ -1507,8 +1516,7 @@ GLXCanUseFBConfig(Display *XDisplay)
if(glXQueryVersion(XDisplay, &GLXMajor, &GLXMinor))
{
fprintf(stderr, "GLX version %d.%d\n", GLXMajor, GLXMinor);
if(((GLXMajor == 1 ) && (GLXMinor >= 3)) ||
(GLXMajor > 1))
if(((GLXMajor == 1 ) && (GLXMinor >= 3)) || (GLXMajor > 1))
{
Result = true;
}
@ -1572,15 +1580,61 @@ internal Init_Input_Result
InitializeXInput(Display *dpy, Window XWindow)
{
Init_Input_Result result = {};
XIMStyle style;
XIMStyles *styles = 0;
i32 i, count;
XIMStyle style;
unsigned long xim_event_mask = 0;
i32 i;
setlocale(LC_ALL, "");
XSetLocaleModifiers("");
fprintf(stderr, "Supported locale?: %s.\n", XSupportsLocale() ? "Yes" : "No");
// TODO(inso): handle the case where it isn't supported somehow?
result.input_method = XOpenIM(dpy, 0, 0, 0);
if (!result.input_method){
// NOTE(inso): Try falling back to the internal XIM implementation that
// should in theory always exist.
XSetLocaleModifiers("@im=none");
result.input_method = XOpenIM(dpy, 0, 0, 0);
}
if (result.input_method){
if (!XGetIMValues(result.input_method, XNQueryInputStyle, &styles, NULL) && styles){
for (i = 0; i < styles->count_styles; ++i){
style = styles->supported_styles[i];
if (style == (XIMPreeditNothing | XIMStatusNothing)){
result.best_style = style;
break;
}
}
}
if (result.best_style){
XFree(styles);
result.xic = XCreateIC(
result.input_method,
XNInputStyle, result.best_style,
XNClientWindow, XWindow,
XNFocusWindow, XWindow,
NULL
);
if (XGetICValues(result.xic, XNFilterEvents, &xim_event_mask, NULL)){
xim_event_mask = 0;
}
}
else{
result = {};
fputs("Could not get minimum required input style.\n", stderr);
}
}
else{
result = {};
fputs("Could not open X Input Method.\n", stderr);
}
XSelectInput(
linuxvars.XDisplay,
linuxvars.XWindow,
@ -1593,53 +1647,10 @@ InitializeXInput(Display *dpy, Window XWindow)
StructureNotifyMask |
MappingNotify |
ExposureMask |
VisibilityChangeMask
VisibilityChangeMask |
xim_event_mask
);
result.input_method = XOpenIM(dpy, 0, 0, 0);
if (!result.input_method){
// NOTE(inso): Try falling back to the internal XIM implementation that
// should in theory always exist.
XSetLocaleModifiers("@im=none");
result.input_method = XOpenIM(dpy, 0, 0, 0);
}
if (result.input_method){
if (!XGetIMValues(result.input_method, XNQueryInputStyle, &styles, NULL) &&
styles){
result.best_style = 0;
count = styles->count_styles;
for (i = 0; i < count; ++i){
style = styles->supported_styles[i];
if (style == (XIMPreeditNothing | XIMStatusNothing)){
result.best_style = style;
break;
}
}
if (result.best_style){
XFree(styles);
result.xic =
XCreateIC(result.input_method, XNInputStyle, result.best_style,
XNClientWindow, XWindow,
XNFocusWindow, XWindow,
0, 0,
NULL);
}
else{
result = {};
fputs("Could not get minimum required input style", stderr);
}
}
}
else{
result = {};
fputs("Could not open X Input Method", stderr);
}
return(result);
}
@ -2616,12 +2627,9 @@ main(int argc, char **argv)
linuxvars.mouse_data.wheel = 0;
File_Slot *file;
int d = 0;
for (file = exchange_vars.file.active.next;
file != &exchange_vars.file.active;
file = file->next){
++d;
if (file->flags & FEx_Save){
Assert((file->flags & FEx_Request) == 0);