diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/render/graphics.cpp | 20 | ||||
-rw-r--r-- | src/render/graphics.h | 13 | ||||
-rw-r--r-- | src/render/mglx.cpp | 2 | ||||
-rw-r--r-- | src/render/mglx.h | 2 | ||||
-rw-r--r-- | src/render/mglxinit.cpp | 2 | ||||
-rw-r--r-- | src/render/mglxtypes.h | 5 | ||||
-rw-r--r-- | src/render/modernopenglgraphics.cpp | 6 | ||||
-rw-r--r-- | src/render/modernopenglgraphics.h | 3 | ||||
-rw-r--r-- | src/sdlshared.h | 1 | ||||
-rw-r--r-- | src/utils/glxhelper.cpp | 120 | ||||
-rw-r--r-- | src/utils/glxhelper.h | 41 | ||||
-rw-r--r-- | src/utils/sdl2helper.cpp | 32 | ||||
-rw-r--r-- | src/utils/sdl2helper.h | 4 | ||||
-rw-r--r-- | src/utils/sdlhelper.cpp | 38 | ||||
-rw-r--r-- | src/utils/sdlhelper.h | 4 |
17 files changed, 291 insertions, 6 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aea741c4c..c96f270c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -659,6 +659,8 @@ SET(SRCS utils/gettext.h utils/gettexthelper.cpp utils/gettexthelper.h + utils/glxhelper.cpp + utils/glxhelper.h utils/langs.cpp utils/langs.h utils/mathutils.h diff --git a/src/Makefile.am b/src/Makefile.am index 842a5e829..3ae2d24be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -777,6 +777,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ utils/gettext.h \ utils/gettexthelper.cpp \ utils/gettexthelper.h \ + utils/glxhelper.cpp \ + utils/glxhelper.h \ utils/langs.cpp \ utils/langs.h \ utils/mathutils.h \ diff --git a/src/render/graphics.cpp b/src/render/graphics.cpp index 5bb90e753..5cb45e8ca 100644 --- a/src/render/graphics.cpp +++ b/src/render/graphics.cpp @@ -71,6 +71,8 @@ #include "graphicsmanager.h" #include "logger.h" +#include "render/mglxinit.h" + #include "resources/imagehelper.h" #include "resources/openglimagehelper.h" @@ -99,10 +101,10 @@ Graphics::Graphics() : mWindow(nullptr), #ifdef USE_SDL2 mRenderer(nullptr), +#endif #ifdef USE_OPENGL mGLContext(nullptr), #endif -#endif mBpp(0), mAlpha(false), mFullscreen(false), @@ -252,11 +254,15 @@ bool Graphics::setOpenGLMode() mActualWidth, mActualHeight, mBpp, getOpenGLFlags()))) { + logger->log("Window/context creation failed"); mRect.w = 0; mRect.h = 0; return false; } +#if defined(USE_OPENGL) && defined(USE_X11) + Glx::initFunctions(); +#endif #ifdef USE_SDL2 int w1 = 0; int h1 = 0; @@ -264,10 +270,10 @@ bool Graphics::setOpenGLMode() mRect.w = static_cast<int32_t>(w1 / mScale); mRect.h = static_cast<int32_t>(h1 / mScale); - mGLContext = SDL_GL_CreateContext(mWindow); - + createGLContext(); #else // USE_SDL2 + createGLContext(); mRect.w = static_cast<uint16_t>(mWindow->w / mScale); mRect.h = static_cast<uint16_t>(mWindow->h / mScale); @@ -353,6 +359,14 @@ int Graphics::getSoftwareFlags() const return displayFlags; } +#ifdef USE_OPENGL +void Graphics::createGLContext() +{ +#ifdef USE_SDL2 + mGLContext = SDL_GL_CreateContext(mWindow); +#endif +} +#endif void Graphics::updateMemoryInfo() { diff --git a/src/render/graphics.h b/src/render/graphics.h index 3100971fc..2c4bc57ec 100644 --- a/src/render/graphics.h +++ b/src/render/graphics.h @@ -496,6 +496,9 @@ class Graphics notfinal bool videoInfo(); +#ifdef USE_OPENGL + virtual void createGLContext(); +#endif /** * Holds the clip area stack. */ @@ -505,10 +508,16 @@ class Graphics notfinal #ifdef USE_SDL2 SDL_Renderer *mRenderer; +#endif // USE_SDL2 #ifdef USE_OPENGL +#ifdef USE_SDL2 SDL_GLContext mGLContext; -#endif -#endif +#else // USE_SDL2 + + void *mGLContext; +#endif // USE_SDL2 +#endif // USE_OPENGL + int mBpp; bool mAlpha; bool mFullscreen; diff --git a/src/render/mglx.cpp b/src/render/mglx.cpp index 4c51cba14..73beb959c 100644 --- a/src/render/mglx.cpp +++ b/src/render/mglx.cpp @@ -30,5 +30,7 @@ defName(glXCreateContext); defName(glXGetCurrentContext); defName(glXCreateContextAttribs); defName(glXChooseFBConfig); +defName(glXDestroyContext); +defName(glXMakeCurrent); #endif diff --git a/src/render/mglx.h b/src/render/mglx.h index ceb916b8d..2e0c93364 100644 --- a/src/render/mglx.h +++ b/src/render/mglx.h @@ -32,6 +32,8 @@ defNameE(glXCreateContext); defNameE(glXGetCurrentContext); defNameE(glXCreateContextAttribs); defNameE(glXChooseFBConfig); +defNameE(glXDestroyContext); +defNameE(glXMakeCurrent); #undef defNameE diff --git a/src/render/mglxinit.cpp b/src/render/mglxinit.cpp index 81035a37c..bcf9eb31e 100644 --- a/src/render/mglxinit.cpp +++ b/src/render/mglxinit.cpp @@ -34,6 +34,8 @@ void Glx::initFunctions() assignFunction(glXGetCurrentContext, "glXGetCurrentContext"); assignFunction(glXCreateContextAttribs, "glXCreateContextAttribsARB"); assignFunction(glXChooseFBConfig, "glXChooseFBConfig"); + assignFunction(glXDestroyContext, "glXDestroyContext"); + assignFunction(glXMakeCurrent, "glXMakeCurrent"); } #endif diff --git a/src/render/mglxtypes.h b/src/render/mglxtypes.h index 700d62287..d8d66bdab 100644 --- a/src/render/mglxtypes.h +++ b/src/render/mglxtypes.h @@ -37,10 +37,13 @@ typedef void *(*glXCreateContext_t) (Display *dpy, XVisualInfo *vis, void *shareList, bool direct); typedef void *(*glXGetCurrentContext_t) (void); -typedef void (*glXCreateContextAttribs_t) (Display *dpy, GLXFBConfig config, +typedef void *(*glXCreateContextAttribs_t) (Display *dpy, GLXFBConfig config, void *share_context, bool direct, const int *attrib_list); typedef GLXFBConfig *(*glXChooseFBConfig_t) (Display *dpy, int screen, const int *attrib_list, int *nelements); +typedef void (*glXDestroyContext_t) (Display *dpy, void *ctx); +typedef bool (*glXMakeCurrent_t) (Display *dpy, + GLXDrawable drawable, void *ctx); #endif // USE_OPENGL #endif // RENDER_MGLXTYPES_H diff --git a/src/render/modernopenglgraphics.cpp b/src/render/modernopenglgraphics.cpp index ce7f86f56..3595d6a78 100644 --- a/src/render/modernopenglgraphics.cpp +++ b/src/render/modernopenglgraphics.cpp @@ -41,6 +41,7 @@ #include "resources/openglimagehelper.h" #include "utils/sdlcheckutils.h" +#include "utils/sdlhelper.h" #include "debug.h" @@ -1260,6 +1261,11 @@ void ModernOpenGLGraphics::clearScreen() const glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } +void ModernOpenGLGraphics::createGLContext() +{ + mGLContext = SDL::createGLContext(mWindow, 3, 3); +} + void ModernOpenGLGraphics::finalize(ImageCollection *const col) { FOR_EACH (ImageCollectionIter, it, col->draws) diff --git a/src/render/modernopenglgraphics.h b/src/render/modernopenglgraphics.h index 28a7f8bbb..2b27c621e 100644 --- a/src/render/modernopenglgraphics.h +++ b/src/render/modernopenglgraphics.h @@ -81,6 +81,9 @@ class ModernOpenGLGraphics final : public Graphics #include "render/openglgraphicsdefadvanced.hpp" + protected: + virtual void createGLContext() override final; + private: inline void drawQuad(const Image *const image, const int srcX, const int srcY, diff --git a/src/sdlshared.h b/src/sdlshared.h index 295cb29e7..a59828f95 100644 --- a/src/sdlshared.h +++ b/src/sdlshared.h @@ -60,6 +60,7 @@ #define SDL_JoystickNameForIndex SDL_JoystickName #define SurfaceImageHelper SDLImageHelper #define SDL_WaitEventTimeout(event, time) SDL_PollEvent(event) +#define SDL_GLContext (void*) #endif // USE_SDL2 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 <http://www.gnu.org/licenses/>. + */ + +#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<Display*>(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 <http://www.gnu.org/licenses/>. + */ + +#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 <SDL_syswm.h> #include <SDL_video.h> @@ -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 |