8047061: [macosx] Crash when setting display mode
Reviewed-by: anthony, alexsch
This commit is contained in:
parent
d39a778d5f
commit
be48d07662
@ -57,7 +57,7 @@ static CFMutableArrayRef getAllValidDisplayModes(jint displayID){
|
||||
CFArrayRef allModes = CGDisplayCopyAllDisplayModes(displayID, NULL);
|
||||
|
||||
CFIndex numModes = CFArrayGetCount(allModes);
|
||||
CFMutableArrayRef validModes = CFArrayCreateMutable(kCFAllocatorDefault, numModes + 1, NULL);
|
||||
CFMutableArrayRef validModes = CFArrayCreateMutable(kCFAllocatorDefault, numModes + 1, &kCFTypeArrayCallBacks);
|
||||
|
||||
CFIndex n;
|
||||
for (n=0; n < numModes; n++) {
|
||||
|
@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2014 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 6275887 6429971 6459792
|
||||
@summary Test that we don't crash when alt+tabbing in and out of
|
||||
fullscreen app
|
||||
@author Dmitri.Trembovetski@sun.com: area=FullScreen
|
||||
@run main/othervm/timeout=100 AltTabCrashTest -auto -changedm
|
||||
@run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -changedm
|
||||
@run main/othervm/timeout=100 -Dsun.java2d.d3d=True AltTabCrashTest -auto -usebs -changedm
|
||||
@run main/othervm/timeout=100 -Dsun.java2d.opengl=True AltTabCrashTest -auto
|
||||
*/
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
import java.awt.DisplayMode;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferStrategy;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.VolatileImage;
|
||||
import java.util.Random;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Note that the alt+tabbing in and out part will most likely only work
|
||||
* on Windows, and only if there are no interventions.
|
||||
*/
|
||||
|
||||
public class AltTabCrashTest extends Frame {
|
||||
public static int width;
|
||||
public static int height;
|
||||
public static volatile boolean autoMode;
|
||||
public static boolean useBS;
|
||||
public static final int NUM_OF_BALLS = 70;
|
||||
// number of times to alt+tab in and out of the app
|
||||
public static int altTabs = 5;
|
||||
private final Vector<Ball> balls = new Vector<>();
|
||||
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice();
|
||||
VolatileImage vimg = null;
|
||||
BufferStrategy bufferStrategy = null;
|
||||
volatile boolean timeToQuit = false;
|
||||
static final Object lock = new Object();
|
||||
|
||||
enum SpriteType {
|
||||
OVALS, VIMAGES, BIMAGES, AAOVALS, TEXT
|
||||
}
|
||||
|
||||
private static boolean changeDM = false;
|
||||
private static SpriteType spriteType;
|
||||
static Random rnd = new Random();
|
||||
|
||||
public AltTabCrashTest( ) {
|
||||
addKeyListener(new KeyAdapter() {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
|
||||
timeToQuit = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
setIgnoreRepaint(true);
|
||||
addMouseListener(new MouseHandler());
|
||||
for (int i = 0; i < NUM_OF_BALLS; i++) {
|
||||
int x = 50 + rnd.nextInt(550), y = 50 + rnd.nextInt(400);
|
||||
|
||||
balls.addElement(createRandomBall(y, x));
|
||||
}
|
||||
setUndecorated(true);
|
||||
gd.setFullScreenWindow(this);
|
||||
GraphicsDevice gd = getGraphicsConfiguration().getDevice();
|
||||
if (gd.isDisplayChangeSupported() && changeDM) {
|
||||
DisplayMode dm = findDisplayMode();
|
||||
if (dm != null) {
|
||||
try {
|
||||
gd.setDisplayMode(dm);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
System.err.println("Error setting display mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (useBS) {
|
||||
createBufferStrategy(2);
|
||||
bufferStrategy = getBufferStrategy();
|
||||
} else {
|
||||
Graphics2D g = (Graphics2D) getGraphics();
|
||||
render(g);
|
||||
g.dispose();
|
||||
}
|
||||
Thread t = new BallThread();
|
||||
t.start();
|
||||
if (autoMode) {
|
||||
Thread tt = new AltTabberThread();
|
||||
tt.start();
|
||||
synchronized (lock) {
|
||||
while (!timeToQuit) {
|
||||
try {
|
||||
lock.wait(200);
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
t = null;
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private Ball createRandomBall(final int y, final int x) {
|
||||
Ball b;
|
||||
SpriteType type;
|
||||
|
||||
if (spriteType == null) {
|
||||
int index = rnd.nextInt(SpriteType.values().length);
|
||||
type = SpriteType.values()[index];
|
||||
} else {
|
||||
type = spriteType;
|
||||
}
|
||||
switch (type) {
|
||||
case VIMAGES: b = new VISpriteBall(x, y); break;
|
||||
case AAOVALS: b = new AAOvalBall(x, y); break;
|
||||
case BIMAGES: b = new BISpriteBall(x, y); break;
|
||||
case TEXT: b = new TextBall(x,y, "Text Sprite!"); break;
|
||||
default: b = new Ball(x, y); break;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private class MouseHandler extends MouseAdapter {
|
||||
public void mousePressed(MouseEvent e) {
|
||||
synchronized (balls) {
|
||||
balls.addElement(createRandomBall(e.getX(), e.getY()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AltTabberThread extends Thread {
|
||||
Robot robot;
|
||||
|
||||
void pressAltTab() {
|
||||
robot.keyPress(KeyEvent.VK_ALT);
|
||||
robot.keyPress(KeyEvent.VK_TAB);
|
||||
robot.keyRelease(KeyEvent.VK_TAB);
|
||||
robot.keyRelease(KeyEvent.VK_ALT);
|
||||
}
|
||||
void pressShiftAltTab() {
|
||||
robot.keyPress(KeyEvent.VK_SHIFT);
|
||||
pressAltTab();
|
||||
robot.keyRelease(KeyEvent.VK_SHIFT);
|
||||
}
|
||||
public void run() {
|
||||
try {
|
||||
robot = new Robot();
|
||||
robot.setAutoDelay(200);
|
||||
} catch (AWTException e) {
|
||||
throw new RuntimeException("Can't create robot");
|
||||
}
|
||||
boolean out = true;
|
||||
while (altTabs-- > 0 && !timeToQuit) {
|
||||
System.err.println("Alt+tabber Iteration: "+altTabs);
|
||||
try { Thread.sleep(2500); } catch (InterruptedException ex) {}
|
||||
|
||||
if (out) {
|
||||
System.err.println("Issuing alt+tab");
|
||||
pressAltTab();
|
||||
} else {
|
||||
System.err.println("Issuing shift ");
|
||||
pressShiftAltTab();
|
||||
}
|
||||
out = !out;
|
||||
}
|
||||
System.err.println("Alt+tabber finished.");
|
||||
synchronized (lock) {
|
||||
timeToQuit = true;
|
||||
lock.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class BallThread extends Thread {
|
||||
public void run() {
|
||||
while (!timeToQuit) {
|
||||
if (useBS) {
|
||||
renderToBS();
|
||||
bufferStrategy.show();
|
||||
} else {
|
||||
Graphics g = AltTabCrashTest.this.getGraphics();
|
||||
render(g);
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
gd.setFullScreenWindow(null);
|
||||
AltTabCrashTest.this.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
static class Ball {
|
||||
|
||||
int x, y; // current location
|
||||
int dx, dy; // motion delta
|
||||
int diameter = 40;
|
||||
Color color = Color.red;
|
||||
|
||||
public Ball() {
|
||||
}
|
||||
|
||||
public Ball(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
dx = x % 20 + 1;
|
||||
dy = y % 20 + 1;
|
||||
color = new Color(rnd.nextInt(0x00ffffff));
|
||||
}
|
||||
|
||||
public void move() {
|
||||
if (x < 10 || x >= AltTabCrashTest.width - 20)
|
||||
dx = -dx;
|
||||
if (y < 10 || y > AltTabCrashTest.height - 20)
|
||||
dy = -dy;
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
|
||||
public void paint(Graphics g, Color c) {
|
||||
if (c == null) {
|
||||
g.setColor(color);
|
||||
} else {
|
||||
g.setColor(c);
|
||||
}
|
||||
g.fillOval(x, y, diameter, diameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TextBall extends Ball {
|
||||
String text;
|
||||
public TextBall(int x, int y, String text) {
|
||||
super(x, y);
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void paint(Graphics g, Color c) {
|
||||
if (c == null) {
|
||||
g.setColor(color);
|
||||
} else {
|
||||
g.setColor(c);
|
||||
}
|
||||
g.drawString(text, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static class AAOvalBall extends Ball {
|
||||
public AAOvalBall(int x, int y) {
|
||||
super(x, y);
|
||||
}
|
||||
public void paint(Graphics g, Color c) {
|
||||
if (c == null) {
|
||||
Graphics2D g2d = (Graphics2D)g.create();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.setColor(color);
|
||||
g2d.fillOval(x, y, diameter, diameter);
|
||||
} else {
|
||||
g.setColor(c);
|
||||
g.fillOval(x-2, y-2, diameter+4, diameter+4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class SpriteBall extends Ball {
|
||||
Image image;
|
||||
public SpriteBall(int x, int y) {
|
||||
super(x, y);
|
||||
image = createSprite();
|
||||
Graphics g = image.getGraphics();
|
||||
g.setColor(color);
|
||||
g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
|
||||
}
|
||||
public void paint(Graphics g, Color c) {
|
||||
if (c != null) {
|
||||
g.setColor(c);
|
||||
g.fillRect(x, y, image.getWidth(null), image.getHeight(null));
|
||||
} else do {
|
||||
validateSprite();
|
||||
g.drawImage(image, x, y, null);
|
||||
} while (renderingIncomplete());
|
||||
}
|
||||
public abstract Image createSprite();
|
||||
public void validateSprite() {}
|
||||
public boolean renderingIncomplete() { return false; }
|
||||
}
|
||||
class VISpriteBall extends SpriteBall {
|
||||
|
||||
public VISpriteBall(int x, int y) {
|
||||
super(x, y);
|
||||
}
|
||||
public boolean renderingIncomplete() {
|
||||
return ((VolatileImage)image).contentsLost();
|
||||
}
|
||||
|
||||
public Image createSprite() {
|
||||
return gd.getDefaultConfiguration().
|
||||
createCompatibleVolatileImage(20, 20);
|
||||
}
|
||||
public void validateSprite() {
|
||||
int result =
|
||||
((VolatileImage)image).validate(getGraphicsConfiguration());
|
||||
if (result == VolatileImage.IMAGE_INCOMPATIBLE) {
|
||||
image = createSprite();
|
||||
result = VolatileImage.IMAGE_RESTORED;
|
||||
}
|
||||
if (result == VolatileImage.IMAGE_RESTORED) {
|
||||
Graphics g = image.getGraphics();
|
||||
g.setColor(color);
|
||||
g.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
class BISpriteBall extends SpriteBall {
|
||||
public BISpriteBall(int x, int y) {
|
||||
super(x, y);
|
||||
}
|
||||
public Image createSprite() {
|
||||
return new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void renderOffscreen() {
|
||||
Graphics2D g2d = (Graphics2D) vimg.getGraphics();
|
||||
synchronized (balls) {
|
||||
for (Ball b : balls) {
|
||||
b.paint(g2d, getBackground());
|
||||
b.move();
|
||||
b.paint(g2d, null);
|
||||
}
|
||||
}
|
||||
g2d.dispose();
|
||||
}
|
||||
|
||||
public void renderToBS() {
|
||||
width = getWidth();
|
||||
height = getHeight();
|
||||
|
||||
do {
|
||||
Graphics2D g2d = (Graphics2D)bufferStrategy.getDrawGraphics();
|
||||
|
||||
g2d.clearRect(0, 0, width, height);
|
||||
synchronized (balls) {
|
||||
for (Ball b : balls) {
|
||||
b.move();
|
||||
b.paint(g2d, null);
|
||||
}
|
||||
}
|
||||
g2d.dispose();
|
||||
} while (bufferStrategy.contentsLost() ||
|
||||
bufferStrategy.contentsRestored());
|
||||
}
|
||||
|
||||
public void render(Graphics g) {
|
||||
do {
|
||||
height = getBounds().height;
|
||||
width = getBounds().width;
|
||||
if (vimg == null) {
|
||||
vimg = createVolatileImage(width, height);
|
||||
renderOffscreen();
|
||||
}
|
||||
int returnCode = vimg.validate(getGraphicsConfiguration());
|
||||
if (returnCode == VolatileImage.IMAGE_RESTORED) {
|
||||
renderOffscreen();
|
||||
} else if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
|
||||
vimg = getGraphicsConfiguration().
|
||||
createCompatibleVolatileImage(width, height);
|
||||
renderOffscreen();
|
||||
} else if (returnCode == VolatileImage.IMAGE_OK) {
|
||||
renderOffscreen();
|
||||
}
|
||||
g.drawImage(vimg, 0, 0, this);
|
||||
} while (vimg.contentsLost());
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
for (String arg : args) {
|
||||
if (arg.equalsIgnoreCase("-auto")) {
|
||||
autoMode = true;
|
||||
System.err.println("Running in automatic mode using Robot");
|
||||
} else if (arg.equalsIgnoreCase("-usebs")) {
|
||||
useBS = true;
|
||||
System.err.println("Using BufferStrategy instead of VI");
|
||||
} else if (arg.equalsIgnoreCase("-changedm")) {
|
||||
changeDM= true;
|
||||
System.err.println("The test will change display mode");
|
||||
} else if (arg.equalsIgnoreCase("-vi")) {
|
||||
spriteType = SpriteType.VIMAGES;
|
||||
} else if (arg.equalsIgnoreCase("-bi")) {
|
||||
spriteType = SpriteType.BIMAGES;
|
||||
} else if (arg.equalsIgnoreCase("-ov")) {
|
||||
spriteType = SpriteType.OVALS;
|
||||
} else if (arg.equalsIgnoreCase("-aaov")) {
|
||||
spriteType = SpriteType.AAOVALS;
|
||||
} else if (arg.equalsIgnoreCase("-tx")) {
|
||||
spriteType = SpriteType.TEXT;
|
||||
} else {
|
||||
System.err.println("Usage: AltTabCrashTest [-usebs][-auto]" +
|
||||
"[-changedm][-vi|-bi|-ov|-aaov|-tx]");
|
||||
System.err.println(" -usebs: use BufferStrategy instead of VI");
|
||||
System.err.println(" -auto: automatically alt+tab in and out" +
|
||||
" of the application ");
|
||||
System.err.println(" -changedm: change display mode");
|
||||
System.err.println(" -(vi|bi|ov|tx|aaov) : use only VI, BI, " +
|
||||
"text or [AA] [draw]Oval sprites");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
if (spriteType != null) {
|
||||
System.err.println("The test will only use "+spriteType+" sprites.");
|
||||
}
|
||||
new AltTabCrashTest();
|
||||
}
|
||||
|
||||
private DisplayMode findDisplayMode() {
|
||||
GraphicsDevice gd = getGraphicsConfiguration().getDevice();
|
||||
DisplayMode dms[] = gd.getDisplayModes();
|
||||
DisplayMode currentDM = gd.getDisplayMode();
|
||||
for (DisplayMode dm : dms) {
|
||||
if (dm.getBitDepth() > 8 &&
|
||||
dm.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI &&
|
||||
dm.getBitDepth() != currentDM.getBitDepth() &&
|
||||
dm.getWidth() == currentDM.getWidth() &&
|
||||
dm.getHeight() == currentDM.getHeight())
|
||||
{
|
||||
// found a mode which has the same dimensions but different
|
||||
// depth
|
||||
return dm;
|
||||
}
|
||||
if (dm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI &&
|
||||
(dm.getWidth() != currentDM.getWidth() ||
|
||||
dm.getHeight() != currentDM.getHeight()))
|
||||
{
|
||||
// found a mode which has the same depth but different
|
||||
// dimensions
|
||||
return dm;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user