GHOST: Optimize and simplify the creation of a GHOST_Context on Windows

Instead of cloning the window to create dummyHWNDs and dummyHDCs to avoid calling the SetPixelFormat more than once in the same window, use the original window and HDC and do not call the SetPixelFormat again.

In addition to avoiding a lot of unnecessary calls, it simplifies the code and makes it match the others OS
This commit is contained in:
Germano Cavalcante 2018-02-10 00:32:13 -02:00
parent 832f7a6648
commit 0bf615fc24
Notes: blender-bot 2023-02-14 06:37:09 +01:00
Referenced by issue #54070, eevee don't render on other windows
Referenced by issue #54064, Cycles / 2.8: Cant create new materials
3 changed files with 63 additions and 165 deletions

View File

@ -745,60 +745,57 @@ static void reportContextString(const char *name, const char *dummy, const char
GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
{
const bool needAlpha = m_alphaBackground;
SetLastError(NO_ERROR);
HGLRC prevHGLRC = ::wglGetCurrentContext();
WIN32_CHK(GetLastError() == NO_ERROR);
HDC prevHDC = ::wglGetCurrentDC();
WIN32_CHK(GetLastError() == NO_ERROR);
if (!WGLEW_ARB_create_context || ::GetPixelFormat(m_hDC) == 0) {
const bool needAlpha = m_alphaBackground;
#ifdef GHOST_OPENGL_STENCIL
const bool needStencil = true;
const bool needStencil = true;
#else
const bool needStencil = false;
const bool needStencil = false;
#endif
#ifdef GHOST_OPENGL_SRGB
const bool sRGB = true;
const bool sRGB = true;
#else
const bool sRGB = false;
const bool sRGB = false;
#endif
int iPixelFormat;
int lastPFD;
HGLRC prevHGLRC;
HDC prevHDC;
PIXELFORMATDESCRIPTOR chosenPFD;
int iPixelFormat;
int lastPFD;
iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);
PIXELFORMATDESCRIPTOR chosenPFD;
if (iPixelFormat == 0) {
::wglMakeCurrent(prevHDC, prevHGLRC);
return GHOST_kFailure;
}
lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
SetLastError(NO_ERROR);
if (!WIN32_CHK(lastPFD != 0)) {
::wglMakeCurrent(prevHDC, prevHGLRC);
return GHOST_kFailure;
}
prevHGLRC = ::wglGetCurrentContext();
WIN32_CHK(GetLastError() == NO_ERROR);
if (needAlpha && chosenPFD.cAlphaBits == 0)
fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
prevHDC = ::wglGetCurrentDC();
WIN32_CHK(GetLastError() == NO_ERROR);
if (needStencil && chosenPFD.cStencilBits == 0)
fprintf(stderr, "Warning! Unable to find a pixel format with a stencil buffer.\n");
iPixelFormat = choose_pixel_format(m_stereoVisual, m_numOfAASamples, needAlpha, needStencil, sRGB);
if (iPixelFormat == 0) {
::wglMakeCurrent(prevHDC, prevHGLRC);
return GHOST_kFailure;
}
lastPFD = ::DescribePixelFormat(m_hDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &chosenPFD);
if (!WIN32_CHK(lastPFD != 0)) {
::wglMakeCurrent(prevHDC, prevHGLRC);
return GHOST_kFailure;
}
if (needAlpha && chosenPFD.cAlphaBits == 0)
fprintf(stderr, "Warning! Unable to find a pixel format with an alpha channel.\n");
if (needStencil && chosenPFD.cStencilBits == 0)
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;
if (!WIN32_CHK(::SetPixelFormat(m_hDC, iPixelFormat, &chosenPFD))) {
::wglMakeCurrent(prevHDC, prevHGLRC);
return GHOST_kFailure;
}
}
if (WGLEW_ARB_create_context) {
@ -909,9 +906,11 @@ GHOST_TSuccess GHOST_ContextWGL::initializeDrawingContext()
const char *version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
#ifndef NDEBUG
reportContextString("Vendor", m_dummyVendor, vendor);
reportContextString("Renderer", m_dummyRenderer, renderer);
reportContextString("Version", m_dummyVersion, version);
if (m_dummyVendor != NULL) {
reportContextString("Vendor", m_dummyVendor, vendor);
reportContextString("Renderer", m_dummyRenderer, renderer);
reportContextString("Version", m_dummyVersion, version);
}
#endif
return GHOST_kSuccess;
@ -927,97 +926,3 @@ GHOST_TSuccess GHOST_ContextWGL::releaseNativeHandles()
return success;
}
/**
* For any given HDC you may call SetPixelFormat once
*
* So we better try to get the correct OpenGL version in a new window altogether, in case it fails.
* (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd369049(v=vs.85).aspx)
*/
static bool TryOpenGLVersion(
HWND hwnd,
bool wantStereoVisual,
bool wantAlphaBackground,
GHOST_TUns16 wantNumOfAASamples,
int contextProfileMask,
bool debugContext,
int major, int minor)
{
HWND dummyHWND = clone_window(hwnd, NULL);
if (dummyHWND == NULL) {
return false;
}
HDC dummyHDC = GetDC(dummyHWND);
if (dummyHDC == NULL) {
return false;
}
GHOST_ContextWGL * context = new GHOST_ContextWGL(
wantStereoVisual,
wantAlphaBackground,
wantNumOfAASamples,
dummyHWND,
dummyHDC,
contextProfileMask,
major, minor,
(debugContext ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
bool result = context->initializeDrawingContext();
delete context;
ReleaseDC(dummyHWND, dummyHDC);
DestroyWindow(dummyHWND);
return result;
}
GHOST_TSuccess GHOST_ContextWGL::getMaximumSupportedOpenGLVersion(
HWND hwnd,
bool wantStereoVisual,
bool wantAlphaBackground,
GHOST_TUns16 wantNumOfAASamples,
int contextProfileMask,
bool debugContext,
GHOST_TUns8 *r_major_version,
GHOST_TUns8 *r_minor_version)
{
/* - AMD and Intel give us exactly this version
* - NVIDIA gives at least this version <-- desired behavior
* So we ask for 4.5, 4.4 ... 3.3 in descending order to get the best version on the user's system. */
for (int minor = 5; minor >= 0; --minor) {
if (TryOpenGLVersion(
hwnd,
wantStereoVisual,
wantAlphaBackground,
wantNumOfAASamples,
contextProfileMask,
debugContext,
4, minor))
{
*r_major_version = 4;
*r_minor_version = minor;
return GHOST_kSuccess;
}
}
/* Fallback to OpenGL 3.3 */
if (TryOpenGLVersion(
hwnd,
wantStereoVisual,
wantAlphaBackground,
wantNumOfAASamples,
contextProfileMask,
debugContext,
3, 3))
{
*r_major_version = 3;
*r_minor_version = 3;
return GHOST_kSuccess;
}
*r_major_version = 0;
*r_minor_version = 0;
return GHOST_kFailure;
}

View File

@ -105,20 +105,6 @@ public:
*/
GHOST_TSuccess getSwapInterval(int &intervalOut);
/**
* Gets the maximum supported OpenGL context for the user hardware
* \return Whether major_version and minor_version resulted in a valid context.
*/
static GHOST_TSuccess getMaximumSupportedOpenGLVersion(
HWND hwnd,
bool wantStereoVisual,
bool wantAlphaBackground,
GHOST_TUns16 wantNumOfAASamples,
int contextProfileMask,
bool debugContext,
GHOST_TUns8 *r_major_version,
GHOST_TUns8 *r_minor_version);
private:
int choose_pixel_format(
bool stereoVisual,

View File

@ -622,17 +622,10 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
GHOST_Context *context;
#if defined(WITH_GL_PROFILE_CORE)
GHOST_TUns8 major, minor;
if (GHOST_ContextWGL::getMaximumSupportedOpenGLVersion(
m_hWnd,
m_wantStereoVisual,
m_wantAlphaBackground,
m_wantNumOfAASamples,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
m_debug_context,
&major, &minor))
{
/* - AMD and Intel give us exactly this version
* - NVIDIA gives at least this version <-- desired behavior
* So we ask for 4.5, 4.4 ... 3.3 in descending order to get the best version on the user's system. */
for (int minor = 5; minor >= 0; --minor) {
context = new GHOST_ContextWGL(
m_wantStereoVisual,
m_wantAlphaBackground,
@ -640,7 +633,7 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
m_hWnd,
m_hDC,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
major, minor,
4, minor,
(m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
@ -651,6 +644,20 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
delete context;
}
}
context = new GHOST_ContextWGL(
m_wantStereoVisual,
m_wantAlphaBackground,
m_wantNumOfAASamples,
m_hWnd,
m_hDC,
WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
3, 3,
(m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
if (context->initializeDrawingContext()) {
return context;
}
else {
MessageBox(
m_hWnd,
@ -658,8 +665,8 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
"The program will now close.",
"Blender - Unsupported Graphics Driver!",
MB_OK | MB_ICONERROR);
delete context;
exit(0);
return NULL;
}
#elif defined(WITH_GL_PROFILE_COMPAT)
@ -675,9 +682,6 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
2, 1,
(m_debug_context ? WGL_CONTEXT_DEBUG_BIT_ARB : 0),
GHOST_OPENGL_WGL_RESET_NOTIFICATION_STRATEGY);
#else
# error // must specify either core or compat at build time
#endif
if (context->initializeDrawingContext()) {
return context;
@ -685,6 +689,9 @@ GHOST_Context *GHOST_WindowWin32::newDrawingContext(GHOST_TDrawingContextType ty
else {
delete context;
}
#else
# error // must specify either core or compat at build time
#endif
}
return NULL;