From 34279cbb4ea6506c3d64a62e20cd97643999ce61 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Mon, 23 Jun 2014 23:18:36 +0300 Subject: Add manual OpenGL context creation. For SDL2 set attributes for context version. For SDL1.2 in X11 create own context. For SDL1.2 and other platforms not implimented for now. Also try fallback if need to older context versions. --- src/utils/glxhelper.cpp | 120 +++++++++++++++++++++++++++++++++++++++++++++++ src/utils/glxhelper.h | 41 ++++++++++++++++ src/utils/sdl2helper.cpp | 32 +++++++++++++ src/utils/sdl2helper.h | 4 ++ src/utils/sdlhelper.cpp | 38 +++++++++++++++ src/utils/sdlhelper.h | 4 ++ 6 files changed, 239 insertions(+) create mode 100644 src/utils/glxhelper.cpp create mode 100644 src/utils/glxhelper.h (limited to 'src/utils') diff --git a/src/utils/glxhelper.cpp b/src/utils/glxhelper.cpp new file mode 100644 index 000000000..1fedeb9c6 --- /dev/null +++ b/src/utils/glxhelper.cpp @@ -0,0 +1,120 @@ +/* + * The ManaPlus Client + * Copyright (C) 2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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 + * any later version. + * + * This program 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 this program. If not, see . + */ + +#include "utils/glxhelper.h" + +#if defined(USE_OPENGL) && defined(USE_X11) + +#include "logger.h" + +#include "render/mglx.h" +#include "render/mglxtypes.h" + +#include "utils/stringutils.h" + +#include "debug.h" + +static int ErrorHandler(Display *d A_UNUSED, XErrorEvent *e A_UNUSED) +{ + return 0; +} + +void *GlxHelper::createContext(unsigned int window, + void *const display0, + const int major, + const int minor) +{ + Display *const display = static_cast(display0); + XSync(display, false); + int (*handler) (Display *, XErrorEvent *) = XSetErrorHandler(ErrorHandler); + void *context = mglXGetCurrentContext(); + if (!mglXGetCurrentContext + || !mglXCreateContextAttribs + || !mglXChooseFBConfig) + { + logger->log("Cant change context, functions in driver " + "not implimented"); + XSetErrorHandler(handler); + return context; + } + if (!context) + { + logger->log("Cant change context, because current " + "context not created"); + XSetErrorHandler(handler); + return context; + } + int glxAttribs[] = + { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_RED_SIZE, 3, + GLX_GREEN_SIZE, 3, + GLX_BLUE_SIZE, 2, + GLX_DOUBLEBUFFER, 1, + 0 + }; + + int fbcount = 0; + GLXFBConfig *framebuffer_config = mglXChooseFBConfig(display, + DefaultScreen(display), + glxAttribs, + &fbcount); + + if (!framebuffer_config || !fbcount) + { + logger->log("No correct fb profile found"); + XSetErrorHandler(handler); + return nullptr; + } + + int attribs[] = + { + GLX_CONTEXT_MAJOR_VERSION_ARB, major, + GLX_CONTEXT_MINOR_VERSION_ARB, minor, + GLX_CONTEXT_PROFILE_MASK_ARB, 0x01, // core profile + 0, 0 + }; + + void *const context2 = mglXCreateContextAttribs(display, + framebuffer_config[0], context, true, attribs); + if (!context2) + { + logger->log("context %d.%d creation failed", major, minor); + XSetErrorHandler(handler); + return nullptr; + } + + XSync(display, false); + XSetErrorHandler(handler); + + if (!mglXMakeCurrent(display, window, context2)) + { + mglXDestroyContext(display, context2); + logger->log("make current context %d.%d failed", major, minor); + return nullptr; + } + +// do not delete SDL context, because on exit it will crash +// mglXDestroyContext(display, context); + logger->log("Context for %d.%d created", major, minor); + return context2; +} + +#endif // defined(USE_OPENGL) && defined(USE_X11) diff --git a/src/utils/glxhelper.h b/src/utils/glxhelper.h new file mode 100644 index 000000000..0378256d0 --- /dev/null +++ b/src/utils/glxhelper.h @@ -0,0 +1,41 @@ +/* + * The ManaPlus Client + * Copyright (C) 2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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 + * any later version. + * + * This program 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 this program. If not, see . + */ + +#ifndef UTILS_GLXHELPER_H +#define UTILS_GLXHELPER_H + +#include "main.h" + +#if defined(USE_OPENGL) && defined(USE_X11) + +#include "localconsts.h" + +//struct Display; + +namespace GlxHelper +{ + void *createContext(unsigned int window, + void *const display, + const int major, + const int minor); +} // namespace Glx + +#endif // defined(USE_OPENGL) && defined(USE_X11) +#endif // UTILS_GLXHELPER_H diff --git a/src/utils/sdl2helper.cpp b/src/utils/sdl2helper.cpp index 22c57116c..3b2b988a0 100644 --- a/src/utils/sdl2helper.cpp +++ b/src/utils/sdl2helper.cpp @@ -94,4 +94,36 @@ SDL_Thread *SDL::createThread(SDL_ThreadFunction fn, return SDL_CreateThread(fn, name, data); } +void *SDL::createGLContext(SDL_Window *const window, + const int major, + const int minor) +{ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, + SDL_GL_CONTEXT_PROFILE_CORE); +// SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG); + SDL_ClearError(); + void *context = SDL_GL_CreateContext(window); + if (SDL_GetError()) + { + if (!context && (major > 3 || (major == 3 && minor > 3))) + { + logger->log("Try fallback to OpenGL 3.3 context"); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_ClearError(); + context = SDL_GL_CreateContext(window); + if (SDL_GetError()) + { + logger->log("Try fallback to OpenGL 3.0 context"); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + context = SDL_GL_CreateContext(window); + } + } + } + return context; +} + #endif // USE_SDL2 diff --git a/src/utils/sdl2helper.h b/src/utils/sdl2helper.h index 9f625ee84..6f59b27a6 100644 --- a/src/utils/sdl2helper.h +++ b/src/utils/sdl2helper.h @@ -51,6 +51,10 @@ namespace SDL SDL_Thread *createThread(SDL_ThreadFunction fn, const char *restrict const name, void *restrict const data); + + void *createGLContext(SDL_Window *const window, + const int major, + const int minor); } // namespace SDL #endif // USE_SDL2 diff --git a/src/utils/sdlhelper.cpp b/src/utils/sdlhelper.cpp index 0f5d67a59..19cffa0a6 100644 --- a/src/utils/sdlhelper.cpp +++ b/src/utils/sdlhelper.cpp @@ -23,9 +23,14 @@ #include "utils/sdlhelper.h" #include "logger.h" +#include "main.h" #include "utils/stringutils.h" +#ifdef USE_X11 +#include "utils/glxhelper.h" +#endif // USE_X11 + #include #include @@ -111,4 +116,37 @@ SDL_Thread *SDL::createThread(int (SDLCALL *fn)(void *), return SDL_CreateThread(fn, data); } +#if defined(USE_X11) && defined(USE_OPENGL) +void *SDL::createGLContext(SDL_Surface *const window A_UNUSED, + const int major, + const int minor) +{ + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + SDL_GetWMInfo(&info); + void *context = GlxHelper::createContext(info.info.x11.window, + info.info.x11.display, major, minor); + if (!context && (major > 3 || (major == 3 && minor > 3))) + { + logger->log("Try fallback to OpenGL 3.3 context"); + context = GlxHelper::createContext(info.info.x11.window, + info.info.x11.display, 3, 3); + if (!context) + { + logger->log("Try fallback to OpenGL 3.0 context"); + context = GlxHelper::createContext(info.info.x11.window, + info.info.x11.display, 3, 0); + } + } + return context; +} +#else +void *SDL::createGLContext(SDL_Surface *const window A_UNUSED, + const int major A_UNUSED, + const int minor A_UNUSED) +{ + return nullptr; +} +#endif + #endif // USE_SDL2 diff --git a/src/utils/sdlhelper.h b/src/utils/sdlhelper.h index a471268af..328c093cd 100644 --- a/src/utils/sdlhelper.h +++ b/src/utils/sdlhelper.h @@ -56,6 +56,10 @@ namespace SDL SDL_Thread *createThread(int (SDLCALL *fn)(void *), const char *const name A_UNUSED, void *const data); + + void *createGLContext(SDL_Surface *const window A_UNUSED, + const int major, + const int minor); } // namespace SDL #endif // USE_SDL2 -- cgit v1.2.3-70-g09d2