8022810: Cannot list all the available display modes on Ubuntu linux in case of two screen devices
authorssadetsky
Tue, 05 Jul 2016 12:37:36 +0300
changeset 39556 50963eeaefca
parent 39555 5cf973a23925
child 39557 2503195ecd80
child 39836 f8ffbd878ae2
8022810: Cannot list all the available display modes on Ubuntu linux in case of two screen devices Reviewed-by: alexsch, serb
jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h
jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c
jdk/src/java.desktop/unix/native/libawt_xawt/awt/randr.h
jdk/test/java/awt/GraphicsDevice/DisplayModes/CompareToXrandrTest.java
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h	Tue Jul 05 09:48:49 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h	Tue Jul 05 12:37:36 2016 +0300
@@ -5,8 +5,8 @@
 /*
  * $XFree86: xc/lib/Xrandr/Xrandr.h,v 1.9 2002/09/29 23:39:44 keithp Exp $
  *
- * Copyright © 2000 Compaq Computer Corporation, Inc.
- * Copyright © 2002 Hewlett-Packard Company, Inc.
+ * Copyright © 2000 Compaq Computer Corporation, Inc.
+ * Copyright © 2002 Hewlett-Packard Company, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -66,6 +66,65 @@
     int mheight;
 } XRRScreenChangeNotifyEvent;
 
+typedef XID RROutput;
+typedef XID RRCrtc;
+typedef XID RRMode;
+
+typedef unsigned long XRRModeFlags;
+
+typedef struct {
+    RRMode              id;
+    unsigned int        width;
+    unsigned int        height;
+    unsigned long       dotClock;
+    unsigned int        hSyncStart;
+    unsigned int        hSyncEnd;
+    unsigned int        hTotal;
+    unsigned int        hSkew;
+    unsigned int        vSyncStart;
+    unsigned int        vSyncEnd;
+    unsigned int        vTotal;
+    char                *name;
+    unsigned int        nameLength;
+    XRRModeFlags        modeFlags;
+} XRRModeInfo;
+
+typedef struct {
+    Time        timestamp;
+    Time        configTimestamp;
+    int         ncrtc;
+    RRCrtc      *crtcs;
+    int         noutput;
+    RROutput    *outputs;
+    int         nmode;
+    XRRModeInfo *modes;
+} XRRScreenResources;
+
+typedef struct {
+    Time            timestamp;
+    RRCrtc          crtc;
+    char            *name;
+    int             nameLen;
+    unsigned long   mm_width;
+    unsigned long   mm_height;
+    Connection      connection;
+    SubpixelOrder   subpixel_order;
+    int             ncrtc;
+    RRCrtc          *crtcs;
+    int             nclone;
+    RROutput        *clones;
+    int             nmode;
+    int             npreferred;
+    RRMode          *modes;
+} XRROutputInfo;
+
+XRRScreenResources *XRRGetScreenResources (Display *dpy, Window window);
+
+void XRRFreeScreenResources (XRRScreenResources *resources);
+
+XRROutputInfo * XRRGetOutputInfo (Display *dpy, XRRScreenResources *resources,
+                                                               RROutput output);
+void XRRFreeOutputInfo (XRROutputInfo *outputInfo);
 
 /* internal representation is private to the library */
 typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c	Tue Jul 05 09:48:49 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c	Tue Jul 05 12:37:36 2016 +0300
@@ -1657,6 +1657,16 @@
     (*XRRConfigRotationsType)(XRRScreenConfiguration *config,
                               Rotation *current_rotation);
 
+typedef XRRScreenResources* (*XRRGetScreenResourcesType)(Display *dpy,
+                                                                 Window window);
+
+typedef void (*XRRFreeScreenResourcesType)(XRRScreenResources *resources);
+
+typedef XRROutputInfo * (*XRRGetOutputInfoType)(Display *dpy,
+                                XRRScreenResources *resources, RROutput output);
+
+typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);
+
 static XRRQueryVersionType               awt_XRRQueryVersion;
 static XRRGetScreenInfoType              awt_XRRGetScreenInfo;
 static XRRFreeScreenConfigInfoType       awt_XRRFreeScreenConfigInfo;
@@ -1666,6 +1676,10 @@
 static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;
 static XRRSetScreenConfigAndRateType     awt_XRRSetScreenConfigAndRate;
 static XRRConfigRotationsType            awt_XRRConfigRotations;
+static XRRGetScreenResourcesType         awt_XRRGetScreenResources;
+static XRRFreeScreenResourcesType        awt_XRRFreeScreenResources;
+static XRRGetOutputInfoType              awt_XRRGetOutputInfo;
+static XRRFreeOutputInfoType             awt_XRRFreeOutputInfo;
 
 #define LOAD_XRANDR_FUNC(f) \
     do { \
@@ -1737,6 +1751,10 @@
     LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);
     LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);
     LOAD_XRANDR_FUNC(XRRConfigRotations);
+    LOAD_XRANDR_FUNC(XRRGetScreenResources);
+    LOAD_XRANDR_FUNC(XRRFreeScreenResources);
+    LOAD_XRANDR_FUNC(XRRGetOutputInfo);
+    LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
 
     return JNI_TRUE;
 }
@@ -1924,36 +1942,73 @@
      jint screen, jobject arrayList)
 {
 #ifndef HEADLESS
-    XRRScreenConfiguration *config;
 
     AWT_LOCK();
 
-    config = awt_XRRGetScreenInfo(awt_display,
-                                  RootWindow(awt_display, screen));
-    if (config != NULL) {
-        int nsizes, i, j;
-        XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
+    if (usingXinerama && XScreenCount(awt_display) > 0) {
+        XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
+                                                    RootWindow(awt_display, 0));
+        if (res) {
+           if (res->noutput > screen) {
+                XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
+                                                     res, res->outputs[screen]);
+                if (output_info) {
+                    int i;
+                    for (i = 0; i < res->nmode; i++) {
+                        RRMode m = output_info->modes[i];
+                        int j;
+                        XRRModeInfo *mode;
+                        for (j = 0; j < res->nmode; j++) {
+                            mode = &res->modes[j];
+                            if (mode->id == m) {
+                                 float rate = 0;
+                                 if (mode->hTotal && mode->vTotal) {
+                                     rate = ((float)mode->dotClock /
+                                                   ((float)mode->hTotal *
+                                                          (float)mode->vTotal));
+                                 }
+                                 X11GD_AddDisplayMode(env, arrayList,
+                                        mode->width, mode->height,
+                                              BIT_DEPTH_MULTI, (int)(rate +.2));
+                                 break;
+                            }
+                        }
+                    }
+                    awt_XRRFreeOutputInfo(output_info);
+                }
+            }
+            awt_XRRFreeScreenResources(res);
+        }
+    } else {
+        XRRScreenConfiguration *config;
 
-        if (sizes != NULL) {
-            for (i = 0; i < nsizes; i++) {
-                int nrates;
-                XRRScreenSize size = sizes[i];
-                short *rates = awt_XRRConfigRates(config, i, &nrates);
+        config = awt_XRRGetScreenInfo(awt_display,
+                                      RootWindow(awt_display, screen));
+        if (config != NULL) {
+            int nsizes, i, j;
+            XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
 
-                for (j = 0; j < nrates; j++) {
-                    X11GD_AddDisplayMode(env, arrayList,
-                                         size.width,
-                                         size.height,
-                                         BIT_DEPTH_MULTI,
-                                         rates[j]);
-                    if ((*env)->ExceptionCheck(env)) {
-                        break;
+            if (sizes != NULL) {
+                for (i = 0; i < nsizes; i++) {
+                    int nrates;
+                    XRRScreenSize size = sizes[i];
+                    short *rates = awt_XRRConfigRates(config, i, &nrates);
+
+                    for (j = 0; j < nrates; j++) {
+                        X11GD_AddDisplayMode(env, arrayList,
+                                             size.width,
+                                             size.height,
+                                             BIT_DEPTH_MULTI,
+                                             rates[j]);
+                        if ((*env)->ExceptionCheck(env)) {
+                            break;
+                        }
                     }
                 }
             }
+
+            awt_XRRFreeScreenConfigInfo(config);
         }
-
-        awt_XRRFreeScreenConfigInfo(config);
     }
 
     AWT_FLUSH_UNLOCK();
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/randr.h	Tue Jul 05 09:48:49 2016 +0300
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/randr.h	Tue Jul 05 12:37:36 2016 +0300
@@ -5,8 +5,8 @@
 /*
  * $XFree86: xc/include/extensions/randr.h,v 1.4 2001/11/24 07:24:58 keithp Exp $
  *
- * Copyright © 2000, Compaq Computer Corporation,
- * Copyright © 2002, Hewlett Packard, Inc.
+ * Copyright © 2000, Compaq Computer Corporation,
+ * Copyright © 2002, Hewlett Packard, Inc.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -31,6 +31,7 @@
 #ifndef _RANDR_H_
 #define _RANDR_H_
 
+typedef unsigned short  Connection;
 typedef unsigned short  Rotation;
 typedef unsigned short  SizeID;
 typedef unsigned short  SubpixelOrder;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/GraphicsDevice/DisplayModes/CompareToXrandrTest.java	Tue Jul 05 12:37:36 2016 +0300
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, 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 8022810
+ * @summary Cannot list all the available display modes on Ubuntu linux in case
+ *          of two screen devices
+ * @run main CompareToXrandrTest
+ */
+
+import java.awt.GraphicsEnvironment;
+import java.awt.GraphicsDevice;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class CompareToXrandrTest {
+
+    public static void main(String[] args) throws Exception {
+        if (!new File("/usr/bin/xrandr").exists()) {
+            System.out.println("No xrandr tool to compare");
+            return;
+        }
+
+        BufferedReader reader = new BufferedReader(new InputStreamReader(
+                Runtime.getRuntime().exec("/usr/bin/xrandr").getInputStream()));
+        reader.readLine();
+        reader.readLine();
+        Pattern pattern = Pattern.compile("^\\s*(\\d+x\\d+)");
+
+        for (GraphicsDevice d : GraphicsEnvironment
+                            .getLocalGraphicsEnvironment().getScreenDevices()) {
+
+            Set<String> xrandrModes = reader.lines().map(pattern::matcher)
+                    .takeWhile(Matcher::find).map(m -> m.group(1))
+                            .collect(Collectors.toSet());
+
+            Set<String> javaModes = Arrays.stream(d.getDisplayModes())
+                    .map(m -> m.getWidth() + "x" + m.getHeight())
+                            .collect(Collectors.toSet());
+
+            if (!xrandrModes.equals(javaModes)) {
+                throw new RuntimeException("Failed");
+            } else {
+                System.out.println("Device " + d + ": " + javaModes.size() +
+                                                               " modes found.");
+            }
+        }
+    }
+}