GTK: Use SDL2 instead of GLX for OpenGL context creation

GLX is tied to X11, while SDL2 works on many other platforms (including
native Wayland).
This commit is contained in:
Emmanuel Gil Peyrot 2020-11-19 01:58:20 +01:00
parent 101fa1ef58
commit d319d2c6fb
6 changed files with 108 additions and 194 deletions

View File

@ -1,165 +0,0 @@
/*
Copyright (C) 2013 The Lemon Man
Copyright (C) 2013-2017 DeSmuME team
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_GL_GLX
#include <stdio.h>
#include <X11/Xlib.h>
#include <GL/glx.h>
#include "../OGLRender.h"
#include "glx_3Demu.h"
static bool glx_beginOpenGL(void) { return 1; }
static void glx_endOpenGL(void) { }
static bool glx_init(void) { return is_glx_initialized(); }
static int xerror_handler(Display *dpy, XErrorEvent *ev) { return 0; }
static GLXContext ctx = NULL;
static GLXPbuffer pbuf;
typedef GLXContext (*wtf)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
bool deinit_glx_3Demu(void)
{
Display *dpy = glXGetCurrentDisplay();
if (dpy)
{
glXDestroyPbuffer(dpy, pbuf);
glXDestroyContext(dpy, ctx);
XCloseDisplay(dpy);
ctx = NULL;
return true;
}
return false;
}
bool init_glx_3Demu(void)
{
Display *dpy = XOpenDisplay(NULL);
XVisualInfo *vis;
GLXFBConfig *cfg;
int maj, min;
if (!dpy)
return false;
// Check if GLX is present
if (!glXQueryVersion(dpy, &maj, &min))
return false;
// We need GLX 1.3 at least
if (maj < 1 || (maj == 1 && min < 3))
return false;
const int vis_attr[] = {
GLX_RGBA,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_DOUBLEBUFFER,
None
};
vis = glXChooseVisual(dpy, DefaultScreen(dpy), (int *)&vis_attr);
if (!vis)
return false;
const int fb_attr[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
GLX_DOUBLEBUFFER, true,
GLX_X_RENDERABLE, true,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
None
};
int configs;
cfg = glXChooseFBConfig(dpy, DefaultScreen(dpy), (int *)&fb_attr, &configs);
if (!cfg)
return false;
const int pbuf_attr[] = {
GLX_PBUFFER_WIDTH, 256,
//GLX_PBUFFER_HEIGHT, 192, // Use a square size to prevent possible incompatibilities
GLX_PBUFFER_HEIGHT, 256,
None
};
// The first should match exactly, otherwise is the least wrong one
pbuf = glXCreatePbuffer(dpy, cfg[0], (int *)&pbuf_attr);
// Dynamic linking is a pain, sigh
OGLEXT(PFNGLXCREATECONTEXTATTRIBSARBPROC, glXCreateContextAttribsARB);
INITOGLEXT(PFNGLXCREATECONTEXTATTRIBSARBPROC, glXCreateContextAttribsARB);
// Try to get a 3.2 core profile context
if (glXCreateContextAttribsARB) {
const int ctx_attr[] = {
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 2,
None
};
// This silly dance is needed because if Xorg can't acquire the context
// we asked for it will throw an error, which is caught by GTK X error
// handler and made fatal. The show must go on.
int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(&xerror_handler);
ctx = glXCreateContextAttribsARB(dpy, cfg[0], 0, true, ctx_attr);
XSetErrorHandler(old_handler);
}
// Something went wrong, try with a standard context
if (!ctx)
ctx = glXCreateContext(dpy, vis, NULL, true);
XFree(cfg);
if (!ctx)
return false;
if (!glXMakeContextCurrent(dpy, pbuf, pbuf, ctx))
return false;
printf("OGL/GLX Renderer has finished the initialization.\n");
oglrender_init = glx_init;
oglrender_beginOpenGL = glx_beginOpenGL;
oglrender_endOpenGL = glx_endOpenGL;
return true;
}
bool is_glx_initialized(void)
{
return (ctx != NULL);
}
#endif // HAVE_GLX

View File

@ -69,9 +69,7 @@
#include "gdbstub.h"
#endif
#if defined(HAVE_LIBOSMESA) || defined(HAVE_GL_GLX)
#define HAVE_OPENGL
#endif
#define HAVE_OPENGL
#ifdef HAVE_OPENGL
#include <GL/gl.h>
@ -79,10 +77,10 @@
#include "OGLRender_3_2.h"
#endif
#if defined(HAVE_GL_GLX)
#include "glx_3Demu.h"
#elif defined(HAVE_LIBOSMESA)
#if defined(HAVE_LIBOSMESA)
#include "osmesa_3Demu.h"
#else
#include "sdl_3Demu.h"
#endif
#include "config.h"
@ -3060,16 +3058,16 @@ static void GraphicsSettingsDialog(GSimpleAction *action, GVariant *parameter, g
{
#if !defined(HAVE_OPENGL)
sel3DCore = RENDERID_SOFTRASTERIZER;
#elif defined(HAVE_GL_GLX)
if (!is_glx_initialized())
{
init_glx_3Demu();
}
#elif defined(HAVE_LIBOSMESA)
if (!is_osmesa_initialized())
{
init_osmesa_3Demu();
}
#else
if (!is_sdl_initialized())
{
init_sdl_3Demu();
}
#endif
}
@ -4466,16 +4464,16 @@ common_gtk_main(GApplication *app, gpointer user_data)
{
#if !defined(HAVE_OPENGL)
core = RENDERID_SOFTRASTERIZER;
#elif defined(HAVE_GL_GLX)
if (!is_glx_initialized())
{
init_glx_3Demu();
}
#elif defined(HAVE_LIBOSMESA)
if (!is_osmesa_initialized())
{
init_osmesa_3Demu();
}
#else
if (!is_sdl_initialized())
{
init_sdl_3Demu();
}
#endif
}
@ -4546,10 +4544,10 @@ static void Teardown() {
desmume_free();
#if defined(HAVE_GL_GLX)
deinit_glx_3Demu();
#elif defined(HAVE_LIBOSMESA)
#if defined(HAVE_LIBOSMESA)
deinit_osmesa_3Demu();
#else
deinit_sdl_3Demu();
#endif
/* Unload joystick */

View File

@ -14,7 +14,7 @@ desmume_src = [
'../shared/sndsdl.cpp',
'../shared/ctrlssdl.cpp',
'osmesa_3Demu.cpp',
'glx_3Demu.cpp',
'sdl_3Demu.cpp',
'cheatsGTK.cpp',
'main.cpp',
]

View File

@ -0,0 +1,83 @@
/*
Copyright (C) 2020 Emmanuel Gil Peyrot
This file 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 file 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 the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <SDL.h>
#include "../OGLRender.h"
#include "sdl_3Demu.h"
static bool sdl_beginOpenGL(void) { return 1; }
static void sdl_endOpenGL(void) { }
static bool sdl_init(void) { return is_sdl_initialized(); }
static SDL_Window *win = NULL;
static SDL_GLContext ctx = NULL;
bool deinit_sdl_3Demu(void)
{
bool ret = false;
if (ctx) {
SDL_GL_DeleteContext(ctx);
ctx = NULL;
ret = true;
}
if (win) {
SDL_DestroyWindow(win);
win = NULL;
ret = true;
}
return ret;
}
bool init_sdl_3Demu(void)
{
win = SDL_CreateWindow(NULL, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 192, SDL_WINDOW_OPENGL | SDL_WINDOW_HIDDEN);
if (!win)
return false;
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, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
ctx = SDL_GL_CreateContext(win);
if (!ctx)
return false;
printf("OGL/SDL Renderer has finished the initialization.\n");
oglrender_init = sdl_init;
oglrender_beginOpenGL = sdl_beginOpenGL;
oglrender_endOpenGL = sdl_endOpenGL;
return true;
}
bool is_sdl_initialized(void)
{
return (ctx != NULL);
}

View File

@ -1,6 +1,5 @@
/*
Copyright (C) 2013 The Lemon Man
Copyright (C) 2013-2017 DeSmuME team
Copyright (C) 2020 Emmanuel Gil Peyrot
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -16,12 +15,12 @@
along with the this software. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GLX_3DEMU_H
#define GLX_3DEMU_H
#ifndef SDL_3DEMU_H
#define SDL_3DEMU_H
bool init_glx_3Demu(void);
bool deinit_glx_3Demu(void);
bool is_glx_initialized(void);
bool init_sdl_3Demu(void);
bool deinit_sdl_3Demu(void);
bool is_sdl_initialized(void);
#endif // GLX_3DEMU_H
#endif // SDL_3DEMU_H

View File

@ -169,7 +169,6 @@ libdesmume_src += [
if dep_gl.found()
dependencies += dep_gl
add_global_arguments('-DHAVE_GL_GLX', language: ['c', 'cpp'])
libdesmume_src += [
'../../OGLRender.cpp',
'../../OGLRender_3_2.cpp',