From 920a67b1ac87a1fc728c9b40ff52b306d8a2cf90 Mon Sep 17 00:00:00 2001 From: Caspian Rychlik-Prince Date: Sat, 29 Mar 2003 21:52:14 +0000 Subject: [PATCH] Stuff for 0.6 --- src/java/org/lwjgl/Display.java | 29 +++-- src/native/common/org_lwjgl_Display.h | 12 +-- src/native/win32/Window.h | 5 + src/native/win32/org_lwjgl_Display.cpp | 141 +++++++++++++++++++++++-- src/native/win32/org_lwjgl_Window.cpp | 10 ++ 5 files changed, 174 insertions(+), 23 deletions(-) diff --git a/src/java/org/lwjgl/Display.java b/src/java/org/lwjgl/Display.java index 9e0abcdb..881cc838 100644 --- a/src/java/org/lwjgl/Display.java +++ b/src/java/org/lwjgl/Display.java @@ -201,19 +201,34 @@ public final class Display { /** * Obtains the display's gamma ramp. The gamma ramp returned is an array of - * integers in the range 0..255. If gamma is not supported by the underlying - * hardware then null is returned. - * @return an array of ints, or null + * 16:16 fixed point values representing 0.0...1.0. The gamma ramp consists of three consecutive + * arrays, one for red, one for green, and one for blue. The length of the + * array is 768 values (so red will be 0..255, green 256...511, and blue 512..767) + * + * If gamma is not supported by the underlying hardware then false is returned. + * + * @param red[] An array of ints to store red gamma in. Must be 256 in length. + * @param green[] An array of ints to store green gamma in. Must be 256 in length. + * @param blue[] An array of ints to store blue gamma in. Must be 256 in length. + * @return true if it succeeds, false if it fails */ - public static native int[] getGammaRamp(); + public static native boolean getGammaRamp(int[] red, int[] green, int[] blue); /** * Sets the display's gamma ramp. The gamma ramp should be an array of ints - * in the range 0...255. The length of the array should match the length of the - * array returned by getGammaRamp(). + * in 16:16 fixed point format, arranged as for getGammaRamp(). + * The length of the array must be 768. * * If the underlying hardware does not support gamma then this command is a no-op. + * + * When LWJGL exits, any gamma changes are automatically undone. + * + * @param red[] An array of ints to store red gamma in. Must be 256 in length. + * @param green[] An array of ints to store green gamma in. Must be 256 in length. + * @param blue[] An array of ints to store blue gamma in. Must be 256 in length. + * + * @return true if it succeeds, false if it fails */ - public static native void setGammaRamp(int[] gamma); + public static native boolean setGammaRamp(int[] red, int[] green, int[] blue); } diff --git a/src/native/common/org_lwjgl_Display.h b/src/native/common/org_lwjgl_Display.h index 94c0abb0..3b9e5d1b 100644 --- a/src/native/common/org_lwjgl_Display.h +++ b/src/native/common/org_lwjgl_Display.h @@ -62,18 +62,18 @@ JNIEXPORT jint JNICALL Java_org_lwjgl_Display_getPlatform /* * Class: org_lwjgl_Display * Method: getGammaRamp - * Signature: ()[I + * Signature: ([I[I[I)Z */ -JNIEXPORT jintArray JNICALL Java_org_lwjgl_Display_getGammaRamp - (JNIEnv *, jclass); +JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_getGammaRamp + (JNIEnv *, jclass, jintArray, jintArray, jintArray); /* * Class: org_lwjgl_Display * Method: setGammaRamp - * Signature: ([I)V + * Signature: ([I[I[I)Z */ -JNIEXPORT void JNICALL Java_org_lwjgl_Display_setGammaRamp - (JNIEnv *, jclass, jintArray); +JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_setGammaRamp + (JNIEnv *, jclass, jintArray, jintArray, jintArray); #ifdef __cplusplus } diff --git a/src/native/win32/Window.h b/src/native/win32/Window.h index edb60e12..d90573dd 100644 --- a/src/native/win32/Window.h +++ b/src/native/win32/Window.h @@ -88,4 +88,9 @@ */ WINDOW_H_API void throwException(JNIEnv * env, const char * err); + /* + * Utility function to throw a RuntimeException + */ + WINDOW_H_API void throwRuntimeException(JNIEnv * env, const char * err); + #endif /* _LWJGL_WINDOW_H_INCLUDED_ */ \ No newline at end of file diff --git a/src/native/win32/org_lwjgl_Display.cpp b/src/native/win32/org_lwjgl_Display.cpp index 487211f2..1a3e9c85 100644 --- a/src/native/win32/org_lwjgl_Display.cpp +++ b/src/native/win32/org_lwjgl_Display.cpp @@ -47,6 +47,7 @@ jobjectArray GetAvailableDisplayModesNT(JNIEnv * env); jobjectArray GetAvailableDisplayModes9x(JNIEnv * env); bool modeSet = false; // Whether we've done a display mode change +WORD* originalGamma = new WORD[256 * 3]; // Original gamma settings /* @@ -238,7 +239,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_setDisplayMode // class's mode instance variable. // Get the screen - HDC screenDC = CreateCompatibleDC(NULL); + HDC screenDC = GetDC(NULL); // Get the device caps width = GetDeviceCaps(screenDC, HORZRES); height = GetDeviceCaps(screenDC, VERTRES); @@ -246,7 +247,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_setDisplayMode freq = GetDeviceCaps(screenDC, VREFRESH); if (freq <= 1) freq = 0; // Unknown - DeleteDC(screenDC); + ReleaseDC(NULL, screenDC); jmethodID ctor = env->GetMethodID(cls_displayMode, "", "(IIII)V"); jobject newMode = env->NewObject(cls_displayMode, ctor, width, height, bpp, freq); @@ -265,6 +266,12 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_setDisplayMode JNIEXPORT void JNICALL Java_org_lwjgl_Display_resetDisplayMode (JNIEnv * env, jclass clazz) { + + // Return device gamma to normal + HDC screenDC = GetDC(NULL); + SetDeviceGammaRamp(screenDC, originalGamma); + ReleaseDC(NULL, screenDC); + if (modeSet) { modeSet = false; // Under Win32, all we have to do is: @@ -280,20 +287,127 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_resetDisplayMode * Method: getGammaRamp * Signature: ()[I */ -JNIEXPORT jintArray JNICALL Java_org_lwjgl_Display_getGammaRamp - (JNIEnv * env, jclass clazz) +JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_getGammaRamp + (JNIEnv * env, jclass clazz, jintArray red, jintArray green, jintArray blue) { - return NULL; +#ifdef _DEBUG + if (red == NULL) { + throwRuntimeException(env, "Null red array."); + return JNI_FALSE; + } + if (green == NULL) { + throwRuntimeException(env, "Null green array."); + return JNI_FALSE; + } + if (blue == NULL) { + throwRuntimeException(env, "Null blue array."); + return JNI_FALSE; + } + if (env->GetArrayLength(red) != 256) { + throwRuntimeException(env, "Red array is not 256 long."); + return JNI_FALSE; + } + if (env->GetArrayLength(green) != 256) { + throwRuntimeException(env, "Green array is not 256 long."); + return JNI_FALSE; + } + if (env->GetArrayLength(blue) != 256) { + throwRuntimeException(env, "Blue array is not 256 long."); + return JNI_FALSE; + } +#endif + + jint * redPtr = env->GetIntArrayElements(red, NULL); + jint * greenPtr = env->GetIntArrayElements(green, NULL); + jint * bluePtr = env->GetIntArrayElements(blue, NULL); + + WORD currentGamma[768]; + HDC screenDC = GetDC(NULL); + if (GetDeviceGammaRamp(screenDC, currentGamma) == FALSE) { +#ifdef _DEBUG + printf("Failed to get device gamma\n"); +#endif + env->ReleaseIntArrayElements(red, redPtr, JNI_ABORT); + env->ReleaseIntArrayElements(green, greenPtr, JNI_ABORT); + env->ReleaseIntArrayElements(blue, bluePtr, JNI_ABORT); + ReleaseDC(NULL, screenDC); + return JNI_FALSE; + } + ReleaseDC(NULL, screenDC); + for (int i = 0; i < 256; i ++) { + redPtr[i] = (jint) currentGamma[i]; + greenPtr[i] = (jint) currentGamma[i + 256]; + bluePtr[i] = (jint) currentGamma[i + 512]; + } + env->ReleaseIntArrayElements(red, redPtr, 0); + env->ReleaseIntArrayElements(green, greenPtr, 0); + env->ReleaseIntArrayElements(blue, bluePtr, 0); + return JNI_TRUE; } /* * Class: org_lwjgl_Display * Method: setGammaRamp - * Signature: ([I)V + * Signature: ([I[I[I)V */ -JNIEXPORT void JNICALL Java_org_lwjgl_Display_setGammaRamp - (JNIEnv * env, jclass clazz, jintArray gamma) +JNIEXPORT jboolean JNICALL Java_org_lwjgl_Display_setGammaRamp + (JNIEnv * env, jclass clazz, jintArray red, jintArray green, jintArray blue) { +#ifdef _DEBUG + if (red == NULL) { + throwRuntimeException(env, "Null red array."); + return JNI_FALSE; + } + if (green == NULL) { + throwRuntimeException(env, "Null green array."); + return JNI_FALSE; + } + if (blue == NULL) { + throwRuntimeException(env, "Null blue array."); + return JNI_FALSE; + } + if (env->GetArrayLength(red) != 256) { + throwRuntimeException(env, "Red array is not 256 long."); + return JNI_FALSE; + } + if (env->GetArrayLength(green) != 256) { + throwRuntimeException(env, "Green array is not 256 long."); + return JNI_FALSE; + } + if (env->GetArrayLength(blue) != 256) { + throwRuntimeException(env, "Blue array is not 256 long."); + return JNI_FALSE; + } +#endif + + jint * redPtr = env->GetIntArrayElements(red, NULL); + jint * greenPtr = env->GetIntArrayElements(green, NULL); + jint * bluePtr = env->GetIntArrayElements(blue, NULL); + + // Turn array of ints into array of RGB WORDs + WORD newGamma[768]; + for (int i = 0; i < 256; i ++) { + newGamma[i] = (WORD)(min(0x00010000, redPtr[i])); + newGamma[i + 256] = (WORD)(min(0x00010000, greenPtr[i])); + newGamma[i + 512] = (WORD)(min(0x00010000, bluePtr[i])); + } + jboolean ret; + HDC screenDC = GetDC(NULL); + if (SetDeviceGammaRamp(screenDC, newGamma) == FALSE) { +#ifdef _DEBUG + printf("Failed to set device gamma\n"); +#endif + ret = JNI_FALSE; + } else { + ret = JNI_TRUE; + } + ReleaseDC(NULL, screenDC); + + env->ReleaseIntArrayElements(red, redPtr, JNI_ABORT); + env->ReleaseIntArrayElements(green, greenPtr, JNI_ABORT); + env->ReleaseIntArrayElements(blue, bluePtr, JNI_ABORT); + + return ret; } @@ -307,7 +421,7 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_init { // Determine the current screen resolution // Get the screen - HDC screenDC = CreateCompatibleDC(NULL); + HDC screenDC = GetDC(NULL); if (!screenDC) { printf("Couldn't get screen DC!\n"); return; @@ -319,7 +433,6 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_init int freq = GetDeviceCaps(screenDC, VREFRESH); if (freq <= 1) freq = 0; // Unknown - DeleteDC(screenDC); jclass jclass_DisplayMode = env->FindClass("org/lwjgl/DisplayMode"); jmethodID ctor = env->GetMethodID(jclass_DisplayMode, "", "(IIII)V"); @@ -327,6 +440,14 @@ JNIEXPORT void JNICALL Java_org_lwjgl_Display_init jfieldID fid_initialMode = env->GetStaticFieldID(clazz, "mode", "Lorg/lwjgl/DisplayMode;"); env->SetStaticObjectField(clazz, fid_initialMode, newMode); env->DeleteLocalRef(newMode); + + // Get the default gamma ramp + if (GetDeviceGammaRamp(screenDC, originalGamma) == FALSE) { +#ifdef _DEBUG + printf("Failed to get initial device gamma\n"); +#endif + } + ReleaseDC(NULL, screenDC); } diff --git a/src/native/win32/org_lwjgl_Window.cpp b/src/native/win32/org_lwjgl_Window.cpp index a9948fc0..bab795ed 100644 --- a/src/native/win32/org_lwjgl_Window.cpp +++ b/src/native/win32/org_lwjgl_Window.cpp @@ -65,6 +65,16 @@ void throwException(JNIEnv * env, const char * err) env->DeleteLocalRef(cls); } +/* + * Utility function to throw a RuntimeException + */ +void throwRuntimeException(JNIEnv * env, const char * err) +{ + jclass cls = env->FindClass("java/lang/RuntimeException"); + env->ThrowNew(cls, err); + env->DeleteLocalRef(cls); +} + /* * Create DirectInput. * Returns true for success, or false for failure