2017-07-04 10:42:16 +00:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2001, 2002 Havoc Pennington
|
|
|
|
* Copyright (C) 2001, 2002 Havoc Pennington
|
|
|
|
* Copyright (C) 2002, 2003 Red Hat Inc.
|
|
|
|
* Some ICCCM manager selection code derived from fvwm2,
|
|
|
|
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
|
|
|
|
* Copyright (C) 2003 Rob Adams
|
|
|
|
* Copyright (C) 2004-2006 Elijah Newren
|
|
|
|
* Copyright (C) 2002, 2003 Red Hat Inc.
|
|
|
|
* Some ICCCM manager selection code derived from fvwm2,
|
|
|
|
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
|
|
|
|
* Copyright (C) 2003 Rob Adams
|
|
|
|
* Copyright (C) 2004-2006 Elijah Newren
|
|
|
|
* Copyright (C) 2013-2017 Red Hat Inc.
|
2020-02-05 00:41:34 +00:00
|
|
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
2017-07-04 10:42:16 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as
|
|
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "backends/x11/meta-output-xrandr.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/Xlib-xcb.h>
|
|
|
|
#include <xcb/randr.h>
|
|
|
|
|
2019-01-11 14:35:42 +00:00
|
|
|
#include "backends/meta-backend-private.h"
|
2017-07-04 10:42:16 +00:00
|
|
|
#include "backends/meta-crtc.h"
|
|
|
|
#include "backends/x11/meta-monitor-manager-xrandr.h"
|
|
|
|
#include "meta/util.h"
|
|
|
|
|
2020-02-26 15:47:03 +00:00
|
|
|
struct _MetaOutputXrandr
|
|
|
|
{
|
|
|
|
MetaOutput parent;
|
x11: Skip sending redundant CTM change requests
The X server generates a property change notification whenever it processes a
property change request, even if the value of the property is not changing. This
triggers libgdk to probe all display outputs, which can be slow depending on
which display driver and hardware are in use.
#0 0x00007f8e4d5e91a0 in XRRUpdateConfiguration () at /usr/lib/libXrandr.so.2
#1 0x00007f8e505208da in _gdk_x11_screen_size_changed (screen=0x5566e4b7e080, event=0x7ffe0e44bd60) at ../gdk/x11/gdkscreen-x11.c:1199
#2 0x00007f8e505066d1 in gdk_x11_display_translate_event (translator=0x5566e4b5b110, display=0x5566e4b5b110, event=0x7f8dec001b20, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkdisplay-x11.c:1201
#3 0x00007f8e505135a0 in _gdk_x11_event_translator_translate (translator=0x5566e4b5b110, display=0x5566e4b5b110, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventtranslator.c:51
#4 0x00007f8e50512c97 in gdk_event_source_translate_event (event_source=0x5566e4b764a0, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventsource.c:243
#5 0x00007f8e50512f57 in _gdk_x11_display_queue_events (display=0x5566e4b5b110) at ../gdk/x11/gdkeventsource.c:341
#6 0x00007f8e50497644 in gdk_display_get_event (display=0x5566e4b5b110) at ../gdk/gdkdisplay.c:442
#7 0x00007f8e5051301f in gdk_event_source_dispatch (source=0x5566e4b764a0, callback=0x0, user_data=0x0) at ../gdk/x11/gdkeventsource.c:363
#8 0x00007f8e516ecf9c in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#9 0x00007f8e51740a49 in () at /usr/lib/libglib-2.0.so.0
#10 0x00007f8e516ec503 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#11 0x00007f8e508ef5fd in meta_run_main_loop () at ../src/core/main.c:928
#12 0x00007f8e508ef60e in meta_run () at ../src/core/main.c:943
#13 0x00005566e450842a in ()
#14 0x00007f8e50649b25 in __libc_start_main () at /usr/lib/libc.so.6
When GNOME is animating a display fade when the night light feature is toggled
on or off, it sends a lot of change requests for the CTM property in the
process, which triggers a lot of display probes from gdk. In the case of the
night light feature, the CTM itself is not actually changing, so these requests
are redundant. Fix this by caching the CTM value in the MetaOutputXrandr and
skipping the server requests if it's not being changed.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3978
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1816>
2021-04-08 20:02:28 +00:00
|
|
|
|
|
|
|
gboolean ctm_initialized;
|
|
|
|
MetaOutputCtm ctm;
|
2020-02-26 15:47:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (MetaOutputXrandr, meta_output_xrandr, META_TYPE_OUTPUT)
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static Display *
|
2020-02-26 08:45:07 +00:00
|
|
|
xdisplay_from_gpu (MetaGpu *gpu)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2019-01-11 14:35:42 +00:00
|
|
|
MetaBackend *backend = meta_gpu_get_backend (gpu);
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
2017-07-04 10:42:16 +00:00
|
|
|
MetaMonitorManagerXrandr *monitor_manager_xrandr =
|
|
|
|
META_MONITOR_MANAGER_XRANDR (monitor_manager);
|
|
|
|
|
|
|
|
return meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
|
|
|
|
}
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
static Display *
|
|
|
|
xdisplay_from_output (MetaOutput *output)
|
|
|
|
{
|
|
|
|
return xdisplay_from_gpu (meta_output_get_gpu (output));
|
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static void
|
|
|
|
output_set_presentation_xrandr (MetaOutput *output,
|
|
|
|
gboolean presentation)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom atom;
|
|
|
|
int value = presentation;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
|
|
|
|
|
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
atom, XCB_ATOM_CARDINAL, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
1, &value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
output_set_underscanning_xrandr (MetaOutput *output,
|
|
|
|
gboolean underscanning)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom prop, valueatom;
|
|
|
|
const char *value;
|
|
|
|
|
|
|
|
prop = XInternAtom (xdisplay, "underscan", False);
|
|
|
|
|
|
|
|
value = underscanning ? "on" : "off";
|
|
|
|
valueatom = XInternAtom (xdisplay, value, False);
|
|
|
|
|
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
prop, XCB_ATOM_ATOM, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
1, &valueatom);
|
|
|
|
|
|
|
|
/* Configure the border at the same time. Currently, we use a
|
|
|
|
* 5% of the width/height of the mode. In the future, we should
|
|
|
|
* make the border configurable. */
|
|
|
|
if (underscanning)
|
|
|
|
{
|
2017-11-03 10:25:30 +00:00
|
|
|
MetaCrtc *crtc;
|
2020-02-26 09:37:53 +00:00
|
|
|
const MetaCrtcConfig *crtc_config;
|
2020-02-26 23:08:58 +00:00
|
|
|
const MetaCrtcModeInfo *crtc_mode_info;
|
2017-07-04 10:42:16 +00:00
|
|
|
uint32_t border_value;
|
|
|
|
|
2017-11-03 10:25:30 +00:00
|
|
|
crtc = meta_output_get_assigned_crtc (output);
|
2020-02-26 09:37:53 +00:00
|
|
|
crtc_config = meta_crtc_get_config (crtc);
|
2020-02-26 23:08:58 +00:00
|
|
|
crtc_mode_info = meta_crtc_mode_get_info (crtc_config->mode);
|
2017-11-03 10:25:30 +00:00
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
prop = XInternAtom (xdisplay, "underscan hborder", False);
|
2020-02-26 23:08:58 +00:00
|
|
|
border_value = crtc_mode_info->width * 0.05;
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
prop, XCB_ATOM_INTEGER, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
1, &border_value);
|
|
|
|
|
|
|
|
prop = XInternAtom (xdisplay, "underscan vborder", False);
|
2020-02-26 23:08:58 +00:00
|
|
|
border_value = crtc_mode_info->height * 0.05;
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
prop, XCB_ATOM_INTEGER, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
1, &border_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-10 08:34:40 +00:00
|
|
|
static void
|
|
|
|
output_set_max_bpc_xrandr (MetaOutput *output,
|
|
|
|
unsigned int max_bpc)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom prop = XInternAtom (xdisplay, "max bpc", False);
|
|
|
|
uint32_t value = max_bpc;
|
|
|
|
|
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
|
|
|
(XID) meta_output_get_id (output),
|
|
|
|
prop, XCB_ATOM_INTEGER, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
1, &value);
|
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
void
|
2020-02-26 15:47:03 +00:00
|
|
|
meta_output_xrandr_apply_mode (MetaOutputXrandr *output_xrandr)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 15:47:03 +00:00
|
|
|
MetaOutput *output = META_OUTPUT (output_xrandr);
|
2017-07-04 10:42:16 +00:00
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
2022-06-10 08:34:40 +00:00
|
|
|
const MetaOutputInfo *output_info = meta_output_get_info (output);
|
|
|
|
unsigned int max_bpc;
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2020-02-25 17:37:21 +00:00
|
|
|
if (meta_output_is_primary (output))
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
XRRSetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay),
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output));
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
2020-02-25 17:37:21 +00:00
|
|
|
output_set_presentation_xrandr (output, meta_output_is_presentation (output));
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
if (meta_output_get_info (output)->supports_underscanning)
|
2020-02-25 17:37:21 +00:00
|
|
|
{
|
|
|
|
output_set_underscanning_xrandr (output,
|
|
|
|
meta_output_is_underscanning (output));
|
|
|
|
}
|
2022-06-10 08:34:40 +00:00
|
|
|
|
|
|
|
if (meta_output_get_max_bpc (output, &max_bpc) &&
|
|
|
|
max_bpc >= output_info->max_bpc_min &&
|
|
|
|
max_bpc <= output_info->max_bpc_max)
|
|
|
|
{
|
|
|
|
output_set_max_bpc_xrandr (output, max_bpc);
|
|
|
|
}
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
normalize_backlight (MetaOutput *output,
|
|
|
|
int hw_value)
|
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
const MetaOutputInfo *output_info = meta_output_get_info (output);
|
|
|
|
|
|
|
|
return round ((double) (hw_value - output_info->backlight_min) /
|
|
|
|
(output_info->backlight_max - output_info->backlight_min) * 100.0);
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-02-26 15:47:03 +00:00
|
|
|
meta_output_xrandr_change_backlight (MetaOutputXrandr *output_xrandr,
|
|
|
|
int value)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 15:47:03 +00:00
|
|
|
MetaOutput *output = META_OUTPUT (output_xrandr);
|
2020-02-26 08:45:07 +00:00
|
|
|
const MetaOutputInfo *output_info = meta_output_get_info (output);
|
2017-07-04 10:42:16 +00:00
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom atom;
|
|
|
|
int hw_value;
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
hw_value = round ((double) value / 100.0 * output_info->backlight_max +
|
|
|
|
output_info->backlight_min);
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "Backlight", False);
|
|
|
|
|
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
atom, XCB_ATOM_INTEGER, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
1, &hw_value);
|
|
|
|
|
|
|
|
/* We're not selecting for property notifies, so update the value immediately */
|
2020-02-25 17:37:21 +00:00
|
|
|
meta_output_set_backlight (output, normalize_backlight (output, hw_value));
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
x11: Skip sending redundant CTM change requests
The X server generates a property change notification whenever it processes a
property change request, even if the value of the property is not changing. This
triggers libgdk to probe all display outputs, which can be slow depending on
which display driver and hardware are in use.
#0 0x00007f8e4d5e91a0 in XRRUpdateConfiguration () at /usr/lib/libXrandr.so.2
#1 0x00007f8e505208da in _gdk_x11_screen_size_changed (screen=0x5566e4b7e080, event=0x7ffe0e44bd60) at ../gdk/x11/gdkscreen-x11.c:1199
#2 0x00007f8e505066d1 in gdk_x11_display_translate_event (translator=0x5566e4b5b110, display=0x5566e4b5b110, event=0x7f8dec001b20, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkdisplay-x11.c:1201
#3 0x00007f8e505135a0 in _gdk_x11_event_translator_translate (translator=0x5566e4b5b110, display=0x5566e4b5b110, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventtranslator.c:51
#4 0x00007f8e50512c97 in gdk_event_source_translate_event (event_source=0x5566e4b764a0, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventsource.c:243
#5 0x00007f8e50512f57 in _gdk_x11_display_queue_events (display=0x5566e4b5b110) at ../gdk/x11/gdkeventsource.c:341
#6 0x00007f8e50497644 in gdk_display_get_event (display=0x5566e4b5b110) at ../gdk/gdkdisplay.c:442
#7 0x00007f8e5051301f in gdk_event_source_dispatch (source=0x5566e4b764a0, callback=0x0, user_data=0x0) at ../gdk/x11/gdkeventsource.c:363
#8 0x00007f8e516ecf9c in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#9 0x00007f8e51740a49 in () at /usr/lib/libglib-2.0.so.0
#10 0x00007f8e516ec503 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#11 0x00007f8e508ef5fd in meta_run_main_loop () at ../src/core/main.c:928
#12 0x00007f8e508ef60e in meta_run () at ../src/core/main.c:943
#13 0x00005566e450842a in ()
#14 0x00007f8e50649b25 in __libc_start_main () at /usr/lib/libc.so.6
When GNOME is animating a display fade when the night light feature is toggled
on or off, it sends a lot of change requests for the CTM property in the
process, which triggers a lot of display probes from gdk. In the case of the
night light feature, the CTM itself is not actually changing, so these requests
are redundant. Fix this by caching the CTM value in the MetaOutputXrandr and
skipping the server requests if it's not being changed.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3978
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1816>
2021-04-08 20:02:28 +00:00
|
|
|
static gboolean
|
|
|
|
ctm_is_equal (const MetaOutputCtm *ctm1,
|
|
|
|
const MetaOutputCtm *ctm2)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < 9; i++)
|
|
|
|
{
|
|
|
|
if (ctm1->matrix[i] != ctm2->matrix[i])
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-02-05 00:41:34 +00:00
|
|
|
void
|
|
|
|
meta_output_xrandr_set_ctm (MetaOutputXrandr *output_xrandr,
|
|
|
|
const MetaOutputCtm *ctm)
|
|
|
|
{
|
x11: Skip sending redundant CTM change requests
The X server generates a property change notification whenever it processes a
property change request, even if the value of the property is not changing. This
triggers libgdk to probe all display outputs, which can be slow depending on
which display driver and hardware are in use.
#0 0x00007f8e4d5e91a0 in XRRUpdateConfiguration () at /usr/lib/libXrandr.so.2
#1 0x00007f8e505208da in _gdk_x11_screen_size_changed (screen=0x5566e4b7e080, event=0x7ffe0e44bd60) at ../gdk/x11/gdkscreen-x11.c:1199
#2 0x00007f8e505066d1 in gdk_x11_display_translate_event (translator=0x5566e4b5b110, display=0x5566e4b5b110, event=0x7f8dec001b20, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkdisplay-x11.c:1201
#3 0x00007f8e505135a0 in _gdk_x11_event_translator_translate (translator=0x5566e4b5b110, display=0x5566e4b5b110, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventtranslator.c:51
#4 0x00007f8e50512c97 in gdk_event_source_translate_event (event_source=0x5566e4b764a0, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventsource.c:243
#5 0x00007f8e50512f57 in _gdk_x11_display_queue_events (display=0x5566e4b5b110) at ../gdk/x11/gdkeventsource.c:341
#6 0x00007f8e50497644 in gdk_display_get_event (display=0x5566e4b5b110) at ../gdk/gdkdisplay.c:442
#7 0x00007f8e5051301f in gdk_event_source_dispatch (source=0x5566e4b764a0, callback=0x0, user_data=0x0) at ../gdk/x11/gdkeventsource.c:363
#8 0x00007f8e516ecf9c in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#9 0x00007f8e51740a49 in () at /usr/lib/libglib-2.0.so.0
#10 0x00007f8e516ec503 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#11 0x00007f8e508ef5fd in meta_run_main_loop () at ../src/core/main.c:928
#12 0x00007f8e508ef60e in meta_run () at ../src/core/main.c:943
#13 0x00005566e450842a in ()
#14 0x00007f8e50649b25 in __libc_start_main () at /usr/lib/libc.so.6
When GNOME is animating a display fade when the night light feature is toggled
on or off, it sends a lot of change requests for the CTM property in the
process, which triggers a lot of display probes from gdk. In the case of the
night light feature, the CTM itself is not actually changing, so these requests
are redundant. Fix this by caching the CTM value in the MetaOutputXrandr and
skipping the server requests if it's not being changed.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3978
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1816>
2021-04-08 20:02:28 +00:00
|
|
|
if (!output_xrandr->ctm_initialized ||
|
|
|
|
!ctm_is_equal (ctm, &output_xrandr->ctm))
|
|
|
|
{
|
|
|
|
MetaOutput *output = META_OUTPUT (output_xrandr);
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom ctm_atom = XInternAtom (xdisplay, "CTM", False);
|
2020-02-05 00:41:34 +00:00
|
|
|
|
x11: Skip sending redundant CTM change requests
The X server generates a property change notification whenever it processes a
property change request, even if the value of the property is not changing. This
triggers libgdk to probe all display outputs, which can be slow depending on
which display driver and hardware are in use.
#0 0x00007f8e4d5e91a0 in XRRUpdateConfiguration () at /usr/lib/libXrandr.so.2
#1 0x00007f8e505208da in _gdk_x11_screen_size_changed (screen=0x5566e4b7e080, event=0x7ffe0e44bd60) at ../gdk/x11/gdkscreen-x11.c:1199
#2 0x00007f8e505066d1 in gdk_x11_display_translate_event (translator=0x5566e4b5b110, display=0x5566e4b5b110, event=0x7f8dec001b20, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkdisplay-x11.c:1201
#3 0x00007f8e505135a0 in _gdk_x11_event_translator_translate (translator=0x5566e4b5b110, display=0x5566e4b5b110, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventtranslator.c:51
#4 0x00007f8e50512c97 in gdk_event_source_translate_event (event_source=0x5566e4b764a0, xevent=0x7ffe0e44bd60) at ../gdk/x11/gdkeventsource.c:243
#5 0x00007f8e50512f57 in _gdk_x11_display_queue_events (display=0x5566e4b5b110) at ../gdk/x11/gdkeventsource.c:341
#6 0x00007f8e50497644 in gdk_display_get_event (display=0x5566e4b5b110) at ../gdk/gdkdisplay.c:442
#7 0x00007f8e5051301f in gdk_event_source_dispatch (source=0x5566e4b764a0, callback=0x0, user_data=0x0) at ../gdk/x11/gdkeventsource.c:363
#8 0x00007f8e516ecf9c in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#9 0x00007f8e51740a49 in () at /usr/lib/libglib-2.0.so.0
#10 0x00007f8e516ec503 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#11 0x00007f8e508ef5fd in meta_run_main_loop () at ../src/core/main.c:928
#12 0x00007f8e508ef60e in meta_run () at ../src/core/main.c:943
#13 0x00005566e450842a in ()
#14 0x00007f8e50649b25 in __libc_start_main () at /usr/lib/libc.so.6
When GNOME is animating a display fade when the night light feature is toggled
on or off, it sends a lot of change requests for the CTM property in the
process, which triggers a lot of display probes from gdk. In the case of the
night light feature, the CTM itself is not actually changing, so these requests
are redundant. Fix this by caching the CTM value in the MetaOutputXrandr and
skipping the server requests if it's not being changed.
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3978
Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1816>
2021-04-08 20:02:28 +00:00
|
|
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
|
|
|
(XID) meta_output_get_id (output),
|
|
|
|
ctm_atom, XCB_ATOM_INTEGER, 32,
|
|
|
|
XCB_PROP_MODE_REPLACE,
|
|
|
|
18, &ctm->matrix);
|
|
|
|
|
|
|
|
output_xrandr->ctm = *ctm;
|
|
|
|
output_xrandr->ctm_initialized = TRUE;
|
|
|
|
}
|
2020-02-05 00:41:34 +00:00
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static gboolean
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_integer_property (Display *xdisplay,
|
|
|
|
RROutput output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
const char *propname,
|
|
|
|
gint *value)
|
|
|
|
{
|
|
|
|
gboolean exists = FALSE;
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
unsigned char *buffer;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, propname, False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_INTEGER,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
exists = (actual_type == XA_INTEGER && actual_format == 32 && nitems == 1);
|
|
|
|
|
|
|
|
if (exists && value != NULL)
|
|
|
|
*value = ((int*)buffer)[0];
|
|
|
|
|
|
|
|
XFree (buffer);
|
|
|
|
return exists;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_property_exists (Display *xdisplay,
|
|
|
|
RROutput output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
const char *propname)
|
|
|
|
{
|
|
|
|
gboolean exists = FALSE;
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
unsigned char *buffer;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, propname, False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, AnyPropertyType,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
exists = (actual_type != None);
|
|
|
|
|
|
|
|
XFree (buffer);
|
|
|
|
return exists;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
output_get_boolean_property (MetaOutput *output,
|
|
|
|
const char *propname)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, propname, False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_CARDINAL,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XA_CARDINAL || actual_format != 32 || nitems < 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return ((int*)buffer)[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
output_get_presentation_xrandr (MetaOutput *output)
|
|
|
|
{
|
|
|
|
return output_get_boolean_property (output, "_MUTTER_PRESENTATION_OUTPUT");
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
output_get_underscanning_xrandr (MetaOutput *output)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
g_autofree char *str = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "underscan", False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_ATOM,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
str = XGetAtomName (xdisplay, *(Atom *)buffer);
|
|
|
|
return (strcmp (str, "on") == 0);
|
|
|
|
}
|
|
|
|
|
2022-06-10 08:34:40 +00:00
|
|
|
static gboolean
|
|
|
|
output_get_max_bpc_xrandr (MetaOutput *output,
|
|
|
|
unsigned int *max_bpc)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "max bpc", False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
|
|
|
(XID) meta_output_get_id (output),
|
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XCB_ATOM_INTEGER,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XCB_ATOM_INTEGER || actual_format != 32 || nitems < 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (max_bpc)
|
|
|
|
*max_bpc = *((uint32_t*) buffer);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static gboolean
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_supports_underscanning_xrandr (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format, i;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
XRRPropertyInfo *property_info;
|
|
|
|
Atom *values;
|
|
|
|
gboolean supports_underscanning = FALSE;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "underscan", False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_ATOM,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
property_info = XRRQueryOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
atom);
|
|
|
|
values = (Atom *) property_info->values;
|
|
|
|
|
|
|
|
for (i = 0; i < property_info->num_values; i++)
|
|
|
|
{
|
|
|
|
/* The output supports underscanning if "on" is a valid value
|
|
|
|
* for the underscan property.
|
|
|
|
*/
|
|
|
|
char *name = XGetAtomName (xdisplay, values[i]);
|
|
|
|
if (strcmp (name, "on") == 0)
|
|
|
|
supports_underscanning = TRUE;
|
|
|
|
|
|
|
|
XFree (name);
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree (property_info);
|
|
|
|
|
|
|
|
return supports_underscanning;
|
|
|
|
}
|
|
|
|
|
2022-06-10 08:34:40 +00:00
|
|
|
static gboolean
|
|
|
|
output_get_max_bpc_range_xrandr (Display *xdisplay,
|
|
|
|
RROutput output_id,
|
|
|
|
unsigned int *min,
|
|
|
|
unsigned int *max)
|
|
|
|
{
|
|
|
|
Atom atom;
|
|
|
|
XRRPropertyInfo *property_info;
|
|
|
|
long *values;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "max bpc", False);
|
|
|
|
|
|
|
|
meta_clutter_x11_trap_x_errors ();
|
|
|
|
property_info = XRRQueryOutputProperty (xdisplay,
|
|
|
|
(XID) output_id,
|
|
|
|
atom);
|
|
|
|
meta_clutter_x11_untrap_x_errors ();
|
|
|
|
|
2022-09-02 08:21:04 +00:00
|
|
|
if (!property_info)
|
2022-06-10 08:34:40 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2022-09-02 08:21:04 +00:00
|
|
|
if (property_info->num_values != 2)
|
|
|
|
{
|
|
|
|
XFree (property_info);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2022-06-10 08:34:40 +00:00
|
|
|
values = (long *) property_info->values;
|
|
|
|
if (min)
|
|
|
|
*min = values[0];
|
|
|
|
if (max)
|
|
|
|
*max = values[1];
|
|
|
|
|
2022-08-21 14:33:16 +00:00
|
|
|
XFree (property_info);
|
|
|
|
|
2022-06-10 08:34:40 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2020-02-05 00:41:34 +00:00
|
|
|
static gboolean
|
|
|
|
output_get_supports_color_transform_xrandr (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
|
|
|
{
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "CTM", False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
|
|
|
(XID) output_id,
|
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_INTEGER,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* X's CTM property is 9 64-bit integers represented as an array of 18 32-bit
|
|
|
|
* integers.
|
|
|
|
*/
|
|
|
|
return (actual_type == XA_INTEGER &&
|
|
|
|
actual_format == 32 &&
|
|
|
|
nitems == 18);
|
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static int
|
|
|
|
output_get_backlight_xrandr (MetaOutput *output)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
int value = -1;
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "Backlight", False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-25 15:13:52 +00:00
|
|
|
(XID) meta_output_get_id (output),
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_INTEGER,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XA_INTEGER || actual_format != 32 || nitems < 1)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
value = ((int*)buffer)[0];
|
|
|
|
if (value > 0)
|
|
|
|
return normalize_backlight (output, value);
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_init_backlight_limits_xrandr (MetaOutputInfo *output_info,
|
|
|
|
Display *xdisplay,
|
|
|
|
xcb_randr_output_t output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
Atom atom;
|
|
|
|
xcb_connection_t *xcb_conn;
|
|
|
|
xcb_randr_query_output_property_cookie_t cookie;
|
|
|
|
g_autofree xcb_randr_query_output_property_reply_t *reply = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "Backlight", False);
|
|
|
|
|
|
|
|
xcb_conn = XGetXCBConnection (xdisplay);
|
|
|
|
cookie = xcb_randr_query_output_property (xcb_conn,
|
2020-02-25 15:13:52 +00:00
|
|
|
output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
(xcb_atom_t) atom);
|
|
|
|
reply = xcb_randr_query_output_property_reply (xcb_conn,
|
|
|
|
cookie,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
/* This can happen on systems without backlights. */
|
|
|
|
if (reply == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!reply->range || reply->length != 2)
|
|
|
|
{
|
2020-10-02 15:47:22 +00:00
|
|
|
meta_verbose ("backlight %s was not range", output_info->name);
|
2017-07-04 10:42:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t *values = xcb_randr_query_output_property_valid_values (reply);
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->backlight_min = values[0];
|
|
|
|
output_info->backlight_max = values[1];
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static guint8 *
|
|
|
|
get_edid_property (Display *xdisplay,
|
|
|
|
RROutput output,
|
|
|
|
Atom atom,
|
|
|
|
gsize *len)
|
|
|
|
{
|
|
|
|
unsigned char *prop;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
Atom actual_type;
|
|
|
|
guint8 *result;
|
|
|
|
|
|
|
|
XRRGetOutputProperty (xdisplay, output, atom,
|
|
|
|
0, 100, False, False,
|
|
|
|
AnyPropertyType,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &prop);
|
|
|
|
|
|
|
|
if (actual_type == XA_INTEGER && actual_format == 8)
|
|
|
|
{
|
2021-02-04 17:45:59 +00:00
|
|
|
result = g_memdup2 (prop, nitems);
|
2017-07-04 10:42:16 +00:00
|
|
|
if (len)
|
|
|
|
*len = nitems;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree (prop);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
static GBytes *
|
|
|
|
read_xrandr_edid (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
Atom edid_atom;
|
|
|
|
guint8 *result;
|
|
|
|
gsize len;
|
|
|
|
|
|
|
|
edid_atom = XInternAtom (xdisplay, "EDID", FALSE);
|
2020-02-26 08:45:07 +00:00
|
|
|
result = get_edid_property (xdisplay, output_id, edid_atom, &len);
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
if (!result)
|
|
|
|
{
|
|
|
|
edid_atom = XInternAtom (xdisplay, "EDID_DATA", FALSE);
|
2020-02-26 08:45:07 +00:00
|
|
|
result = get_edid_property (xdisplay, output_id, edid_atom, &len);
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
{
|
|
|
|
if (len > 0 && len % 128 == 0)
|
|
|
|
return g_bytes_new_take (result, len);
|
|
|
|
else
|
|
|
|
g_free (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
GBytes *
|
|
|
|
meta_output_xrandr_read_edid (MetaOutput *output)
|
|
|
|
{
|
|
|
|
Display *xdisplay = xdisplay_from_output (output);
|
|
|
|
RROutput output_id = (RROutput) meta_output_get_id (output);
|
|
|
|
|
|
|
|
return read_xrandr_edid (xdisplay, output_id);
|
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static gboolean
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_hotplug_mode_update (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
return output_get_property_exists (xdisplay, output_id, "hotplug_mode_update");
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_suggested_x (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
gint val;
|
2020-02-26 08:45:07 +00:00
|
|
|
if (output_get_integer_property (xdisplay, output_id, "suggested X", &val))
|
2017-07-04 10:42:16 +00:00
|
|
|
return val;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_suggested_y (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
gint val;
|
2020-02-26 08:45:07 +00:00
|
|
|
if (output_get_integer_property (xdisplay, output_id, "suggested Y", &val))
|
2017-07-04 10:42:16 +00:00
|
|
|
return val;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaConnectorType
|
|
|
|
connector_type_from_atom (Display *xdisplay,
|
|
|
|
Atom atom)
|
|
|
|
{
|
|
|
|
if (atom == XInternAtom (xdisplay, "HDMI", True))
|
|
|
|
return META_CONNECTOR_TYPE_HDMIA;
|
|
|
|
if (atom == XInternAtom (xdisplay, "VGA", True))
|
|
|
|
return META_CONNECTOR_TYPE_VGA;
|
|
|
|
/* Doesn't have a DRM equivalent, but means an internal panel.
|
|
|
|
* We could pick either LVDS or eDP here. */
|
|
|
|
if (atom == XInternAtom (xdisplay, "Panel", True))
|
|
|
|
return META_CONNECTOR_TYPE_LVDS;
|
|
|
|
if (atom == XInternAtom (xdisplay, "DVI", True) ||
|
|
|
|
atom == XInternAtom (xdisplay, "DVI-I", True))
|
|
|
|
return META_CONNECTOR_TYPE_DVII;
|
|
|
|
if (atom == XInternAtom (xdisplay, "DVI-A", True))
|
|
|
|
return META_CONNECTOR_TYPE_DVIA;
|
|
|
|
if (atom == XInternAtom (xdisplay, "DVI-D", True))
|
|
|
|
return META_CONNECTOR_TYPE_DVID;
|
|
|
|
if (atom == XInternAtom (xdisplay, "DisplayPort", True))
|
|
|
|
return META_CONNECTOR_TYPE_DisplayPort;
|
|
|
|
|
|
|
|
if (atom == XInternAtom (xdisplay, "TV", True))
|
|
|
|
return META_CONNECTOR_TYPE_TV;
|
|
|
|
if (atom == XInternAtom (xdisplay, "TV-Composite", True))
|
|
|
|
return META_CONNECTOR_TYPE_Composite;
|
|
|
|
if (atom == XInternAtom (xdisplay, "TV-SVideo", True))
|
|
|
|
return META_CONNECTOR_TYPE_SVIDEO;
|
|
|
|
/* Another set of mismatches. */
|
|
|
|
if (atom == XInternAtom (xdisplay, "TV-SCART", True))
|
|
|
|
return META_CONNECTOR_TYPE_TV;
|
|
|
|
if (atom == XInternAtom (xdisplay, "TV-C4", True))
|
|
|
|
return META_CONNECTOR_TYPE_TV;
|
|
|
|
|
|
|
|
return META_CONNECTOR_TYPE_Unknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaConnectorType
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_connector_type_from_prop (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
Atom atom, actual_type, connector_type_atom;
|
|
|
|
int actual_format;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "ConnectorType", False);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
atom,
|
|
|
|
0, G_MAXLONG, False, False, XA_ATOM,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
|
|
|
return META_CONNECTOR_TYPE_Unknown;
|
|
|
|
|
|
|
|
connector_type_atom = ((Atom *) buffer)[0];
|
|
|
|
return connector_type_from_atom (xdisplay, connector_type_atom);
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaConnectorType
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_get_connector_type_from_name (const MetaOutputInfo *output_info)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
const char *name = output_info->name;
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
/* drmmode_display.c, which was copy/pasted across all the FOSS
|
|
|
|
* xf86-video-* drivers, seems to name its outputs based on the
|
|
|
|
* connector type, so look for that....
|
|
|
|
*
|
|
|
|
* SNA has its own naming scheme, because what else did you expect
|
|
|
|
* from SNA, but it's not too different, so we can thankfully use
|
|
|
|
* that with minor changes.
|
|
|
|
*
|
|
|
|
* http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/drivers/modesetting/drmmode_display.c#n953
|
|
|
|
* http://cgit.freedesktop.org/xorg/driver/xf86-video-intel/tree/src/sna/sna_display.c#n3486
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (g_str_has_prefix (name, "DVI"))
|
|
|
|
return META_CONNECTOR_TYPE_DVII;
|
|
|
|
if (g_str_has_prefix (name, "LVDS"))
|
|
|
|
return META_CONNECTOR_TYPE_LVDS;
|
|
|
|
if (g_str_has_prefix (name, "HDMI"))
|
|
|
|
return META_CONNECTOR_TYPE_HDMIA;
|
|
|
|
if (g_str_has_prefix (name, "VGA"))
|
|
|
|
return META_CONNECTOR_TYPE_VGA;
|
|
|
|
/* SNA uses DP, not DisplayPort. Test for both. */
|
|
|
|
if (g_str_has_prefix (name, "DP") || g_str_has_prefix (name, "DisplayPort"))
|
|
|
|
return META_CONNECTOR_TYPE_DisplayPort;
|
|
|
|
if (g_str_has_prefix (name, "eDP"))
|
|
|
|
return META_CONNECTOR_TYPE_eDP;
|
|
|
|
if (g_str_has_prefix (name, "Virtual"))
|
|
|
|
return META_CONNECTOR_TYPE_VIRTUAL;
|
|
|
|
if (g_str_has_prefix (name, "Composite"))
|
|
|
|
return META_CONNECTOR_TYPE_Composite;
|
|
|
|
if (g_str_has_prefix (name, "S-video"))
|
|
|
|
return META_CONNECTOR_TYPE_SVIDEO;
|
|
|
|
if (g_str_has_prefix (name, "TV"))
|
|
|
|
return META_CONNECTOR_TYPE_TV;
|
|
|
|
if (g_str_has_prefix (name, "CTV"))
|
|
|
|
return META_CONNECTOR_TYPE_Composite;
|
|
|
|
if (g_str_has_prefix (name, "DSI"))
|
|
|
|
return META_CONNECTOR_TYPE_DSI;
|
|
|
|
if (g_str_has_prefix (name, "DIN"))
|
|
|
|
return META_CONNECTOR_TYPE_9PinDIN;
|
|
|
|
|
|
|
|
return META_CONNECTOR_TYPE_Unknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaConnectorType
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_get_connector_type (MetaOutputInfo *output_info,
|
|
|
|
Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
MetaConnectorType ret;
|
|
|
|
|
|
|
|
/* The "ConnectorType" property is considered mandatory since RandR 1.3,
|
|
|
|
* but none of the FOSS drivers support it, because we're a bunch of
|
|
|
|
* professional software developers.
|
|
|
|
*
|
|
|
|
* Try poking it first, without any expectations that it will work.
|
|
|
|
* If it's not there, we thankfully have other bonghits to try next.
|
|
|
|
*/
|
2020-02-26 08:45:07 +00:00
|
|
|
ret = output_get_connector_type_from_prop (xdisplay, output_id);
|
2017-07-04 10:42:16 +00:00
|
|
|
if (ret != META_CONNECTOR_TYPE_Unknown)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* Fall back to heuristics based on the output name. */
|
2020-02-26 08:45:07 +00:00
|
|
|
ret = output_info_get_connector_type_from_name (output_info);
|
2017-07-04 10:42:16 +00:00
|
|
|
if (ret != META_CONNECTOR_TYPE_Unknown)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
return META_CONNECTOR_TYPE_Unknown;
|
|
|
|
}
|
|
|
|
|
2017-10-24 10:43:58 +00:00
|
|
|
static gint
|
2020-02-26 08:45:07 +00:00
|
|
|
output_get_panel_orientation_transform (Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-10-24 10:43:58 +00:00
|
|
|
{
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
Atom atom, actual_type;
|
|
|
|
int actual_format;
|
|
|
|
g_autofree unsigned char *buffer = NULL;
|
|
|
|
g_autofree char *str = NULL;
|
|
|
|
|
|
|
|
atom = XInternAtom (xdisplay, "panel orientation", False);
|
2020-02-25 15:13:52 +00:00
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2020-02-25 15:13:52 +00:00
|
|
|
atom,
|
2017-10-24 10:43:58 +00:00
|
|
|
0, G_MAXLONG, False, False, XA_ATOM,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &buffer);
|
|
|
|
|
|
|
|
if (actual_type != XA_ATOM || actual_format != 32 || nitems < 1)
|
|
|
|
return META_MONITOR_TRANSFORM_NORMAL;
|
|
|
|
|
|
|
|
str = XGetAtomName (xdisplay, *(Atom *)buffer);
|
|
|
|
if (strcmp (str, "Upside Down") == 0)
|
|
|
|
return META_MONITOR_TRANSFORM_180;
|
|
|
|
|
|
|
|
if (strcmp (str, "Left Side Up") == 0)
|
|
|
|
return META_MONITOR_TRANSFORM_90;
|
|
|
|
|
|
|
|
if (strcmp (str, "Right Side Up") == 0)
|
|
|
|
return META_MONITOR_TRANSFORM_270;
|
|
|
|
|
|
|
|
return META_MONITOR_TRANSFORM_NORMAL;
|
|
|
|
}
|
|
|
|
|
2017-07-04 10:42:16 +00:00
|
|
|
static void
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_init_tile_info (MetaOutputInfo *output_info,
|
|
|
|
Display *xdisplay,
|
|
|
|
RROutput output_id)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
Atom tile_atom;
|
|
|
|
unsigned char *prop;
|
|
|
|
unsigned long nitems, bytes_after;
|
|
|
|
int actual_format;
|
|
|
|
Atom actual_type;
|
|
|
|
|
|
|
|
tile_atom = XInternAtom (xdisplay, "TILE", FALSE);
|
|
|
|
XRRGetOutputProperty (xdisplay,
|
2020-02-26 08:45:07 +00:00
|
|
|
(XID) output_id,
|
2017-07-04 10:42:16 +00:00
|
|
|
tile_atom, 0, 100, False,
|
|
|
|
False, AnyPropertyType,
|
|
|
|
&actual_type, &actual_format,
|
|
|
|
&nitems, &bytes_after, &prop);
|
|
|
|
|
|
|
|
if (actual_type == XA_INTEGER && actual_format == 32 && nitems == 8)
|
|
|
|
{
|
|
|
|
long *values = (long *)prop;
|
2020-02-26 08:45:07 +00:00
|
|
|
|
|
|
|
output_info->tile_info.group_id = values[0];
|
|
|
|
output_info->tile_info.flags = values[1];
|
|
|
|
output_info->tile_info.max_h_tiles = values[2];
|
|
|
|
output_info->tile_info.max_v_tiles = values[3];
|
|
|
|
output_info->tile_info.loc_h_tile = values[4];
|
|
|
|
output_info->tile_info.loc_v_tile = values[5];
|
|
|
|
output_info->tile_info.tile_w = values[6];
|
|
|
|
output_info->tile_info.tile_h = values[7];
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
XFree (prop);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_init_modes (MetaOutputInfo *output_info,
|
|
|
|
MetaGpu *gpu,
|
|
|
|
XRROutputInfo *xrandr_output)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
unsigned int n_actual_modes;
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->modes = g_new0 (MetaCrtcMode *, xrandr_output->nmode);
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
n_actual_modes = 0;
|
|
|
|
for (i = 0; i < (unsigned int) xrandr_output->nmode; i++)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
2017-07-10 10:19:32 +00:00
|
|
|
for (l = meta_gpu_get_modes (gpu); l; l = l->next)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
MetaCrtcMode *mode = l->data;
|
|
|
|
|
2020-02-26 23:08:58 +00:00
|
|
|
if (xrandr_output->modes[i] == (XID) meta_crtc_mode_get_id (mode))
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->modes[n_actual_modes] = mode;
|
2017-07-04 10:42:16 +00:00
|
|
|
n_actual_modes += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->n_modes = n_actual_modes;
|
2017-07-04 10:42:16 +00:00
|
|
|
if (n_actual_modes > 0)
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->preferred_mode = output_info->modes[0];
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_init_crtcs (MetaOutputInfo *output_info,
|
|
|
|
MetaGpu *gpu,
|
|
|
|
XRROutputInfo *xrandr_output)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
unsigned int n_actual_crtcs;
|
|
|
|
GList *l;
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->possible_crtcs = g_new0 (MetaCrtc *, xrandr_output->ncrtc);
|
2017-07-04 10:42:16 +00:00
|
|
|
|
|
|
|
n_actual_crtcs = 0;
|
|
|
|
for (i = 0; i < (unsigned int) xrandr_output->ncrtc; i++)
|
|
|
|
{
|
2017-07-10 10:19:32 +00:00
|
|
|
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
MetaCrtc *crtc = l->data;
|
|
|
|
|
2020-02-25 10:34:43 +00:00
|
|
|
if ((XID) meta_crtc_get_id (crtc) == xrandr_output->crtcs[i])
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->possible_crtcs[n_actual_crtcs] = crtc;
|
2017-07-04 10:42:16 +00:00
|
|
|
n_actual_crtcs += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->n_possible_crtcs = n_actual_crtcs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static MetaCrtc *
|
|
|
|
find_assigned_crtc (MetaGpu *gpu,
|
|
|
|
XRROutputInfo *xrandr_output)
|
|
|
|
{
|
|
|
|
GList *l;
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2017-07-10 10:19:32 +00:00
|
|
|
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
MetaCrtc *crtc = l->data;
|
|
|
|
|
2020-02-25 10:34:43 +00:00
|
|
|
if ((XID) meta_crtc_get_id (crtc) == xrandr_output->crtc)
|
2020-02-26 08:45:07 +00:00
|
|
|
return crtc;
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
2020-02-25 17:37:21 +00:00
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
return NULL;
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 15:47:03 +00:00
|
|
|
MetaOutputXrandr *
|
|
|
|
meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|
|
|
XRROutputInfo *xrandr_output,
|
|
|
|
RROutput output_id,
|
|
|
|
RROutput primary_output)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
MetaGpu *gpu = META_GPU (gpu_xrandr);
|
|
|
|
MetaBackend *backend = meta_gpu_get_backend (gpu);
|
|
|
|
MetaMonitorManager *monitor_manager =
|
|
|
|
meta_backend_get_monitor_manager (backend);
|
|
|
|
MetaMonitorManagerXrandr *monitor_manager_xrandr =
|
|
|
|
META_MONITOR_MANAGER_XRANDR (monitor_manager);
|
|
|
|
Display *xdisplay =
|
|
|
|
meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
|
|
|
|
g_autoptr (MetaOutputInfo) output_info = NULL;
|
2017-07-04 10:42:16 +00:00
|
|
|
MetaOutput *output;
|
|
|
|
GBytes *edid;
|
2020-02-25 17:37:21 +00:00
|
|
|
MetaCrtc *assigned_crtc;
|
2017-07-04 10:42:16 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info = meta_output_info_new ();
|
|
|
|
|
|
|
|
output_info->name = g_strdup (xrandr_output->name);
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
edid = read_xrandr_edid (xdisplay, output_id);
|
2021-10-28 13:25:58 +00:00
|
|
|
if (edid)
|
|
|
|
{
|
|
|
|
meta_output_info_parse_edid (output_info, edid);
|
|
|
|
g_bytes_unref (edid);
|
|
|
|
}
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
|
|
|
output_info->hotplug_mode_update = output_get_hotplug_mode_update (xdisplay,
|
|
|
|
output_id);
|
|
|
|
output_info->suggested_x = output_get_suggested_x (xdisplay, output_id);
|
|
|
|
output_info->suggested_y = output_get_suggested_y (xdisplay, output_id);
|
|
|
|
output_info->connector_type = output_info_get_connector_type (output_info,
|
|
|
|
xdisplay,
|
|
|
|
output_id);
|
|
|
|
output_info->panel_orientation_transform =
|
|
|
|
output_get_panel_orientation_transform (xdisplay, output_id);
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2022-07-12 09:35:10 +00:00
|
|
|
if (meta_monitor_transform_is_rotated (output_info->panel_orientation_transform))
|
2017-10-25 13:44:10 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->width_mm = xrandr_output->mm_height;
|
|
|
|
output_info->height_mm = xrandr_output->mm_width;
|
2017-10-25 13:44:10 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->width_mm = xrandr_output->mm_width;
|
|
|
|
output_info->height_mm = xrandr_output->mm_height;
|
|
|
|
}
|
|
|
|
|
2020-11-05 07:46:40 +00:00
|
|
|
if (meta_monitor_manager_xrandr_has_randr15 (monitor_manager_xrandr))
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_init_tile_info (output_info, xdisplay, output_id);
|
|
|
|
output_info_init_modes (output_info, gpu, xrandr_output);
|
|
|
|
output_info_init_crtcs (output_info, gpu, xrandr_output);
|
|
|
|
|
|
|
|
output_info->n_possible_clones = xrandr_output->nclone;
|
|
|
|
output_info->possible_clones = g_new0 (MetaOutput *,
|
|
|
|
output_info->n_possible_clones);
|
|
|
|
/*
|
|
|
|
* We can build the list of clones now, because we don't have the list of
|
|
|
|
* outputs yet, so temporarily set the pointers to the bare XIDs, and then
|
|
|
|
* we'll fix them in a second pass.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < (unsigned int) xrandr_output->nclone; i++)
|
|
|
|
{
|
|
|
|
output_info->possible_clones[i] = GINT_TO_POINTER (xrandr_output->clones[i]);
|
2017-10-25 13:44:10 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info->supports_underscanning =
|
|
|
|
output_get_supports_underscanning_xrandr (xdisplay, output_id);
|
2022-06-10 08:34:40 +00:00
|
|
|
output_get_max_bpc_range_xrandr (xdisplay,
|
|
|
|
output_id,
|
|
|
|
&output_info->max_bpc_min,
|
|
|
|
&output_info->max_bpc_max);
|
2020-02-05 00:41:34 +00:00
|
|
|
output_info->supports_color_transform =
|
|
|
|
output_get_supports_color_transform_xrandr (xdisplay, output_id);
|
2020-02-26 08:45:07 +00:00
|
|
|
output_info_init_backlight_limits_xrandr (output_info, xdisplay, output_id);
|
|
|
|
|
2020-02-26 15:47:03 +00:00
|
|
|
output = g_object_new (META_TYPE_OUTPUT_XRANDR,
|
2020-07-23 15:01:16 +00:00
|
|
|
"id", (uint64_t) output_id,
|
2020-02-26 08:45:07 +00:00
|
|
|
"gpu", gpu_xrandr,
|
|
|
|
"info", output_info,
|
|
|
|
NULL);
|
2020-02-25 17:37:21 +00:00
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
assigned_crtc = find_assigned_crtc (gpu, xrandr_output);
|
2020-02-25 17:37:21 +00:00
|
|
|
if (assigned_crtc)
|
|
|
|
{
|
2020-02-25 19:30:46 +00:00
|
|
|
MetaOutputAssignment output_assignment;
|
2020-02-25 17:37:21 +00:00
|
|
|
|
2020-02-25 19:30:46 +00:00
|
|
|
output_assignment = (MetaOutputAssignment) {
|
2020-02-25 17:37:21 +00:00
|
|
|
.is_primary = (XID) meta_output_get_id (output) == primary_output,
|
|
|
|
.is_presentation = output_get_presentation_xrandr (output),
|
|
|
|
.is_underscanning = output_get_underscanning_xrandr (output),
|
|
|
|
};
|
2022-06-10 08:34:40 +00:00
|
|
|
output_assignment.has_max_bpc =
|
|
|
|
output_get_max_bpc_xrandr (output, &output_assignment.max_bpc);
|
|
|
|
|
2020-02-25 19:30:46 +00:00
|
|
|
meta_output_assign_crtc (output, assigned_crtc, &output_assignment);
|
2020-02-25 17:37:21 +00:00
|
|
|
}
|
2020-02-26 08:45:07 +00:00
|
|
|
else
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
2020-02-26 08:45:07 +00:00
|
|
|
meta_output_unassign_crtc (output);
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
if (!(output_info->backlight_min == 0 && output_info->backlight_max == 0))
|
2020-02-25 17:37:21 +00:00
|
|
|
meta_output_set_backlight (output, output_get_backlight_xrandr (output));
|
2017-07-04 10:42:16 +00:00
|
|
|
|
2020-02-26 08:45:07 +00:00
|
|
|
if (output_info->n_modes == 0 || output_info->n_possible_crtcs == 0)
|
2017-07-04 10:42:16 +00:00
|
|
|
{
|
|
|
|
g_object_unref (output);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-02-26 15:47:03 +00:00
|
|
|
return META_OUTPUT_XRANDR (output);
|
2017-07-04 10:42:16 +00:00
|
|
|
}
|
|
|
|
}
|
2020-02-26 15:47:03 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
meta_output_xrandr_init (MetaOutputXrandr *output_xrandr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_output_xrandr_class_init (MetaOutputXrandrClass *klass)
|
|
|
|
{
|
|
|
|
}
|