DisplayConfig: Add support for interlaced modes

Differentiate between non-interlaced and interlaced modes. This is done
by appending an "i" after the resolution part of the mode ID, and
adding a 'is-interlaced' (b) property to the mode properties.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
This commit is contained in:
Jonas Ådahl 2017-06-14 14:41:13 +08:00
parent 85638c1b19
commit 49c5228655
7 changed files with 93 additions and 16 deletions

View File

@ -53,6 +53,7 @@
* <width>1920</width> * <width>1920</width>
* <height>1080</height> * <height>1080</height>
* <rate>60.049972534179688</rate> * <rate>60.049972534179688</rate>
* <flag>interlace</flag>
* </mode> * </mode>
* </monitor> * </monitor>
* <transform> * <transform>
@ -135,6 +136,7 @@ typedef enum
STATE_MONITOR_MODE_WIDTH, STATE_MONITOR_MODE_WIDTH,
STATE_MONITOR_MODE_HEIGHT, STATE_MONITOR_MODE_HEIGHT,
STATE_MONITOR_MODE_RATE, STATE_MONITOR_MODE_RATE,
STATE_MONITOR_MODE_FLAG,
STATE_MONITOR_UNDERSCANNING STATE_MONITOR_UNDERSCANNING
} ParserState; } ParserState;
@ -384,6 +386,10 @@ handle_start_element (GMarkupParseContext *context,
{ {
parser->state = STATE_MONITOR_MODE_RATE; parser->state = STATE_MONITOR_MODE_RATE;
} }
else if (g_str_equal (element_name, "flag"))
{
parser->state = STATE_MONITOR_MODE_FLAG;
}
else else
{ {
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
@ -397,6 +403,7 @@ handle_start_element (GMarkupParseContext *context,
case STATE_MONITOR_MODE_WIDTH: case STATE_MONITOR_MODE_WIDTH:
case STATE_MONITOR_MODE_HEIGHT: case STATE_MONITOR_MODE_HEIGHT:
case STATE_MONITOR_MODE_RATE: case STATE_MONITOR_MODE_RATE:
case STATE_MONITOR_MODE_FLAG:
{ {
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT,
"Invalid mode sub element '%s'", element_name); "Invalid mode sub element '%s'", element_name);
@ -539,6 +546,7 @@ handle_end_element (GMarkupParseContext *context,
case STATE_MONITOR_MODE_WIDTH: case STATE_MONITOR_MODE_WIDTH:
case STATE_MONITOR_MODE_HEIGHT: case STATE_MONITOR_MODE_HEIGHT:
case STATE_MONITOR_MODE_RATE: case STATE_MONITOR_MODE_RATE:
case STATE_MONITOR_MODE_FLAG:
{ {
parser->state = STATE_MONITOR_MODE; parser->state = STATE_MONITOR_MODE;
return; return;
@ -909,6 +917,22 @@ handle_text (GMarkupParseContext *context,
return; return;
} }
case STATE_MONITOR_MODE_FLAG:
{
if (strncmp (text, "interlace", text_len) == 0)
{
parser->current_monitor_mode_spec->flags |=
META_CRTC_MODE_FLAG_INTERLACE;
}
else
{
g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT,
"Invalid mode flag %.*s", (int) text_len, text);
}
return;
}
case STATE_MONITOR_UNDERSCANNING: case STATE_MONITOR_UNDERSCANNING:
{ {
read_bool (text, text_len, read_bool (text, text_len,
@ -1007,6 +1031,8 @@ append_monitors (GString *buffer,
monitor_config->mode_spec->height); monitor_config->mode_spec->height);
g_string_append_printf (buffer, " <rate>%s</rate>\n", g_string_append_printf (buffer, " <rate>%s</rate>\n",
rate_str); rate_str);
if (monitor_config->mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE)
g_string_append_printf (buffer, " <flag>interlace</flag>\n");
g_string_append (buffer, " </mode>\n"); g_string_append (buffer, " </mode>\n");
if (monitor_config->enable_underscanning) if (monitor_config->enable_underscanning)
g_string_append (buffer, " <underscanning>yes</underscanning>\n"); g_string_append (buffer, " <underscanning>yes</underscanning>\n");

View File

@ -131,6 +131,28 @@ typedef enum
META_CONNECTOR_TYPE_DSI = 16, META_CONNECTOR_TYPE_DSI = 16,
} MetaConnectorType; } MetaConnectorType;
/* Same as KMS mode flags and X11 randr flags */
typedef enum
{
META_CRTC_MODE_FLAG_NONE = 0,
META_CRTC_MODE_FLAG_PHSYNC = (1 << 0),
META_CRTC_MODE_FLAG_NHSYNC = (1 << 1),
META_CRTC_MODE_FLAG_PVSYNC = (1 << 2),
META_CRTC_MODE_FLAG_NVSYNC = (1 << 3),
META_CRTC_MODE_FLAG_INTERLACE = (1 << 4),
META_CRTC_MODE_FLAG_DBLSCAN = (1 << 5),
META_CRTC_MODE_FLAG_CSYNC = (1 << 6),
META_CRTC_MODE_FLAG_PCSYNC = (1 << 7),
META_CRTC_MODE_FLAG_NCSYNC = (1 << 8),
META_CRTC_MODE_FLAG_HSKEW = (1 << 9),
META_CRTC_MODE_FLAG_BCAST = (1 << 10),
META_CRTC_MODE_FLAG_PIXMUX = (1 << 11),
META_CRTC_MODE_FLAG_DBLCLK = (1 << 12),
META_CRTC_MODE_FLAG_CLKDIV2 = (1 << 13),
META_CRTC_MODE_FLAG_MASK = 0x3fff
} MetaCrtcModeFlag;
struct _MetaTileInfo struct _MetaTileInfo
{ {
guint32 group_id; guint32 group_id;
@ -231,7 +253,7 @@ struct _MetaCrtcMode
int width; int width;
int height; int height;
float refresh_rate; float refresh_rate;
guint32 flags; MetaCrtcModeFlag flags;
gpointer driver_private; gpointer driver_private;
GDestroyNotify driver_notify; GDestroyNotify driver_notify;

View File

@ -1556,6 +1556,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
float *supported_scales; float *supported_scales;
int n_supported_scales; int n_supported_scales;
GVariantBuilder mode_properties_builder; GVariantBuilder mode_properties_builder;
MetaCrtcModeFlag mode_flags;
mode_id = meta_monitor_mode_get_id (monitor_mode); mode_id = meta_monitor_mode_get_id (monitor_mode);
meta_monitor_mode_get_resolution (monitor_mode, meta_monitor_mode_get_resolution (monitor_mode,
@ -1580,6 +1581,8 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
(double) supported_scales[i]); (double) supported_scales[i]);
g_free (supported_scales); g_free (supported_scales);
mode_flags = meta_monitor_mode_get_flags (monitor_mode);
g_variant_builder_init (&mode_properties_builder, g_variant_builder_init (&mode_properties_builder,
G_VARIANT_TYPE ("a{sv}")); G_VARIANT_TYPE ("a{sv}"));
if (monitor_mode == current_mode) if (monitor_mode == current_mode)
@ -1590,6 +1593,10 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&mode_properties_builder, "{sv}", g_variant_builder_add (&mode_properties_builder, "{sv}",
"is-preferred", "is-preferred",
g_variant_new_boolean (TRUE)); g_variant_new_boolean (TRUE));
if (mode_flags & META_CRTC_MODE_FLAG_INTERLACE)
g_variant_builder_add (&mode_properties_builder, "{sv}",
"is-interlaced",
g_variant_new_boolean (TRUE));
g_variant_builder_add (&modes_builder, MODE_FORMAT, g_variant_builder_add (&modes_builder, MODE_FORMAT,
mode_id, mode_id,

View File

@ -31,6 +31,8 @@
#define MINIMUM_SCALE_FACTOR 0.5f #define MINIMUM_SCALE_FACTOR 0.5f
#define MAXIMUM_SCALE_FACTOR 4.0f #define MAXIMUM_SCALE_FACTOR 4.0f
#define HANDLED_CRTC_MODE_FLAGS (META_CRTC_MODE_FLAG_INTERLACE)
typedef struct _MetaMonitorMode typedef struct _MetaMonitorMode
{ {
char *id; char *id;
@ -360,14 +362,17 @@ meta_monitor_class_init (MetaMonitorClass *klass)
static char * static char *
generate_mode_id (MetaMonitorModeSpec *monitor_mode_spec) generate_mode_id (MetaMonitorModeSpec *monitor_mode_spec)
{ {
gboolean is_interlaced;
char refresh_rate_str[G_ASCII_DTOSTR_BUF_SIZE]; char refresh_rate_str[G_ASCII_DTOSTR_BUF_SIZE];
is_interlaced = !!(monitor_mode_spec->flags & META_CRTC_MODE_FLAG_INTERLACE);
g_ascii_dtostr (refresh_rate_str, G_ASCII_DTOSTR_BUF_SIZE, g_ascii_dtostr (refresh_rate_str, G_ASCII_DTOSTR_BUF_SIZE,
monitor_mode_spec->refresh_rate); monitor_mode_spec->refresh_rate);
return g_strdup_printf ("%dx%d@%s", return g_strdup_printf ("%dx%d%s@%s",
monitor_mode_spec->width, monitor_mode_spec->width,
monitor_mode_spec->height, monitor_mode_spec->height,
is_interlaced ? "i" : "",
refresh_rate_str); refresh_rate_str);
} }
@ -406,7 +411,8 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
mode->spec = (MetaMonitorModeSpec) { mode->spec = (MetaMonitorModeSpec) {
.width = crtc_mode->width, .width = crtc_mode->width,
.height = crtc_mode->height, .height = crtc_mode->height,
.refresh_rate = crtc_mode->refresh_rate .refresh_rate = crtc_mode->refresh_rate,
.flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
}, },
mode->id = generate_mode_id (&mode->spec); mode->id = generate_mode_id (&mode->spec);
mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1); mode->crtc_modes = g_new (MetaMonitorCrtcMode, 1);
@ -674,8 +680,8 @@ is_crtc_mode_tiled (MetaOutput *output,
} }
static MetaCrtcMode * static MetaCrtcMode *
find_tiled_crtc_mode (MetaOutput *output, find_tiled_crtc_mode (MetaOutput *output,
float refresh_rate) MetaCrtcMode *reference_crtc_mode)
{ {
MetaCrtcMode *crtc_mode; MetaCrtcMode *crtc_mode;
unsigned int i; unsigned int i;
@ -691,7 +697,10 @@ find_tiled_crtc_mode (MetaOutput *output,
if (!is_crtc_mode_tiled (output, crtc_mode)) if (!is_crtc_mode_tiled (output, crtc_mode))
continue; continue;
if (crtc_mode->refresh_rate != refresh_rate) if (crtc_mode->refresh_rate != reference_crtc_mode->refresh_rate)
continue;
if (crtc_mode->flags != reference_crtc_mode->flags)
continue; continue;
return crtc_mode; return crtc_mode;
@ -702,7 +711,7 @@ find_tiled_crtc_mode (MetaOutput *output,
static MetaMonitorMode * static MetaMonitorMode *
create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled, create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
float refresh_rate, MetaCrtcMode *reference_crtc_mode,
gboolean *out_is_preferred) gboolean *out_is_preferred)
{ {
MetaMonitor *monitor = META_MONITOR (monitor_tiled); MetaMonitor *monitor = META_MONITOR (monitor_tiled);
@ -721,7 +730,8 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
mode->parent.spec = (MetaMonitorModeSpec) { mode->parent.spec = (MetaMonitorModeSpec) {
.width = width, .width = width,
.height = height, .height = height,
.refresh_rate = refresh_rate, .refresh_rate = reference_crtc_mode->refresh_rate,
.flags = reference_crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
}; };
mode->parent.id = generate_mode_id (&mode->parent.spec); mode->parent.id = generate_mode_id (&mode->parent.spec);
@ -732,11 +742,10 @@ create_tiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
MetaOutput *output = l->data; MetaOutput *output = l->data;
MetaCrtcMode *tiled_crtc_mode; MetaCrtcMode *tiled_crtc_mode;
tiled_crtc_mode = find_tiled_crtc_mode (output, refresh_rate); tiled_crtc_mode = find_tiled_crtc_mode (output, reference_crtc_mode);
if (!tiled_crtc_mode) if (!tiled_crtc_mode)
{ {
g_warning ("No tiled mode with refresh rate %f on %s", g_warning ("No tiled mode found on %s", output->name);
refresh_rate, output->name);
meta_monitor_mode_free ((MetaMonitorMode *) mode); meta_monitor_mode_free ((MetaMonitorMode *) mode);
return NULL; return NULL;
} }
@ -770,14 +779,14 @@ generate_tiled_monitor_modes (MetaMonitorTiled *monitor_tiled)
for (i = 0; i < main_output->n_modes; i++) for (i = 0; i < main_output->n_modes; i++)
{ {
MetaCrtcMode *crtc_mode = main_output->modes[i]; MetaCrtcMode *reference_crtc_mode = main_output->modes[i];
MetaMonitorMode *mode; MetaMonitorMode *mode;
gboolean is_preferred; gboolean is_preferred;
if (!is_crtc_mode_tiled (main_output, crtc_mode)) if (!is_crtc_mode_tiled (main_output, reference_crtc_mode))
continue; continue;
mode = create_tiled_monitor_mode (monitor_tiled, crtc_mode->refresh_rate, mode = create_tiled_monitor_mode (monitor_tiled, reference_crtc_mode,
&is_preferred); &is_preferred);
if (!mode) if (!mode)
continue; continue;
@ -836,7 +845,8 @@ create_untiled_monitor_mode (MetaMonitorTiled *monitor_tiled,
mode->parent.spec = (MetaMonitorModeSpec) { mode->parent.spec = (MetaMonitorModeSpec) {
.width = crtc_mode->width, .width = crtc_mode->width,
.height = crtc_mode->height, .height = crtc_mode->height,
.refresh_rate = crtc_mode->refresh_rate .refresh_rate = crtc_mode->refresh_rate,
.flags = crtc_mode->flags & HANDLED_CRTC_MODE_FLAGS
}; };
mode->parent.id = generate_mode_id (&mode->parent.spec); mode->parent.id = generate_mode_id (&mode->parent.spec);
mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode, mode->parent.crtc_modes = g_new0 (MetaMonitorCrtcMode,
@ -1224,7 +1234,8 @@ meta_monitor_mode_spec_equals (MetaMonitorModeSpec *monitor_mode_spec,
return (monitor_mode_spec->width == other_monitor_mode_spec->width && return (monitor_mode_spec->width == other_monitor_mode_spec->width &&
monitor_mode_spec->height == other_monitor_mode_spec->height && monitor_mode_spec->height == other_monitor_mode_spec->height &&
(monitor_mode_spec->refresh_rate == (monitor_mode_spec->refresh_rate ==
other_monitor_mode_spec->refresh_rate)); other_monitor_mode_spec->refresh_rate) &&
monitor_mode_spec->flags == other_monitor_mode_spec->flags);
} }
MetaMonitorMode * MetaMonitorMode *
@ -1543,6 +1554,12 @@ meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode)
return monitor_mode->spec.refresh_rate; return monitor_mode->spec.refresh_rate;
} }
MetaCrtcModeFlag
meta_monitor_mode_get_flags (MetaMonitorMode *monitor_mode)
{
return monitor_mode->spec.flags;
}
gboolean gboolean
meta_monitor_mode_foreach_crtc (MetaMonitor *monitor, meta_monitor_mode_foreach_crtc (MetaMonitor *monitor,
MetaMonitorMode *mode, MetaMonitorMode *mode,

View File

@ -39,6 +39,7 @@ typedef struct _MetaMonitorModeSpec
int width; int width;
int height; int height;
float refresh_rate; float refresh_rate;
MetaCrtcModeFlag flags;
} MetaMonitorModeSpec; } MetaMonitorModeSpec;
typedef struct _MetaMonitorCrtcMode typedef struct _MetaMonitorCrtcMode
@ -187,6 +188,8 @@ void meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,
float meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode); float meta_monitor_mode_get_refresh_rate (MetaMonitorMode *monitor_mode);
MetaCrtcModeFlag meta_monitor_mode_get_flags (MetaMonitorMode *monitor_mode);
gboolean meta_monitor_mode_foreach_crtc (MetaMonitor *monitor, gboolean meta_monitor_mode_foreach_crtc (MetaMonitor *monitor,
MetaMonitorMode *mode, MetaMonitorMode *mode,
MetaMonitorModeFunc func, MetaMonitorModeFunc func,

View File

@ -325,6 +325,7 @@
* a{sv} properties: optional properties, including: * a{sv} properties: optional properties, including:
- "is-current" (b): the mode is currently active mode - "is-current" (b): the mode is currently active mode
- "is-preferred" (b): the mode is the preferred mode - "is-preferred" (b): the mode is the preferred mode
- "is-interlaced" (b): the mode is an interlaced mode
* a{sv} properties: optional properties, including: * a{sv} properties: optional properties, including:
- "width-mm" (i): physical width of monitor in millimeters - "width-mm" (i): physical width of monitor in millimeters
- "height-mm" (i): physical height of monitor in millimeters - "height-mm" (i): physical height of monitor in millimeters

View File

@ -36,6 +36,7 @@ typedef struct _MonitorTestCaseMonitorMode
int width; int width;
int height; int height;
float refresh_rate; float refresh_rate;
MetaCrtcModeFlag flags;
} MonitorTestCaseMonitorMode; } MonitorTestCaseMonitorMode;
typedef struct _MonitorTestCaseMonitor typedef struct _MonitorTestCaseMonitor