diff --git a/src/java/org/lwjgl/opengl/Display.java b/src/java/org/lwjgl/opengl/Display.java index 596de68d..6d9a50cd 100644 --- a/src/java/org/lwjgl/opengl/Display.java +++ b/src/java/org/lwjgl/opengl/Display.java @@ -508,19 +508,29 @@ public final class Display { throw new IllegalStateException("Only one LWJGL context may be instantiated at any one time."); if (fullscreen) switchDisplayMode(current_mode); - createContext(pixel_format); - context = new Display(); try { - createWindow(); + GLContext.loadOpenGLLibrary(); + try { + createContext(pixel_format); + try { + context = new Display(); + createWindow(); + makeCurrent(); + initContext(); + } catch (LWJGLException e) { + destroyContext(); + context = null; + throw e; + } + } catch (LWJGLException e) { + GLContext.unloadOpenGLLibrary(); + throw e; + } } catch (LWJGLException e) { - destroyContext(); - context = null; if (fullscreen) resetDisplayMode(); throw e; } - makeCurrent(); - initContext(); } /** @@ -595,6 +605,7 @@ public final class Display { destroyWindow(); destroyContext(); + GLContext.unloadOpenGLLibrary(); context = null; try { GLContext.useContext(null); diff --git a/src/java/org/lwjgl/opengl/GLContext.java b/src/java/org/lwjgl/opengl/GLContext.java index 6c80a983..b61ba93e 100644 --- a/src/java/org/lwjgl/opengl/GLContext.java +++ b/src/java/org/lwjgl/opengl/GLContext.java @@ -183,6 +183,8 @@ public final class GLContext { /** Map of classes that have native stubs loaded */ private static Map exts; + private static int gl_ref_count = 0; + private static boolean did_auto_load = false; static { Sys.initialize(); @@ -228,6 +230,8 @@ public final class GLContext { public static synchronized void useContext(Object context) throws LWJGLException { if (context == null) { unloadStubs(); + if (did_auto_load) + unloadOpenGLLibrary(); return; } // Is this the same as last time? @@ -238,11 +242,19 @@ public final class GLContext { } // Ok, now it's the current context. - loadOpenGLLibrary(); - GL11.initNativeStubs(); - loadStubs(); - currentContext = new WeakReference(context); - VBOTracker.setCurrent(currentContext); + if (gl_ref_count == 0) { + loadOpenGLLibrary(); + did_auto_load = true; + } + try { + GL11.initNativeStubs(); + loadStubs(); + currentContext = new WeakReference(context); + VBOTracker.setCurrent(currentContext); + } catch (LWJGLException e) { + if (did_auto_load) + unloadOpenGLLibrary(); + } } private static void getExtensionClassesAndNames(Map exts, Set exts_names) { @@ -338,9 +350,28 @@ public final class GLContext { } /** - * Native method to load the OpenGL library + * If the OpenGL reference count is 0, the library is loaded. The + * reference count is then incremented. */ - private static native void loadOpenGLLibrary(); + public static void loadOpenGLLibrary() throws LWJGLException { + if (gl_ref_count == 0) + nLoadOpenGLLibrary(); + gl_ref_count++; + } + + private static native void nLoadOpenGLLibrary() throws LWJGLException; + + /** + * The OpenGL library reference count is decremented, and if it + * reaches 0, the library is unloaded. + */ + public static void unloadOpenGLLibrary() { + gl_ref_count--; + if (gl_ref_count == 0) + nUnloadOpenGLLibrary(); + } + + private static native void nUnloadOpenGLLibrary(); /** * Native method to clear native stub bindings diff --git a/src/java/org/lwjgl/test/opengl/PbufferTest.java b/src/java/org/lwjgl/test/opengl/PbufferTest.java index 1be0886a..033f2d31 100644 --- a/src/java/org/lwjgl/test/opengl/PbufferTest.java +++ b/src/java/org/lwjgl/test/opengl/PbufferTest.java @@ -97,6 +97,7 @@ public class PbufferTest { private void initialize() { try { //find displaymode + pbuffer = new Pbuffer(512, 512, new PixelFormat(), null); mode = findDisplayMode(800, 600, 16); Display.setDisplayMode(mode); // start of in windowed mode @@ -175,7 +176,12 @@ public class PbufferTest { if (pbuffer.isBufferLost()) { System.out.println("Buffer contents lost - will recreate the buffer"); pbuffer.destroy(); - initPbuffer(); + try { + pbuffer = new Pbuffer(512, 512, new PixelFormat(), null); + initPbuffer(); + } catch (LWJGLException e) { + e.printStackTrace(); + } } try { pbuffer.makeCurrent(); @@ -235,7 +241,6 @@ public class PbufferTest { private void initPbuffer() { try { - pbuffer = new Pbuffer(512, 512, new PixelFormat(), null); pbuffer.makeCurrent(); initGLState(256, 256, 0.5f); GL11.glBindTexture(GL11.GL_TEXTURE_2D, tex_handle); diff --git a/src/native/common/org_lwjgl_opengl_GLContext.cpp b/src/native/common/org_lwjgl_opengl_GLContext.cpp index db462297..1a383620 100644 --- a/src/native/common/org_lwjgl_opengl_GLContext.cpp +++ b/src/native/common/org_lwjgl_opengl_GLContext.cpp @@ -34,13 +34,17 @@ #include "extgl.h" #include "common_tools.h" -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_loadOpenGLLibrary(JNIEnv * env, jclass clazz) { +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_nLoadOpenGLLibrary(JNIEnv * env, jclass clazz) { if (!extgl_Open()) { throwException(env, "Failed to load OpenGL library"); return; } } +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_nUnloadOpenGLLibrary(JNIEnv * env, jclass clazz) { + extgl_Close(); +} + JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_resetNativeStubs(JNIEnv *env, jclass clazz, jclass gl_class) { env->UnregisterNatives(gl_class); } diff --git a/src/native/common/org_lwjgl_opengl_GLContext.h b/src/native/common/org_lwjgl_opengl_GLContext.h index 58bec9ab..7ae822e4 100644 --- a/src/native/common/org_lwjgl_opengl_GLContext.h +++ b/src/native/common/org_lwjgl_opengl_GLContext.h @@ -120,15 +120,25 @@ extern "C" { /* Inaccessible static: OpenGL13 */ /* Inaccessible static: OpenGL14 */ /* Inaccessible static: OpenGL15 */ -/* Inaccessible static: extension_classes */ -/* Inaccessible static: class_00024org_00024lwjgl_00024opengl_00024GL12 */ +/* Inaccessible static: exts */ +/* Inaccessible static: gl_ref_count */ +/* Inaccessible static: did_auto_load */ /* Inaccessible static: class_00024org_00024lwjgl_00024opengl_00024GLContext */ +/* Inaccessible static: class_00024org_00024lwjgl_00024opengl_00024GL11 */ /* * Class: org_lwjgl_opengl_GLContext - * Method: loadOpenGLLibrary + * Method: nLoadOpenGLLibrary * Signature: ()V */ -JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_loadOpenGLLibrary +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_nLoadOpenGLLibrary + (JNIEnv *, jclass); + +/* + * Class: org_lwjgl_opengl_GLContext + * Method: nUnloadOpenGLLibrary + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_org_lwjgl_opengl_GLContext_nUnloadOpenGLLibrary (JNIEnv *, jclass); /* diff --git a/src/native/linux/org_lwjgl_opengl_Display.cpp b/src/native/linux/org_lwjgl_opengl_Display.cpp index 989a8194..0114a447 100644 --- a/src/native/linux/org_lwjgl_opengl_Display.cpp +++ b/src/native/linux/org_lwjgl_opengl_Display.cpp @@ -520,7 +520,6 @@ static void destroyContext(void) { context = NULL; setRepeatMode(AutoRepeatModeDefault); decDisplay(); - extgl_Close(); } static bool initWindowGLX13(JNIEnv *env, jobject pixel_format) { @@ -618,17 +617,12 @@ JNIEXPORT jstring JNICALL Java_org_lwjgl_opengl_Display_getVersion(JNIEnv *env, } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Display_createContext(JNIEnv *env, jclass clazz, jobject pixel_format) { - if (!extgl_Open()) { - throwException(env, "Could not load gl libs"); - return; - } Display *disp = incDisplay(env); if (disp == NULL) return; current_screen = XDefaultScreen(disp); if (!extgl_InitGLX(env, disp, current_screen)) { decDisplay(); - extgl_Close(); throwException(env, "Could not init GLX"); return; } @@ -640,7 +634,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Display_createContext(JNIEnv *env, } if (!create_success) { decDisplay(); - extgl_Close(); return; } } diff --git a/src/native/macosx/org_lwjgl_opengl_Window.cpp b/src/native/macosx/org_lwjgl_opengl_Window.cpp index bd19219e..9b69911a 100644 --- a/src/native/macosx/org_lwjgl_opengl_Window.cpp +++ b/src/native/macosx/org_lwjgl_opengl_Window.cpp @@ -59,7 +59,6 @@ static void destroy(JNIEnv *env, jclass clazz) { CGLSetCurrentContext(NULL); CGLDestroyContext(context); destroyMode(env, clazz); - extgl_Close(); } static bool createFullscreenContext(JNIEnv *env, jint bpp, jint alpha, jint depth, jint stencil) { @@ -114,10 +113,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nMakeCurrent JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass clazz, jstring title, jint x, jint y, jint width, jint height, jboolean fullscreen, jint bpp, jint alpha, jint depth, jint stencil, jint samples) { vsync_enabled = false; current_fullscreen = fullscreen == JNI_TRUE; - if (!extgl_Open()) { - throwException(env, "Could not load gl library"); - return; - } if (!extgl_InitAGL(env)) { throwException(env, "Could not load agl symbols"); return; @@ -125,14 +120,12 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Window_nCreate(JNIEnv *env, jclass if (!current_fullscreen) { if (!switchToNearestMode(env, width, height, bpp, 60)) { destroyMode(env, clazz); - extgl_Close(); throwException(env, "Could not switch mode."); return; } } if (!createFullscreenContext(env, bpp, alpha, depth, stencil)) { destroyMode(env, clazz); - extgl_Close(); return; } FlushEventQueue(GetMainEventQueue()); diff --git a/src/native/win32/org_lwjgl_opengl_Display.cpp b/src/native/win32/org_lwjgl_opengl_Display.cpp index a14a3a0a..7f09c25d 100644 --- a/src/native/win32/org_lwjgl_opengl_Display.cpp +++ b/src/native/win32/org_lwjgl_opengl_Display.cpp @@ -674,11 +674,6 @@ JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_Display_init(JNIEnv *env, jclass } JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Display_createContext(JNIEnv *env, jclass clazz, jobject pixel_format) { - if (!extgl_Open()) { - throwException(env, "Failed to open extgl"); - return; - } - // 1. Register window class if necessary if (!registerWindow()) { throwException(env, "Could not register window class"); @@ -686,25 +681,21 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Display_createContext(JNIEnv *env, } if (!createWindow(env, 1, 1, false, false)) { - extgl_Close(); return; } pixel_format_index = findPixelFormat(env, pixel_format); if (pixel_format_index == -1) { - extgl_Close(); return; } // Special option for allowing software opengl if (!applyPixelFormat(env, hdc, pixel_format_index)) { closeWindow(); - extgl_Close(); return; } hglrc = wglCreateContext(hdc); if (hglrc == NULL) { throwException(env, "Failed to create OpenGL rendering context"); - extgl_Close(); return; } BOOL result = wglMakeCurrent(hdc, hglrc); @@ -724,23 +715,19 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Display_createContext(JNIEnv *env, wglDeleteContext(hglrc); closeWindow(); if (pixel_format_index == -1) { - extgl_Close(); return; } if (!createWindow(env, 1, 1, false, false)) { - extgl_Close(); return; } if (!applyPixelFormat(env, hdc, pixel_format_index)) { closeWindow(); - extgl_Close(); return; } hglrc = wglCreateContext(hdc); closeWindow(); if (hglrc == NULL) { throwException(env, "Failed to create OpenGL rendering context (ARB)"); - extgl_Close(); return; } } else @@ -756,5 +743,4 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_Display_destroyContext(JNIEnv *env, wglDeleteContext(hglrc); hglrc = NULL; } - extgl_Close(); }