diff options
author | Ubuntu <ubuntu@cert-jenkins-slave-1-201406-15260.maas> | 2022-06-15 17:25:47 +0000 |
---|---|---|
committer | Ubuntu <ubuntu@cert-jenkins-slave-1-201406-15260.maas> | 2022-06-15 17:25:47 +0000 |
commit | 91478e881f1672cb9c9a3f68fd7b2d31b6602b07 (patch) | |
tree | 04070515cb7f058368e84209477f85fb73a62be8 | |
parent | e25b1973fc78bb10c8a709362ae7d5932769a1d0 (diff) | |
parent | a028a44bb18f0f2e9e26c91c3e7f216c70911509 (diff) |
Merge #424146 from ~pieq/plainbox-provider-checkbox:1968943-rework-max-resolution-job
-rwxr-xr-x | bin/graphics_max_resolution.py | 148 | ||||
-rwxr-xr-x | bin/graphics_modes_info.py | 74 | ||||
-rw-r--r-- | units/graphics/jobs.pxu | 18 | ||||
-rw-r--r-- | units/graphics/legacy.pxu | 8 |
4 files changed, 149 insertions, 99 deletions
diff --git a/bin/graphics_max_resolution.py b/bin/graphics_max_resolution.py new file mode 100755 index 0000000..56628a4 --- /dev/null +++ b/bin/graphics_max_resolution.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# +# This file is part of Checkbox. +# +# Copyright 2022 Canonical Ltd. +# +# Authors: +# Pierre Equoy <pierre.equoy@canonical.com> +# +# Checkbox is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3, +# as published by the Free Software Foundation. +# +# Checkbox 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 for more details. +# +# You should have received a copy of the GNU General Public License +# along with Checkbox. If not, see <http://www.gnu.org/licenses/>. + +import gi +from glob import glob +import os +import sys +from pathlib import Path + +gi.require_versions({"Gtk": "3.0", "Gdk": "3.0"}) +from gi.repository import Gdk, Gtk # noqa: E402 + + +def get_sysfs_info(): + """ + Go through each graphics cards sysfs entries to find max resolution if + connected to a monitor. + Return a list of ports with information about them. + """ + ports = glob("/sys/class/drm/card*-*") + entries = [] + for p in ports: + with open(Path(p) / "modes") as f: + # Topmost line in the modes file is the max resolution + max_resolution = f.readline().strip() + if max_resolution: + # e.g. "/sys/class/drm/card0-HDMI-A-1" + port = p.split("/")[-1] + width, height = max_resolution.split("x") + with open(Path(p) / "enabled") as f: + enabled = f.readline().strip() + with open(Path(p) / "dpms") as f: + dpms = f.readline().strip() + with open(Path(p) / "status") as f: + status = f.readline().strip() + port_info = { + "port": port, + "width": int(width), + "height": int(height), + "enabled": enabled, # "enabled" or "disabled" + "status": status, # "connected" or "disconnected" + "dpms": dpms, # "On" or "Off" + } + entries.append(port_info) + return entries + + +def get_monitors_info(): + """ + Get information (model, manufacturer, resolution) from each connected + monitors using Gtk. + Return a list of monitors with their information. + """ + Gtk.init() + display = Gdk.Display.get_default() + monitors = [] + for i in range(display.get_n_monitors()): + mon = display.get_monitor(i) + monitor = { + "model": mon.get_model(), + "manufacturer": mon.get_manufacturer(), + "width": mon.get_geometry().width, + "height": mon.get_geometry().height, + "scale_factor": mon.get_scale_factor(), + } + monitors.append(monitor) + return monitors + + +if __name__ == "__main__": + sysfs_entries = get_sysfs_info() + mons_entries = get_monitors_info() + total_sysfs_res = 0 + total_mons_res = 0 + compositor = os.environ.get("XDG_SESSION_TYPE") + print("Current compositor: {}".format(compositor)) + print() + print("Maximum resolution found for each connected monitors:") + for p in sysfs_entries: + port = p["port"] + width = p["width"] + height = p["height"] + enabled = p["enabled"] + status = p["status"] + dpms = p["dpms"].lower() + print( + "\t{}: {}x{} ({}, {}, {})".format( + port, width, height, dpms, status, enabled + ) + ) + # If the monitor is disabled (e.g. "Single Display" mode), don't take + # its surface into account. + if enabled == "enabled": + total_sysfs_res += width * height + print() + print("Current resolution found for each connected monitors:") + for m in mons_entries: + model = m["model"] + manufacturer = m["manufacturer"] + scale = m["scale_factor"] + # Under X11, the returned width and height are in "application pixels", + # not "device pixels", so it has to be multiplied by the scale factor. + # However, Wayland always returns the "device pixels" width and height. + # + # Example: a 3840x2160 screen set to 200% scale will have + # width = 1920, height = 1080, scale_factor = 2 on X11 + # width = 3840, height = 2160, scale_factor = 2 on Wayland + if compositor == "x11": + width = m["width"] * m["scale_factor"] + height = m["height"] * m["scale_factor"] + else: + width = m["width"] + height = m["height"] + print( + "\t{} ({}): {}x{} @{}%".format( + model, manufacturer, width, height, scale * 100 + ) + ) + total_mons_res += width * height + print() + if total_sysfs_res == total_mons_res: + print("The displays are configured at their maximum resolution.") + else: + sys.exit( + ( + "The displays do not seem to be configured at their maximum " + "resolution.\nPlease switch to the maximum resolution before " + "continuing." + ) + ) diff --git a/bin/graphics_modes_info.py b/bin/graphics_modes_info.py deleted file mode 100755 index f92cd76..0000000 --- a/bin/graphics_modes_info.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# graphics_modes_info.py -# -# This file is part of Checkbox. -# -# Copyright 2012 Canonical Ltd. -# -# Authors: Alberto Milone <alberto.milone@canonical.com> -# -# Checkbox is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 3, -# as published by the Free Software Foundation. - -# -# Checkbox 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 for more details. -# -# You should have received a copy of the GNU General Public License -# along with Checkbox. If not, see <http://www.gnu.org/licenses/>. - -from __future__ import print_function -from __future__ import unicode_literals -import sys - -from checkbox_support.contrib import xrandr - - -def print_modes_info(screen): - """Print some information about the detected screen and its outputs""" - xrandr._check_required_version((1, 0)) - print("Screen %s: minimum %s x %s, current %s x %s, maximum %s x %s" % - (screen._screen, - screen._width_min, screen._height_min, - screen._width, screen._height, - screen._width_max, screen._height_max)) - print(" %smm x %smm" % (screen._width_mm, screen._height_mm)) - print("Outputs:") - for o in list(screen.outputs.keys()): - output = screen.outputs[o] - print(" %s" % o, end=' ') - if output.is_connected(): - print("(%smm x %smm)" % (output.get_physical_width(), - output.get_physical_height())) - modes = output.get_available_modes() - print(" Modes:") - for m in range(len(modes)): - mode = modes[m] - refresh = mode.dotClock / (mode.hTotal * mode.vTotal) - print( - " [%s] %s x %s @ %s Hz" % - (m, mode.width, mode.height, refresh), end=' ') - if mode.id == output._mode: - print("(current)", end=' ') - if m == output.get_preferred_mode(): - print("(preferred)", end=' ') - print("") - else: - print("(not connected)") - - -def main(): - screen = xrandr.get_current_screen() - try: - print_modes_info(screen) - except(xrandr.UnsupportedRRError): - print('Error: RandR version lower than 1.0', file=sys.stderr) - - -if __name__ == '__main__': - main() diff --git a/units/graphics/jobs.pxu b/units/graphics/jobs.pxu index 4dde304..8206f1a 100644 --- a/units/graphics/jobs.pxu +++ b/units/graphics/jobs.pxu @@ -133,13 +133,7 @@ category_id: com.canonical.plainbox::graphics requires: device.category == 'VIDEO' command: - # shellcheck disable=SC1091 - source graphics_env.sh {driver} {index} - maxi="$(xrandr -q |grep -A 1 "connected\( primary\)* [0-9]" |tail -1 |awk '{{print $1}}')" - now="$(python3 -c 'from gi.repository import Gdk; screen=Gdk.Screen.get_default(); geo = screen.get_monitor_geometry(screen.get_primary_monitor()); print(geo.width, "x", geo.height, sep="")')" - test "$maxi" != "$now" && notify="\nPlease switch to the maximum resolution \nfor every graphic tests" - echo "Maximum resolution: $maxi" - echo "Current resolution: $now $notify" + graphics_max_resolution.py estimated_duration: 10.0 _summary: Test maximum supported resolution for {vendor} {product} _description: @@ -154,16 +148,6 @@ _description: unit: template template-resource: graphics_card -id: graphics/{index}_modes_{product_slug} -plugin: shell -category_id: com.canonical.plainbox::graphics -command: graphics_modes_info.py -estimated_duration: 0.250 -_description: Collect info on graphics modes (screen resolution and refresh rate) for {vendor} {product} -_summary: Test graphic modes info for {vendor} {product} - -unit: template -template-resource: graphics_card id: graphics/{index}_color_depth_{product_slug} plugin: shell category_id: com.canonical.plainbox::graphics diff --git a/units/graphics/legacy.pxu b/units/graphics/legacy.pxu index 14969b0..2b9545d 100644 --- a/units/graphics/legacy.pxu +++ b/units/graphics/legacy.pxu @@ -96,14 +96,6 @@ _description: VERIFICATION: Is this the display's maximum resolution? -id: graphics/modes -plugin: shell -category_id: com.canonical.plainbox::graphics -command: graphics_modes_info.py -estimated_duration: 0.250 -_description: Collect info on graphics modes (screen resolution and refresh rate) -_summary: Collect info on graphics modes - id: graphics/color_depth plugin: shell category_id: com.canonical.plainbox::graphics |