summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2014-06-23 23:18:36 +0300
committerAndrei Karas <akaras@inbox.ru>2014-06-24 00:38:16 +0300
commit34279cbb4ea6506c3d64a62e20cd97643999ce61 (patch)
tree834f737ba88af9b718ab2097e77f9953afcaa586
parenta1521294fda5b8b5bba3e7b512573bfcbc4c7fbe (diff)
downloadplus-34279cbb4ea6506c3d64a62e20cd97643999ce61.tar.gz
plus-34279cbb4ea6506c3d64a62e20cd97643999ce61.tar.bz2
plus-34279cbb4ea6506c3d64a62e20cd97643999ce61.tar.xz
plus-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.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