GHOST: Unify behavior of offscreen context creation

This makes sure the previously bound context is restored after creating a
new context. This follows what is already happening on windows.

All system backend are patched.

This also removes the goto and some code duplication.

Differential Revision: https://developer.blender.org/D12455
This commit is contained in:
Clément Foucault 2021-09-10 21:53:33 +02:00
parent a2daf92a57
commit 6535779c92
5 changed files with 94 additions and 114 deletions

View file

@ -767,13 +767,18 @@ GHOST_IWindow *GHOST_SystemCocoa::createWindow(const char *title,
*/
GHOST_IContext *GHOST_SystemCocoa::createOffscreenContext(GHOST_GLSettings glSettings)
{
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL);
if (context->initializeDrawingContext())
return context;
else
delete context;
NSOpenGLContext *prevContext = [NSOpenGLContext currentContext];
return NULL;
GHOST_Context *context = new GHOST_ContextCGL(false, NULL, NULL, NULL);
if (context->initializeDrawingContext() == false) {
delete context;
context = nullptr;
}
/* Restore previously bound context. This is just to follow the win32 behavior. */
if (prevContext) {
[prevContext makeCurrentContext];
}
return context;
}
/**

View file

@ -141,6 +141,9 @@ uint8_t GHOST_SystemSDL::getNumDisplays() const
GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings glSettings)
{
SDL_GLContext prev_context = SDL_GL_GetCurrentContext();
SDL_Window *prev_window = SDL_GL_GetCurrentWindow();
GHOST_Context *context = new GHOST_ContextSDL(0,
NULL,
0, /* Profile bit. */
@ -149,12 +152,18 @@ GHOST_IContext *GHOST_SystemSDL::createOffscreenContext(GHOST_GLSettings glSetti
GHOST_OPENGL_SDL_CONTEXT_FLAGS,
GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY);
if (context->initializeDrawingContext())
return context;
else
if (context->initializeDrawingContext()) {
/* Pass */
}
else {
delete context;
context = nullptr;
}
return NULL;
if (m_context) {
SDL_GL_MakeCurrent(prev_window, prev_context);
}
return context;
}
GHOST_TSuccess GHOST_SystemSDL::disposeContext(GHOST_IContext *context)

View file

@ -1599,45 +1599,47 @@ GHOST_IContext *GHOST_SystemWayland::createOffscreenContext(GHOST_GLSettings /*g
GHOST_Context *context;
for (int minor = 6; minor >= 0; --minor) {
EGLDisplay prev_display = eglGetCurrentDisplay();
/* It doesn't matter which one we query since we use the same surface for both read and write. */
EGLSurface prev_surface = eglGetCurrentSurface(EGL_DRAW);
EGLContext prev_context = eglGetCurrentContext();
const int versions[][2] = {{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}};
const int versions_len = sizeof(versions) / sizeof(versions[0]);
for (int i = 0; i < versions_len; i++) {
int major = versions[i][0];
int minor = versions[i][1];
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
4,
major,
minor,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext())
return context;
else
if (context->initializeDrawingContext()) {
break;
}
else {
delete context;
context = nullptr;
}
}
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(os_egl_window),
EGLNativeDisplayType(d->display),
EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
3,
3,
GHOST_OPENGL_EGL_CONTEXT_FLAGS,
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
if (context->initializeDrawingContext()) {
return context;
}
else {
delete context;
if (context == nullptr) {
GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
}
GHOST_PRINT("Cannot create off-screen EGL context" << std::endl);
return nullptr;
if (prev_context) {
/* Restore previously bound context. This is just to follow the win32 behavior. */
eglMakeCurrent(prev_display, prev_surface, prev_surface, prev_context);
}
return context;
}
GHOST_TSuccess GHOST_SystemWayland::disposeContext(GHOST_IContext *context)

View file

@ -284,69 +284,36 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContext(GHOST_GLSettings glSet
HDC mHDC = GetDC(wnd);
HDC prev_hdc = wglGetCurrentDC();
HGLRC prev_context = wglGetCurrentContext();
#if defined(WITH_GL_PROFILE_CORE)
for (int minor = 5; minor >= 0; --minor) {
const int versions[][2] = {{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}};
const int versions_len = sizeof(versions) / sizeof(versions[0]);
for (int i = 0; i < versions_len; i++) {
int major = versions[i][0];
int minor = versions[i][1];
context = new GHOST_ContextWGL(false,
true,
wnd,
mHDC,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
4,
major,
minor,
(debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
if (context->initializeDrawingContext()) {
goto finished;
break;
}
else {
delete context;
context = nullptr;
}
}
context = new GHOST_ContextWGL(false,
true,
wnd,
mHDC,
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()) {
goto finished;
if (prev_context) {
wglMakeCurrent(prev_hdc, prev_context);
}
else {
delete context;
return NULL;
}
#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,
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
finished:
wglMakeCurrent(prev_hdc, prev_context);
return context;
}

View file

@ -437,16 +437,32 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
# endif
#endif
#if defined(WITH_GL_EGL)
EGLDisplay prev_display = eglGetCurrentDisplay();
/* It doesn't matter which one we query since we use the same surface for both read and write. */
EGLSurface prev_surface = eglGetCurrentSurface(EGL_DRAW);
EGLContext prev_context = eglGetCurrentContext();
#else
Display *prev_display = glXGetCurrentDisplay();
GLXDrawable prev_drawable = glXGetCurrentDrawable();
GLXContext prev_context = glXGetCurrentContext();
#endif
GHOST_Context *context;
for (int minor = 5; minor >= 0; --minor) {
const int versions[][2] = {{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}};
const int versions_len = sizeof(versions) / sizeof(versions[0]);
for (int i = 0; i < versions_len; i++) {
int major = versions[i][0];
int minor = versions[i][1];
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
4,
major,
minor,
GHOST_OPENGL_EGL_CONTEXT_FLAGS |
(debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
@ -458,50 +474,31 @@ GHOST_IContext *GHOST_SystemX11::createOffscreenContext(GHOST_GLSettings glSetti
m_display,
(GLXFBConfig)NULL,
profile_mask,
4,
major,
minor,
GHOST_OPENGL_GLX_CONTEXT_FLAGS |
(debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
#endif
if (context->initializeDrawingContext())
return context;
else
if (context->initializeDrawingContext()) {
break;
}
else {
delete context;
context = nullptr;
}
}
if (prev_context) {
/* Restore previously bound context. This is just to follow the win32 behavior. */
#if defined(WITH_GL_EGL)
context = new GHOST_ContextEGL(this,
false,
EGLNativeWindowType(nullptr),
EGLNativeDisplayType(m_display),
profile_mask,
3,
3,
GHOST_OPENGL_EGL_CONTEXT_FLAGS |
(debug_context ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY,
EGL_OPENGL_API);
eglMakeCurrent(prev_display, prev_surface, prev_surface, prev_context);
#else
context = new GHOST_ContextGLX(false,
(Window)NULL,
m_display,
(GLXFBConfig)NULL,
profile_mask,
3,
3,
GHOST_OPENGL_GLX_CONTEXT_FLAGS |
(debug_context ? GLX_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_GLX_RESET_NOTIFICATION_STRATEGY);
glXMakeCurrent(prev_display, prev_drawable, prev_context);
#endif
if (context->initializeDrawingContext())
return context;
else
delete context;
return NULL;
}
return context;
}
/**