[mutter] backends/x11: Move output code to its own file
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] backends/x11: Move output code to its own file
- Date: Fri, 6 Oct 2017 18:23:40 +0000 (UTC)
commit e32d52b9b8eca6c82747afb59dea7d0464f435ee
Author: Jonas Ådahl <jadahl gmail com>
Date: Tue Jul 4 18:42:16 2017 +0800
backends/x11: Move output code to its own file
Move code dealing with X11 MetaOutputs and related functionality to its
own file. Eventually, a MetaOutputXrandr should be introduced, based on
MetaOutput, and this commit is in preparation for that.
https://bugzilla.gnome.org/show_bug.cgi?id=785381
src/Makefile.am | 2 +
src/backends/x11/meta-monitor-manager-xrandr.c | 738 +---------------------
src/backends/x11/meta-monitor-manager-xrandr.h | 4 +
src/backends/x11/meta-output-xrandr.c | 786 ++++++++++++++++++++++++
src/backends/x11/meta-output-xrandr.h | 42 ++
5 files changed, 860 insertions(+), 712 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index afcbc3e..71a846a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -171,6 +171,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
backends/x11/meta-input-settings-x11.h \
backends/x11/meta-monitor-manager-xrandr.c \
backends/x11/meta-monitor-manager-xrandr.h \
+ backends/x11/meta-output-xrandr.c \
+ backends/x11/meta-output-xrandr.h \
backends/x11/meta-renderer-x11.c \
backends/x11/meta-renderer-x11.h \
backends/x11/meta-stage-x11-nested.c \
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 5f78c6a..f8eec04 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -32,11 +32,8 @@
#include <math.h>
#include <clutter/clutter.h>
-#include <X11/Xatom.h>
#include <X11/Xlibint.h>
-#include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.h>
-#include <X11/extensions/extutil.h>
#include <X11/Xlib-xcb.h>
#include <xcb/randr.h>
@@ -47,6 +44,7 @@
#include "backends/meta-monitor-config-manager.h"
#include "backends/meta-logical-monitor.h"
#include "backends/meta-output.h"
+#include "backends/x11/meta-output-xrandr.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@@ -91,6 +89,18 @@ typedef struct _MetaMonitorXrandrData
GQuark quark_meta_monitor_xrandr_data;
#endif /* HAVE_RANDR15 */
+Display *
+meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr)
+{
+ return manager_xrandr->xdisplay;
+}
+
+gboolean
+meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr)
+{
+ return manager_xrandr->has_randr15;
+}
+
static MetaMonitorTransform
meta_monitor_transform_from_xrandr (Rotation rotation)
{
@@ -162,226 +172,6 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
return ret;
}
-static gboolean
-output_get_integer_property (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output, 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 (manager_xrandr->xdisplay, propname, False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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
-output_get_property_exists (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output, const char *propname)
-{
- gboolean exists = FALSE;
- Atom atom, actual_type;
- int actual_format;
- unsigned long nitems, bytes_after;
- unsigned char *buffer;
-
- atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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 (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output, const char *propname)
-{
- Atom atom, actual_type;
- int actual_format;
- unsigned long nitems, bytes_after;
- g_autofree unsigned char *buffer = NULL;
-
- atom = XInternAtom (manager_xrandr->xdisplay, propname, False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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 (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- return output_get_boolean_property (manager_xrandr, output, "_MUTTER_PRESENTATION_OUTPUT");
-}
-
-static gboolean
-output_get_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *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 (manager_xrandr->xdisplay, "underscan", False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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 (manager_xrandr->xdisplay, *(Atom *)buffer);
- return (strcmp (str, "on") == 0);
-}
-
-static gboolean
-output_get_supports_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- 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 (manager_xrandr->xdisplay, "underscan", False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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 (manager_xrandr->xdisplay,
- (XID) output->winsys_id,
- 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 (manager_xrandr->xdisplay, values[i]);
- if (strcmp (name, "on") == 0)
- supports_underscanning = TRUE;
-
- XFree (name);
- }
-
- XFree (property_info);
-
- return supports_underscanning;
-}
-
-static int
-normalize_backlight (MetaOutput *output,
- int hw_value)
-{
- return round ((double)(hw_value - output->backlight_min) /
- (output->backlight_max - output->backlight_min) * 100.0);
-}
-
-static int
-output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- int value = -1;
- Atom atom, actual_type;
- int actual_format;
- unsigned long nitems, bytes_after;
- g_autofree unsigned char *buffer = NULL;
-
- atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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
-output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- Atom atom;
- xcb_connection_t *xcb_conn;
- g_autofree xcb_randr_query_output_property_reply_t *reply = NULL;
-
- atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
-
- xcb_conn = XGetXCBConnection (manager_xrandr->xdisplay);
- reply = xcb_randr_query_output_property_reply (xcb_conn,
- xcb_randr_query_output_property (xcb_conn,
- (xcb_randr_output_t)
output->winsys_id,
- (xcb_atom_t) atom),
- NULL);
-
- /* This can happen on systems without backlights. */
- if (reply == NULL)
- return;
-
- if (!reply->range || reply->length != 2)
- {
- meta_verbose ("backlight %s was not range\n", output->name);
- return;
- }
-
- int32_t *values = xcb_randr_query_output_property_valid_values (reply);
- output->backlight_min = values[0];
- output->backlight_max = values[1];
-}
-
static int
compare_outputs (const void *one,
const void *two)
@@ -391,342 +181,6 @@ compare_outputs (const void *one,
return strcmp (o_one->name, o_two->name);
}
-static guint8 *
-get_edid_property (Display *dpy,
- RROutput output,
- Atom atom,
- gsize *len)
-{
- unsigned char *prop;
- int actual_format;
- unsigned long nitems, bytes_after;
- Atom actual_type;
- guint8 *result;
-
- XRRGetOutputProperty (dpy, output, atom,
- 0, 100, False, False,
- AnyPropertyType,
- &actual_type, &actual_format,
- &nitems, &bytes_after, &prop);
-
- if (actual_type == XA_INTEGER && actual_format == 8)
- {
- result = g_memdup (prop, nitems);
- if (len)
- *len = nitems;
- }
- else
- {
- result = NULL;
- }
-
- XFree (prop);
-
- return result;
-}
-
-static GBytes *
-read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
- XID winsys_id)
-{
- Atom edid_atom;
- guint8 *result;
- gsize len;
-
- edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
- result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
-
- if (!result)
- {
- edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
- result = get_edid_property (manager_xrandr->xdisplay, winsys_id, edid_atom, &len);
- }
-
- if (result)
- {
- if (len > 0 && len % 128 == 0)
- return g_bytes_new_take (result, len);
- else
- g_free (result);
- }
-
- return NULL;
-}
-
-static void
-output_get_tile_info (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- Atom tile_atom;
- unsigned char *prop;
- unsigned long nitems, bytes_after;
- int actual_format;
- Atom actual_type;
-
- if (manager_xrandr->has_randr15 == FALSE)
- return;
-
- tile_atom = XInternAtom (manager_xrandr->xdisplay, "TILE", FALSE);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- output->winsys_id,
- 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;
- output->tile_info.group_id = values[0];
- output->tile_info.flags = values[1];
- output->tile_info.max_h_tiles = values[2];
- output->tile_info.max_v_tiles = values[3];
- output->tile_info.loc_h_tile = values[4];
- output->tile_info.loc_v_tile = values[5];
- output->tile_info.tile_w = values[6];
- output->tile_info.tile_h = values[7];
- }
- XFree (prop);
-}
-
-static gboolean
-output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- return output_get_property_exists (manager_xrandr, output, "hotplug_mode_update");
-}
-
-static gint
-output_get_suggested_x (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- gint val;
- if (output_get_integer_property (manager_xrandr, output, "suggested X", &val))
- return val;
-
- return -1;
-}
-
-static gint
-output_get_suggested_y (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- gint val;
- if (output_get_integer_property (manager_xrandr, output, "suggested Y", &val))
- return val;
-
- return -1;
-}
-
-static MetaConnectorType
-connector_type_from_atom (MetaMonitorManagerXrandr *manager_xrandr,
- Atom atom)
-{
- Display *xdpy = manager_xrandr->xdisplay;
-
- if (atom == XInternAtom (xdpy, "HDMI", True))
- return META_CONNECTOR_TYPE_HDMIA;
- if (atom == XInternAtom (xdpy, "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 (xdpy, "Panel", True))
- return META_CONNECTOR_TYPE_LVDS;
- if (atom == XInternAtom (xdpy, "DVI", True) || atom == XInternAtom (xdpy, "DVI-I", True))
- return META_CONNECTOR_TYPE_DVII;
- if (atom == XInternAtom (xdpy, "DVI-A", True))
- return META_CONNECTOR_TYPE_DVIA;
- if (atom == XInternAtom (xdpy, "DVI-D", True))
- return META_CONNECTOR_TYPE_DVID;
- if (atom == XInternAtom (xdpy, "DisplayPort", True))
- return META_CONNECTOR_TYPE_DisplayPort;
-
- if (atom == XInternAtom (xdpy, "TV", True))
- return META_CONNECTOR_TYPE_TV;
- if (atom == XInternAtom (xdpy, "TV-Composite", True))
- return META_CONNECTOR_TYPE_Composite;
- if (atom == XInternAtom (xdpy, "TV-SVideo", True))
- return META_CONNECTOR_TYPE_SVIDEO;
- /* Another set of mismatches. */
- if (atom == XInternAtom (xdpy, "TV-SCART", True))
- return META_CONNECTOR_TYPE_TV;
- if (atom == XInternAtom (xdpy, "TV-C4", True))
- return META_CONNECTOR_TYPE_TV;
-
- return META_CONNECTOR_TYPE_Unknown;
-}
-
-static MetaConnectorType
-output_get_connector_type_from_prop (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- Atom atom, actual_type, connector_type_atom;
- int actual_format;
- unsigned long nitems, bytes_after;
- g_autofree unsigned char *buffer = NULL;
-
- atom = XInternAtom (manager_xrandr->xdisplay, "ConnectorType", False);
- XRRGetOutputProperty (manager_xrandr->xdisplay,
- (XID)output->winsys_id,
- 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 (manager_xrandr, connector_type_atom);
-}
-
-static MetaConnectorType
-output_get_connector_type_from_name (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- const char *name = output->name;
-
- /* 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
-output_get_connector_type (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output)
-{
- 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.
- */
- ret = output_get_connector_type_from_prop (manager_xrandr, output);
- if (ret != META_CONNECTOR_TYPE_Unknown)
- return ret;
-
- /* Fall back to heuristics based on the output name. */
- ret = output_get_connector_type_from_name (manager_xrandr, output);
- if (ret != META_CONNECTOR_TYPE_Unknown)
- return ret;
-
- return META_CONNECTOR_TYPE_Unknown;
-}
-
-static void
-output_get_modes (MetaMonitorManager *manager,
- MetaOutput *output,
- XRROutputInfo *xrandr_output)
-{
- guint j;
- guint n_actual_modes;
-
- output->modes = g_new0 (MetaCrtcMode *, xrandr_output->nmode);
-
- n_actual_modes = 0;
- for (j = 0; j < (guint)xrandr_output->nmode; j++)
- {
- GList *l;
-
- for (l = manager->modes; l; l = l->next)
- {
- MetaCrtcMode *mode = l->data;
-
- if (xrandr_output->modes[j] == (XID) mode->mode_id)
- {
- output->modes[n_actual_modes] = mode;
- n_actual_modes += 1;
- break;
- }
- }
- }
- output->n_modes = n_actual_modes;
- if (n_actual_modes > 0)
- output->preferred_mode = output->modes[0];
-}
-
-static void
-output_get_crtcs (MetaMonitorManager *manager,
- MetaOutput *output,
- XRROutputInfo *xrandr_output)
-{
- guint j;
- guint n_actual_crtcs;
- GList *l;
-
- output->possible_crtcs = g_new0 (MetaCrtc *, xrandr_output->ncrtc);
-
- n_actual_crtcs = 0;
- for (j = 0; j < (unsigned) xrandr_output->ncrtc; j++)
- {
- for (l = manager->crtcs; l; l = l->next)
- {
- MetaCrtc *crtc = l->data;
-
- if ((XID) crtc->crtc_id == xrandr_output->crtcs[j])
- {
- output->possible_crtcs[n_actual_crtcs] = crtc;
- n_actual_crtcs += 1;
- break;
- }
- }
- }
- output->n_possible_crtcs = n_actual_crtcs;
-
- output->crtc = NULL;
- for (l = manager->crtcs; l; l = l->next)
- {
- MetaCrtc *crtc = l->data;
-
- if ((XID) crtc->crtc_id == xrandr_output->crtc)
- {
- output->crtc = crtc;
- break;
- }
- }
-}
-
static char *
get_xmode_name (XRRModeInfo *xmode)
{
@@ -864,70 +318,24 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
for (i = 0; i < (unsigned)resources->noutput; i++)
{
+ RROutput output_id;
XRROutputInfo *xrandr_output;
- MetaOutput *output;
+ output_id = resources->outputs[i];
xrandr_output = XRRGetOutputInfo (manager_xrandr->xdisplay,
- resources, resources->outputs[i]);
+ resources, output_id);
if (!xrandr_output)
continue;
- output = g_object_new (META_TYPE_OUTPUT, NULL);
- output->monitor_manager = manager;
-
if (xrandr_output->connection != RR_Disconnected)
{
- GBytes *edid;
-
- output->winsys_id = resources->outputs[i];
- output->name = g_strdup (xrandr_output->name);
-
- edid = read_output_edid (manager_xrandr, output->winsys_id);
- meta_output_parse_edid (output, edid);
- g_bytes_unref (edid);
-
- output->width_mm = xrandr_output->mm_width;
- output->height_mm = xrandr_output->mm_height;
- output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
- output->hotplug_mode_update =
- output_get_hotplug_mode_update (manager_xrandr, output);
- output->suggested_x = output_get_suggested_x (manager_xrandr, output);
- output->suggested_y = output_get_suggested_y (manager_xrandr, output);
- output->connector_type = output_get_connector_type (manager_xrandr,
- output);
-
- output_get_tile_info (manager_xrandr, output);
- output_get_modes (manager, output, xrandr_output);
- output_get_crtcs (manager, output, xrandr_output);
-
- output->n_possible_clones = xrandr_output->nclone;
- output->possible_clones = g_new0 (MetaOutput *,
- output->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 (j = 0; j < (unsigned) xrandr_output->nclone; j++)
- {
- output->possible_clones[j] =
- GINT_TO_POINTER (xrandr_output->clones[j]);
- }
-
- output->is_primary = ((XID) output->winsys_id == primary_output);
- output->is_presentation = output_get_presentation_xrandr (manager_xrandr, output);
- output->is_underscanning = output_get_underscanning_xrandr (manager_xrandr, output);
- output->supports_underscanning =
- output_get_supports_underscanning_xrandr (manager_xrandr, output);
- output_get_backlight_limits_xrandr (manager_xrandr, output);
+ MetaOutput *output;
- if (!(output->backlight_min == 0 && output->backlight_max == 0))
- output->backlight = output_get_backlight_xrandr (manager_xrandr, output);
- else
- output->backlight = -1;
-
- if (output->n_modes == 0 || output->n_possible_crtcs == 0)
- g_object_unref (output);
- else
+ output = meta_create_xrandr_output (manager,
+ xrandr_output,
+ output_id,
+ primary_output);
+ if (output)
manager->outputs = g_list_prepend (manager->outputs, output);
}
@@ -965,9 +373,7 @@ static GBytes *
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
{
- MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
-
- return read_output_edid (manager_xrandr, output->winsys_id);
+ return meta_output_xrandr_read_edid (output);
}
static void
@@ -1024,69 +430,6 @@ meta_monitor_transform_to_xrandr (MetaMonitorTransform transform)
g_assert_not_reached ();
}
-static void
-output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output,
- gboolean presentation)
-{
- Atom atom;
- int value = presentation;
-
- atom = XInternAtom (manager_xrandr->xdisplay, "_MUTTER_PRESENTATION_OUTPUT", False);
-
- xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
- (XID)output->winsys_id,
- atom, XCB_ATOM_CARDINAL, 32,
- XCB_PROP_MODE_REPLACE,
- 1, &value);
-}
-
-static void
-output_set_underscanning_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
- MetaOutput *output,
- gboolean underscanning)
-{
- Atom prop, valueatom;
- const char *value;
-
- prop = XInternAtom (manager_xrandr->xdisplay, "underscan", False);
-
- value = underscanning ? "on" : "off";
- valueatom = XInternAtom (manager_xrandr->xdisplay, value, False);
-
- xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
- (XID)output->winsys_id,
- 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)
- {
- uint32_t border_value;
-
- prop = XInternAtom (manager_xrandr->xdisplay, "underscan hborder", False);
- border_value = output->crtc->current_mode->width * 0.05;
-
- xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
- (XID)output->winsys_id,
- prop, XCB_ATOM_INTEGER, 32,
- XCB_PROP_MODE_REPLACE,
- 1, &border_value);
-
- prop = XInternAtom (manager_xrandr->xdisplay, "underscan vborder", False);
- border_value = output->crtc->current_mode->height * 0.05;
-
- xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
- (XID)output->winsys_id,
- prop, XCB_ATOM_INTEGER, 32,
- XCB_PROP_MODE_REPLACE,
- 1, &border_value);
- }
-}
-
static gboolean
xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr,
gboolean save_timestamp,
@@ -1437,25 +780,11 @@ apply_crtc_assignments (MetaMonitorManager *manager,
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
- if (output_info->is_primary)
- {
- XRRSetOutputPrimary (manager_xrandr->xdisplay,
- DefaultRootWindow (manager_xrandr->xdisplay),
- (XID)output_info->output->winsys_id);
- }
-
- output_set_presentation_xrandr (manager_xrandr,
- output_info->output,
- output_info->is_presentation);
-
- if (output_get_supports_underscanning_xrandr (manager_xrandr, output_info->output))
- output_set_underscanning_xrandr (manager_xrandr,
- output_info->output,
- output_info->is_underscanning);
-
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
output->is_underscanning = output_info->is_underscanning;
+
+ meta_output_xrandr_apply_mode (output);
}
/* Disable outputs not mentioned in the list */
@@ -1557,22 +886,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
MetaOutput *output,
gint value)
{
- MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
- Atom atom;
- int hw_value;
-
- hw_value = round ((double)value / 100.0 * output->backlight_max + output->backlight_min);
-
- atom = XInternAtom (manager_xrandr->xdisplay, "Backlight", False);
-
- xcb_randr_change_output_property (XGetXCBConnection (manager_xrandr->xdisplay),
- (XID)output->winsys_id,
- atom, XCB_ATOM_INTEGER, 32,
- XCB_PROP_MODE_REPLACE,
- 1, &hw_value);
-
- /* We're not selecting for property notifies, so update the value immediately */
- output->backlight = normalize_backlight (output, hw_value);
+ meta_output_xrandr_change_backlight (output, value);
}
static void
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h
index 3076e24..9f1d6ff 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.h
+++ b/src/backends/x11/meta-monitor-manager-xrandr.h
@@ -29,6 +29,10 @@
G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr,
META, MONITOR_MANAGER_XRANDR, MetaMonitorManager)
+Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr);
+
+gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr);
+
gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager,
XEvent *event);
diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c
new file mode 100644
index 0000000..608c6b6
--- /dev/null
+++ b/src/backends/x11/meta-output-xrandr.c
@@ -0,0 +1,786 @@
+/* -*- 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.
+ *
+ * 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>
+
+#include "backends/meta-crtc.h"
+#include "backends/x11/meta-monitor-manager-xrandr.h"
+#include "meta/util.h"
+
+static Display *
+xdisplay_from_output (MetaOutput *output)
+{
+ MetaMonitorManager *monitor_manager =
+ meta_output_get_monitor_manager (output);
+ MetaMonitorManagerXrandr *monitor_manager_xrandr =
+ META_MONITOR_MANAGER_XRANDR (monitor_manager);
+
+ return meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
+}
+
+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),
+ (XID) output->winsys_id,
+ 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),
+ (XID) output->winsys_id,
+ 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)
+ {
+ uint32_t border_value;
+
+ prop = XInternAtom (xdisplay, "underscan hborder", False);
+ border_value = output->crtc->current_mode->width * 0.05;
+
+ xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
+ (XID) output->winsys_id,
+ prop, XCB_ATOM_INTEGER, 32,
+ XCB_PROP_MODE_REPLACE,
+ 1, &border_value);
+
+ prop = XInternAtom (xdisplay, "underscan vborder", False);
+ border_value = output->crtc->current_mode->height * 0.05;
+
+ xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
+ (XID) output->winsys_id,
+ prop, XCB_ATOM_INTEGER, 32,
+ XCB_PROP_MODE_REPLACE,
+ 1, &border_value);
+ }
+}
+
+void
+meta_output_xrandr_apply_mode (MetaOutput *output)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+
+ if (output->is_primary)
+ {
+ XRRSetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay),
+ (XID) output->winsys_id);
+ }
+
+ output_set_presentation_xrandr (output, output->is_presentation);
+
+ if (output->supports_underscanning)
+ output_set_underscanning_xrandr (output, output->is_underscanning);
+}
+
+static int
+normalize_backlight (MetaOutput *output,
+ int hw_value)
+{
+ return round ((double)(hw_value - output->backlight_min) /
+ (output->backlight_max - output->backlight_min) * 100.0);
+}
+
+void
+meta_output_xrandr_change_backlight (MetaOutput *output,
+ int value)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ Atom atom;
+ int hw_value;
+
+ hw_value = round ((double) value / 100.0 * output->backlight_max +
+ output->backlight_min);
+
+ atom = XInternAtom (xdisplay, "Backlight", False);
+
+ xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
+ (XID)output->winsys_id,
+ atom, XCB_ATOM_INTEGER, 32,
+ XCB_PROP_MODE_REPLACE,
+ 1, &hw_value);
+
+ /* We're not selecting for property notifies, so update the value immediately */
+ output->backlight = normalize_backlight (output, hw_value);
+}
+
+static gboolean
+output_get_integer_property (MetaOutput *output,
+ const char *propname,
+ gint *value)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ 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,
+ (XID)output->winsys_id,
+ 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
+output_get_property_exists (MetaOutput *output,
+ const char *propname)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ 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,
+ (XID)output->winsys_id,
+ 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,
+ (XID)output->winsys_id,
+ 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,
+ (XID)output->winsys_id,
+ 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);
+}
+
+static gboolean
+output_get_supports_underscanning_xrandr (MetaOutput *output)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ 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,
+ (XID)output->winsys_id,
+ 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,
+ (XID) output->winsys_id,
+ 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;
+}
+
+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,
+ (XID)output->winsys_id,
+ 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
+output_get_backlight_limits_xrandr (MetaOutput *output)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ 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,
+ (xcb_randr_output_t) output->winsys_id,
+ (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)
+ {
+ meta_verbose ("backlight %s was not range\n", output->name);
+ return;
+ }
+
+ int32_t *values = xcb_randr_query_output_property_valid_values (reply);
+ output->backlight_min = values[0];
+ output->backlight_max = values[1];
+}
+
+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)
+ {
+ result = g_memdup (prop, nitems);
+ if (len)
+ *len = nitems;
+ }
+ else
+ {
+ result = NULL;
+ }
+
+ XFree (prop);
+
+ return result;
+}
+
+GBytes *
+meta_output_xrandr_read_edid (MetaOutput *output)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ Atom edid_atom;
+ guint8 *result;
+ gsize len;
+
+ edid_atom = XInternAtom (xdisplay, "EDID", FALSE);
+ result = get_edid_property (xdisplay, output->winsys_id, edid_atom, &len);
+
+ if (!result)
+ {
+ edid_atom = XInternAtom (xdisplay, "EDID_DATA", FALSE);
+ result = get_edid_property (xdisplay, output->winsys_id, edid_atom, &len);
+ }
+
+ if (result)
+ {
+ if (len > 0 && len % 128 == 0)
+ return g_bytes_new_take (result, len);
+ else
+ g_free (result);
+ }
+
+ return NULL;
+}
+
+static gboolean
+output_get_hotplug_mode_update (MetaOutput *output)
+{
+ return output_get_property_exists (output, "hotplug_mode_update");
+}
+
+static gint
+output_get_suggested_x (MetaOutput *output)
+{
+ gint val;
+ if (output_get_integer_property (output, "suggested X", &val))
+ return val;
+
+ return -1;
+}
+
+static gint
+output_get_suggested_y (MetaOutput *output)
+{
+ gint val;
+ if (output_get_integer_property (output, "suggested Y", &val))
+ 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
+output_get_connector_type_from_prop (MetaOutput *output)
+{
+ Display *xdisplay = xdisplay_from_output (output);
+ 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,
+ (XID)output->winsys_id,
+ 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
+output_get_connector_type_from_name (MetaOutput *output)
+{
+ const char *name = output->name;
+
+ /* 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
+output_get_connector_type (MetaOutput *output)
+{
+ 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.
+ */
+ ret = output_get_connector_type_from_prop (output);
+ if (ret != META_CONNECTOR_TYPE_Unknown)
+ return ret;
+
+ /* Fall back to heuristics based on the output name. */
+ ret = output_get_connector_type_from_name (output);
+ if (ret != META_CONNECTOR_TYPE_Unknown)
+ return ret;
+
+ return META_CONNECTOR_TYPE_Unknown;
+}
+
+static void
+output_get_tile_info (MetaOutput *output)
+{
+ MetaMonitorManager *monitor_manager =
+ meta_output_get_monitor_manager (output);
+ MetaMonitorManagerXrandr *monitor_manager_xrandr =
+ META_MONITOR_MANAGER_XRANDR (monitor_manager);
+ Display *xdisplay = xdisplay_from_output (output);
+ Atom tile_atom;
+ unsigned char *prop;
+ unsigned long nitems, bytes_after;
+ int actual_format;
+ Atom actual_type;
+
+ if (!meta_monitor_manager_xrandr_has_randr15 (monitor_manager_xrandr))
+ return;
+
+ tile_atom = XInternAtom (xdisplay, "TILE", FALSE);
+ XRRGetOutputProperty (xdisplay,
+ output->winsys_id,
+ 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;
+ output->tile_info.group_id = values[0];
+ output->tile_info.flags = values[1];
+ output->tile_info.max_h_tiles = values[2];
+ output->tile_info.max_v_tiles = values[3];
+ output->tile_info.loc_h_tile = values[4];
+ output->tile_info.loc_v_tile = values[5];
+ output->tile_info.tile_w = values[6];
+ output->tile_info.tile_h = values[7];
+ }
+ XFree (prop);
+}
+
+
+static void
+output_get_modes (MetaMonitorManager *monitor_manager,
+ MetaOutput *output,
+ XRROutputInfo *xrandr_output)
+{
+ unsigned int i;
+ unsigned int n_actual_modes;
+
+ output->modes = g_new0 (MetaCrtcMode *, xrandr_output->nmode);
+
+ n_actual_modes = 0;
+ for (i = 0; i < (unsigned int) xrandr_output->nmode; i++)
+ {
+ GList *l;
+
+ for (l = monitor_manager->modes; l; l = l->next)
+ {
+ MetaCrtcMode *mode = l->data;
+
+ if (xrandr_output->modes[i] == (XID) mode->mode_id)
+ {
+ output->modes[n_actual_modes] = mode;
+ n_actual_modes += 1;
+ break;
+ }
+ }
+ }
+ output->n_modes = n_actual_modes;
+ if (n_actual_modes > 0)
+ output->preferred_mode = output->modes[0];
+}
+
+static void
+output_get_crtcs (MetaMonitorManager *monitor_manager,
+ MetaOutput *output,
+ XRROutputInfo *xrandr_output)
+{
+ unsigned int i;
+ unsigned int n_actual_crtcs;
+ GList *l;
+
+ output->possible_crtcs = g_new0 (MetaCrtc *, xrandr_output->ncrtc);
+
+ n_actual_crtcs = 0;
+ for (i = 0; i < (unsigned int) xrandr_output->ncrtc; i++)
+ {
+ for (l = monitor_manager->crtcs; l; l = l->next)
+ {
+ MetaCrtc *crtc = l->data;
+
+ if ((XID) crtc->crtc_id == xrandr_output->crtcs[i])
+ {
+ output->possible_crtcs[n_actual_crtcs] = crtc;
+ n_actual_crtcs += 1;
+ break;
+ }
+ }
+ }
+ output->n_possible_crtcs = n_actual_crtcs;
+
+ output->crtc = NULL;
+ for (l = monitor_manager->crtcs; l; l = l->next)
+ {
+ MetaCrtc *crtc = l->data;
+
+ if ((XID) crtc->crtc_id == xrandr_output->crtc)
+ {
+ output->crtc = crtc;
+ break;
+ }
+ }
+}
+
+MetaOutput *
+meta_create_xrandr_output (MetaMonitorManager *monitor_manager,
+ XRROutputInfo *xrandr_output,
+ RROutput output_id,
+ RROutput primary_output)
+{
+ MetaOutput *output;
+ GBytes *edid;
+ unsigned int i;
+
+ output = g_object_new (META_TYPE_OUTPUT, NULL);
+ output->monitor_manager = monitor_manager;
+ output->winsys_id = output_id;
+ output->name = g_strdup (xrandr_output->name);
+
+ edid = meta_output_xrandr_read_edid (output);
+ meta_output_parse_edid (output, edid);
+ g_bytes_unref (edid);
+
+ output->width_mm = xrandr_output->mm_width;
+ output->height_mm = xrandr_output->mm_height;
+ output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
+ output->hotplug_mode_update = output_get_hotplug_mode_update (output);
+ output->suggested_x = output_get_suggested_x (output);
+ output->suggested_y = output_get_suggested_y (output);
+ output->connector_type = output_get_connector_type (output);
+
+ output_get_tile_info (output);
+ output_get_modes (monitor_manager, output, xrandr_output);
+ output_get_crtcs (monitor_manager, output, xrandr_output);
+
+ output->n_possible_clones = xrandr_output->nclone;
+ output->possible_clones = g_new0 (MetaOutput *,
+ output->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->possible_clones[i] = GINT_TO_POINTER (xrandr_output->clones[i]);
+ }
+
+ output->is_primary = ((XID) output->winsys_id == primary_output);
+ output->is_presentation = output_get_presentation_xrandr (output);
+ output->is_underscanning = output_get_underscanning_xrandr (output);
+ output->supports_underscanning =
+ output_get_supports_underscanning_xrandr (output);
+ output_get_backlight_limits_xrandr (output);
+
+ if (!(output->backlight_min == 0 && output->backlight_max == 0))
+ output->backlight = output_get_backlight_xrandr (output);
+ else
+ output->backlight = -1;
+
+ if (output->n_modes == 0 || output->n_possible_crtcs == 0)
+ {
+ g_object_unref (output);
+ return NULL;
+ }
+ else
+ {
+ return output;
+ }
+}
diff --git a/src/backends/x11/meta-output-xrandr.h b/src/backends/x11/meta-output-xrandr.h
new file mode 100644
index 0000000..3a263a4
--- /dev/null
+++ b/src/backends/x11/meta-output-xrandr.h
@@ -0,0 +1,42 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * 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.
+ */
+
+#ifndef META_OUTPUT_XRANDR
+#define META_OUTPUT_XRANDR
+
+#include <X11/extensions/Xrandr.h>
+
+#include "backends/meta-output.h"
+#include "backends/x11/meta-monitor-manager-xrandr.h"
+
+void meta_output_xrandr_apply_mode (MetaOutput *output);
+
+void meta_output_xrandr_change_backlight (MetaOutput *output,
+ int value);
+
+GBytes * meta_output_xrandr_read_edid (MetaOutput *output);
+
+MetaOutput * meta_create_xrandr_output (MetaMonitorManager *monitor_manager,
+ XRROutputInfo *xrandr_output,
+ RROutput output_id,
+ RROutput primary_output);
+
+#endif /* META_OUTPUT_XRANDR */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]