8252133: The java/awt/GraphicsDevice/DisplayModes/CycleDMImage.java fails if metal pipeline is active

Reviewed-by: prr
This commit is contained in:
Sergey Bylokhov 2020-10-21 00:15:46 +00:00
parent afc967fcd0
commit e5870cf002
3 changed files with 84 additions and 56 deletions

View file

@ -131,9 +131,14 @@ public final class CGraphicsDevice extends GraphicsDevice
return scale; return scale;
} }
public void invalidate(final int defaultDisplayID) { /**
* Invalidates this device so it will point to some other "new" device.
*
* @param device the new device, usually the main screen
*/
public void invalidate(CGraphicsDevice device) {
//TODO do we need to restore the full-screen window/modes on old device? //TODO do we need to restore the full-screen window/modes on old device?
displayID = defaultDisplayID; displayID = device.displayID;
} }
@Override @Override

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,6 @@
package sun.awt; package sun.awt;
import java.awt.AWTError;
import java.awt.Font; import java.awt.Font;
import java.awt.GraphicsConfiguration; import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice; import java.awt.GraphicsDevice;
@ -112,7 +111,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
} }
/* Populate the device table */ /* Populate the device table */
initDevices(); rebuildDevices();
/* Register our display reconfiguration listener */ /* Register our display reconfiguration listener */
displayReconfigContext = registerDisplayReconfiguration(); displayReconfigContext = registerDisplayReconfiguration();
@ -121,33 +120,27 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
} }
} }
/**
* Updates the list of devices and notify listeners.
*/
private void rebuildDevices() {
initDevices();
displayChanged();
}
/** /**
* Called by the CoreGraphics Display Reconfiguration Callback. * Called by the CoreGraphics Display Reconfiguration Callback.
* *
* @param displayId CoreGraphics displayId * @param displayId CoreGraphics displayId
* @param removed true if displayId was removed, false otherwise. * @param removed true if displayId was removed, false otherwise.
*/ */
void _displayReconfiguration(final int displayId, final boolean removed) { void _displayReconfiguration(int displayId, boolean removed) {
synchronized (this) { // we ignore the passed parameters and check removed devices ourself
if (removed && devices.containsKey(displayId)) { // Note that it is possible that this callback is called when the
final CGraphicsDevice gd = devices.remove(displayId); // monitors are not added nor removed, but when the video card is
oldDevices.add(new WeakReference<>(gd)); // switched to/from the discrete video card, so we should try to map the
} // old to the new devices.
} rebuildDevices();
initDevices();
// Need to notify old devices, in case the user hold the reference to it
for (ListIterator<WeakReference<CGraphicsDevice>> it =
oldDevices.listIterator(); it.hasNext(); ) {
CGraphicsDevice gd = it.next().get();
if (gd != null) {
gd.invalidate(mainDisplayID);
gd.displayChanged();
} else {
// no more references to this device, remove it
it.remove();
}
}
} }
@Override @Override
@ -163,44 +156,74 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
/** /**
* (Re)create all CGraphicsDevices, reuses a devices if it is possible. * (Re)create all CGraphicsDevices, reuses a devices if it is possible.
*/ */
private void initDevices() { private synchronized void initDevices() {
synchronized (this) { Map<Integer, CGraphicsDevice> old = new HashMap<>(devices);
final Map<Integer, CGraphicsDevice> old = new HashMap<>(devices);
devices.clear(); devices.clear();
mainDisplayID = getMainDisplayID(); mainDisplayID = getMainDisplayID();
// initialization of the graphics device may change // initialization of the graphics device may change list of displays on
// list of displays on hybrid systems via an activation // hybrid systems via an activation of discrete video.
// of discrete video. // So, we initialize the main display first, then retrieve actual list
// So, we initialize the main display first, and then // of displays, and then recheck the main display again.
// retrieve actual list of displays.
if (!old.containsKey(mainDisplayID)) { if (!old.containsKey(mainDisplayID)) {
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID)); old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID));
} }
for (final int id : getDisplayIDs()) { int[] displayIDs = getDisplayIDs();
devices.put(id, old.containsKey(id) ? old.get(id) if (displayIDs.length == 0) {
// we could throw AWTError in this case.
displayIDs = new int[]{mainDisplayID};
}
for (int id : displayIDs) {
devices.put(id, old.containsKey(id) ? old.remove(id)
: new CGraphicsDevice(id)); : new CGraphicsDevice(id));
} }
// fetch the main display again, the old value might be outdated
mainDisplayID = getMainDisplayID();
// unlikely but make sure the main screen is in the list of screens,
// most probably one more "displayReconfiguration" is on the road if not
if (!devices.containsKey(mainDisplayID)) {
mainDisplayID = displayIDs[0]; // best we can do
} }
displayChanged(); // if a device was not reused it should be invalidated
for (CGraphicsDevice gd : old.values()) {
oldDevices.add(new WeakReference<>(gd));
}
// Need to notify old devices, in case the user hold the reference to it
for (ListIterator<WeakReference<CGraphicsDevice>> it =
oldDevices.listIterator(); it.hasNext(); ) {
CGraphicsDevice gd = it.next().get();
if (gd != null) {
// If the old device has the same bounds as some new device
// then map that old device to the new, or to the main screen.
CGraphicsDevice similarDevice = getSimilarDevice(gd);
if (similarDevice == null) {
gd.invalidate(devices.get(mainDisplayID));
} else {
gd.invalidate(similarDevice);
}
gd.displayChanged();
} else {
// no more references to this device, remove it
it.remove();
}
}
}
private CGraphicsDevice getSimilarDevice(CGraphicsDevice old) {
for (CGraphicsDevice device : devices.values()) {
if (device.getBounds().equals(old.getBounds())) {
// for now we will use the bounds only
return device;
}
}
return null;
} }
@Override @Override
public synchronized GraphicsDevice getDefaultScreenDevice() throws HeadlessException { public synchronized GraphicsDevice getDefaultScreenDevice() throws HeadlessException {
CGraphicsDevice d = devices.get(mainDisplayID); return devices.get(mainDisplayID);
if (d == null) {
// we do not expect that this may happen, the only response
// is to re-initialize the list of devices
initDevices();
d = devices.get(mainDisplayID);
if (d == null) {
throw new AWTError("no screen devices");
}
}
return d;
} }
@Override @Override

View file

@ -41,7 +41,7 @@ import java.util.ArrayList;
/** /**
* @test * @test
* @bug 4836241 6364134 8232200 * @bug 4836241 6364134 8232200 8252133
* @key headful * @key headful
* @summary verify that images are restored correctly after display mode * @summary verify that images are restored correctly after display mode
* switches and that no other rendering or crash problems occur * switches and that no other rendering or crash problems occur