Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-02-26 21:10:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-02-26 21:10:15 +0300
commit0940e89e604d85d717f792b73e30e5e96a42e7c6 (patch)
tree4160e3fe1477cb9644fe2fc9163c4dffc31a5a86
parentd6df23d9d96bfefb6a0a0f3979d3440d0fef05cc (diff)
GHOST: Add new interface to manage offscreen contexts.
Offscreen contexts are not attached to a window and can only be used for rendering to frambuffer objects. CGL implementation : Brecht Van Lommel (brecht) GLX implementation : Clément Foucault (fclem) WGL implementation : Germano Cavalcante (mano-wii) Other implementation are just place holder for now.
-rw-r--r--intern/ghost/CMakeLists.txt1
-rw-r--r--intern/ghost/GHOST_C-api.h32
-rw-r--r--intern/ghost/GHOST_IContext.h78
-rw-r--r--intern/ghost/GHOST_ISystem.h15
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp28
-rw-r--r--intern/ghost/intern/GHOST_Context.h9
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.h6
-rw-r--r--intern/ghost/intern/GHOST_ContextCGL.mm39
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.cpp11
-rw-r--r--intern/ghost/intern/GHOST_ContextEGL.h6
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.cpp35
-rw-r--r--intern/ghost/intern/GHOST_ContextGLX.h6
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.cpp6
-rw-r--r--intern/ghost/intern/GHOST_ContextNone.h6
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.cpp12
-rw-r--r--intern/ghost/intern/GHOST_ContextSDL.h6
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.cpp131
-rw-r--r--intern/ghost/intern/GHOST_ContextWGL.h10
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h19
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm70
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.cpp94
-rw-r--r--intern/ghost/intern/GHOST_SystemWin32.h15
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp99
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.h20
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm2
25 files changed, 686 insertions, 70 deletions
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 5a97da28d17..7771af93d4f 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -54,6 +54,7 @@ set(SRC
intern/GHOST_WindowManager.cpp
GHOST_C-api.h
+ GHOST_IContext.h
GHOST_IEvent.h
GHOST_IEventConsumer.h
GHOST_ISystem.h
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 967d3f58143..d5d8be7db8e 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -52,6 +52,7 @@ GHOST_DECLARE_HANDLE(GHOST_WindowHandle);
GHOST_DECLARE_HANDLE(GHOST_EventHandle);
GHOST_DECLARE_HANDLE(GHOST_RectangleHandle);
GHOST_DECLARE_HANDLE(GHOST_EventConsumerHandle);
+GHOST_DECLARE_HANDLE(GHOST_ContextHandle);
/**
@@ -189,6 +190,23 @@ extern GHOST_WindowHandle GHOST_CreateWindow(
GHOST_GLSettings glSettings);
/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \param systemhandle The handle to the system
+ * \return A handle to the new context ( == NULL if creation failed).
+ */
+extern GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle);
+
+/**
+ * Dispose of a context.
+ * \param systemhandle The handle to the system
+ * \param contexthandle Handle to the context to be disposed.
+ * \return Indication of success.
+ */
+extern GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
+ GHOST_ContextHandle contexthandle);
+
+/**
* Returns the window user data.
* \param windowhandle The handle to the window
* \return The window user data.
@@ -711,6 +729,20 @@ extern GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle wind
extern GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle);
/**
+ * Activates the drawing context of this context.
+ * \param contexthandle The handle to the context
+ * \return A success indicator.
+ */
+extern GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle);
+
+/**
+ * Release the drawing context bound to this thread.
+ * \param contexthandle The handle to the context
+ * \return A success indicator.
+ */
+extern GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle);
+
+/**
* Returns the status of the tablet
* \param windowhandle The handle to the window
* \return Status of tablet
diff --git a/intern/ghost/GHOST_IContext.h b/intern/ghost/GHOST_IContext.h
new file mode 100644
index 00000000000..5b027a614ab
--- /dev/null
+++ b/intern/ghost/GHOST_IContext.h
@@ -0,0 +1,78 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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 (at your option) 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, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ghost/GHOST_IContext.h
+ * \ingroup GHOST
+ * Declaration of GHOST_IContext interface class.
+ */
+
+#ifndef __GHOST_IContext_H__
+#define __GHOST_IContext_H__
+
+#include "STR_String.h"
+#include "GHOST_Types.h"
+
+
+/**
+ * Interface for GHOST context.
+ *
+ * You can create a offscreen context (windowless) with the system's
+ * GHOST_ISystem::createOffscreenContext method.
+ * \see GHOST_ISystem#createOffscreenContext
+ *
+ * \author Clément Foucault
+ * \date Feb 9, 2018
+ */
+class GHOST_IContext
+{
+public:
+ /**
+ * Destructor.
+ */
+ virtual ~GHOST_IContext()
+ {
+ }
+
+ /**
+ * Activates the drawing context.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess activateDrawingContext() = 0;
+
+ /**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess releaseDrawingContext() = 0;
+
+#ifdef WITH_CXX_GUARDEDALLOC
+ MEM_CXX_CLASS_ALLOC_FUNCS("GHOST:GHOST_IContext")
+#endif
+};
+
+#endif // __GHOST_IContext_H__
+
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 03193d6e1da..5c5590ef069 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -36,6 +36,7 @@
#define __GHOST_ISYSTEM_H__
#include "GHOST_Types.h"
+#include "GHOST_IContext.h"
#include "GHOST_ITimerTask.h"
#include "GHOST_IWindow.h"
@@ -262,6 +263,20 @@ public:
virtual GHOST_TSuccess disposeWindow(GHOST_IWindow *window) = 0;
/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+ virtual GHOST_IContext *createOffscreenContext() = 0;
+
+ /**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+ virtual GHOST_TSuccess disposeContext(GHOST_IContext *context) = 0;
+
+ /**
* Returns whether a window is valid.
* \param window Pointer to the window to be checked.
* \return Indication of validity.
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index ce653188760..2fe94171cf8 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -132,6 +132,22 @@ void GHOST_GetAllDisplayDimensions(GHOST_SystemHandle systemhandle,
system->getAllDisplayDimensions(*width, *height);
}
+GHOST_ContextHandle GHOST_CreateOpenGLContext(GHOST_SystemHandle systemhandle)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *) systemhandle;
+
+ return (GHOST_ContextHandle) system->createOffscreenContext();
+}
+
+GHOST_TSuccess GHOST_DisposeOpenGLContext(GHOST_SystemHandle systemhandle,
+ GHOST_ContextHandle contexthandle)
+{
+ GHOST_ISystem *system = (GHOST_ISystem *) systemhandle;
+ GHOST_IContext *context = (GHOST_IContext *) contexthandle;
+
+ return system->disposeContext(context);
+}
+
GHOST_WindowHandle GHOST_CreateWindow(GHOST_SystemHandle systemhandle,
const char *title,
GHOST_TInt32 left,
@@ -713,7 +729,19 @@ GHOST_TSuccess GHOST_ActivateWindowDrawingContext(GHOST_WindowHandle windowhandl
return window->activateDrawingContext();
}
+GHOST_TSuccess GHOST_ActivateOpenGLContext(GHOST_ContextHandle contexthandle)
+{
+ GHOST_IContext *context = (GHOST_IContext *) contexthandle;
+
+ return context->activateDrawingContext();
+}
+
+GHOST_TSuccess GHOST_ReleaseOpenGLContext(GHOST_ContextHandle contexthandle)
+{
+ GHOST_IContext *context = (GHOST_IContext *) contexthandle;
+ return context->releaseDrawingContext();
+}
GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle)
{
diff --git a/intern/ghost/intern/GHOST_Context.h b/intern/ghost/intern/GHOST_Context.h
index 8776fa4764f..670b86d456f 100644
--- a/intern/ghost/intern/GHOST_Context.h
+++ b/intern/ghost/intern/GHOST_Context.h
@@ -33,6 +33,7 @@
#ifndef __GHOST_CONTEXT_H__
#define __GHOST_CONTEXT_H__
+#include "GHOST_IContext.h"
#include "GHOST_Types.h"
#include "glew-mx.h"
@@ -40,7 +41,7 @@
#include <cstdlib> // for NULL
-class GHOST_Context
+class GHOST_Context : public GHOST_IContext
{
public:
/**
@@ -72,6 +73,12 @@ public:
virtual GHOST_TSuccess activateDrawingContext() = 0;
/**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ virtual GHOST_TSuccess releaseDrawingContext()= 0;
+
+ /**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
diff --git a/intern/ghost/intern/GHOST_ContextCGL.h b/intern/ghost/intern/GHOST_ContextCGL.h
index 6dcc4da0f0a..ea6eb485ce2 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.h
+++ b/intern/ghost/intern/GHOST_ContextCGL.h
@@ -83,6 +83,12 @@ public:
GHOST_TSuccess activateDrawingContext();
/**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ /**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm
index 03af3cc497e..46993a1cd1d 100644
--- a/intern/ghost/intern/GHOST_ContextCGL.mm
+++ b/intern/ghost/intern/GHOST_ContextCGL.mm
@@ -35,6 +35,8 @@
#include <Cocoa/Cocoa.h>
+//#define GHOST_MULTITHREADED_OPENGL
+
#ifdef GHOST_MULTITHREADED_OPENGL
#include <OpenGL/OpenGL.h>
#endif
@@ -62,8 +64,6 @@ GHOST_ContextCGL::GHOST_ContextCGL(
m_openGLContext(nil),
m_debug(contextFlags)
{
- assert(openGLView != nil);
-
// for now be very strict about OpenGL version requested
switch (contextMajorVersion) {
case 2:
@@ -73,7 +73,7 @@ GHOST_ContextCGL::GHOST_ContextCGL(
break;
case 3:
// Apple didn't implement 3.0 or 3.1
- assert(contextMinorVersion == 2);
+ assert(contextMinorVersion == 3);
assert(contextProfileMask == GL_CONTEXT_CORE_PROFILE_BIT);
m_coreProfile = true;
break;
@@ -88,7 +88,10 @@ GHOST_ContextCGL::~GHOST_ContextCGL()
if (m_openGLContext != nil) {
if (m_openGLContext == [NSOpenGLContext currentContext]) {
[NSOpenGLContext clearCurrentContext];
- [m_openGLView clearGLContext];
+
+ if(m_openGLView) {
+ [m_openGLView clearGLContext];
+ }
}
if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) {
@@ -167,6 +170,18 @@ GHOST_TSuccess GHOST_ContextCGL::activateDrawingContext()
}
}
+GHOST_TSuccess GHOST_ContextCGL::releaseDrawingContext()
+{
+ if (m_openGLContext != nil) {
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ [NSOpenGLContext clearCurrentContext];
+ [pool drain];
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
GHOST_TSuccess GHOST_ContextCGL::updateDrawingContext()
{
@@ -258,7 +273,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
std::vector<NSOpenGLPixelFormatAttribute> attribs;
attribs.reserve(40);
- NSOpenGLContext *prev_openGLContext = [m_openGLView openGLContext];
+ NSOpenGLContext *prev_openGLContext = (m_openGLView) ? [m_openGLView openGLContext] : NULL;
#ifdef GHOST_OPENGL_ALPHA
static const bool needAlpha = true;
@@ -346,8 +361,7 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
#ifdef GHOST_MULTITHREADED_OPENGL
//Switch openGL to multhreaded mode
- CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj];
- if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError)
+ if (CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine) == kCGLNoError)
if (m_debug)
fprintf(stderr, "\nSwitched OpenGL to multithreaded mode\n");
#endif
@@ -362,8 +376,10 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
initContextGLEW();
- [m_openGLView setOpenGLContext:m_openGLContext];
- [m_openGLContext setView:m_openGLView];
+ if (m_openGLView) {
+ [m_openGLView setOpenGLContext:m_openGLContext];
+ [m_openGLContext setView:m_openGLView];
+ }
if (s_sharedCount == 0)
s_sharedOpenGLContext = m_openGLContext;
@@ -380,7 +396,10 @@ GHOST_TSuccess GHOST_ContextCGL::initializeDrawingContext()
error:
- [m_openGLView setOpenGLContext:prev_openGLContext];
+ if (m_openGLView) {
+ [m_openGLView setOpenGLContext:prev_openGLContext];
+ }
+
[pixelFormat release];
[pool drain];
diff --git a/intern/ghost/intern/GHOST_ContextEGL.cpp b/intern/ghost/intern/GHOST_ContextEGL.cpp
index a591d9b7583..56962d24939 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextEGL.cpp
@@ -312,6 +312,17 @@ GHOST_TSuccess GHOST_ContextEGL::activateDrawingContext()
}
}
+GHOST_TSuccess GHOST_ContextEGL::releaseDrawingContext()
+{
+ if (m_display) {
+ bindAPI(m_api);
+
+ return EGL_CHK(::eglMakeCurrent(m_display, None, None, NULL)) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
void GHOST_ContextEGL::initContextEGLEW()
{
diff --git a/intern/ghost/intern/GHOST_ContextEGL.h b/intern/ghost/intern/GHOST_ContextEGL.h
index 6dfb177f26d..83415f6be54 100644
--- a/intern/ghost/intern/GHOST_ContextEGL.h
+++ b/intern/ghost/intern/GHOST_ContextEGL.h
@@ -81,6 +81,12 @@ public:
GHOST_TSuccess activateDrawingContext();
/**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ /**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
diff --git a/intern/ghost/intern/GHOST_ContextGLX.cpp b/intern/ghost/intern/GHOST_ContextGLX.cpp
index 061ac29945b..fb7fa4ee762 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.cpp
+++ b/intern/ghost/intern/GHOST_ContextGLX.cpp
@@ -74,7 +74,6 @@ GHOST_ContextGLX::GHOST_ContextGLX(
m_contextResetNotificationStrategy(contextResetNotificationStrategy),
m_context(None)
{
- assert(m_window != 0);
assert(m_display != NULL);
}
@@ -119,6 +118,16 @@ GHOST_TSuccess GHOST_ContextGLX::activateDrawingContext()
}
}
+GHOST_TSuccess GHOST_ContextGLX::releaseDrawingContext()
+{
+ if (m_display) {
+ return ::glXMakeCurrent(m_display, None, NULL) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
void GHOST_ContextGLX::initContextGLXEW()
{
initContextGLEW();
@@ -246,9 +255,22 @@ const bool GLXEW_ARB_create_context_robustness =
}
attribs[i++] = 0;
+ /* Some drivers don't like having a true offscreen context.
+ * Create a pixel buffer instead of a window to render to.
+ * even if it will never be used for drawing. */
+ int pbuffer_attribs[] = {
+ GLX_PBUFFER_WIDTH, 1,
+ GLX_PBUFFER_HEIGHT, 1,
+ None
+ };
+
/* Create a GL 3.x context */
if (m_fbconfig) {
m_context = glXCreateContextAttribsARB(m_display, m_fbconfig, s_sharedContext, true, attribs);
+
+ if (!m_window) {
+ m_window = (Window)glXCreatePbuffer(m_display, m_fbconfig, pbuffer_attribs);
+ }
}
else {
GLXFBConfig *framebuffer_config = NULL;
@@ -263,6 +285,11 @@ const bool GLXEW_ARB_create_context_robustness =
if (framebuffer_config) {
m_context = glXCreateContextAttribsARB(m_display, framebuffer_config[0], s_sharedContext, True, attribs);
+
+ if (!m_window) {
+ m_window = (Window)glXCreatePbuffer(m_display, framebuffer_config[0], pbuffer_attribs);
+ }
+
XFree(framebuffer_config);
}
}
@@ -288,8 +315,10 @@ const bool GLXEW_ARB_create_context_robustness =
// which means we cannot use glX extensions until after we create a context
initContextGLXEW();
- initClearGL();
- ::glXSwapBuffers(m_display, m_window);
+ if (m_window) {
+ initClearGL();
+ ::glXSwapBuffers(m_display, m_window);
+ }
/* re initialize to get the extensions properly */
initContextGLXEW();
diff --git a/intern/ghost/intern/GHOST_ContextGLX.h b/intern/ghost/intern/GHOST_ContextGLX.h
index 51fb1dd57dc..ded1b293659 100644
--- a/intern/ghost/intern/GHOST_ContextGLX.h
+++ b/intern/ghost/intern/GHOST_ContextGLX.h
@@ -82,6 +82,12 @@ public:
GHOST_TSuccess activateDrawingContext();
/**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ /**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
diff --git a/intern/ghost/intern/GHOST_ContextNone.cpp b/intern/ghost/intern/GHOST_ContextNone.cpp
index 380ab532f7a..89bdf6b89fa 100644
--- a/intern/ghost/intern/GHOST_ContextNone.cpp
+++ b/intern/ghost/intern/GHOST_ContextNone.cpp
@@ -46,6 +46,12 @@ GHOST_TSuccess GHOST_ContextNone::activateDrawingContext()
}
+GHOST_TSuccess GHOST_ContextNone::releaseDrawingContext()
+{
+ return GHOST_kSuccess;
+}
+
+
GHOST_TSuccess GHOST_ContextNone::updateDrawingContext()
{
return GHOST_kSuccess;
diff --git a/intern/ghost/intern/GHOST_ContextNone.h b/intern/ghost/intern/GHOST_ContextNone.h
index 80cce76190d..9f2af4ae235 100644
--- a/intern/ghost/intern/GHOST_ContextNone.h
+++ b/intern/ghost/intern/GHOST_ContextNone.h
@@ -61,6 +61,12 @@ public:
/**
* Dummy function
+ * \return Always succeeds
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ /**
+ * Dummy function
* \return Always succeeds
*/
GHOST_TSuccess updateDrawingContext();
diff --git a/intern/ghost/intern/GHOST_ContextSDL.cpp b/intern/ghost/intern/GHOST_ContextSDL.cpp
index 7a02e9743c3..1ba591bd0b2 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.cpp
+++ b/intern/ghost/intern/GHOST_ContextSDL.cpp
@@ -105,6 +105,18 @@ GHOST_TSuccess GHOST_ContextSDL::activateDrawingContext()
}
+GHOST_TSuccess GHOST_ContextSDL::releaseDrawingContext()
+{
+ if (m_context) {
+ /* Untested, may not work */
+ return SDL_GL_MakeCurrent(NULL, NULL) ? GHOST_kSuccess : GHOST_kFailure;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
+
GHOST_TSuccess GHOST_ContextSDL::initializeDrawingContext()
{
#ifdef GHOST_OPENGL_ALPHA
diff --git a/intern/ghost/intern/GHOST_ContextSDL.h b/intern/ghost/intern/GHOST_ContextSDL.h
index 61f339c1bc2..681d24bb7c6 100644
--- a/intern/ghost/intern/GHOST_ContextSDL.h
+++ b/intern/ghost/intern/GHOST_ContextSDL.h
@@ -86,6 +86,12 @@ public:
GHOST_TSuccess activateDrawingContext();
/**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ /**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
diff --git a/intern/ghost/intern/GHOST_ContextWGL.cpp b/intern/ghost/intern/GHOST_ContextWGL.cpp
index 7b5e30247a8..a23c0b0b26c 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.cpp
+++ b/intern/ghost/intern/GHOST_ContextWGL.cpp
@@ -43,14 +43,7 @@
HGLRC GHOST_ContextWGL::s_sharedHGLRC = NULL;
int GHOST_ContextWGL::s_sharedCount = 0;
-bool GHOST_ContextWGL::s_singleContextMode = false;
-
-
-/* Intel video-cards don't work fine with multiple contexts and
- * have to share the same context for all windows.
- * But if we just share context for all windows it could work incorrect
- * with multiple videocards configuration. Suppose, that Intel videocards
- * can't be in multiple-devices configuration. */
+/* Some third-generation Intel video-cards are constantly bring problems */
static bool is_crappy_intel_card()
{
return strstr((const char *)glGetString(GL_VENDOR), "Intel") != NULL;
@@ -69,6 +62,7 @@ GHOST_ContextWGL::GHOST_ContextWGL(
int contextFlags,
int contextResetNotificationStrategy)
: GHOST_Context(stereoVisual, numOfAASamples),
+ m_dummyPbuffer(NULL),
m_hWnd(hWnd),
m_hDC(hDC),
m_contextProfileMask(contextProfileMask),
@@ -85,8 +79,6 @@ GHOST_ContextWGL::GHOST_ContextWGL(
m_dummyVersion(NULL)
#endif
{
- assert(m_hWnd);
- assert(m_hDC);
}
@@ -106,12 +98,20 @@ GHOST_ContextWGL::~GHOST_ContextWGL()
WIN32_CHK(::wglDeleteContext(m_hGLRC));
}
+ if (m_dummyPbuffer) {
+ if (m_hDC != NULL)
+ WIN32_CHK(::wglReleasePbufferDCARB(m_dummyPbuffer, m_hDC));
+
+ WIN32_CHK(::wglDestroyPbufferARB(m_dummyPbuffer));
+ }
}
#ifndef NDEBUG
- free((void*)m_dummyRenderer);
- free((void*)m_dummyVendor);
- free((void*)m_dummyVersion);
+ if (m_dummyRenderer) {
+ free((void*)m_dummyRenderer);
+ free((void*)m_dummyVendor);
+ free((void*)m_dummyVersion);
+ }
#endif
}
@@ -154,6 +154,16 @@ GHOST_TSuccess GHOST_ContextWGL::activateDrawingContext()
}
+GHOST_TSuccess GHOST_ContextWGL::releaseDrawingContext()
+{
+ if (WIN32_CHK(::wglMakeCurrent(NULL, NULL))) {
+ return GHOST_kSuccess;
+ }
+ else {
+ return GHOST_kFailure;
+ }
+}
+
/* Ron Fosner's code for weighting pixel formats and forcing software.
* See http://www.opengl.org/resources/faq/technical/weight.cpp
*/
@@ -317,6 +327,8 @@ static HWND clone_window(HWND hWnd, LPVOID lpParam)
void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
{
HWND dummyHWND = NULL;
+ HPBUFFERARB dummyhBuffer = NULL;
+
HDC dummyHDC = NULL;
HGLRC dummyHGLRC = NULL;
@@ -333,23 +345,29 @@ void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
prevHGLRC = ::wglGetCurrentContext();
WIN32_CHK(GetLastError() == NO_ERROR);
- dummyHWND = clone_window(m_hWnd, NULL);
+ iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
- if (dummyHWND == NULL)
+ if (iPixelFormat == 0)
goto finalize;
- dummyHDC = GetDC(dummyHWND);
-
- if (!WIN32_CHK(dummyHDC != NULL))
+ PIXELFORMATDESCRIPTOR chosenPFD;
+ if (!WIN32_CHK(::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
goto finalize;
- iPixelFormat = choose_pixel_format_legacy(dummyHDC, preferredPFD);
+ if (m_hWnd) {
+ dummyHWND = clone_window(m_hWnd, NULL);
- if (iPixelFormat == 0)
- goto finalize;
+ if (dummyHWND == NULL)
+ goto finalize;
- PIXELFORMATDESCRIPTOR chosenPFD;
- if (!WIN32_CHK(::DescribePixelFormat(dummyHDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
+ dummyHDC = GetDC(dummyHWND);
+ }
+ else {
+ dummyhBuffer = wglCreatePbufferARB(m_hDC, iPixelFormat, 1, 1, 0);
+ dummyHDC = wglGetPbufferDCARB(dummyhBuffer);
+ }
+
+ if (!WIN32_CHK(dummyHDC != NULL))
goto finalize;
if (!WIN32_CHK(::SetPixelFormat(dummyHDC, iPixelFormat, &chosenPFD)))
@@ -378,8 +396,6 @@ void GHOST_ContextWGL::initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD)
m_dummyVersion = _strdup(reinterpret_cast<const char *>(glGetString(GL_VERSION)));
#endif
- s_singleContextMode = is_crappy_intel_card();
-
finalize:
WIN32_CHK(::wglMakeCurrent(prevHDC, prevHGLRC));
@@ -392,6 +408,12 @@ finalize:
WIN32_CHK(::DestroyWindow(dummyHWND));
}
+ else if (dummyhBuffer != NULL) {
+ if (dummyHDC != NULL)
+ WIN32_CHK(::wglReleasePbufferDCARB(dummyhBuffer, dummyHDC));
+
+ WIN32_CHK(::wglDestroyPbufferARB(dummyhBuffer));
+ }
}
@@ -753,7 +775,9 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
HDC prevHDC = ::wglGetCurrentDC();
WIN32_CHK(GetLastError() == NO_ERROR);
- if (!WGLEW_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) {
+ const bool create_hDC = m_hDC == NULL;
+
+ if (!WGLEW_ARB_create_context || create_hDC || ::GetPixelFormat(m_hDC) == 0) {
const bool needAlpha = m_alphaBackground;
#ifdef GHOST_OPENGL_STENCIL
@@ -770,20 +794,32 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
int iPixelFormat;
int lastPFD;
+ if (create_hDC) {
+ /* get a handle to a device context with graphics accelerator enabled */
+ m_hDC = wglGetCurrentDC();
+ if (m_hDC == NULL) {
+ m_hDC = GetDC(NULL);
+ }
+ }
+
PIXELFORMATDESCRIPTOR chosenPFD;
iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);
if (iPixelFormat == 0) {
- ::wglMakeCurrent(prevHDC, prevHGLRC);
- return GHOST_kFailure;
+ goto error;
+ }
+
+ if (create_hDC) {
+ /* create an off-screen pixel buffer (Pbuffer) */
+ m_dummyPbuffer = wglCreatePbufferARB(m_hDC, iPixelFormat, 1, 1, 0);
+ m_hDC = wglGetPbufferDCARB(m_dummyPbuffer);
}
lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
if (!WIN32_CHK(lastPFD != 0)) {
- ::wglMakeCurrent(prevHDC, prevHGLRC);
- return GHOST_kFailure;
+ goto error;
}
if (needAlpha && chosenPFD.cAlphaBits == 0)
@@ -793,8 +829,7 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n");
if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
- ::wglMakeCurrent(prevHDC, prevHGLRC);
- return GHOST_kFailure;
+ goto error;
}
}
@@ -870,30 +905,24 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
iAttributes.push_back(0);
- if (!s_singleContextMode || s_sharedHGLRC == NULL)
- m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
- else
- m_hGLRC = s_sharedHGLRC;
+ m_hGLRC = ::wglCreateContextAttribsARB(m_hDC, NULL, &(iAttributes[0]));
}
if (!WIN32_CHK(m_hGLRC != NULL)) {
- ::wglMakeCurrent(prevHDC, prevHGLRC);
- return GHOST_kFailure;
+ goto error;
}
- if (s_sharedHGLRC == NULL)
- s_sharedHGLRC = m_hGLRC;
-
s_sharedCount++;
- if (!s_singleContextMode && s_sharedHGLRC != m_hGLRC && !WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
- ::wglMakeCurrent(prevHDC, prevHGLRC);
- return GHOST_kFailure;
+ if (s_sharedHGLRC == NULL) {
+ s_sharedHGLRC = m_hGLRC;
+ }
+ else if (!WIN32_CHK(::wglShareLists(s_sharedHGLRC, m_hGLRC))) {
+ goto error;
}
if (!WIN32_CHK(::wglMakeCurrent(m_hDC, m_hGLRC))) {
- ::wglMakeCurrent(prevHDC, prevHGLRC);
- return GHOST_kFailure;
+ goto error;
}
initContextGLEW();
@@ -923,6 +952,16 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
#endif
return GHOST_kSuccess;
+error:
+ if (m_dummyPbuffer) {
+ if (m_hDC != NULL)
+ WIN32_CHK(::wglReleasePbufferDCARB(m_dummyPbuffer, m_hDC));
+
+ WIN32_CHK(::wglDestroyPbufferARB(m_dummyPbuffer));
+ }
+ ::wglMakeCurrent(prevHDC, prevHGLRC);
+ return GHOST_kFailure;
+
}
diff --git a/intern/ghost/intern/GHOST_ContextWGL.h b/intern/ghost/intern/GHOST_ContextWGL.h
index a07cc1b6301..b3b66c5f6e2 100644
--- a/intern/ghost/intern/GHOST_ContextWGL.h
+++ b/intern/ghost/intern/GHOST_ContextWGL.h
@@ -79,6 +79,12 @@ public:
GHOST_TSuccess activateDrawingContext();
/**
+ * Release the drawing context of the calling thread.
+ * \return A boolean success indicator.
+ */
+ GHOST_TSuccess releaseDrawingContext();
+
+ /**
* Call immediately after new to initialize. If this fails then immediately delete the object.
* \return Indication as to whether initialization has succeeded.
*/
@@ -137,6 +143,10 @@ private:
void initContextWGLEW(PIXELFORMATDESCRIPTOR &preferredPFD);
+ /* offscreen buffer with size of 1x1 pixel,
+ * kept here to release the device constext when closing the program. */
+ HPBUFFERARB m_dummyPbuffer;
+
HWND m_hWnd;
HDC m_hDC;
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 6802ad42c7b..62d9774d81d 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -123,6 +123,25 @@ public:
const GHOST_TEmbedderWindowID parentWindow = 0
);
+ /**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+ GHOST_IContext *
+ createOffscreenContext(
+ );
+
+ /**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess
+ disposeContext(
+ GHOST_IContext *context
+ );
+
/***************************************************************************************
* Event management functionality
***************************************************************************************/
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index e9fffb6f60b..011719ea946 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -27,15 +27,6 @@
* ***** END GPL LICENSE BLOCK *****
*/
-#import <Cocoa/Cocoa.h>
-
-/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
-#include <Carbon/Carbon.h>
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/sysctl.h>
-
#include "GHOST_SystemCocoa.h"
#include "GHOST_DisplayManagerCocoa.h"
@@ -51,12 +42,26 @@
#include "GHOST_WindowManager.h"
#include "GHOST_WindowCocoa.h"
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextCGL.h"
+#endif
+
#ifdef WITH_INPUT_NDOF
#include "GHOST_NDOFManagerCocoa.h"
#endif
#include "AssertMacros.h"
+#import <Cocoa/Cocoa.h>
+
+/* For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible) */
+#include <Carbon/Carbon.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/sysctl.h>
#pragma mark KeyMap, mouse converters
@@ -581,6 +586,53 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
}
/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+GHOST_IContext *
+GHOST_SystemCocoa::
+createOffscreenContext()
+{
+ GHOST_Context *context = new GHOST_ContextCGL(
+ false,
+ 0,
+ NULL,
+ NULL,
+
+#if defined(WITH_GL_PROFILE_CORE)
+ GL_CONTEXT_CORE_PROFILE_BIT,
+ 3, 3,
+#else
+ 0, // no profile bit
+ 2, 1,
+#endif
+ GHOST_OPENGL_CGL_CONTEXT_FLAGS,
+ GHOST_OPENGL_CGL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+
+ return NULL;
+}
+
+/**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+GHOST_TSuccess
+GHOST_SystemCocoa::
+disposeContext(GHOST_IContext *context)
+{
+ delete context;
+
+ return GHOST_kSuccess;
+}
+
+/**
* \note : returns coordinates in Cocoa screen coordinates
*/
GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index b0dae432643..056b5536ab0 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -56,6 +56,12 @@
#include "GHOST_WindowManager.h"
#include "GHOST_WindowWin32.h"
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextWGL.h"
+#endif
+
#ifdef WITH_INPUT_NDOF
#include "GHOST_NDOFManagerWin32.h"
#endif
@@ -299,6 +305,94 @@ GHOST_IWindow *GHOST_SystemWin32::createWindow(
}
+/**
+ * Create a new offscreen context.
+ * Never explicitly delete the window, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+GHOST_IContext *GHOST_SystemWin32::createOffscreenContext()
+{
+ bool debug_context = false; /* TODO: inform as a parameter */
+
+ GHOST_Context *context;
+
+#if defined(WITH_GL_PROFILE_CORE)
+ for (int minor = 5; minor >= 0; --minor) {
+ context = new GHOST_ContextWGL(
+ false, true, 0,
+ NULL, NULL,
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 4, minor,
+ (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ delete context;
+ }
+ }
+
+ context = new GHOST_ContextWGL(
+ false, true, 0,
+ NULL, NULL,
+ WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
+ 3, 3,
+ (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ MessageBox(
+ NULL,
+ "Blender requires a graphics driver with at least OpenGL 3.3 support.\n\n"
+ "The program will now close.",
+ "Blender - Unsupported Graphics Driver!",
+ MB_OK | MB_ICONERROR);
+ delete context;
+ exit();
+ }
+
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ // ask for 2.1 context, driver gives any GL version >= 2.1 (hopefully the latest compatibility profile)
+ // 2.1 ignores the profile bit & is incompatible with core profile
+ context = new GHOST_ContextWGL(
+ false, true, 0,
+ NULL, NULL,
+ 0, // no profile bit
+ 2, 1,
+ (debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext()) {
+ return context;
+ }
+ else {
+ delete context;
+ }
+#else
+# error // must specify either core or compat at build time
+#endif
+
+ return NULL;
+}
+
+/**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context)
+{
+ delete context;
+
+ return GHOST_kSuccess;
+}
+
+
bool GHOST_SystemWin32::processEvents(bool waitForEvent)
{
MSG msg;
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 099d14e68ae..6bf2c5b8d6f 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -132,6 +132,21 @@ public:
const bool exclusive = false,
const GHOST_TEmbedderWindowID parentWindow = 0);
+
+ /**
+ * Create a new offscreen context.
+ * Never explicitly delete the window, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+ GHOST_IContext *createOffscreenContext();
+
+ /**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess disposeContext(GHOST_IContext *context);
+
/***************************************************************************************
** Event management functionality
***************************************************************************************/
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index 9b617a34e1a..0de6e2f7d4a 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -57,6 +57,12 @@
#include "GHOST_Debug.h"
+#if defined(WITH_GL_EGL)
+# include "GHOST_ContextEGL.h"
+#else
+# include "GHOST_ContextGLX.h"
+#endif
+
#ifdef WITH_XF86KEYSYM
#include <X11/XF86keysym.h>
#endif
@@ -113,6 +119,7 @@ GHOST_SystemX11(
: GHOST_System(),
m_start_time(0)
{
+ XInitThreads();
m_display = XOpenDisplay(NULL);
if (!m_display) {
@@ -379,6 +386,98 @@ createWindow(const STR_String& title,
return window;
}
+
+/**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+GHOST_IContext *
+GHOST_SystemX11::
+createOffscreenContext()
+{
+ // During development:
+ // try 4.x compatibility profile
+ // try 3.3 compatibility profile
+ // fall back to 3.0 if needed
+ //
+ // Final Blender 2.8:
+ // try 4.x core profile
+ // try 3.3 core profile
+ // no fallbacks
+
+#if defined(WITH_GL_PROFILE_CORE)
+ {
+ const char *version_major = (char*)glewGetString(GLEW_VERSION_MAJOR);
+ if (version_major != NULL && version_major[0] == '1') {
+ fprintf(stderr, "Error: GLEW version 2.0 and above is required.\n");
+ abort();
+ }
+ }
+#endif
+
+ const int profile_mask =
+#if defined(WITH_GL_PROFILE_CORE)
+ GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+#elif defined(WITH_GL_PROFILE_COMPAT)
+ GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+#else
+# error // must specify either core or compat at build time
+#endif
+
+ GHOST_Context *context;
+
+ for (int minor = 5; minor >= 0; --minor) {
+ context = new GHOST_ContextGLX(
+ false,
+ 0,
+ (Window)NULL,
+ m_display,
+ (GLXFBConfig)NULL,
+ profile_mask,
+ 4, minor,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+ }
+
+ context = new GHOST_ContextGLX(
+ false,
+ 0,
+ (Window)NULL,
+ m_display,
+ (GLXFBConfig)NULL,
+ profile_mask,
+ 3, 3,
+ GHOST_OPENGL_GLX_CONTEXT_FLAGS | (false ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
+ GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
+
+ if (context->initializeDrawingContext())
+ return context;
+ else
+ delete context;
+
+ return NULL;
+}
+
+/**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+GHOST_TSuccess
+GHOST_SystemX11::
+disposeContext(GHOST_IContext *context)
+{
+ delete context;
+
+ return GHOST_kSuccess;
+}
+
#if defined(WITH_X11_XINPUT) && defined(X_HAVE_UTF8_STRING)
static void destroyIMCallback(XIM /*xim*/, XPointer ptr, XPointer /*data*/)
{
diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h
index e60cab6a194..1ad8277a431 100644
--- a/intern/ghost/intern/GHOST_SystemX11.h
+++ b/intern/ghost/intern/GHOST_SystemX11.h
@@ -171,6 +171,26 @@ public:
const GHOST_TEmbedderWindowID parentWindow = 0
);
+
+ /**
+ * Create a new offscreen context.
+ * Never explicitly delete the context, use disposeContext() instead.
+ * \return The new context (or 0 if creation failed).
+ */
+ GHOST_IContext *
+ createOffscreenContext(
+ );
+
+ /**
+ * Dispose of a context.
+ * \param context Pointer to the context to be disposed.
+ * \return Indication of success.
+ */
+ GHOST_TSuccess
+ disposeContext(
+ GHOST_IContext *context
+ );
+
/**
* Retrieves events from the system and stores them in the queue.
* \param waitForEvent Flag to wait for an event (or return immediately).
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 309c19f92af..2b986428fd3 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -1005,7 +1005,7 @@ GHOST_Context *GHOST_WindowCocoa::newDrawingContext(GHOST_TDrawingContextType ty
#if defined(WITH_GL_PROFILE_CORE)
GL_CONTEXT_CORE_PROFILE_BIT,
- 3, 2,
+ 3, 3,
#else
0, // no profile bit
2, 1,