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.
This commit is contained in:
2018-02-26 19:10:15 +01:00
parent d6df23d9d9
commit 0940e89e60
25 changed files with 688 additions and 72 deletions

View File

@@ -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

View File

@@ -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);
/**
@@ -188,6 +189,23 @@ extern GHOST_WindowHandle GHOST_CreateWindow(
GHOST_TDrawingContextType type,
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
@@ -710,6 +728,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

View File

@@ -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__

View File

@@ -36,6 +36,7 @@
#define __GHOST_ISYSTEM_H__
#include "GHOST_Types.h"
#include "GHOST_IContext.h"
#include "GHOST_ITimerTask.h"
#include "GHOST_IWindow.h"
@@ -261,6 +262,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.

View File

@@ -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)
{

View File

@@ -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:
/**
@@ -71,6 +72,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.

View File

@@ -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.

View File

@@ -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];

View File

@@ -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()
{

View File

@@ -80,6 +80,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.

View File

@@ -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();

View File

@@ -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.

View File

@@ -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;

View File

@@ -59,6 +59,12 @@ public:
*/
GHOST_TSuccess activateDrawingContext();
/**
* Dummy function
* \return Always succeeds
*/
GHOST_TSuccess releaseDrawingContext();
/**
* Dummy function
* \return Always succeeds

View File

@@ -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

View File

@@ -85,6 +85,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.

View File

@@ -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);
if (dummyHWND == NULL)
goto finalize;
dummyHDC = GetDC(dummyHWND);
if (!WIN32_CHK(dummyHDC != NULL))
goto finalize;
iPixelFormat = choose_pixel_format_legacy(dummyHDC, preferredPFD);
iPixelFormat = choose_pixel_format_legacy(m_hDC, preferredPFD);
if (iPixelFormat == 0)
goto finalize;
PIXELFORMATDESCRIPTOR chosenPFD;
if (!WIN32_CHK(::DescribePixelFormat(dummyHDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
if (!WIN32_CHK(::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD)))
goto finalize;
if (m_hWnd) {
dummyHWND = clone_window(m_hWnd, NULL);
if (dummyHWND == NULL)
goto finalize;
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;
}

View File

@@ -78,6 +78,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;

View File

@@ -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
***************************************************************************************/

View File

@@ -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
@@ -580,6 +585,53 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow(
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_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
*/

View File

@@ -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;

View File

@@ -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
***************************************************************************************/

View File

@@ -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*/)
{

View File

@@ -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).

View File

@@ -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,