Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java
41152 views
1
/*
2
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.awt;
27
28
import java.awt.AWTPermission;
29
import java.awt.DisplayMode;
30
import java.awt.GraphicsConfiguration;
31
import java.awt.GraphicsDevice;
32
import java.awt.GraphicsEnvironment;
33
import java.awt.Rectangle;
34
import java.awt.Window;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
37
import java.util.ArrayList;
38
import java.util.HashMap;
39
import java.util.HashSet;
40
41
import sun.awt.util.ThreadGroupUtils;
42
import sun.java2d.SunGraphicsEnvironment;
43
import sun.java2d.loops.SurfaceType;
44
import sun.java2d.opengl.GLXGraphicsConfig;
45
import sun.java2d.pipe.Region;
46
import sun.java2d.xr.XRGraphicsConfig;
47
48
/**
49
* This is an implementation of a GraphicsDevice object for a single
50
* X11 screen.
51
*
52
* @see GraphicsEnvironment
53
* @see GraphicsConfiguration
54
*/
55
public final class X11GraphicsDevice extends GraphicsDevice
56
implements DisplayChangedListener {
57
/**
58
* X11 screen number. This identifier can become non-valid at any time
59
* therefore methods, which is using this id should be ready to it.
60
*/
61
private volatile int screen;
62
HashMap<SurfaceType, Object> x11ProxyKeyMap = new HashMap<>();
63
64
private static AWTPermission fullScreenExclusivePermission;
65
private static Boolean xrandrExtSupported;
66
private final Object configLock = new Object();
67
private SunDisplayChanger topLevels = new SunDisplayChanger();
68
private DisplayMode origDisplayMode;
69
private boolean shutdownHookRegistered;
70
private int scale;
71
72
public X11GraphicsDevice(int screennum) {
73
this.screen = screennum;
74
this.scale = initScaleFactor();
75
}
76
77
/**
78
* Returns the X11 screen of the device.
79
*/
80
public int getScreen() {
81
return screen;
82
}
83
84
public Object getProxyKeyFor(SurfaceType st) {
85
synchronized (x11ProxyKeyMap) {
86
Object o = x11ProxyKeyMap.get(st);
87
if (o == null) {
88
o = new Object();
89
x11ProxyKeyMap.put(st, o);
90
}
91
return o;
92
}
93
}
94
95
/**
96
* Returns the X11 Display of this device.
97
* This method is also in MDrawingSurfaceInfo but need it here
98
* to be able to allow a GraphicsConfigTemplate to get the Display.
99
*/
100
public native long getDisplay();
101
102
/**
103
* Returns the type of the graphics device.
104
* @see #TYPE_RASTER_SCREEN
105
* @see #TYPE_PRINTER
106
* @see #TYPE_IMAGE_BUFFER
107
*/
108
@Override
109
public int getType() {
110
return TYPE_RASTER_SCREEN;
111
}
112
113
public int scaleUp(int x) {
114
return Region.clipRound(x * (double)getScaleFactor());
115
}
116
117
public int scaleDown(int x) {
118
return Region.clipRound(x / (double)getScaleFactor());
119
}
120
121
public Rectangle getBounds() {
122
Rectangle rect = pGetBounds(getScreen());
123
if (getScaleFactor() != 1) {
124
rect.x = scaleDown(rect.x);
125
rect.y = scaleDown(rect.y);
126
rect.width = scaleDown(rect.width);
127
rect.height = scaleDown(rect.height);
128
}
129
return rect;
130
}
131
132
/**
133
* Returns the identification string associated with this graphics
134
* device.
135
*/
136
@Override
137
public String getIDstring() {
138
return ":0."+screen;
139
}
140
141
142
GraphicsConfiguration[] configs;
143
GraphicsConfiguration defaultConfig;
144
HashSet<Integer> doubleBufferVisuals;
145
146
/**
147
* Returns all of the graphics
148
* configurations associated with this graphics device.
149
*/
150
@Override
151
public GraphicsConfiguration[] getConfigurations() {
152
if (configs == null) {
153
synchronized (configLock) {
154
makeConfigurations();
155
}
156
}
157
return configs.clone();
158
}
159
160
private void makeConfigurations() {
161
if (configs == null) {
162
int i = 1; // Index 0 is always the default config
163
int num = getNumConfigs(screen);
164
GraphicsConfiguration[] ret = new GraphicsConfiguration[num];
165
if (defaultConfig == null) {
166
ret [0] = getDefaultConfiguration();
167
}
168
else {
169
ret [0] = defaultConfig;
170
}
171
172
boolean glxSupported = X11GraphicsEnvironment.isGLXAvailable();
173
boolean xrenderSupported = X11GraphicsEnvironment.isXRenderAvailable();
174
175
boolean dbeSupported = isDBESupported();
176
if (dbeSupported && doubleBufferVisuals == null) {
177
doubleBufferVisuals = new HashSet<>();
178
getDoubleBufferVisuals(screen);
179
}
180
for ( ; i < num; i++) {
181
int visNum = getConfigVisualId(i, screen);
182
int depth = getConfigDepth (i, screen);
183
if (glxSupported) {
184
ret[i] = GLXGraphicsConfig.getConfig(this, visNum);
185
}
186
if (ret[i] == null) {
187
boolean doubleBuffer =
188
(dbeSupported &&
189
doubleBufferVisuals.contains(Integer.valueOf(visNum)));
190
191
if (xrenderSupported) {
192
ret[i] = XRGraphicsConfig.getConfig(this, visNum, depth,
193
getConfigColormap(i, screen), doubleBuffer);
194
} else {
195
ret[i] = X11GraphicsConfig.getConfig(this, visNum, depth,
196
getConfigColormap(i, screen),
197
doubleBuffer);
198
}
199
}
200
}
201
configs = ret;
202
}
203
}
204
205
/*
206
* Returns the number of X11 visuals representable as an
207
* X11GraphicsConfig object.
208
*/
209
public native int getNumConfigs(int screen);
210
211
/*
212
* Returns the visualid for the given index of graphics configurations.
213
*/
214
public native int getConfigVisualId (int index, int screen);
215
/*
216
* Returns the depth for the given index of graphics configurations.
217
*/
218
private native int getConfigDepth(int index, int screen);
219
220
/*
221
* Returns the colormap for the given index of graphics configurations.
222
*/
223
private native int getConfigColormap(int index, int screen);
224
225
// Whether or not double-buffering extension is supported
226
static native boolean isDBESupported();
227
// Callback for adding a new double buffer visual into our set
228
private void addDoubleBufferVisual(int visNum) {
229
doubleBufferVisuals.add(Integer.valueOf(visNum));
230
}
231
// Enumerates all visuals that support double buffering
232
private native void getDoubleBufferVisuals(int screen);
233
234
/**
235
* Returns the default graphics configuration
236
* associated with this graphics device.
237
*/
238
@Override
239
public GraphicsConfiguration getDefaultConfiguration() {
240
if (defaultConfig == null) {
241
synchronized (configLock) {
242
makeDefaultConfiguration();
243
}
244
}
245
return defaultConfig;
246
}
247
248
private void makeDefaultConfiguration() {
249
if (defaultConfig == null) {
250
int visNum = getConfigVisualId(0, screen);
251
if (X11GraphicsEnvironment.isGLXAvailable()) {
252
defaultConfig = GLXGraphicsConfig.getConfig(this, visNum);
253
if (X11GraphicsEnvironment.isGLXVerbose()) {
254
if (defaultConfig != null) {
255
System.out.print("OpenGL pipeline enabled");
256
} else {
257
System.out.print("Could not enable OpenGL pipeline");
258
}
259
System.out.println(" for default config on screen " +
260
screen);
261
}
262
}
263
if (defaultConfig == null) {
264
int depth = getConfigDepth(0, screen);
265
boolean doubleBuffer = false;
266
if (isDBESupported() && doubleBufferVisuals == null) {
267
doubleBufferVisuals = new HashSet<>();
268
getDoubleBufferVisuals(screen);
269
doubleBuffer =
270
doubleBufferVisuals.contains(Integer.valueOf(visNum));
271
}
272
273
if (X11GraphicsEnvironment.isXRenderAvailable()) {
274
if (X11GraphicsEnvironment.isXRenderVerbose()) {
275
System.out.println("XRender pipeline enabled");
276
}
277
defaultConfig = XRGraphicsConfig.getConfig(this, visNum,
278
depth, getConfigColormap(0, screen),
279
doubleBuffer);
280
} else {
281
defaultConfig = X11GraphicsConfig.getConfig(this, visNum,
282
depth, getConfigColormap(0, screen),
283
doubleBuffer);
284
}
285
}
286
}
287
}
288
289
private static native void enterFullScreenExclusive(long window);
290
private static native void exitFullScreenExclusive(long window);
291
private static native boolean initXrandrExtension();
292
private static native DisplayMode getCurrentDisplayMode(int screen);
293
private static native void enumDisplayModes(int screen,
294
ArrayList<DisplayMode> modes);
295
private static native void configDisplayMode(int screen,
296
int width, int height,
297
int displayMode);
298
private static native double getNativeScaleFactor(int screen);
299
private native Rectangle pGetBounds(int screenNum);
300
301
/**
302
* Returns true only if:
303
* - the Xrandr extension is present
304
* - the necessary Xrandr functions were loaded successfully
305
*/
306
private static synchronized boolean isXrandrExtensionSupported() {
307
if (xrandrExtSupported == null) {
308
xrandrExtSupported =
309
Boolean.valueOf(initXrandrExtension());
310
}
311
return xrandrExtSupported.booleanValue();
312
}
313
314
@Override
315
public boolean isFullScreenSupported() {
316
boolean fsAvailable = isXrandrExtensionSupported();
317
if (fsAvailable) {
318
@SuppressWarnings("removal")
319
SecurityManager security = System.getSecurityManager();
320
if (security != null) {
321
if (fullScreenExclusivePermission == null) {
322
fullScreenExclusivePermission =
323
new AWTPermission("fullScreenExclusive");
324
}
325
try {
326
security.checkPermission(fullScreenExclusivePermission);
327
} catch (SecurityException e) {
328
return false;
329
}
330
}
331
}
332
return fsAvailable;
333
}
334
335
@Override
336
public boolean isDisplayChangeSupported() {
337
return (isFullScreenSupported()
338
&& (getFullScreenWindow() != null)
339
&& !((X11GraphicsEnvironment) GraphicsEnvironment
340
.getLocalGraphicsEnvironment()).runningXinerama());
341
}
342
343
private static void enterFullScreenExclusive(Window w) {
344
X11ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);
345
if (peer != null) {
346
enterFullScreenExclusive(peer.getWindow());
347
peer.setFullScreenExclusiveModeState(true);
348
}
349
}
350
351
private static void exitFullScreenExclusive(Window w) {
352
X11ComponentPeer peer = AWTAccessor.getComponentAccessor().getPeer(w);
353
if (peer != null) {
354
peer.setFullScreenExclusiveModeState(false);
355
exitFullScreenExclusive(peer.getWindow());
356
}
357
}
358
359
@Override
360
public synchronized void setFullScreenWindow(Window w) {
361
Window old = getFullScreenWindow();
362
if (w == old) {
363
return;
364
}
365
366
boolean fsSupported = isFullScreenSupported();
367
if (fsSupported && old != null) {
368
// enter windowed mode (and restore original display mode)
369
exitFullScreenExclusive(old);
370
if (isDisplayChangeSupported()) {
371
setDisplayMode(origDisplayMode);
372
}
373
}
374
375
super.setFullScreenWindow(w);
376
377
if (fsSupported && w != null) {
378
// save original display mode
379
if (origDisplayMode == null) {
380
origDisplayMode = getDisplayMode();
381
}
382
383
// enter fullscreen mode
384
enterFullScreenExclusive(w);
385
}
386
}
387
388
private DisplayMode getDefaultDisplayMode() {
389
GraphicsConfiguration gc = getDefaultConfiguration();
390
Rectangle r = gc.getBounds();
391
return new DisplayMode(r.width, r.height,
392
DisplayMode.BIT_DEPTH_MULTI,
393
DisplayMode.REFRESH_RATE_UNKNOWN);
394
}
395
396
@Override
397
public synchronized DisplayMode getDisplayMode() {
398
if (isFullScreenSupported()) {
399
DisplayMode mode = getCurrentDisplayMode(screen);
400
if (mode == null) {
401
mode = getDefaultDisplayMode();
402
}
403
return mode;
404
} else {
405
if (origDisplayMode == null) {
406
origDisplayMode = getDefaultDisplayMode();
407
}
408
return origDisplayMode;
409
}
410
}
411
412
@Override
413
public synchronized DisplayMode[] getDisplayModes() {
414
if (!isFullScreenSupported()
415
|| ((X11GraphicsEnvironment) GraphicsEnvironment
416
.getLocalGraphicsEnvironment()).runningXinerama()) {
417
// only the current mode will be returned
418
return super.getDisplayModes();
419
}
420
ArrayList<DisplayMode> modes = new ArrayList<DisplayMode>();
421
enumDisplayModes(screen, modes);
422
DisplayMode[] retArray = new DisplayMode[modes.size()];
423
return modes.toArray(retArray);
424
}
425
426
@SuppressWarnings("removal")
427
@Override
428
public synchronized void setDisplayMode(DisplayMode dm) {
429
if (!isDisplayChangeSupported()) {
430
super.setDisplayMode(dm);
431
return;
432
}
433
Window w = getFullScreenWindow();
434
if (w == null) {
435
throw new IllegalStateException("Must be in fullscreen mode " +
436
"in order to set display mode");
437
}
438
if (getDisplayMode().equals(dm)) {
439
return;
440
}
441
if (dm == null ||
442
(dm = getMatchingDisplayMode(dm)) == null)
443
{
444
throw new IllegalArgumentException("Invalid display mode");
445
}
446
447
if (!shutdownHookRegistered) {
448
// register a shutdown hook so that we return to the
449
// original DisplayMode when the VM exits (if the application
450
// is already in the original DisplayMode at that time, this
451
// hook will have no effect)
452
shutdownHookRegistered = true;
453
PrivilegedAction<Void> a = () -> {
454
Runnable r = () -> {
455
Window old = getFullScreenWindow();
456
if (old != null) {
457
exitFullScreenExclusive(old);
458
if (isDisplayChangeSupported()) {
459
setDisplayMode(origDisplayMode);
460
}
461
}
462
};
463
String name = "Display-Change-Shutdown-Thread-" + screen;
464
Thread t = new Thread(
465
ThreadGroupUtils.getRootThreadGroup(), r, name, 0, false);
466
t.setContextClassLoader(null);
467
Runtime.getRuntime().addShutdownHook(t);
468
return null;
469
};
470
AccessController.doPrivileged(a);
471
}
472
473
// switch to the new DisplayMode
474
configDisplayMode(screen,
475
dm.getWidth(), dm.getHeight(),
476
dm.getRefreshRate());
477
478
// update bounds of the fullscreen window
479
w.setBounds(0, 0, dm.getWidth(), dm.getHeight());
480
481
// configDisplayMode() is synchronous, so the display change will be
482
// complete by the time we get here (and it is therefore safe to call
483
// displayChanged() now)
484
((X11GraphicsEnvironment)
485
GraphicsEnvironment.getLocalGraphicsEnvironment()).displayChanged();
486
}
487
488
private synchronized DisplayMode getMatchingDisplayMode(DisplayMode dm) {
489
if (!isDisplayChangeSupported()) {
490
return null;
491
}
492
DisplayMode[] modes = getDisplayModes();
493
for (DisplayMode mode : modes) {
494
if (dm.equals(mode) ||
495
(dm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN &&
496
dm.getWidth() == mode.getWidth() &&
497
dm.getHeight() == mode.getHeight() &&
498
dm.getBitDepth() == mode.getBitDepth()))
499
{
500
return mode;
501
}
502
}
503
return null;
504
}
505
506
/**
507
* From the DisplayChangedListener interface; called from
508
* X11GraphicsEnvironment when the display mode has been changed.
509
*/
510
@Override
511
public synchronized void displayChanged() {
512
scale = initScaleFactor();
513
// On X11 the visuals do not change, and therefore we don't need
514
// to reset the defaultConfig, config, doubleBufferVisuals,
515
// neither do we need to reset the native data.
516
517
// pass on to all top-level windows on this screen
518
topLevels.notifyListeners();
519
}
520
521
/**
522
* From the DisplayChangedListener interface; devices do not need
523
* to react to this event.
524
*/
525
@Override
526
public void paletteChanged() {
527
}
528
529
/**
530
* Add a DisplayChangeListener to be notified when the display settings
531
* are changed. Typically, only top-level containers need to be added
532
* to X11GraphicsDevice.
533
*/
534
public void addDisplayChangedListener(DisplayChangedListener client) {
535
topLevels.add(client);
536
}
537
538
public int getScaleFactor() {
539
return scale;
540
}
541
542
public int getNativeScale() {
543
return (int)Math.round(getNativeScaleFactor(screen));
544
}
545
546
private int initScaleFactor() {
547
548
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
549
550
double debugScale = SunGraphicsEnvironment.getDebugScale();
551
552
if (debugScale >= 1) {
553
return (int) debugScale;
554
}
555
int nativeScale = getNativeScale();
556
return nativeScale >= 1 ? nativeScale : 1;
557
}
558
559
return 1;
560
}
561
562
/**
563
* Remove a DisplayChangeListener from this X11GraphicsDevice.
564
*/
565
public void removeDisplayChangedListener(DisplayChangedListener client) {
566
topLevels.remove(client);
567
}
568
569
public String toString() {
570
return ("X11GraphicsDevice[screen="+screen+"]");
571
}
572
573
public void invalidate(X11GraphicsDevice device) {
574
screen = device.screen;
575
}
576
}
577
578