2017-07-04 00:11:44 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2013-2017 Red Hat
|
2018-10-11 10:15:37 -04:00
|
|
|
* Copyright (C) 2018 DisplayLink (UK) Ltd.
|
2017-07-04 00:11:44 -04: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/native/meta-output-kms.h"
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "backends/meta-crtc.h"
|
2019-03-08 10:23:15 -05:00
|
|
|
#include "backends/native/meta-kms-connector.h"
|
2017-07-04 04:04:39 -04:00
|
|
|
#include "backends/native/meta-crtc-kms.h"
|
2018-07-07 09:28:41 -04:00
|
|
|
|
|
|
|
#include "meta-default-modes.h"
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
#define SYNC_TOLERANCE 0.01 /* 1 percent */
|
|
|
|
|
|
|
|
typedef struct _MetaOutputKms
|
|
|
|
{
|
|
|
|
MetaOutput parent;
|
|
|
|
|
2019-03-08 10:23:15 -05:00
|
|
|
MetaKmsConnector *kms_connector;
|
|
|
|
|
2017-07-04 00:11:44 -04:00
|
|
|
drmModeConnector *connector;
|
|
|
|
|
|
|
|
uint32_t dpms_prop_id;
|
|
|
|
|
2019-03-26 05:09:45 -04:00
|
|
|
uint32_t underscan_prop_id;
|
|
|
|
uint32_t underscan_hborder_prop_id;
|
|
|
|
uint32_t underscan_vborder_prop_id;
|
2017-07-04 00:11:44 -04:00
|
|
|
} MetaOutputKms;
|
|
|
|
|
2017-07-04 04:04:39 -04:00
|
|
|
void
|
|
|
|
meta_output_kms_set_underscan (MetaOutput *output)
|
|
|
|
{
|
2019-03-26 05:09:45 -04:00
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
|
|
|
MetaGpu *gpu = meta_output_get_gpu (output);
|
|
|
|
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
|
2017-11-03 06:25:30 -04:00
|
|
|
MetaCrtc *crtc;
|
2019-03-26 05:09:45 -04:00
|
|
|
int kms_fd;
|
|
|
|
uint32_t connector_id;
|
2017-11-03 06:25:30 -04:00
|
|
|
|
2019-03-26 05:09:45 -04:00
|
|
|
if (!output_kms->underscan_prop_id)
|
2017-07-04 04:04:39 -04:00
|
|
|
return;
|
|
|
|
|
2019-03-26 05:09:45 -04:00
|
|
|
crtc = meta_output_get_assigned_crtc (output);
|
|
|
|
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
|
|
|
connector_id = output_kms->connector->connector_id;
|
|
|
|
|
|
|
|
if (output->is_underscanning && crtc && crtc->current_mode)
|
|
|
|
{
|
|
|
|
drmModeObjectSetProperty (kms_fd, connector_id,
|
|
|
|
DRM_MODE_OBJECT_CONNECTOR,
|
|
|
|
output_kms->underscan_prop_id,
|
|
|
|
(uint64_t) 1);
|
|
|
|
|
|
|
|
if (output_kms->underscan_hborder_prop_id)
|
|
|
|
{
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
value = MIN (128, crtc->current_mode->width * 0.05);
|
|
|
|
drmModeObjectSetProperty (kms_fd, connector_id,
|
|
|
|
DRM_MODE_OBJECT_CONNECTOR,
|
|
|
|
output_kms->underscan_hborder_prop_id,
|
|
|
|
value);
|
|
|
|
}
|
|
|
|
if (output_kms->underscan_vborder_prop_id)
|
|
|
|
{
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
value = MIN (128, crtc->current_mode->height * 0.05);
|
|
|
|
drmModeObjectSetProperty (kms_fd, connector_id,
|
|
|
|
DRM_MODE_OBJECT_CONNECTOR,
|
|
|
|
output_kms->underscan_vborder_prop_id,
|
|
|
|
value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
drmModeObjectSetProperty (kms_fd, connector_id,
|
|
|
|
DRM_MODE_OBJECT_CONNECTOR,
|
|
|
|
output_kms->underscan_prop_id,
|
|
|
|
(uint64_t) 0);
|
|
|
|
}
|
2017-07-04 04:04:39 -04:00
|
|
|
}
|
|
|
|
|
2018-10-11 10:15:37 -04:00
|
|
|
uint32_t
|
|
|
|
meta_output_kms_get_connector_id (MetaOutput *output)
|
|
|
|
{
|
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
|
|
|
|
2019-03-08 10:23:15 -05:00
|
|
|
return meta_kms_connector_get_id (output_kms->kms_connector);
|
2018-10-11 10:15:37 -04:00
|
|
|
}
|
|
|
|
|
2017-07-04 00:11:44 -04:00
|
|
|
void
|
|
|
|
meta_output_kms_set_power_save_mode (MetaOutput *output,
|
|
|
|
uint64_t state)
|
|
|
|
{
|
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
2017-07-10 06:19:32 -04:00
|
|
|
MetaGpu *gpu = meta_output_get_gpu (output);
|
|
|
|
MetaGpuKms *gpu_kms = META_GPU_KMS (gpu);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
if (output_kms->dpms_prop_id != 0)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
2017-07-10 06:19:32 -04:00
|
|
|
fd = meta_gpu_kms_get_fd (gpu_kms);
|
2018-10-11 10:15:37 -04:00
|
|
|
if (drmModeObjectSetProperty (fd, output_kms->connector->connector_id,
|
2017-07-04 00:11:44 -04:00
|
|
|
DRM_MODE_OBJECT_CONNECTOR,
|
|
|
|
output_kms->dpms_prop_id, state) < 0)
|
|
|
|
g_warning ("Failed to set power save mode for output %s: %s",
|
|
|
|
output->name, strerror (errno));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
meta_output_kms_can_clone (MetaOutput *output,
|
|
|
|
MetaOutput *other_output)
|
|
|
|
{
|
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
|
|
|
MetaOutputKms *other_output_kms = other_output->driver_private;
|
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
return meta_kms_connector_can_clone (output_kms->kms_connector,
|
|
|
|
other_output_kms->kms_connector);
|
2017-07-04 00:11:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
GBytes *
|
|
|
|
meta_output_kms_read_edid (MetaOutput *output)
|
|
|
|
{
|
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
2019-03-09 09:55:24 -05:00
|
|
|
const MetaKmsConnectorState *connector_state;
|
|
|
|
GBytes *edid_data;
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
connector_state =
|
|
|
|
meta_kms_connector_get_current_state (output_kms->kms_connector);
|
|
|
|
edid_data = connector_state->edid_data;
|
|
|
|
if (!edid_data)
|
2017-07-04 00:11:44 -04:00
|
|
|
return NULL;
|
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
return g_bytes_new_from_bytes (edid_data, 0, g_bytes_get_size (edid_data));
|
2017-07-04 00:11:44 -04:00
|
|
|
}
|
|
|
|
|
2017-10-24 06:43:58 -04:00
|
|
|
static void
|
2019-03-09 09:55:24 -05:00
|
|
|
find_connector_properties (MetaGpuKms *gpu_kms,
|
|
|
|
MetaOutput *output,
|
|
|
|
drmModeConnector *connector)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2017-10-24 06:43:58 -04:00
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
2017-07-04 00:11:44 -04:00
|
|
|
int fd;
|
|
|
|
int i;
|
|
|
|
|
2017-07-10 06:19:32 -04:00
|
|
|
fd = meta_gpu_kms_get_fd (gpu_kms);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
for (i = 0; i < connector->count_props; i++)
|
|
|
|
{
|
|
|
|
drmModePropertyPtr prop = drmModeGetProperty (fd, connector->props[i]);
|
|
|
|
if (!prop)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
|
|
|
|
strcmp (prop->name, "DPMS") == 0)
|
|
|
|
output_kms->dpms_prop_id = prop->prop_id;
|
2019-03-26 05:09:45 -04:00
|
|
|
else if ((prop->flags & DRM_MODE_PROP_ENUM) &&
|
|
|
|
strcmp (prop->name, "underscan") == 0)
|
|
|
|
output_kms->underscan_prop_id = prop->prop_id;
|
|
|
|
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
|
|
|
|
strcmp (prop->name, "underscan hborder") == 0)
|
|
|
|
output_kms->underscan_hborder_prop_id = prop->prop_id;
|
|
|
|
else if ((prop->flags & DRM_MODE_PROP_RANGE) &&
|
|
|
|
strcmp (prop->name, "underscan vborder") == 0)
|
|
|
|
output_kms->underscan_vborder_prop_id = prop->prop_id;
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
drmModeFreeProperty (prop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_output_destroy_notify (MetaOutput *output)
|
|
|
|
{
|
|
|
|
MetaOutputKms *output_kms;
|
|
|
|
|
|
|
|
output_kms = output->driver_private;
|
|
|
|
|
|
|
|
g_slice_free (MetaOutputKms, output_kms);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-07-10 06:19:32 -04:00
|
|
|
add_common_modes (MetaOutput *output,
|
|
|
|
MetaGpuKms *gpu_kms)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2017-10-24 09:47:30 -04:00
|
|
|
const drmModeModeInfo *drm_mode;
|
|
|
|
MetaCrtcMode *crtc_mode;
|
2017-07-04 00:11:44 -04:00
|
|
|
GPtrArray *array;
|
2017-10-24 09:47:30 -04:00
|
|
|
float refresh_rate;
|
2017-07-04 00:11:44 -04:00
|
|
|
unsigned i;
|
|
|
|
unsigned max_hdisplay = 0;
|
|
|
|
unsigned max_vdisplay = 0;
|
|
|
|
float max_refresh_rate = 0.0;
|
|
|
|
|
|
|
|
for (i = 0; i < output->n_modes; i++)
|
|
|
|
{
|
|
|
|
drm_mode = output->modes[i]->driver_private;
|
|
|
|
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
|
|
|
max_hdisplay = MAX (max_hdisplay, drm_mode->hdisplay);
|
|
|
|
max_vdisplay = MAX (max_vdisplay, drm_mode->vdisplay);
|
|
|
|
max_refresh_rate = MAX (max_refresh_rate, refresh_rate);
|
|
|
|
}
|
|
|
|
|
|
|
|
max_refresh_rate = MAX (max_refresh_rate, 60.0);
|
|
|
|
max_refresh_rate *= (1 + SYNC_TOLERANCE);
|
|
|
|
|
|
|
|
array = g_ptr_array_new ();
|
2017-10-24 09:47:30 -04:00
|
|
|
if (max_hdisplay > max_vdisplay)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2017-10-24 09:47:30 -04:00
|
|
|
for (i = 0; i < G_N_ELEMENTS (meta_default_landscape_drm_mode_infos); i++)
|
|
|
|
{
|
|
|
|
drm_mode = &meta_default_landscape_drm_mode_infos[i];
|
|
|
|
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
|
|
|
if (drm_mode->hdisplay > max_hdisplay ||
|
|
|
|
drm_mode->vdisplay > max_vdisplay ||
|
|
|
|
refresh_rate > max_refresh_rate)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms,
|
|
|
|
drm_mode);
|
|
|
|
g_ptr_array_add (array, crtc_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (meta_default_portrait_drm_mode_infos); i++)
|
|
|
|
{
|
|
|
|
drm_mode = &meta_default_portrait_drm_mode_infos[i];
|
|
|
|
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
|
|
|
if (drm_mode->hdisplay > max_hdisplay ||
|
|
|
|
drm_mode->vdisplay > max_vdisplay ||
|
|
|
|
refresh_rate > max_refresh_rate)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms,
|
|
|
|
drm_mode);
|
|
|
|
g_ptr_array_add (array, crtc_mode);
|
|
|
|
}
|
2017-07-04 00:11:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
output->modes = g_renew (MetaCrtcMode *, output->modes,
|
|
|
|
output->n_modes + array->len);
|
|
|
|
memcpy (output->modes + output->n_modes, array->pdata,
|
|
|
|
array->len * sizeof (MetaCrtcMode *));
|
|
|
|
output->n_modes += array->len;
|
|
|
|
|
|
|
|
g_ptr_array_free (array, TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
compare_modes (const void *one,
|
|
|
|
const void *two)
|
|
|
|
{
|
|
|
|
MetaCrtcMode *a = *(MetaCrtcMode **) one;
|
|
|
|
MetaCrtcMode *b = *(MetaCrtcMode **) two;
|
|
|
|
|
|
|
|
if (a->width != b->width)
|
|
|
|
return a->width > b->width ? -1 : 1;
|
|
|
|
if (a->height != b->height)
|
|
|
|
return a->height > b->height ? -1 : 1;
|
|
|
|
if (a->refresh_rate != b->refresh_rate)
|
|
|
|
return a->refresh_rate > b->refresh_rate ? -1 : 1;
|
|
|
|
|
|
|
|
return g_strcmp0 (b->name, a->name);
|
|
|
|
}
|
|
|
|
|
2017-11-03 03:55:07 -04:00
|
|
|
static gboolean
|
|
|
|
init_output_modes (MetaOutput *output,
|
|
|
|
MetaGpuKms *gpu_kms,
|
|
|
|
GError **error)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
|
|
|
MetaOutputKms *output_kms = output->driver_private;
|
2019-03-09 09:55:24 -05:00
|
|
|
const MetaKmsConnectorState *connector_state;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
connector_state =
|
|
|
|
meta_kms_connector_get_current_state (output_kms->kms_connector);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
output->preferred_mode = NULL;
|
2019-03-09 09:55:24 -05:00
|
|
|
|
|
|
|
output->n_modes = connector_state->n_modes;
|
2017-07-04 00:11:44 -04:00
|
|
|
output->modes = g_new0 (MetaCrtcMode *, output->n_modes);
|
2019-03-09 09:55:24 -05:00
|
|
|
for (i = 0; i < connector_state->n_modes; i++)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2019-03-09 09:55:24 -05:00
|
|
|
drmModeModeInfo *drm_mode = &connector_state->modes[i];
|
2017-07-04 00:11:44 -04:00
|
|
|
MetaCrtcMode *crtc_mode;
|
|
|
|
|
2017-07-10 06:19:32 -04:00
|
|
|
crtc_mode = meta_gpu_kms_get_mode_from_drm_mode (gpu_kms, drm_mode);
|
2017-07-04 00:11:44 -04:00
|
|
|
output->modes[i] = crtc_mode;
|
2019-03-09 09:55:24 -05:00
|
|
|
if (drm_mode->type & DRM_MODE_TYPE_PREFERRED)
|
2017-07-04 00:11:44 -04:00
|
|
|
output->preferred_mode = output->modes[i];
|
|
|
|
}
|
|
|
|
|
2017-11-03 03:55:07 -04:00
|
|
|
/* FIXME: MSC feature bit? */
|
|
|
|
/* Presume that if the output supports scaling, then we have
|
|
|
|
* a panel fitter capable of adjusting any mode to suit.
|
|
|
|
*/
|
2019-03-09 09:55:24 -05:00
|
|
|
if (connector_state->has_scaling)
|
2017-11-03 03:55:07 -04:00
|
|
|
add_common_modes (output, gpu_kms);
|
|
|
|
|
|
|
|
if (!output->modes)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"No modes available");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
qsort (output->modes, output->n_modes,
|
|
|
|
sizeof (MetaCrtcMode *), compare_modes);
|
|
|
|
|
2017-07-04 00:11:44 -04:00
|
|
|
if (!output->preferred_mode)
|
|
|
|
output->preferred_mode = output->modes[0];
|
2017-11-03 03:55:07 -04:00
|
|
|
|
|
|
|
return TRUE;
|
2017-07-04 00:11:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
MetaOutput *
|
2017-11-03 03:55:07 -04:00
|
|
|
meta_create_kms_output (MetaGpuKms *gpu_kms,
|
2019-03-08 10:23:15 -05:00
|
|
|
MetaKmsConnector *kms_connector,
|
2017-11-03 03:55:07 -04:00
|
|
|
drmModeConnector *connector,
|
|
|
|
MetaOutput *old_output,
|
|
|
|
GError **error)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2017-07-10 06:19:32 -04:00
|
|
|
MetaGpu *gpu = META_GPU (gpu_kms);
|
2017-07-04 00:11:44 -04:00
|
|
|
MetaOutput *output;
|
|
|
|
MetaOutputKms *output_kms;
|
2019-03-09 09:55:24 -05:00
|
|
|
const MetaKmsConnectorState *connector_state;
|
|
|
|
MetaMonitorTransform panel_orientation_transform;
|
2019-03-08 10:23:15 -05:00
|
|
|
uint32_t connector_id;
|
2017-07-04 00:11:44 -04:00
|
|
|
GArray *crtcs;
|
|
|
|
GList *l;
|
2019-03-08 10:23:15 -05:00
|
|
|
uint32_t gpu_id;
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
output = g_object_new (META_TYPE_OUTPUT, NULL);
|
|
|
|
|
|
|
|
output_kms = g_slice_new0 (MetaOutputKms);
|
|
|
|
output->driver_private = output_kms;
|
|
|
|
output->driver_notify = (GDestroyNotify) meta_output_destroy_notify;
|
|
|
|
|
2017-07-10 06:19:32 -04:00
|
|
|
output->gpu = gpu;
|
2019-03-08 10:23:15 -05:00
|
|
|
output->name = g_strdup (meta_kms_connector_get_name (kms_connector));
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-08 10:23:15 -05:00
|
|
|
gpu_id = meta_gpu_kms_get_id (gpu_kms);
|
|
|
|
connector_id = meta_kms_connector_get_id (kms_connector);
|
|
|
|
output->winsys_id = ((uint64_t) gpu_id << 32) | connector_id;
|
2018-10-11 10:20:00 -04:00
|
|
|
|
2019-03-08 10:23:15 -05:00
|
|
|
output_kms->kms_connector = kms_connector;
|
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
find_connector_properties (gpu_kms, output, connector);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
connector_state = meta_kms_connector_get_current_state (kms_connector);
|
|
|
|
|
|
|
|
panel_orientation_transform = connector_state->panel_orientation_transform;
|
|
|
|
if (meta_monitor_transform_is_rotated (panel_orientation_transform))
|
2017-10-25 09:44:10 -04:00
|
|
|
{
|
2019-03-09 09:55:24 -05:00
|
|
|
output->width_mm = connector_state->height_mm;
|
|
|
|
output->height_mm = connector_state->width_mm;
|
2017-10-25 09:44:10 -04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-03-09 09:55:24 -05:00
|
|
|
output->width_mm = connector_state->width_mm;
|
|
|
|
output->height_mm = connector_state->height_mm;
|
2017-10-25 09:44:10 -04:00
|
|
|
}
|
|
|
|
|
2017-11-03 03:55:07 -04:00
|
|
|
if (!init_output_modes (output, gpu_kms, error))
|
|
|
|
{
|
|
|
|
g_object_unref (output);
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCrtc *));
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2019-03-09 09:55:24 -05:00
|
|
|
MetaCrtc *crtc = l->data;
|
|
|
|
MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc);
|
|
|
|
uint32_t crtc_idx;
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
crtc_idx = meta_kms_crtc_get_idx (kms_crtc);
|
|
|
|
if (connector_state->common_possible_crtcs & (1 << crtc_idx))
|
|
|
|
g_array_append_val (crtcs, crtc);
|
2017-07-04 00:11:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
output->n_possible_crtcs = crtcs->len;
|
2019-03-09 09:55:24 -05:00
|
|
|
output->possible_crtcs = (MetaCrtc **) g_array_free (crtcs, FALSE);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
if (connector_state->current_crtc_id)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2017-07-10 06:19:32 -04:00
|
|
|
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
|
|
|
MetaCrtc *crtc = l->data;
|
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
if (crtc->crtc_id == connector_state->current_crtc_id)
|
2017-07-04 00:11:44 -04:00
|
|
|
{
|
2017-11-03 06:25:30 -04:00
|
|
|
meta_output_assign_crtc (output, crtc);
|
2017-07-04 00:11:44 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-11-03 06:25:30 -04:00
|
|
|
meta_output_unassign_crtc (output);
|
2017-07-04 00:11:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (old_output)
|
|
|
|
{
|
|
|
|
output->is_primary = old_output->is_primary;
|
|
|
|
output->is_presentation = old_output->is_presentation;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
output->is_primary = FALSE;
|
|
|
|
output->is_presentation = FALSE;
|
|
|
|
}
|
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
output->suggested_x = connector_state->suggested_x;
|
|
|
|
output->suggested_y = connector_state->suggested_y;
|
|
|
|
output->hotplug_mode_update = connector_state->hotplug_mode_update;
|
2019-03-26 05:09:45 -04:00
|
|
|
output->supports_underscanning = output_kms->underscan_prop_id != 0;
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
meta_output_parse_edid (output, connector_state->edid_data);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-08 10:23:15 -05:00
|
|
|
output->connector_type = meta_kms_connector_get_connector_type (kms_connector);
|
2017-07-04 00:11:44 -04:00
|
|
|
|
2019-03-09 09:55:24 -05:00
|
|
|
output->tile_info = connector_state->tile_info;
|
2017-07-04 00:11:44 -04:00
|
|
|
|
|
|
|
/* FIXME: backlight is a very driver specific thing unfortunately,
|
|
|
|
every DDX does its own thing, and the dumb KMS API does not include it.
|
|
|
|
|
|
|
|
For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
|
|
|
|
(one for each major HW maker, and then some).
|
|
|
|
We can't do the same because we're not root.
|
|
|
|
It might be best to leave backlight out of the story and rely on the setuid
|
|
|
|
helper in gnome-settings-daemon.
|
|
|
|
*/
|
|
|
|
output->backlight_min = 0;
|
|
|
|
output->backlight_max = 0;
|
|
|
|
output->backlight = -1;
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|