diff options
author | Andrei Karas <akaras@inbox.ru> | 2014-06-23 23:18:36 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2014-06-24 00:38:16 +0300 |
commit | 34279cbb4ea6506c3d64a62e20cd97643999ce61 (patch) | |
tree | 834f737ba88af9b718ab2097e77f9953afcaa586 | |
parent | a1521294fda5b8b5bba3e7b512573bfcbc4c7fbe (diff) | |
download | manaverse-34279cbb4ea6506c3d64a62e20cd97643999ce61.tar.gz manaverse-34279cbb4ea6506c3d64a62e20cd97643999ce61.tar.bz2 manaverse-34279cbb4ea6506c3d64a62e20cd97643999ce61.tar.xz manaverse-34279cbb4ea6506c3d64a62e20cd97643999ce61.zip |
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.
-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 |