From 733dd3bb35b93bb2e616df920ca9b554d588f65c Mon Sep 17 00:00:00 2001 From: Christoph Caks Date: Mon, 11 Jan 2021 17:32:24 +0100 Subject: [PATCH] improved wgl context creation error handling --- .../src/main/cpp/driftgl/DriftGL.cpp | 13 ++ .../main/cpp/driftgl/win32/DriftGL_wgl.cpp | 198 ++++++++++++------ .../src/main/cpp/jni_GL.cpp | 10 + .../src/main/headers/DriftGL.h | 3 + .../org/eclipse/fx/drift/internal/GL.java | 4 +- 5 files changed, 166 insertions(+), 62 deletions(-) diff --git a/org.eclipse.fx.drift.native/src/main/cpp/driftgl/DriftGL.cpp b/org.eclipse.fx.drift.native/src/main/cpp/driftgl/DriftGL.cpp index 0d1699d..efda22e 100644 --- a/org.eclipse.fx.drift.native/src/main/cpp/driftgl/DriftGL.cpp +++ b/org.eclipse.fx.drift.native/src/main/cpp/driftgl/DriftGL.cpp @@ -10,4 +10,17 @@ * Christoph Caks - initial API and implementation * ******************************************************************************/ +#include +namespace driftgl { + + const char* lastError; + +} + +const char* driftgl::GetLastDriftGLError() { + return lastError; +} +void driftgl::SetLastDriftGLError(const char* errorMsg) { + lastError = errorMsg; +} \ No newline at end of file diff --git a/org.eclipse.fx.drift.native/src/main/cpp/driftgl/win32/DriftGL_wgl.cpp b/org.eclipse.fx.drift.native/src/main/cpp/driftgl/win32/DriftGL_wgl.cpp index 40a8622..d666b18 100644 --- a/org.eclipse.fx.drift.native/src/main/cpp/driftgl/win32/DriftGL_wgl.cpp +++ b/org.eclipse.fx.drift.native/src/main/cpp/driftgl/win32/DriftGL_wgl.cpp @@ -46,6 +46,11 @@ namespace driftgl { std::mutex knownContextsMutex; std::map knownContexts; + void logError(std::string message) { + // TODO send message to java based logger + std::cerr << "[C] " << message << std::endl; + } + void registerContext(HGLRC hglrc, Context* context) { knownContextsMutex.lock(); knownContexts[hglrc] = context; @@ -107,7 +112,8 @@ HWND CreateDriftGLWindow(HINSTANCE hInstance) { hInstance, NULL); // instance, param } -void SetupPixelFormat(HDC hDC) { +bool SetupPixelFormat(HDC hDC) { + bool success = false; int pixel_format_attribs[] = { WGL_SUPPORT_OPENGL_ARB, GL_TRUE, WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, @@ -116,12 +122,24 @@ void SetupPixelFormat(HDC hDC) { int pixel_format; UINT num_formats; - wglChoosePixelFormatARB(hDC, pixel_format_attribs, 0, 1, &pixel_format, &num_formats); + if (!wglChoosePixelFormatARB(hDC, pixel_format_attribs, 0, 1, &pixel_format, &num_formats)) { + return false; + } PIXELFORMATDESCRIPTOR pfd; - DescribePixelFormat(hDC, pixel_format, sizeof(pfd), &pfd); - BOOL result = SetPixelFormat(hDC, pixel_format, &pfd); - //std::cout << "SetPixelFormat: " << result << std::endl; + int index = DescribePixelFormat(hDC, pixel_format, sizeof(pfd), &pfd); + if (index > 0) { + if (SetPixelFormat(hDC, pixel_format, &pfd)) { + success = true; + } + else { + //SetPixelFormat() failed. + } + } + else { + //DescribePixelFormat() failed. + } + return success; } typedef HANDLE (* PFNWGLDXOPENDEVICENV) (void* dxDevice); @@ -171,6 +189,39 @@ bool wglDXUnlockObjectsNV(HANDLE hDevice, GLint count, HANDLE* hObjects) { bool wglDXSetResourceShareHandleNV(void* dxObject, HANDLE shareHandle) { return pfnWglDXSetResourceShareHandleNV(dxObject, shareHandle); } +typedef GLubyte* (*PFNGLGETSTRING) (GLenum name); +void showContextInfo(std::string name, PFNGLGETSTRING glGetString) { + std::cout << "[C] OpenGL Context information \"" << name << "\"" << std::endl; + std::cout << "[C] Version: " << glGetString(GL_VERSION) << std::endl; + std::cout << "[C] Vendor: " << glGetString(GL_VENDOR) << std::endl; + std::cout << "[C] Renderer: " << glGetString(GL_RENDERER) << std::endl; +} + +PROC doGetProcAddress(LPCSTR name) { + PROC proc = wglGetProcAddress(name); + //std::cout << " * " << name << ": " << proc << std::endl; + if (proc == 0) { + DWORD errWgl = GetLastError(); + // fallback for old functions on m$ + HMODULE hModuleGL = GetModuleHandle("opengl32"); + proc = GetProcAddress(hModuleGL, name); + if (proc == 0) { + DWORD errWin = GetLastError(); + //std::cout << " ! Could not acquire " << name << " (Error: " << errWgl << " / " << errWin << ")" << std::endl; + } + } + return proc; +} + + + +void debugCurrentContext(std::string name) { + PFNGLGETSTRING glGetString = (PFNGLGETSTRING)doGetProcAddress("glGetString"); + showContextInfo(name, glGetString); +} + +bool successContextCreationPointers = false; +bool successGLPointers = false; void doInitializeContextCreationPointers(HINSTANCE hInstance) { @@ -197,102 +248,127 @@ void doInitializeContextCreationPointers(HINSTANCE hInstance) { 0, 0, 0 }; int pf = ChoosePixelFormat(hDC, &pfd); - SetPixelFormat(hDC, pf, &pfd); - - HGLRC dummyContext = wglCreateContext(hDC); - BOOL c = wglMakeCurrent(hDC, dummyContext); - if (!c) { - // big error + if (pf != 0) { + if (SetPixelFormat(hDC, pf, &pfd) == true) { + HGLRC dummyContext = wglCreateContext(hDC); + if (dummyContext != 0) { + if (wglMakeCurrent(hDC, dummyContext) == true) { + + debugCurrentContext("Dummy Context"); + + // get the pointers + pfnWglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); + pfnWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + + if (pfnWglChoosePixelFormatARB != 0 && pfnWglCreateContextAttribsARB != 0) { + successContextCreationPointers = true; + } + else { + SetLastDriftGLError("failed to get proc address of 'wglChoosePixelFormatARB' and 'wglCreateContextAttribsARB' from the dummy context."); + } + + wglMakeCurrent(NULL, NULL); + } + else { + SetLastDriftGLError("failed to make the dummy opengl context current."); + } + wglDeleteContext(dummyContext); + } + else { + SetLastDriftGLError("failed to create a dummy opengl context."); + } + } + else { + SetLastDriftGLError("failed to set the pixel format during dummy context creation."); + } + } + else { + SetLastDriftGLError("failed to choose the pixel format during dummy context creation."); } - pfnWglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); - pfnWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); - - wglMakeCurrent(NULL, NULL); - wglDeleteContext(dummyContext); ReleaseDC(window, hDC); DestroyWindow(window); } -void InitializeContextCreationPointers(HINSTANCE hInstance) { +bool InitializeContextCreationPointers(HINSTANCE hInstance) { if (pfnWglChoosePixelFormatARB == 0) { // we do this on a different thread to prevent changes to the calling thread's current gl context std::thread initPointers(doInitializeContextCreationPointers, hInstance); initPointers.join(); - } + return successContextCreationPointers; } void doInitializeGLPointers(HINSTANCE hInstance) { HWND window = CreateDriftGLWindow(hInstance); HDC hDC = GetDC(window); - - //std::cout << "SetupPixelForm from Initialize" << std::endl; - SetupPixelFormat(hDC); - int attribList[] = { - WGL_CONTEXT_MAJOR_VERSION_ARB, 4, - WGL_CONTEXT_MINOR_VERSION_ARB, 5, - WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + if (SetupPixelFormat(hDC) == true) { + int attribList[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, 4, + WGL_CONTEXT_MINOR_VERSION_ARB, 5, + WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB, 0, - }; - HGLRC realContext = wglCreateContextAttribsARB(hDC, NULL, attribList); + }; + HGLRC realContext = wglCreateContextAttribsARB(hDC, NULL, attribList); + if (realContext != 0) { + if (wglMakeCurrent(hDC, realContext) == true) { - wglMakeCurrent(hDC, realContext); + debugCurrentContext("Function Pointer Resolving Context"); - PROC getString = wglGetProcAddress("glGetString"); - procs::Initialize([](const char* name) { - PROC proc = wglGetProcAddress(name); - //std::cout << " * " << name << ": " << proc << std::endl; - if (proc == 0) { - DWORD errWgl = GetLastError(); - // fallback for old functions on m$ - HMODULE hModuleGL = GetModuleHandle("opengl32"); - proc = GetProcAddress(hModuleGL, name); - if (proc == 0) { - DWORD errWin = GetLastError(); - //std::cout << " ! Could not acquire " << name << " (Error: " << errWgl << " / " << errWin << ")" << std::endl; + // init GL pointers + procs::Initialize([](const char* name) { return (void*)doGetProcAddress(name); }); + + // init NV_DX_interop pointers + pfnWglDXOpenDeviceNV = (PFNWGLDXOPENDEVICENV)wglGetProcAddress("wglDXOpenDeviceNV"); + pfnWglDXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENV)wglGetProcAddress("wglDXCloseDeviceNV"); + pfnWglDXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNV)wglGetProcAddress("wglDXRegisterObjectNV"); + pfnWglDXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNV)wglGetProcAddress("wglDXUnregisterObjectNV"); + pfnWglDXObjectAccessNV = (PFNWGLDXOBJECTACCESSNV)wglGetProcAddress("wglDXObjectAccessNV"); + pfnWglDXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNV)wglGetProcAddress("wglDXLockObjectsNV"); + pfnWglDXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNV)wglGetProcAddress("wglDXUnlockObjectsNV"); + pfnWglDXSetResourceShareHandleNV = (PFNWGLDXSETRESOURCESHAREHANDLENV)wglGetProcAddress("wglDXSetResourceShareHandleNV"); + + successGLPointers = true; + + wglMakeCurrent(NULL, NULL); + } + else { + SetLastDriftGLError("failed to make the function pointer resolving context current."); } + wglDeleteContext(realContext); } - return (void*)proc; - }); - - pfnWglDXOpenDeviceNV = (PFNWGLDXOPENDEVICENV)wglGetProcAddress("wglDXOpenDeviceNV"); - pfnWglDXCloseDeviceNV = (PFNWGLDXCLOSEDEVICENV)wglGetProcAddress("wglDXCloseDeviceNV"); - pfnWglDXRegisterObjectNV = (PFNWGLDXREGISTEROBJECTNV)wglGetProcAddress("wglDXRegisterObjectNV"); - pfnWglDXUnregisterObjectNV = (PFNWGLDXUNREGISTEROBJECTNV)wglGetProcAddress("wglDXUnregisterObjectNV"); - pfnWglDXObjectAccessNV = (PFNWGLDXOBJECTACCESSNV)wglGetProcAddress("wglDXObjectAccessNV"); - pfnWglDXLockObjectsNV = (PFNWGLDXLOCKOBJECTSNV)wglGetProcAddress("wglDXLockObjectsNV"); - pfnWglDXUnlockObjectsNV = (PFNWGLDXUNLOCKOBJECTSNV)wglGetProcAddress("wglDXUnlockObjectsNV"); - pfnWglDXSetResourceShareHandleNV = (PFNWGLDXSETRESOURCESHAREHANDLENV)wglGetProcAddress("wglDXSetResourceShareHandleNV"); - - //std::cout << "Initialze OpenGL Version: " << glGetString(GL_VERSION) << std::endl; - wglMakeCurrent(NULL, NULL); - //wglDeleteContext(dummyContext); - wglDeleteContext(realContext); + else { + SetLastDriftGLError("failed to create the function pointer resolving context."); + } + } + else { + SetLastDriftGLError("failed to setup the pixel format during function pointer resolving context creation."); + } ReleaseDC(window, hDC); DestroyWindow(window); } -void InitializeGLPointers(HINSTANCE hInstance) { +bool InitializeGLPointers(HINSTANCE hInstance) { // we do this on a different thread to prevent changes to the calling thread's current gl context std::thread initPointers(doInitializeGLPointers, hInstance); initPointers.join(); + return successGLPointers; } bool Initialize() { HINSTANCE hInstance = NULL; - InitializeContextCreationPointers(hInstance); - - InitializeGLPointers(hInstance); + if (!InitializeContextCreationPointers(hInstance)) { + return false; + } - return true; + return InitializeGLPointers(hInstance); } bool Destroy() { diff --git a/org.eclipse.fx.drift.native/src/main/cpp/jni_GL.cpp b/org.eclipse.fx.drift.native/src/main/cpp/jni_GL.cpp index d691a1b..61d3a3a 100644 --- a/org.eclipse.fx.drift.native/src/main/cpp/jni_GL.cpp +++ b/org.eclipse.fx.drift.native/src/main/cpp/jni_GL.cpp @@ -262,3 +262,13 @@ extern "C" JNIEXPORT void JNICALL Java_org_eclipse_fx_drift_internal_GL_glWaitSy glWaitSync(fence, 0, GL_TIMEOUT_IGNORED); } +extern "C" JNIEXPORT jstring JNICALL Java_org_eclipse_fx_drift_internal_GL_getLastDriftGLError(JNIEnv * env, jclass cls) { + + const char* lastError = driftgl::GetLastDriftGLError(); + + if (lastError == NULL) { + return 0; + } + + return env->NewStringUTF(lastError); +} diff --git a/org.eclipse.fx.drift.native/src/main/headers/DriftGL.h b/org.eclipse.fx.drift.native/src/main/headers/DriftGL.h index 2064b62..13ce0ee 100644 --- a/org.eclipse.fx.drift.native/src/main/headers/DriftGL.h +++ b/org.eclipse.fx.drift.native/src/main/headers/DriftGL.h @@ -35,6 +35,9 @@ namespace driftgl { DRIFTGL_EXPORT void* GetNativeContextHandle(Context* context); DRIFTGL_EXPORT Context* GetCurrentContext(); + + DRIFTGL_EXPORT const char* GetLastDriftGLError(); + DRIFTGL_EXPORT void SetLastDriftGLError(const char* errorMsg); } diff --git a/org.eclipse.fx.drift/src/main/java/org/eclipse/fx/drift/internal/GL.java b/org.eclipse.fx.drift/src/main/java/org/eclipse/fx/drift/internal/GL.java index 3fa9d90..d85caf3 100644 --- a/org.eclipse.fx.drift/src/main/java/org/eclipse/fx/drift/internal/GL.java +++ b/org.eclipse.fx.drift/src/main/java/org/eclipse/fx/drift/internal/GL.java @@ -19,7 +19,8 @@ private GL() {} DriftFX.require(); if (!initialize()) { // TODO throw exception in native code ? - throw new RuntimeException("Error during DriftGL initialization"); + String error = getLastDriftGLError(); + throw new RuntimeException("Error during DriftGL initialization: " + error); } } @@ -137,5 +138,6 @@ public static void require() {} public static native int glGetInteger(int pname); public static native float glGetFloat(int pname); + public static native String getLastDriftGLError(); }