summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/render/graphics.cpp20
-rw-r--r--src/render/graphics.h13
-rw-r--r--src/render/mglx.cpp2
-rw-r--r--src/render/mglx.h2
-rw-r--r--src/render/mglxinit.cpp2
-rw-r--r--src/render/mglxtypes.h5
-rw-r--r--src/render/modernopenglgraphics.cpp6
-rw-r--r--src/render/modernopenglgraphics.h3
-rw-r--r--src/sdlshared.h1
-rw-r--r--src/utils/glxhelper.cpp120
-rw-r--r--src/utils/glxhelper.h41
-rw-r--r--src/utils/sdl2helper.cpp32
-rw-r--r--src/utils/sdl2helper.h4
-rw-r--r--src/utils/sdlhelper.cpp38
-rw-r--r--src/utils/sdlhelper.h4
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