Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/awt/X11GraphicsDevice.java
32287 views
/*1* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.awt;2627import java.awt.AWTPermission;28import java.awt.DisplayMode;29import java.awt.GraphicsEnvironment;30import java.awt.GraphicsDevice;31import java.awt.GraphicsConfiguration;32import java.awt.Rectangle;33import java.awt.Window;34import java.security.AccessController;35import java.security.PrivilegedAction;36import java.util.ArrayList;37import java.util.HashSet;38import java.util.HashMap;3940import sun.java2d.opengl.GLXGraphicsConfig;41import sun.java2d.xr.XRGraphicsConfig;42import sun.java2d.loops.SurfaceType;4344import sun.misc.ThreadGroupUtils;4546/**47* This is an implementation of a GraphicsDevice object for a single48* X11 screen.49*50* @see GraphicsEnvironment51* @see GraphicsConfiguration52*/53public class X11GraphicsDevice54extends GraphicsDevice55implements DisplayChangedListener56{57int screen;58HashMap x11ProxyKeyMap = new HashMap();5960private static AWTPermission fullScreenExclusivePermission;61private static Boolean xrandrExtSupported;62private final Object configLock = new Object();63private SunDisplayChanger topLevels = new SunDisplayChanger();64private DisplayMode origDisplayMode;65private boolean shutdownHookRegistered;6667public X11GraphicsDevice(int screennum) {68this.screen = screennum;69}7071/*72* Initialize JNI field and method IDs for fields that may be73* accessed from C.74*/75private static native void initIDs();7677static {78if (!GraphicsEnvironment.isHeadless()) {79initIDs();80}81}8283/**84* Returns the X11 screen of the device.85*/86public int getScreen() {87return screen;88}8990public Object getProxyKeyFor(SurfaceType st) {91synchronized (x11ProxyKeyMap) {92Object o = x11ProxyKeyMap.get(st);93if (o == null) {94o = new Object();95x11ProxyKeyMap.put(st, o);96}97return o;98}99}100101/**102* Returns the X11 Display of this device.103* This method is also in MDrawingSurfaceInfo but need it here104* to be able to allow a GraphicsConfigTemplate to get the Display.105*/106public native long getDisplay();107108/**109* Returns the type of the graphics device.110* @see #TYPE_RASTER_SCREEN111* @see #TYPE_PRINTER112* @see #TYPE_IMAGE_BUFFER113*/114public int getType() {115return TYPE_RASTER_SCREEN;116}117118/**119* Returns the identification string associated with this graphics120* device.121*/122public String getIDstring() {123return ":0."+screen;124}125126127GraphicsConfiguration[] configs;128GraphicsConfiguration defaultConfig;129HashSet doubleBufferVisuals;130131/**132* Returns all of the graphics133* configurations associated with this graphics device.134*/135public GraphicsConfiguration[] getConfigurations() {136if (configs == null) {137synchronized (configLock) {138makeConfigurations();139}140}141return configs.clone();142}143144private void makeConfigurations() {145if (configs == null) {146int i = 1; // Index 0 is always the default config147int num = getNumConfigs(screen);148GraphicsConfiguration[] ret = new GraphicsConfiguration[num];149if (defaultConfig == null) {150ret [0] = getDefaultConfiguration();151}152else {153ret [0] = defaultConfig;154}155156boolean glxSupported = X11GraphicsEnvironment.isGLXAvailable();157boolean xrenderSupported = X11GraphicsEnvironment.isXRenderAvailable();158159boolean dbeSupported = isDBESupported();160if (dbeSupported && doubleBufferVisuals == null) {161doubleBufferVisuals = new HashSet();162getDoubleBufferVisuals(screen);163}164for ( ; i < num; i++) {165int visNum = getConfigVisualId(i, screen);166int depth = getConfigDepth (i, screen);167if (glxSupported) {168ret[i] = GLXGraphicsConfig.getConfig(this, visNum);169}170if (ret[i] == null) {171boolean doubleBuffer =172(dbeSupported &&173doubleBufferVisuals.contains(Integer.valueOf(visNum)));174175if (xrenderSupported) {176ret[i] = XRGraphicsConfig.getConfig(this, visNum, depth, getConfigColormap(i, screen),177doubleBuffer);178} else {179ret[i] = X11GraphicsConfig.getConfig(this, visNum, depth,180getConfigColormap(i, screen),181doubleBuffer);182}183}184}185configs = ret;186}187}188189/*190* Returns the number of X11 visuals representable as an191* X11GraphicsConfig object.192*/193public native int getNumConfigs(int screen);194195/*196* Returns the visualid for the given index of graphics configurations.197*/198public native int getConfigVisualId (int index, int screen);199/*200* Returns the depth for the given index of graphics configurations.201*/202public native int getConfigDepth (int index, int screen);203204/*205* Returns the colormap for the given index of graphics configurations.206*/207public native int getConfigColormap (int index, int screen);208209210// Whether or not double-buffering extension is supported211public static native boolean isDBESupported();212// Callback for adding a new double buffer visual into our set213private void addDoubleBufferVisual(int visNum) {214doubleBufferVisuals.add(Integer.valueOf(visNum));215}216// Enumerates all visuals that support double buffering217private native void getDoubleBufferVisuals(int screen);218219/**220* Returns the default graphics configuration221* associated with this graphics device.222*/223public GraphicsConfiguration getDefaultConfiguration() {224if (defaultConfig == null) {225synchronized (configLock) {226makeDefaultConfiguration();227}228}229return defaultConfig;230}231232private void makeDefaultConfiguration() {233if (defaultConfig == null) {234int visNum = getConfigVisualId(0, screen);235if (X11GraphicsEnvironment.isGLXAvailable()) {236defaultConfig = GLXGraphicsConfig.getConfig(this, visNum);237if (X11GraphicsEnvironment.isGLXVerbose()) {238if (defaultConfig != null) {239System.out.print("OpenGL pipeline enabled");240} else {241System.out.print("Could not enable OpenGL pipeline");242}243System.out.println(" for default config on screen " +244screen);245}246}247if (defaultConfig == null) {248int depth = getConfigDepth(0, screen);249boolean doubleBuffer = false;250if (isDBESupported() && doubleBufferVisuals == null) {251doubleBufferVisuals = new HashSet();252getDoubleBufferVisuals(screen);253doubleBuffer =254doubleBufferVisuals.contains(Integer.valueOf(visNum));255}256257if (X11GraphicsEnvironment.isXRenderAvailable()) {258if (X11GraphicsEnvironment.isXRenderVerbose()) {259System.out.println("XRender pipeline enabled");260}261defaultConfig = XRGraphicsConfig.getConfig(this, visNum,262depth, getConfigColormap(0, screen),263doubleBuffer);264} else {265defaultConfig = X11GraphicsConfig.getConfig(this, visNum,266depth, getConfigColormap(0, screen),267doubleBuffer);268}269}270}271}272273private static native void enterFullScreenExclusive(long window);274private static native void exitFullScreenExclusive(long window);275private static native boolean initXrandrExtension();276private static native DisplayMode getCurrentDisplayMode(int screen);277private static native void enumDisplayModes(int screen,278ArrayList<DisplayMode> modes);279private static native void configDisplayMode(int screen,280int width, int height,281int displayMode);282private static native void resetNativeData(int screen);283284/**285* Returns true only if:286* - the Xrandr extension is present287* - the necessary Xrandr functions were loaded successfully288*/289private static synchronized boolean isXrandrExtensionSupported() {290if (xrandrExtSupported == null) {291xrandrExtSupported =292Boolean.valueOf(initXrandrExtension());293}294return xrandrExtSupported.booleanValue();295}296297@Override298public boolean isFullScreenSupported() {299boolean fsAvailable = isXrandrExtensionSupported();300if (fsAvailable) {301SecurityManager security = System.getSecurityManager();302if (security != null) {303if (fullScreenExclusivePermission == null) {304fullScreenExclusivePermission =305new AWTPermission("fullScreenExclusive");306}307try {308security.checkPermission(fullScreenExclusivePermission);309} catch (SecurityException e) {310return false;311}312}313}314return fsAvailable;315}316317@Override318public boolean isDisplayChangeSupported() {319return (isFullScreenSupported()320&& (getFullScreenWindow() != null)321&& !((X11GraphicsEnvironment) GraphicsEnvironment322.getLocalGraphicsEnvironment()).runningXinerama());323}324325private static void enterFullScreenExclusive(Window w) {326X11ComponentPeer peer = (X11ComponentPeer)w.getPeer();327if (peer != null) {328enterFullScreenExclusive(peer.getWindow());329peer.setFullScreenExclusiveModeState(true);330}331}332333private static void exitFullScreenExclusive(Window w) {334X11ComponentPeer peer = (X11ComponentPeer)w.getPeer();335if (peer != null) {336peer.setFullScreenExclusiveModeState(false);337exitFullScreenExclusive(peer.getWindow());338}339}340341@Override342public synchronized void setFullScreenWindow(Window w) {343Window old = getFullScreenWindow();344if (w == old) {345return;346}347348boolean fsSupported = isFullScreenSupported();349if (fsSupported && old != null) {350// enter windowed mode (and restore original display mode)351exitFullScreenExclusive(old);352if (isDisplayChangeSupported()) {353setDisplayMode(origDisplayMode);354}355}356357super.setFullScreenWindow(w);358359if (fsSupported && w != null) {360// save original display mode361if (origDisplayMode == null) {362origDisplayMode = getDisplayMode();363}364365// enter fullscreen mode366enterFullScreenExclusive(w);367}368}369370private DisplayMode getDefaultDisplayMode() {371GraphicsConfiguration gc = getDefaultConfiguration();372Rectangle r = gc.getBounds();373return new DisplayMode(r.width, r.height,374DisplayMode.BIT_DEPTH_MULTI,375DisplayMode.REFRESH_RATE_UNKNOWN);376}377378@Override379public synchronized DisplayMode getDisplayMode() {380if (isFullScreenSupported()) {381DisplayMode mode = getCurrentDisplayMode(screen);382if (mode == null) {383mode = getDefaultDisplayMode();384}385return mode;386} else {387if (origDisplayMode == null) {388origDisplayMode = getDefaultDisplayMode();389}390return origDisplayMode;391}392}393394@Override395public synchronized DisplayMode[] getDisplayModes() {396if (!isFullScreenSupported()) {397return super.getDisplayModes();398}399ArrayList<DisplayMode> modes = new ArrayList<DisplayMode>();400enumDisplayModes(screen, modes);401DisplayMode[] retArray = new DisplayMode[modes.size()];402return modes.toArray(retArray);403}404405@Override406public synchronized void setDisplayMode(DisplayMode dm) {407if (!isDisplayChangeSupported()) {408super.setDisplayMode(dm);409return;410}411Window w = getFullScreenWindow();412if (w == null) {413throw new IllegalStateException("Must be in fullscreen mode " +414"in order to set display mode");415}416if (getDisplayMode().equals(dm)) {417return;418}419if (dm == null ||420(dm = getMatchingDisplayMode(dm)) == null)421{422throw new IllegalArgumentException("Invalid display mode");423}424425if (!shutdownHookRegistered) {426// register a shutdown hook so that we return to the427// original DisplayMode when the VM exits (if the application428// is already in the original DisplayMode at that time, this429// hook will have no effect)430shutdownHookRegistered = true;431PrivilegedAction<Void> a = () -> {432ThreadGroup rootTG = ThreadGroupUtils.getRootThreadGroup();433Runnable r = () -> {434Window old = getFullScreenWindow();435if (old != null) {436exitFullScreenExclusive(old);437if (isDisplayChangeSupported()) {438setDisplayMode(origDisplayMode);439}440}441};442Thread t = new Thread(rootTG, r,"Display-Change-Shutdown-Thread-"+screen);443t.setContextClassLoader(null);444Runtime.getRuntime().addShutdownHook(t);445return null;446};447AccessController.doPrivileged(a);448}449450// switch to the new DisplayMode451configDisplayMode(screen,452dm.getWidth(), dm.getHeight(),453dm.getRefreshRate());454455// update bounds of the fullscreen window456w.setBounds(0, 0, dm.getWidth(), dm.getHeight());457458// configDisplayMode() is synchronous, so the display change will be459// complete by the time we get here (and it is therefore safe to call460// displayChanged() now)461((X11GraphicsEnvironment)462GraphicsEnvironment.getLocalGraphicsEnvironment()).displayChanged();463}464465private synchronized DisplayMode getMatchingDisplayMode(DisplayMode dm) {466if (!isDisplayChangeSupported()) {467return null;468}469DisplayMode[] modes = getDisplayModes();470for (DisplayMode mode : modes) {471if (dm.equals(mode) ||472(dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN &&473dm.getWidth() == mode.getWidth() &&474dm.getHeight() == mode.getHeight() &&475dm.getBitDepth() == mode.getBitDepth()))476{477return mode;478}479}480return null;481}482483/**484* From the DisplayChangedListener interface; called from485* X11GraphicsEnvironment when the display mode has been changed.486*/487public synchronized void displayChanged() {488// On X11 the visuals do not change, and therefore we don't need489// to reset the defaultConfig, config, doubleBufferVisuals,490// neither do we need to reset the native data.491492// pass on to all top-level windows on this screen493topLevels.notifyListeners();494}495496/**497* From the DisplayChangedListener interface; devices do not need498* to react to this event.499*/500public void paletteChanged() {501}502503/**504* Add a DisplayChangeListener to be notified when the display settings505* are changed. Typically, only top-level containers need to be added506* to X11GraphicsDevice.507*/508public void addDisplayChangedListener(DisplayChangedListener client) {509topLevels.add(client);510}511512/**513* Remove a DisplayChangeListener from this X11GraphicsDevice.514*/515public void removeDisplayChangedListener(DisplayChangedListener client) {516topLevels.remove(client);517}518519public String toString() {520return ("X11GraphicsDevice[screen="+screen+"]");521}522}523524525