Linux: Move gamma ramps to java code

This commit is contained in:
Elias Naur 2005-11-21 16:32:34 +00:00
parent c9669d20c9
commit debaaf6538
4 changed files with 120 additions and 90 deletions

View File

@ -44,6 +44,7 @@ import java.nio.IntBuffer;
import org.lwjgl.LWJGLException; import org.lwjgl.LWJGLException;
import org.lwjgl.LWJGLUtil; import org.lwjgl.LWJGLUtil;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
final class LinuxDisplay implements DisplayImplementation { final class LinuxDisplay implements DisplayImplementation {
@ -78,6 +79,28 @@ final class LinuxDisplay implements DisplayImplementation {
private static PeerInfo peer_info; private static PeerInfo peer_info;
/** Saved gamma used to restore display settings */
private static ByteBuffer saved_gamma;
private static ByteBuffer current_gamma;
private static ByteBuffer getCurrentGammaRamp() throws LWJGLException {
lockAWT();
try {
incDisplay();
try {
if (isXF86VidModeSupported())
return nGetCurrentGammaRamp();
else
return BufferUtils.createByteBuffer(0);
} finally {
decDisplay();
}
} finally {
unlockAWT();
}
}
private static native ByteBuffer nGetCurrentGammaRamp() throws LWJGLException;
private static int getBestDisplayModeExtension() throws LWJGLException { private static int getBestDisplayModeExtension() throws LWJGLException {
lockAWT(); lockAWT();
try { try {
@ -233,30 +256,55 @@ final class LinuxDisplay implements DisplayImplementation {
public void resetDisplayMode() { public void resetDisplayMode() {
lockAWT(); lockAWT();
try { try {
nResetDisplayMode(current_displaymode_extension); nResetDisplayMode(current_displaymode_extension, saved_gamma);
} finally { } finally {
unlockAWT(); unlockAWT();
} }
} }
private static native void nResetDisplayMode(int extension); private static native void nResetDisplayMode(int extension, ByteBuffer gamma_ramp);
public int getGammaRampLength() { public int getGammaRampLength() {
lockAWT(); lockAWT();
int length = nGetGammaRampLength(); try {
unlockAWT(); try {
return length; incDisplay();
int length;
if (isXF86VidModeSupported()) {
length = nGetGammaRampLength();
} else
length = 0;
decDisplay();
return length;
} catch (LWJGLException e) {
LWJGLUtil.log("Failed to get gamma ramp length: " + e);
return 0;
}
} finally {
unlockAWT();
}
} }
private static native int nGetGammaRampLength(); private static native int nGetGammaRampLength();
public void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException { public void setGammaRamp(FloatBuffer gammaRamp) throws LWJGLException {
lockAWT(); lockAWT();
try { try {
nSetGammaRamp(gammaRamp); incDisplay();
boolean xf86_support = isXF86VidModeSupported();
decDisplay();
if (!xf86_support)
throw new LWJGLException("No gamma ramp support (Missing XF86VM extension)");
current_gamma = convertToNativeRamp(gammaRamp);
nSetGammaRamp(current_gamma);
} finally { } finally {
unlockAWT(); unlockAWT();
} }
} }
private static native void nSetGammaRamp(FloatBuffer gammaRamp) throws LWJGLException; private static native void nSetGammaRamp(ByteBuffer gammaRamp) throws LWJGLException;
private static ByteBuffer convertToNativeRamp(FloatBuffer ramp) throws LWJGLException {
return nConvertToNativeRamp(ramp, ramp.position(), ramp.remaining());
}
private static native ByteBuffer nConvertToNativeRamp(FloatBuffer ramp, int offset, int length) throws LWJGLException;
public String getAdapter() { public String getAdapter() {
return null; return null;
@ -273,6 +321,8 @@ final class LinuxDisplay implements DisplayImplementation {
if (current_displaymode_extension == NONE) if (current_displaymode_extension == NONE)
throw new LWJGLException("No display mode extension is available"); throw new LWJGLException("No display mode extension is available");
DisplayMode mode = nInit(current_displaymode_extension); DisplayMode mode = nInit(current_displaymode_extension);
saved_gamma = getCurrentGammaRamp();
current_gamma = saved_gamma;
return mode; return mode;
} finally { } finally {
unlockAWT(); unlockAWT();
@ -327,10 +377,10 @@ final class LinuxDisplay implements DisplayImplementation {
public void update() { public void update() {
lockAWT(); lockAWT();
nUpdate(current_displaymode_extension, current_window_mode); nUpdate(current_displaymode_extension, current_window_mode, saved_gamma, current_gamma);
unlockAWT(); unlockAWT();
} }
private static native void nUpdate(int extension, int current_window_mode); private static native void nUpdate(int extension, int current_window_mode, ByteBuffer saved_gamma, ByteBuffer current_gamma);
public void reshape(int x, int y, int width, int height) { public void reshape(int x, int y, int width, int height) {
lockAWT(); lockAWT();

View File

@ -70,10 +70,6 @@ static int saved_freq;
static int current_width; static int current_width;
static int current_height; static int current_height;
static int current_freq; static int current_freq;
static int saved_gamma_ramp_length = 0;
static unsigned short *saved_ramp = NULL;
static unsigned short *current_ramp = NULL;
static int current_gamma_ramp_length = 0;
int getScreenModeWidth(void) { int getScreenModeWidth(void) {
return current_width; return current_width;
@ -281,18 +277,8 @@ static bool setMode(JNIEnv *env, Display *disp, int screen, jint extension, int
return result; return result;
} }
static void freeSavedGammaRamps() { int getGammaRampLengthOfDisplay(JNIEnv *env, Display *disp, int screen) {
free(saved_ramp);
saved_ramp = NULL;
saved_gamma_ramp_length = 0;
}
static int getGammaRampLengthOfDisplay(JNIEnv *env, Display *disp, int screen) {
int ramp_size; int ramp_size;
if (!isXF86VidModeSupported(env, disp)) {
printfDebugJava(env, "XF86VidMode extension version >= 2 not found");
return 0;
}
if (XF86VidModeGetGammaRampSize(disp, screen, &ramp_size) == False) { if (XF86VidModeGetGammaRampSize(disp, screen, &ramp_size) == False) {
printfDebugJava(env, "XF86VidModeGetGammaRampSize call failed"); printfDebugJava(env, "XF86VidModeGetGammaRampSize call failed");
return 0; return 0;
@ -300,15 +286,23 @@ static int getGammaRampLengthOfDisplay(JNIEnv *env, Display *disp, int screen) {
return ramp_size; return ramp_size;
} }
int getGammaRampLength(JNIEnv *env, int screen) { JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nConvertToNativeRamp(JNIEnv *env, jclass unused, jobject ramp_buffer, jint buffer_offset, jint length) {
Display *disp = XOpenDisplay(NULL); const jfloat *ramp_ptr = (const jfloat *)(*env)->GetDirectBufferAddress(env, ramp_buffer) + buffer_offset;
if (disp == NULL) { jobject native_ramp = newJavaManagedByteBuffer(env, length*3*sizeof(unsigned short));
printfDebugJava(env, "Could not open display"); if (native_ramp == NULL) {
return 0; throwException(env, "Failed to allocate gamma ramp buffer");
return NULL;
} }
int length = getGammaRampLengthOfDisplay(env, disp, screen); unsigned short *native_ramp_ptr = (unsigned short *)(*env)->GetDirectBufferAddress(env, native_ramp);
XCloseDisplay(disp); int i;
return length; for (i = 0; i < length; i++) {
float scaled_gamma = ramp_ptr[i]*0xffff;
short scaled_gamma_short = (unsigned short)round(scaled_gamma);
native_ramp_ptr[i] = scaled_gamma_short;
native_ramp_ptr[i + length] = scaled_gamma_short;
native_ramp_ptr[i + length*2] = scaled_gamma_short;
}
return native_ramp;
} }
jobject initDisplay(JNIEnv *env, int screen, jint extension) { jobject initDisplay(JNIEnv *env, int screen, jint extension) {
@ -337,38 +331,41 @@ jobject initDisplay(JNIEnv *env, int screen, jint extension) {
free(avail_modes); free(avail_modes);
/* Fetch the current gamma ramp */
saved_gamma_ramp_length = getGammaRampLengthOfDisplay(env, disp, screen);
if (saved_gamma_ramp_length > 0) {
saved_ramp = (unsigned short *)malloc(sizeof(unsigned short)*3*saved_gamma_ramp_length);
if (!XF86VidModeGetGammaRamp(disp, screen, saved_gamma_ramp_length, saved_ramp,
saved_ramp + saved_gamma_ramp_length, saved_ramp + saved_gamma_ramp_length*2))
freeSavedGammaRamps();
}
XCloseDisplay(disp); XCloseDisplay(disp);
return newMode; return newMode;
} }
static void freeCurrentGamma(void) { JNIEXPORT jobject JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetCurrentGammaRamp(JNIEnv *env, jclass unused) {
if (current_ramp != NULL) { int ramp_size = getGammaRampLengthOfDisplay(env, getDisplay(), getCurrentScreen());
free(current_ramp); jobject ramp_buffer = newJavaManagedByteBuffer(env, sizeof(unsigned short)*3*ramp_size);
current_ramp = NULL; if (ramp_buffer == NULL) {
current_gamma_ramp_length = 0; throwException(env, "Could not allocate gamma ramp buffer");
return NULL;
} }
unsigned short *ramp = (unsigned short *)(*env)->GetDirectBufferAddress(env, ramp_buffer);
if (!XF86VidModeGetGammaRamp(getDisplay(), getCurrentScreen(), ramp_size, ramp,
ramp + ramp_size, ramp + ramp_size*2)) {
throwException(env, "Could not get the current gamma ramp");
return NULL;
}
return ramp_buffer;
} }
static void setCurrentGamma(Display *disp, int screen, JNIEnv *env) { static void setGamma(JNIEnv *env, Display *disp, int screen, jobject ramp_buffer, bool throw_on_error) {
if (current_gamma_ramp_length == 0) unsigned short *ramp_ptr = (unsigned short *)(*env)->GetDirectBufferAddress(env, ramp_buffer);
jlong capacity = (*env)->GetDirectBufferCapacity(env, ramp_buffer);
int size = capacity/(sizeof(unsigned short)*3);
if (size == 0)
return; return;
if (XF86VidModeSetGammaRamp(disp, screen, current_gamma_ramp_length, current_ramp, current_ramp, current_ramp) == False) { if (XF86VidModeSetGammaRamp(disp, screen, size, ramp_ptr, ramp_ptr + size, ramp_ptr + size*2) == False) {
if (env != NULL) if (throw_on_error)
throwException(env, "Could not set gamma ramp."); throwException(env, "Could not set gamma ramp.");
else else
printfDebugJava(env, "Could not set gamma ramp"); printfDebugJava(env, "Could not set gamma ramp.");
} }
} }
void temporaryRestoreMode(JNIEnv *env, int screen, jint extension) { void temporaryRestoreMode(JNIEnv *env, int screen, jint extension, jobject saved_gamma_ramp) {
Display *disp = XOpenDisplay(NULL); Display *disp = XOpenDisplay(NULL);
if (disp == NULL) { if (disp == NULL) {
printfDebugJava(env, "Could not open display"); printfDebugJava(env, "Could not open display");
@ -376,9 +373,9 @@ void temporaryRestoreMode(JNIEnv *env, int screen, jint extension) {
} }
if (!setMode(env, disp, screen, extension, current_width, current_height, current_freq, false)) if (!setMode(env, disp, screen, extension, current_width, current_height, current_freq, false))
printfDebugJava(env, "Could not restore mode"); printfDebugJava(env, "Could not restore mode");
setCurrentGamma(disp, screen, NULL);
XCloseDisplay(disp);
// Don't propagate error to caller // Don't propagate error to caller
setGamma(env, disp, screen, saved_gamma_ramp, false);
XCloseDisplay(disp);
} }
void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension) { void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension) {
@ -403,7 +400,7 @@ void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension) {
XCloseDisplay(disp); XCloseDisplay(disp);
} }
void resetDisplayMode(JNIEnv *env, int screen, jint extension, bool temporary) { void resetDisplayMode(JNIEnv *env, int screen, jint extension, jobject gamma_ramp, bool temporary) {
Display *disp = XOpenDisplay(NULL); Display *disp = XOpenDisplay(NULL);
if (disp == NULL) { if (disp == NULL) {
printfDebugJava(env, "Failed to contact X Server"); printfDebugJava(env, "Failed to contact X Server");
@ -412,11 +409,7 @@ void resetDisplayMode(JNIEnv *env, int screen, jint extension, bool temporary) {
if (!setMode(env, disp, screen, extension, saved_width, saved_height, saved_freq, temporary)) { if (!setMode(env, disp, screen, extension, saved_width, saved_height, saved_freq, temporary)) {
printfDebugJava(env, "Failed to reset mode"); printfDebugJava(env, "Failed to reset mode");
} }
if (saved_gamma_ramp_length > 0) { setGamma(env, disp, screen, gamma_ramp, false);
XF86VidModeSetGammaRamp(disp, screen, saved_gamma_ramp_length, saved_ramp, saved_ramp +
saved_gamma_ramp_length, saved_ramp + saved_gamma_ramp_length*2);
}
// decDisplay();
XCloseDisplay(disp); XCloseDisplay(disp);
} }
@ -456,19 +449,6 @@ void setGammaRamp(JNIEnv *env, jobject gamma_ramp_buffer, int screen) {
throwException(env, "Could not open display"); throwException(env, "Could not open display");
return; return;
} }
freeCurrentGamma(); setGamma(env, disp, screen, gamma_ramp_buffer, true);
current_gamma_ramp_length = getGammaRampLengthOfDisplay(env, disp, screen);
if (current_gamma_ramp_length == 0) {
throwException(env, "Gamma ramp not supported");
return;
}
const float *gamma_ramp = (const float *)(*env)->GetDirectBufferAddress(env, gamma_ramp_buffer);
current_ramp = (unsigned short *)malloc(sizeof(unsigned short)*current_gamma_ramp_length);
int i;
for (i = 0; i < current_gamma_ramp_length; i++) {
float scaled_gamma = gamma_ramp[i]*0xffff;
current_ramp[i] = (unsigned short)round(scaled_gamma);
}
setCurrentGamma(disp, screen, env);
XCloseDisplay(disp); XCloseDisplay(disp);
} }

View File

@ -49,10 +49,10 @@ extern int getScreenModeWidth(void);
extern int getScreenModeHeight(void); extern int getScreenModeHeight(void);
extern jobject initDisplay(JNIEnv *env, int screen, jint extension); extern jobject initDisplay(JNIEnv *env, int screen, jint extension);
extern void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension); extern void switchDisplayMode(JNIEnv * env, jobject mode, int screen, jint extension);
extern void resetDisplayMode(JNIEnv *env, int screen, jint extension, bool temporary); extern void resetDisplayMode(JNIEnv *env, int screen, jint extension, jobject gamma_ramp, bool temporary);
extern jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen, jint extension); extern jobjectArray getAvailableDisplayModes(JNIEnv * env, int screen, jint extension);
extern int getGammaRampLength(JNIEnv *env, int screen); extern int getGammaRampLengthOfDisplay(JNIEnv *env, Display *disp, int screen);
extern void setGammaRamp(JNIEnv *env, jobject gamma_ramp_buffer, int screen); extern void setGammaRamp(JNIEnv *env, jobject gamma_ramp_buffer, int screen);
extern void temporaryRestoreMode(JNIEnv *env, int screen, jint extension); extern void temporaryRestoreMode(JNIEnv *env, int screen, jint extension, jobject gamma_ramp);
#endif #endif

View File

@ -182,7 +182,7 @@ static void setDecorations(int dec) {
XChangeProperty (getDisplay(), getCurrentWindow(), motif_hints_atom, motif_hints_atom, 32, PropModeReplace, (unsigned char *)&motif_hints, sizeof(MotifWmHints)/sizeof(long)); XChangeProperty (getDisplay(), getCurrentWindow(), motif_hints_atom, motif_hints_atom, 32, PropModeReplace, (unsigned char *)&motif_hints, sizeof(MotifWmHints)/sizeof(long));
} }
static bool releaseInput(JNIEnv *env, jint extension, jint window_mode) { static bool releaseInput(JNIEnv *env, jint extension, jint window_mode, jobject gamma_ramp) {
if (isLegacyFullscreen(window_mode) || input_released) if (isLegacyFullscreen(window_mode) || input_released)
return false; return false;
input_released = true; input_released = true;
@ -190,19 +190,19 @@ static bool releaseInput(JNIEnv *env, jint extension, jint window_mode) {
updateInputGrab(window_mode); updateInputGrab(window_mode);
if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) { if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) {
XIconifyWindow(getDisplay(), getCurrentWindow(), getCurrentScreen()); XIconifyWindow(getDisplay(), getCurrentWindow(), getCurrentScreen());
resetDisplayMode(env, getCurrentScreen(), extension, true); resetDisplayMode(env, getCurrentScreen(), extension, gamma_ramp, true);
} }
return true; return true;
} }
static void acquireInput(JNIEnv *env, jint extension, jint window_mode) { static void acquireInput(JNIEnv *env, jint extension, jint window_mode, jobject gamma_ramp) {
if (isLegacyFullscreen(window_mode) || !input_released) if (isLegacyFullscreen(window_mode) || !input_released)
return; return;
input_released = false; input_released = false;
setRepeatMode(env, AutoRepeatModeOff); setRepeatMode(env, AutoRepeatModeOff);
updateInputGrab(window_mode); updateInputGrab(window_mode);
if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) { if (window_mode == org_lwjgl_opengl_LinuxDisplay_FULLSCREEN_NETWM) {
temporaryRestoreMode(env, getCurrentScreen(), extension); temporaryRestoreMode(env, getCurrentScreen(), extension, gamma_ramp);
} }
} }
@ -229,20 +229,20 @@ void setGrab(jint window_mode, bool new_grab) {
} }
} }
static void checkInput(JNIEnv *env, jint extension, jint window_mode) { static void checkInput(JNIEnv *env, jint extension, jint window_mode, jobject saved_gamma, jobject current_gamma) {
Window win; Window win;
int revert_mode; int revert_mode;
XGetInputFocus(getDisplay(), &win, &revert_mode); XGetInputFocus(getDisplay(), &win, &revert_mode);
if (win == current_win) { if (win == current_win) {
acquireInput(env, extension, window_mode); acquireInput(env, extension, window_mode, current_gamma);
focused = true; focused = true;
} else { } else {
releaseInput(env, extension, window_mode); releaseInput(env, extension, window_mode, saved_gamma);
focused = false; focused = false;
} }
} }
void handleMessages(JNIEnv *env, jint extension, jint window_mode) { void handleMessages(JNIEnv *env, jint extension, jint window_mode, jobject saved_gamma, jobject current_gamma) {
XEvent event; XEvent event;
/* Window win; /* Window win;
int revert_mode;*/ int revert_mode;*/
@ -293,7 +293,7 @@ void handleMessages(JNIEnv *env, jint extension, jint window_mode) {
break; break;
} }
} }
checkInput(env, extension, window_mode); checkInput(env, extension, window_mode, saved_gamma, current_gamma);
} }
static void setWindowTitle(const char *title) { static void setWindowTitle(const char *title) {
@ -454,9 +454,9 @@ int getWindowHeight(void) {
} }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUpdate JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nUpdate
(JNIEnv *env, jclass clazz, jint extension, jint window_mode) (JNIEnv *env, jclass clazz, jint extension, jint window_mode, jobject saved_gamma, jobject current_gamma)
{ {
handleMessages(env, extension, window_mode); handleMessages(env, extension, window_mode, saved_gamma, current_gamma);
} }
JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableDisplayModes(JNIEnv *env, jclass clazz, jint extension) { JNIEXPORT jobjectArray JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetAvailableDisplayModes(JNIEnv *env, jclass clazz, jint extension) {
@ -467,12 +467,12 @@ JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSwitchDisplayMode(JNI
switchDisplayMode(env, mode, getCurrentScreen(), extension); switchDisplayMode(env, mode, getCurrentScreen(), extension);
} }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nResetDisplayMode(JNIEnv *env, jclass clazz, jint extension) { JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nResetDisplayMode(JNIEnv *env, jclass clazz, jint extension, jobject gamma_ramp) {
resetDisplayMode(env, getCurrentScreen(), extension, false); resetDisplayMode(env, getCurrentScreen(), extension, gamma_ramp, false);
} }
JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jclass clazz) { JNIEXPORT jint JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nGetGammaRampLength(JNIEnv *env, jclass clazz) {
return (jint)getGammaRampLength(env, getCurrentScreen()); return (jint)getGammaRampLengthOfDisplay(env, getDisplay(), getCurrentScreen());
} }
JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv *env, jclass clazz, jobject gamma_buffer) { JNIEXPORT void JNICALL Java_org_lwjgl_opengl_LinuxDisplay_nSetGammaRamp(JNIEnv *env, jclass clazz, jobject gamma_buffer) {