From 29891baca2427483f96e6d1a8c3b13892ba5facc Mon Sep 17 00:00:00 2001 From: Rami Santina Date: Wed, 20 Oct 2010 16:26:45 +0300 Subject: Added Windows Impl for ScreenMode and rotation change; Windows Fullscreen Hint Added windows implemenation for screen mode change lifecycle and screen rotation screen modes. +++++++++++ Added getHighestAvailableRate() to Screen mode as a helper function which loops over the available rates of this screen mode and returns the highest available. Added toString impl to ScreenMode. +++++++++++ Unit Tests: TestScreenMode01NEWT,TestScreenMode02NEWT are modified adding the gears as GL event listeners. +++++++++++ Notes: 1- Screen modes with bits per pixel values not same as current are currently filtered out. 2- Since windows stores the Display settings differently you will see some duplicate values which the documentation says is usual. These modes are not filtered out in getScreenModes(). Keeping values same as provided from windows enum. 3- BitsPerPixel is currently natively read on windows only. --- .../test/junit/newt/TestScreenMode01NEWT.java | 78 +++--- .../test/junit/newt/TestScreenMode02NEWT.java | 8 +- .../classes/com/jogamp/newt/impl/ScreenMode.java | 37 ++- .../classes/com/jogamp/newt/impl/WindowImpl.java | 2 +- .../jogamp/newt/impl/windows/WindowsScreen.java | 157 +++++++++++- .../jogamp/newt/impl/windows/WindowsWindow.java | 4 +- src/newt/native/WindowsWindow.c | 263 ++++++++++++++++++++- 7 files changed, 495 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java b/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java index 5dbc56c7d..a3da32bd3 100644 --- a/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java +++ b/src/junit/com/jogamp/test/junit/newt/TestScreenMode01NEWT.java @@ -29,8 +29,9 @@ package com.jogamp.test.junit.newt; import java.io.IOException; -import javax.media.nativewindow.Capabilities; import javax.media.nativewindow.NativeWindowFactory; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; import org.junit.Assert; import org.junit.BeforeClass; @@ -41,13 +42,17 @@ import com.jogamp.newt.NewtFactory; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.impl.ScreenMode; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.test.junit.jogl.demos.gl2.gears.Gears; import com.jogamp.test.junit.util.UITestCase; public class TestScreenMode01NEWT extends UITestCase { + static GLProfile glp; static int width, height; - static int waitTimeShort = 1000; //1 sec - static int waitTimeLong = 6000; //6 sec + static int waitTimeShort = 4; //1 sec + static int waitTimeLong = 6; //6 sec + @BeforeClass @@ -55,34 +60,19 @@ public class TestScreenMode01NEWT extends UITestCase { NativeWindowFactory.initSingleton(true); width = 640; height = 480; + glp = GLProfile.getDefault(); } - static Window createWindow(Screen screen, Capabilities caps, int width, int height, boolean onscreen, boolean undecorated) { + static GLWindow createWindow(Screen screen, GLCapabilities caps, int width, int height, boolean onscreen, boolean undecorated) { Assert.assertNotNull(caps); caps.setOnscreen(onscreen); - // Create native windowing resources .. X11/Win/OSX - // - Window window = NewtFactory.createWindow(screen, caps); + + boolean destroyWhenUnused = screen.getDestroyWhenUnused(); + GLWindow window = GLWindow.create(screen, caps); + window.addGLEventListener(new Gears()); Assert.assertNotNull(window); - window.setUndecorated(onscreen && undecorated); - window.setSize(width, height); - Assert.assertEquals(false,window.isNativeValid()); - Assert.assertEquals(false,window.isVisible()); + Assert.assertEquals(destroyWhenUnused, window.getScreen().getDestroyWhenUnused()); window.setVisible(true); - Assert.assertEquals(true,window.isVisible()); - Assert.assertEquals(true,window.isNativeValid()); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - caps = window.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); - Assert.assertNotNull(caps); - Assert.assertTrue(caps.getGreenBits()>5); - Assert.assertTrue(caps.getBlueBits()>5); - Assert.assertTrue(caps.getRedBits()>5); - Assert.assertEquals(caps.isOnscreen(),onscreen); - return window; } @@ -100,21 +90,21 @@ public class TestScreenMode01NEWT extends UITestCase { @Test public void testFullscreenChange01() throws InterruptedException { - Capabilities caps = new Capabilities(); + GLCapabilities caps = new GLCapabilities(glp); Assert.assertNotNull(caps); Display display = NewtFactory.createDisplay(null); // local display Assert.assertNotNull(display); Screen screen = NewtFactory.createScreen(display, 0); // screen 0 Assert.assertNotNull(screen); - Window window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); - - window.setFullscreen(true); + GLWindow window = createWindow(screen, caps, width, height, true /* onscreen */, false /* undecorated */); + window.setFullscreen(true); Assert.assertEquals(true, window.isFullscreen()); - Thread.sleep(waitTimeShort); - + for(int state=0; state 4) + { + modeIndex = screenModes.length - 2; + } ScreenMode screenMode = screenModes[modeIndex]; Assert.assertNotNull(screenMode); diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java b/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java index 74dd8ebcd..2b61d34c4 100644 --- a/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java +++ b/src/newt/classes/com/jogamp/newt/impl/ScreenMode.java @@ -9,6 +9,8 @@ public class ScreenMode { private int index; private int width; private int height; + private int bitsPerPixel = -1; + private short[] rates = null; public ScreenMode(int index, int width, int height) { @@ -16,7 +18,15 @@ public class ScreenMode { this.width = width; this.height = height; } - + /** Not safe to use this on platforms + * other than windows. Since the mode ids + * on X11 match the native ids. unlike windows + * where the ids are generated . + * @param index + */ + public void setIndex(int index) { + this.index = index; + } public int getIndex() { return index; } @@ -38,4 +48,29 @@ public class ScreenMode { public void setRates(short[] rates) { this.rates = rates; } + + public int getBitsPerPixel() { + return bitsPerPixel; + } + + public void setBitsPerPixel(int bitsPerPixel) { + this.bitsPerPixel = bitsPerPixel; + } + + public short getHighestAvailableRate(){ + short highest = rates[0]; + if(rates.length > 1){ + for (int i = 1; i < rates.length; i++) { + if(rates[i] > highest){ + highest = rates[i]; + } + } + } + return highest; + } + + public String toString() { + return "ScreenMode: " + this.index + " - " + this.width + " x " + + this.height + " " + getHighestAvailableRate() + " Hz"; + } } diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java index a0879a634..49816c79d 100644 --- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java +++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java @@ -1165,7 +1165,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer h = nfs_height; } if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen); + System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen); } this.fullscreen = fullscreen; reconfigureWindowImpl(x, y, w, h); diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java index 5dd2689e5..3cac617ab 100644 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsScreen.java @@ -33,8 +33,13 @@ package com.jogamp.newt.impl.windows; +import java.util.ArrayList; + import com.jogamp.newt.*; import com.jogamp.newt.impl.ScreenImpl; +import com.jogamp.newt.impl.ScreenMode; +import com.jogamp.newt.impl.ScreenModeStatus; + import javax.media.nativewindow.*; public class WindowsScreen extends ScreenImpl { @@ -52,7 +57,155 @@ public class WindowsScreen extends ScreenImpl { } protected void closeNativeImpl() { } + + public int getDesktopScreenModeIndex() { + int index = super.getDesktopScreenModeIndex(); + if(index == -1) { + /** Set the current screen mode to refering to index zero + * dependent on the impl of getScreenModes which saves the + * current screen mode at index 0 which is the original screen mode + */ + ScreenMode[] screenModes = getScreenModes(); + if(screenModes != null) { + if(screenModes[0] != null) { + index = screenModes[0].getIndex(); + } + } + } + return index; + } + + public void setScreenMode(int modeIndex, short rate) { + ScreenModeStatus sms = screensModeState.getScreenModeController(getScreenFQN()); + ScreenMode[] screenModes = sms.getScreenModes(); + + short selectedRate = rate; + int selectedMode = modeIndex; + + if(modeIndex < 0 || (modeIndex > screenModes.length)){ + selectedMode = sms.getOriginalScreenMode(); + } + ScreenMode sm = screenModes[selectedMode]; + + if(selectedRate == -1){ + selectedRate = sms.getOriginalScreenRate(); + } + + boolean rateAvailable = false; + short[] rates = sm.getRates(); + for(int i=0;i 0) { + screenModes = new ScreenMode[numModes]; + for(int i=0;iNewIntArray(env, prop_size); + + //Fill the properties in temp jint array + jint prop[prop_size]; + if (0 == EnumDisplaySettings(NULL /*current display device*/, devModeID, &dm)) + { + return NULL; + } + prop[propIndex++] = dm.dmPelsWidth; + prop[propIndex++] = dm.dmPelsHeight; + prop[propIndex++] = dm.dmBitsPerPel; + prop[propIndex++] = dm.dmDisplayFrequency; + + (*env)->SetIntArrayRegion(env, properties, 0, prop_size, prop); + + return properties; +} + +#define SCREEN_MODE_NOERROR 0 +#define SCREEN_MODE_ERROR 1 +/* + * Class: com_jogamp_newt_impl_windows_WindowsScreen + * Method: setScreenMode0 + * Signature: (IIIIS)I + */ +JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setScreenMode0 + (JNIEnv *env, jobject object, jint scrn_idx, jint width, jint height, jint bits, jshort rate) +{ + DEVMODE dm; + // initialize the DEVMODE structure + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + + if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm)) + { + return SCREEN_MODE_ERROR; + } + + dm.dmPelsWidth = (int)width; + dm.dmPelsHeight = (int)height; + dm.dmBitsPerPel = (int)bits; + dm.dmDisplayFrequency = (int)rate; + dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; + + long result = ChangeDisplaySettings(&dm, 0); + if(result == DISP_CHANGE_SUCCESSFUL) + { + return SCREEN_MODE_NOERROR; + } + return SCREEN_MODE_ERROR; +} + +#define SCREEN_ROT_ERROR -1 +/* + * Class: com_jogamp_newt_impl_windows_WindowsScreen + * Method: getCurrentScreenRotation0 + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getCurrentScreenRotation0 + (JNIEnv *env, jobject object, jint scrn_idx) +{ + DEVMODE dm; + // initialize the DEVMODE structure + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + + if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm)) + { + return SCREEN_ROT_ERROR; + } + + int currentRotation = -1; + switch (dm.dmDisplayOrientation) + { + case DMDO_DEFAULT: + currentRotation = 0; + break; + case DMDO_270: + currentRotation = 270; + break; + case DMDO_180: + currentRotation = 180; + break; + case DMDO_90: + currentRotation = 90; + break; + default: + break; + } + return currentRotation; +} +/* + * Class: com_jogamp_newt_impl_windows_WindowsScreen + * Method: setScreenRotation0 + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_setScreenRotation0 + (JNIEnv *env, jobject object, jint scrn_idx, jint rot) +{ + DEVMODE dm; + // initialize the DEVMODE structure + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + + if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm)) + { + return SCREEN_MODE_ERROR; + } + int requestedRotation = dm.dmDisplayOrientation; + int currentRotation = dm.dmDisplayOrientation; + + int shouldFlipDims = 0; + + int rotation = (int)rot; + switch (rotation) + { + case 0: + requestedRotation = DMDO_DEFAULT; + if (currentRotation == DMDO_90 || currentRotation == DMDO_270) + { + shouldFlipDims = 1; + } + break; + case 270: + requestedRotation = DMDO_270; + if (currentRotation == DMDO_DEFAULT || currentRotation == DMDO_180) + { + shouldFlipDims = 1; + } + break; + case 180: + requestedRotation = DMDO_180; + if (currentRotation == DMDO_90 || currentRotation == DMDO_270) + { + shouldFlipDims = 1; + } + break; + case 90: + requestedRotation = DMDO_90; + if (currentRotation == DMDO_DEFAULT || currentRotation == DMDO_180) + { + shouldFlipDims = 1; + } + break; + default: + //requested rotation not available + return SCREEN_MODE_ERROR; + break; + } + /** swap width and height if changing from vertical to horizantal + * or horizantal to vertical + */ + if (shouldFlipDims) + { + int tempWidth = dm.dmPelsWidth; + dm.dmPelsWidth = dm.dmPelsHeight; + dm.dmPelsHeight = tempWidth; + } + dm.dmDisplayOrientation = requestedRotation; + dm.dmFields = DM_DISPLAYORIENTATION | DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; + + long result = ChangeDisplaySettings(&dm, 0); + if(result == DISP_CHANGE_SUCCESSFUL) + { + return SCREEN_MODE_NOERROR; + } + return SCREEN_MODE_ERROR; +} + /* * Class: com_jogamp_newt_impl_windows_WindowsWindow * Method: initIDs0 @@ -1365,13 +1581,45 @@ static void NewtWindows_reparentWindow(JNIEnv *env, jobject obj, HWND hwndP, HWN DBG_PRINT("*** WindowsWindow: reparentWindow.X\n"); } +#define FULLSCREEN_NOERROR 0 +#define FULLSCREEN_ERROR 1 + +static int NewtWindows_setFullScreen(jboolean fullscreen) +{ + int flags = 0; + DEVMODE dm; + // initialize the DEVMODE structure + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + + if (0 == EnumDisplaySettings(NULL /*current display device*/, ENUM_CURRENT_SETTINGS, &dm)) + { + return FULLSCREEN_ERROR; + } + + if(fullscreen == JNI_TRUE) + { + flags = CDS_FULLSCREEN; //set fullscreen temporary + } + else + { + flags = CDS_RESET; // reset to registery values + } + long result = ChangeDisplaySettings(&dm, flags); + if(result == DISP_CHANGE_SUCCESSFUL) + { + return FULLSCREEN_NOERROR; + } + return FULLSCREEN_ERROR; +} + /* * Class: com_jogamp_newt_impl_windows_WindowsWindow * Method: reconfigureWindow0 * Signature: (JIIIIZ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reconfigureWindow0 - (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated) + (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated, jboolean isFullscreen) { UINT flags; HWND hwndP = (HWND) (intptr_t) parent; @@ -1382,9 +1630,18 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reconfigu DBG_PRINT("*** WindowsWindow: reconfigureWindow0.1 parent %p, window %p, %d/%d %dx%d undeco %d visible\n", parent, window, x, y, width, height, bIsUndecorated, isVisible); + if(isFullscreen == JNI_FALSE) + { + NewtWindows_setFullScreen(isFullscreen); + } NewtWindows_reparentWindow(env, obj, hwndP, hwnd, FALSE, x, y, width, height, bIsUndecorated); - - if ( NULL == hwndP ) { + + if(isFullscreen == JNI_TRUE) + { + NewtWindows_setFullScreen(isFullscreen); + } + + if ( NULL == hwndP ) { flags = SWP_SHOWWINDOW; hWndInsertAfter = HWND_TOPMOST; } else { -- cgit v1.2.3