Question about Full screen exclusive mode

S

Soren

Hello

I write a program in which i use fullscreen mode.
I have read about this a little. I learn from David Brackeen's book -
Developing Games in Java and of course from java docs but there is a
problem i cannot handle by myself so please help me i you'll be so kind :)

I have configuration dialog from which the user can select display mode
and test it. I use ScreenManager class that has been presented in David
Brackeen's book.

The problem is as follows:
I choose a mode form settings dialog and when i test it everything seems
to be fine but only at the first time. Problem appears when i try to
test it again or test another mode higher than that i'm normally working in.

The graphics card enters the selected mode but the window content is
painted only to the level of windows display mode.For example.
I am working in 1024x768 resolution and when i choose 1280x960
resolution only 1024x768 arena is painted. The remain area is unpainted
so i can see windows desktop.

After returning to the Windows, the settings dialog window is repainted
with the content of the frame that is under settings dialog.

ScreenManager class:
----------------------------------------------------------------------
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.*;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;

/**
The ScreenManager class manages initializing and displaying
full screen graphics modes.
*/
public class ScreenManager {
private GraphicsDevice device;
private DisplayMode basicMode;
/**
Creates a new ScreenManager object.
*/
public ScreenManager() {
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
device = environment.getDefaultScreenDevice();
basicMode = device.getDisplayMode();
}
/**
Returns a list of compatible display modes for the
default device on the system.
*/
public DisplayMode[] getCompatibleDisplayModes() {
return device.getDisplayModes();
}
/**
Returns the first compatible mode in a list of modes.
Returns null if no modes are compatible.
*/
public DisplayMode findFirstCompatibleMode(
DisplayMode modes[])
{
DisplayMode goodModes[] = device.getDisplayModes();
for (int i = 0; i < modes.length; i++) {
for (int j = 0; j < goodModes.length; j++) {
if (displayModesMatch(modes, goodModes[j])) {
return modes;
}
}
}
return null;
}
/**
Returns the current display mode.
*/
public DisplayMode getCurrentDisplayMode() {
return device.getDisplayMode();
}
/**
Determines if two display modes "match". Two display
modes match if they have the same resolution, bit depth,
and refresh rate. The bit depth is ignored if one of the
modes has a bit depth of DisplayMode.BIT_DEPTH_MULTI.
Likewise, the refresh rate is ignored if one of the
modes has a refresh rate of
DisplayMode.REFRESH_RATE_UNKNOWN.
*/
public boolean displayModesMatch(DisplayMode mode1,
DisplayMode mode2)
{
if (mode1.getWidth() != mode2.getWidth() ||
mode1.getHeight() != mode2.getHeight())
{
return false;
}

if (mode1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
mode2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
mode1.getBitDepth() != mode2.getBitDepth())
{
return false;
}
if (mode1.getRefreshRate() !=
DisplayMode.REFRESH_RATE_UNKNOWN &&
mode2.getRefreshRate() !=
DisplayMode.REFRESH_RATE_UNKNOWN &&
mode1.getRefreshRate() != mode2.getRefreshRate())
{
return false;
}
return true;
}
/**
Enters full screen mode and changes the display mode.
If the specified display mode is null or not compatible
with this device, or if the display mode cannot be
changed on this system, the current display mode is used.
<p>
The display uses a BufferStrategy with 2 buffers.
*/
public void setFullScreen(DisplayMode displayMode) {
JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.setIgnoreRepaint(true);
frame.setResizable(false);
device.setFullScreenWindow(frame);

if (displayMode != null &&
device.isDisplayChangeSupported())
{
try {
device.setDisplayMode(displayMode);
}
catch (IllegalArgumentException ex) { }
}
frame.createBufferStrategy(2);
}

/**
Gets the graphics context for the display. The
ScreenManager uses double buffering, so applications must
call update() to show any graphics drawn.
<p>
The application must dispose of the graphics object.
*/
public Graphics2D getGraphics() {
Window window = device.getFullScreenWindow();
if (window != null) {
BufferStrategy strategy = window.getBufferStrategy();
return (Graphics2D)strategy.getDrawGraphics();
}

else {
return null;
}
}
/**
Updates the display.
*/
public void update() {
Window window = device.getFullScreenWindow();
if (window != null) {
BufferStrategy strategy = window.getBufferStrategy();
if (!strategy.contentsLost()) {
strategy.show();
}
}
// Sync the display on some systems.
// (on Linux, this fixes event queue problems)
Toolkit.getDefaultToolkit().sync();
}
/**
Returns the window currently used in full screen mode.
Returns null if the device is not in full screen mode.
*/
public Window getFullScreenWindow() {
return device.getFullScreenWindow();
}
/**
Returns the width of the window currently used in full
screen mode. Returns 0 if the device is not in full
screen mode.
*/
public int getWidth() {
Window window = device.getFullScreenWindow();
if (window != null) {
return window.getWidth();
}
else {
return 0;
}
}
/**
Returns the height of the window currently used in full
screen mode. Returns 0 if the device is not in full
screen mode.
*/
public int getHeight() {
Window window = device.getFullScreenWindow();
if (window != null) {
return window.getHeight();
}
else {
return 0;

}
}
/**
Restores the screen's display mode.
*/
public void restoreScreen() {
device.setDisplayMode( basicMode );
Window window = device.getFullScreenWindow();
if (window != null) {
window.dispose();
}
device.setFullScreenWindow( null );
}
/**
Creates an image compatible with the current display.
*/
public BufferedImage createCompatibleImage(int w, int h,
int transparency)
{
Window window = device.getFullScreenWindow();
if (window != null) {
GraphicsConfiguration gc =
window.getGraphicsConfiguration();
return gc.createCompatibleImage(w, h, transparency);
}
return null;
}
}

----------------------------------------------------------------------
 
A

Andrew Thompson

Soren said:
Hello

I write a program in which i use fullscreen mode.

I noticed you posted around 270 lines of it, yes.

Unfortunately, it is not runnable, and me reading
your 270 lines of code is not neally as effective
(for me helping you) as me seeing the problem
on-screen, so I did not bother (reading the 270 lines).

You might consider posting what is locally known as
an SSCCE* - an example that can be copy/paste/run
to demonstrate the problem - then it is likely to get more
attention.

But note that you should be able to demonstrate the
problem in less than 50 lines of code (as opposed to
270 lines, plus the other two classes you were just
thinking of posting).

* For more tips on posting code examples, see
<http://www.physci.org/codes/sscce>

Andrew T.
 
S

Soren

I tryied to prepare working SSCCE version
and made it as shorter as i could.
I hope it will work ;]
There are 2 files
- Test( with main method ) 42 lines
- ScreenManager 52 lines

----------------- Test.java ------------------
public class Test
{
ScreenManager screen = null;
java.awt.DisplayMode oldMode = null;
java.awt.DisplayMode testedMode = null;

private Test()
{
screen = new ScreenManager();
}

public static void main( String[] args ) {
Test.Run( 1024, 768, 32, 70);
Test.Run( 1280, 960, 32, 70);
}

public static void Run( int width, int height, int bitDepth, int
refreshRate )
{
Test test = new Test();;
test.testedMode = new java.awt.DisplayMode( width, height, bitDepth,
refreshRate );
test.oldMode = test.screen.getCurrentDisplayMode();
try
{
test.screen.setFullScreen( test.testedMode );
try
{
Thread.sleep( 5000 );
}catch( InterruptedException ex ) { /*...*/ }
}
catch( Throwable t )
{
t.printStackTrace( System.err );
}
finally
{
test.screen.restoreScreen();
test.screen.setFullScreen( test.oldMode );
test.screen.restoreScreen();
}
}

}
----------------- Test.java ---------------------------
and...
----------------- ScreenManager.java ------------------
import java.awt.DisplayMode;
import java.awt.GraphicsDevice;
import java.awt.*;
import java.awt.GraphicsEnvironment;
import javax.swing.JFrame;

public class ScreenManager {
private GraphicsDevice device;
private DisplayMode basicMode;

public ScreenManager() {
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
device = environment.getDefaultScreenDevice();
basicMode = device.getDisplayMode();
}

public DisplayMode getCurrentDisplayMode() {
return device.getDisplayMode();
}

public void setFullScreen(DisplayMode displayMode) {
JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.setIgnoreRepaint(true);
frame.setResizable(false);
device.setFullScreenWindow(frame);

if (displayMode != null &&
device.isDisplayChangeSupported())
{
try {
device.setDisplayMode(displayMode);
}
catch (IllegalArgumentException ex) { }
}
frame.createBufferStrategy(2);
}

public Window getFullScreenWindow() {
return device.getFullScreenWindow();
}

public void restoreScreen() {
device.setDisplayMode( basicMode );
Window window = device.getFullScreenWindow();
if (window != null) {
window.dispose();
}
device.setFullScreenWindow( null );
}
}
----------------- ScreenManager.java ------------------
 
O

Oliver Wong

Soren said:
I tryied to prepare working SSCCE version
and made it as shorter as i could.
I hope it will work ;]

As far as I can see, neither your 270 line version, nor this shorter
version, "demonstrates the problem". That is, neither of them attempt to
draw a 1280x960 image, only to have the top left 1024x768 portion of it show
up, and the rest being blank.

- Oliver
 
S

Soren

Oliver said:
As far as I can see, neither your 270 line version, nor this shorter
version, "demonstrates the problem". That is, neither of them attempt to
draw a 1280x960 image, only to have the top left 1024x768 portion of it show
up, and the rest being blank.

First it test 1024x768 and then 1280x960 with only the top left 1024x768
portion visible. On my computer it attempted successfully to show this
problem. I have no idea why on yours it didn't :(
 
O

Oliver Wong

Soren said:
First it test 1024x768 and then 1280x960 with only the top left 1024x768
portion visible. On my computer it attempted successfully to show this
problem. I have no idea why on yours it didn't :(

On mine, my screen just becomes all black for a while, then goes back to
the normal desktop. I don't know what resolution my monitor is set at during
this phase where it displays the black screen, but it doesn't look like it's
changing resolution more than twice (once from my preferred resolution to
some resolution you specified, and then back).

Maybe you can modify the program so that it draws, as text, the current
resolution it's set at, and also draw a rectangle with the diagonals drawn,
so we can see if there is indeed a portion of the screen not being updated:

+----+
|\ /|
| \/ |
| /\ |
|/ \|
+----+

- Oliver
 
S

Soren

+----+
|\ /|
| \/ |
| /\ |
|/ \|
+----+
OK I prepared such a version.
- Test.java 66 lines
- ScreenManager.java 73 lines

Hope it will work :)

------------------- Test.java --------------------------
public class Test
{
ScreenManager screen = null;
java.awt.DisplayMode oldMode = null;
java.awt.DisplayMode testedMode = null;

private Test()
{
screen = new ScreenManager();
}

public static void main( String[] args ) {
Test.Run( 1024, 768, 32, 70);
Test.Run( 1280, 960, 32, 70);
}

public static void Run( int width, int height, int bitDepth, int
refreshRate )
{
Test test = new Test();;
test.testedMode = new java.awt.DisplayMode( width, height, bitDepth,
refreshRate );
test.oldMode = test.screen.getCurrentDisplayMode();
try
{
test.screen.setFullScreen( test.testedMode );
test.drawLoop();
}
catch( Throwable t )
{
t.printStackTrace( System.err );
}
finally
{
test.screen.restoreScreen();
test.screen.setFullScreen( test.oldMode );
test.screen.restoreScreen();
}
}

private void drawLoop() {
long start = System.currentTimeMillis(),
current = start;
while( current < start + 10000 )
{
current = System.currentTimeMillis();
java.awt.Graphics2D graphics = this.screen.getGraphics();
draw( graphics );
this.screen.update();

try
{
Thread.sleep( 25 );
}catch( InterruptedException ex) { /**/ }
}
}

private void draw( java.awt.Graphics2D g ) {
g.setPaint( java.awt.Color.blue );
g.fillRect(0, 0, testedMode.getWidth(), testedMode.getHeight() );
g.setPaint( java.awt.Color.white );
g.setFont( new java.awt.Font("Dialog", java.awt.Font.BOLD, 20) );
g.drawString( "Current resolution: "
+testedMode.getWidth()+"x"+testedMode.getHeight(), 50, 100);
g.drawRect(0, 0, testedMode.getWidth()-1, testedMode.getHeight()-1 );
g.draw( new java.awt.geom.Line2D.Double( 0,0,testedMode.getWidth()-1,
testedMode.getHeight()-1 ) );
g.draw( new java.awt.geom.Line2D.Double( testedMode.getWidth()-1, 0,
0, testedMode.getHeight()-1 ) );
}
}
------------------- Test.java --------------------------
.... and ...
------------------- ScreenManager.java --------------------------
package temp;

import java.awt.*;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

public class ScreenManager {
private GraphicsDevice device;
private DisplayMode basicMode;

public ScreenManager() {
GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();
device = environment.getDefaultScreenDevice();
basicMode = device.getDisplayMode();
}

public DisplayMode getCurrentDisplayMode() {
return device.getDisplayMode();
}

public void setFullScreen(DisplayMode displayMode) {
JFrame frame = new JFrame();
frame.setUndecorated(true);
frame.setIgnoreRepaint(true);
frame.setResizable(false);
device.setFullScreenWindow(frame);

if (displayMode != null &&
device.isDisplayChangeSupported())
{
try {
device.setDisplayMode(displayMode);
}
catch (IllegalArgumentException ex) { }
}
frame.createBufferStrategy(2);
}

public Window getFullScreenWindow() {
return device.getFullScreenWindow();
}

public void restoreScreen() {
device.setDisplayMode( basicMode );
Window window = device.getFullScreenWindow();
if (window != null) {
window.dispose();
}
device.setFullScreenWindow( null );
}

public Graphics2D getGraphics() {
Window window = device.getFullScreenWindow();
if (window != null) {
BufferStrategy strategy = window.getBufferStrategy();
return (Graphics2D)strategy.getDrawGraphics();
}

else {
return null;
}
}

public void update() {
Window window = device.getFullScreenWindow();
if (window != null) {
BufferStrategy strategy = window.getBufferStrategy();
if (!strategy.contentsLost()) {
strategy.show();
}
}
}
}
------------------- ScreenManager.java --------------------------
 
O

Oliver Wong

Soren said:
+----+
|\ /|
| \/ |
| /\ |
|/ \|
+----+
OK I prepared such a version.
- Test.java 66 lines
- ScreenManager.java 73 lines

Hope it will work :)

Yup, I clearly see the problem now. It looks like the issue is that
depending on what resolutions you choose, you may enter full screen in
"Exclusive Mode", or in "Simulated Mode", and you can't seem to really
control which one you get, except by varying the resolution. For example,
when I changed your program to resolutions which my LCD preferred:

Test.Run(1600, 900, 32, 70);
Test.Run(1680, 1050, 32, 70);

The *first* screen appeared in the top left corner in simulated mode,
while the latter screen appeared in exclusive mode, so it has nothing to do
with "remembering settings", or anything like that.

Consider enumerating over all available resolutions (perhaps via
GraphicsDevice.getDisplayModes()) and letting the end user decide which one
they prefer, or use GraphicsDevice.getBestConfiguration().

Note that if a user has two or more screens (which is the case for me,
for example), then there are multiple GraphicsDevice that you'll have to
enumerate over as well, to upon decide which screen the full screen game
will appear.

- Oliver
 
S

Soren

Oliver said:
Yup, I clearly see the problem now. It looks like the issue is that
depending on what resolutions you choose, you may enter full screen in
"Exclusive Mode", or in "Simulated Mode", and you can't seem to really
control which one you get, except by varying the resolution. For example,
when I changed your program to resolutions which my LCD preferred:

Thanks for helping. I needed it for school project. I wanted to write
fullscreen game but now when i see that this problem is really serious i
must consider changing project's subject. ;]
 
K

Knute Johnson

Oliver said:
Yup, I clearly see the problem now. It looks like the issue is that
depending on what resolutions you choose, you may enter full screen in
"Exclusive Mode", or in "Simulated Mode", and you can't seem to really
control which one you get, except by varying the resolution. For example,
when I changed your program to resolutions which my LCD preferred:

Test.Run(1600, 900, 32, 70);
Test.Run(1680, 1050, 32, 70);

The *first* screen appeared in the top left corner in simulated mode,
while the latter screen appeared in exclusive mode, so it has nothing to do
with "remembering settings", or anything like that.

Consider enumerating over all available resolutions (perhaps via
GraphicsDevice.getDisplayModes()) and letting the end user decide which one
they prefer, or use GraphicsDevice.getBestConfiguration().

Note that if a user has two or more screens (which is the case for me,
for example), then there are multiple GraphicsDevice that you'll have to
enumerate over as well, to upon decide which screen the full screen game
will appear.

- Oliver

If you have more than one physical display device you will have problems
with Full Screen Exclusive Mode. Any input on any screen will cause it
to return from FSEM. I've gone to active rendering which is almost as
fast without all the attendant problems.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top