Path: blob/master/src/java.desktop/macosx/classes/sun/awt/CGraphicsDevice.java
41152 views
/*1* Copyright (c) 2012, 2021, 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.GraphicsConfiguration;30import java.awt.GraphicsDevice;31import java.awt.Insets;32import java.awt.Rectangle;33import java.awt.Window;34import java.awt.geom.Rectangle2D;35import java.awt.peer.WindowPeer;36import java.util.Objects;3738import sun.java2d.SunGraphicsEnvironment;39import sun.java2d.MacOSFlags;40import sun.java2d.metal.MTLGraphicsConfig;41import sun.java2d.opengl.CGLGraphicsConfig;4243import static java.awt.peer.ComponentPeer.SET_BOUNDS;4445public final class CGraphicsDevice extends GraphicsDevice46implements DisplayChangedListener {4748/**49* CoreGraphics display ID. This identifier can become non-valid at any time50* therefore methods, which is using this id should be ready to it.51*/52private volatile int displayID;53private volatile double xResolution;54private volatile double yResolution;55private volatile Rectangle bounds;56private volatile int scale;5758private GraphicsConfiguration config;59private static boolean metalPipelineEnabled = false;60private static boolean oglPipelineEnabled = false;616263private static AWTPermission fullScreenExclusivePermission;6465// Save/restore DisplayMode for the Full Screen mode66private DisplayMode originalMode;6768public CGraphicsDevice(final int displayID) {69this.displayID = displayID;7071if (MacOSFlags.isMetalEnabled()) {72// Try to create MTLGraphicsConfig, if it fails,73// try to create CGLGraphicsConfig as a fallback74this.config = MTLGraphicsConfig.getConfig(this, displayID);7576if (this.config != null) {77metalPipelineEnabled = true;78} else {79// Try falling back to OpenGL pipeline80if (MacOSFlags.isMetalVerbose()) {81System.out.println("Metal rendering pipeline" +82" initialization failed,using OpenGL" +83" rendering pipeline");84}8586this.config = CGLGraphicsConfig.getConfig(this);8788if (this.config != null) {89oglPipelineEnabled = true;90}91}92} else {93// Try to create CGLGraphicsConfig, if it fails,94// try to create MTLGraphicsConfig as a fallback95this.config = CGLGraphicsConfig.getConfig(this);9697if (this.config != null) {98oglPipelineEnabled = true;99} else {100// Try falling back to Metal pipeline101if (MacOSFlags.isOGLVerbose()) {102System.out.println("OpenGL rendering pipeline" +103" initialization failed,using Metal" +104" rendering pipeline");105}106107this.config = MTLGraphicsConfig.getConfig(this, displayID);108109if (this.config != null) {110metalPipelineEnabled = true;111}112}113}114115if (!metalPipelineEnabled && !oglPipelineEnabled) {116// This indicates fallback to other rendering pipeline also failed.117// Should never reach here118throw new InternalError("Error - unable to initialize any" +119" rendering pipeline.");120}121122if (metalPipelineEnabled && MacOSFlags.isMetalVerbose()) {123System.out.println("Metal pipeline enabled on screen " + displayID);124} else if (oglPipelineEnabled && MacOSFlags.isOGLVerbose()) {125System.out.println("OpenGL pipeline enabled on screen " + displayID);126}127128// initializes default device state, might be redundant step since we129// call "displayChanged()" later anyway, but we do not want to leave the130// device in an inconsistent state after construction131displayChanged();132}133134/**135* Return a list of all configurations.136*/137@Override138public GraphicsConfiguration[] getConfigurations() {139return new GraphicsConfiguration[]{config};140}141142/**143* Return the default configuration.144*/145@Override146public GraphicsConfiguration getDefaultConfiguration() {147return config;148}149150/**151* Return a human-readable screen description.152*/153@Override154public String getIDstring() {155return "Display " + displayID;156}157158/**159* Returns the type of the graphics device.160* @see #TYPE_RASTER_SCREEN161* @see #TYPE_PRINTER162* @see #TYPE_IMAGE_BUFFER163*/164@Override165public int getType() {166return TYPE_RASTER_SCREEN;167}168169public double getXResolution() {170return xResolution;171}172173public double getYResolution() {174return yResolution;175}176177Rectangle getBounds() {178return bounds.getBounds();179}180181public Insets getScreenInsets() {182// the insets are queried synchronously and are not cached183// since there are no Quartz or Cocoa means to receive notifications184// on insets changes (e.g. when the Dock is resized):185// the existing CGDisplayReconfigurationCallBack is not notified186// as well as the NSApplicationDidChangeScreenParametersNotification187// is fired on the Dock location changes only188return nativeGetScreenInsets(displayID);189}190191public int getScaleFactor() {192return scale;193}194195/**196* Invalidates this device so it will point to some other "new" device.197*198* @param device the new device, usually the main screen199*/200public void invalidate(CGraphicsDevice device) {201//TODO do we need to restore the full-screen window/modes on old device?202displayID = device.displayID;203}204205@Override206public void displayChanged() {207xResolution = nativeGetXResolution(displayID);208yResolution = nativeGetYResolution(displayID);209bounds = nativeGetBounds(displayID).getBounds(); //does integer rounding210initScaleFactor();211resizeFSWindow(getFullScreenWindow(), bounds);212//TODO configs?213}214215@Override216public void paletteChanged() {217// devices do not need to react to this event.218}219220/**221* Enters full-screen mode, or returns to windowed mode.222*/223@Override224public synchronized void setFullScreenWindow(Window w) {225Window old = getFullScreenWindow();226if (w == old) {227return;228}229230boolean fsSupported = isFullScreenSupported();231232if (fsSupported && old != null) {233// enter windowed mode and restore original display mode234exitFullScreenExclusive(old);235if (originalMode != null) {236setDisplayMode(originalMode);237originalMode = null;238}239}240241super.setFullScreenWindow(w);242243if (fsSupported && w != null) {244if (isDisplayChangeSupported()) {245originalMode = getDisplayMode();246}247// enter fullscreen mode248enterFullScreenExclusive(w);249}250}251252/**253* Returns true if this GraphicsDevice supports254* full-screen exclusive mode and false otherwise.255*/256@Override257public boolean isFullScreenSupported() {258return isFSExclusiveModeAllowed();259}260261private static boolean isFSExclusiveModeAllowed() {262@SuppressWarnings("removal")263SecurityManager security = System.getSecurityManager();264if (security != null) {265if (fullScreenExclusivePermission == null) {266fullScreenExclusivePermission =267new AWTPermission("fullScreenExclusive");268}269try {270security.checkPermission(fullScreenExclusivePermission);271} catch (SecurityException e) {272return false;273}274}275return true;276}277278private static void enterFullScreenExclusive(Window w) {279FullScreenCapable peer = AWTAccessor.getComponentAccessor().getPeer(w);280if (peer != null) {281peer.enterFullScreenMode();282}283}284285private static void exitFullScreenExclusive(Window w) {286FullScreenCapable peer = AWTAccessor.getComponentAccessor().getPeer(w);287if (peer != null) {288peer.exitFullScreenMode();289}290}291292/**293* Reapplies the size of this device to the full-screen window.294*/295private static void resizeFSWindow(final Window w, final Rectangle b) {296if (w != null) {297WindowPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);298if (peer != null) {299peer.setBounds(b.x, b.y, b.width, b.height, SET_BOUNDS);300}301}302}303304@Override305public boolean isDisplayChangeSupported() {306return true;307}308309@Override310public void setDisplayMode(final DisplayMode dm) {311if (dm == null) {312throw new IllegalArgumentException("Invalid display mode");313}314if (!Objects.equals(dm, getDisplayMode())) {315nativeSetDisplayMode(displayID, dm.getWidth(), dm.getHeight(),316dm.getBitDepth(), dm.getRefreshRate());317}318}319320@Override321public DisplayMode getDisplayMode() {322return nativeGetDisplayMode(displayID);323}324325@Override326public DisplayMode[] getDisplayModes() {327return nativeGetDisplayModes(displayID);328}329330public static boolean usingMetalPipeline() {331return metalPipelineEnabled;332}333334private void initScaleFactor() {335if (SunGraphicsEnvironment.isUIScaleEnabled()) {336double debugScale = SunGraphicsEnvironment.getDebugScale();337scale = (int) (debugScale >= 1338? Math.round(debugScale)339: nativeGetScaleFactor(displayID));340} else {341scale = 1;342}343}344345private static native double nativeGetScaleFactor(int displayID);346347private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate);348349private static native DisplayMode nativeGetDisplayMode(int displayID);350351private static native DisplayMode[] nativeGetDisplayModes(int displayID);352353private static native double nativeGetXResolution(int displayID);354355private static native double nativeGetYResolution(int displayID);356357private static native Insets nativeGetScreenInsets(int displayID);358359private static native Rectangle2D nativeGetBounds(int displayID);360}361362363