DisplayConfig: Make supported scales per mode

This changes the API to pass supported scales per mode instead of
providing a global list. This allows for more flexible scaling
scenarious, where a scale compatible with one mode can still be made
available even though another mode is incompatible.

https://bugzilla.gnome.org/show_bug.cgi?id=765011
This commit is contained in:
Jonas Ådahl 2017-06-05 15:59:47 +08:00
parent 5ab116a87f
commit b2a530b326
10 changed files with 177 additions and 137 deletions

View File

@ -950,16 +950,6 @@ meta_verify_logical_monitor_config (MetaLogicalMonitorConfig *logical_monitor
int expected_mode_width = 0;
int expected_mode_height = 0;
if (!meta_monitor_manager_is_scale_supported (monitor_manager,
layout_mode,
logical_monitor_config->scale))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Invalid logical monitor config scale %g",
logical_monitor_config->scale);
return FALSE;
}
if (logical_monitor_config->layout.x < 0 ||
logical_monitor_config->layout.y < 0)
{

View File

@ -31,6 +31,7 @@
#include <meta/util.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-monitor.h"
#include "backends/meta-monitor-config-manager.h"
#define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
@ -40,17 +41,6 @@
#define MAX_CRTCS (MAX_MONITORS * 2)
#define MAX_MODES (MAX_MONITORS * 4)
static float supported_scales_dummy_logical[] = {
1.0,
1.5,
2.0
};
static float supported_scales_dummy_physical[] = {
1.0,
2.0
};
struct _MetaMonitorManagerDummy
{
MetaMonitorManager parent_instance;
@ -320,12 +310,8 @@ meta_monitor_manager_dummy_read_current (MetaMonitorManager *manager)
for (i = 0; i < num_monitors && scales_str_list[i]; i++)
{
float scale = g_ascii_strtod (scales_str_list[i], NULL);
if (meta_monitor_manager_is_scale_supported (manager,
manager->layout_mode,
scale))
monitor_scales[i] = scale;
else
meta_warning ("Invalid dummy monitor scale\n");
monitor_scales[i] = scale;
}
g_strfreev (scales_str_list);
}
@ -614,23 +600,28 @@ meta_monitor_manager_dummy_calculate_monitor_mode_scale (MetaMonitorManager *man
return output_dummy->scale;
}
static void
meta_monitor_manager_dummy_get_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
float **scales,
int *n_scales)
static float *
meta_monitor_manager_dummy_calculate_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
int *n_supported_scales)
{
MetaMonitorScalesConstraint constraints =
META_MONITOR_SCALES_CONSTRAINT_NONE;
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
*scales = supported_scales_dummy_logical;
*n_scales = G_N_ELEMENTS (supported_scales_dummy_logical);
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
*scales = supported_scales_dummy_physical;
*n_scales = G_N_ELEMENTS (supported_scales_dummy_physical);
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
break;
}
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints,
n_supported_scales);
}
static gboolean
@ -699,7 +690,7 @@ meta_monitor_manager_dummy_class_init (MetaMonitorManagerDummyClass *klass)
manager_class->apply_configuration = meta_monitor_manager_dummy_apply_config;
manager_class->is_transform_handled = meta_monitor_manager_dummy_is_transform_handled;
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_dummy_calculate_monitor_mode_scale;
manager_class->get_supported_scales = meta_monitor_manager_dummy_get_supported_scales;
manager_class->calculate_supported_scales = meta_monitor_manager_dummy_calculate_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_dummy_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_dummy_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_dummy_get_default_layout_mode;

View File

@ -394,10 +394,11 @@ struct _MetaMonitorManagerClass
MetaMonitor *,
MetaMonitorMode *);
void (*get_supported_scales) (MetaMonitorManager *,
MetaLogicalMonitorLayoutMode ,
float **,
int *);
float * (*calculate_supported_scales) (MetaMonitorManager *,
MetaLogicalMonitorLayoutMode ,
MetaMonitor *,
MetaMonitorMode *,
int *);
MetaMonitorManagerCapability (*get_capabilities) (MetaMonitorManager *);
@ -509,8 +510,16 @@ float meta_monitor_manager_calculate_monitor_mode_scale (MetaMonito
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode);
float * meta_monitor_manager_calculate_supported_scales (MetaMonitorManager *,
MetaLogicalMonitorLayoutMode ,
MetaMonitor *,
MetaMonitorMode *,
int *);
gboolean meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
float scale);
MetaMonitorManagerCapability

View File

@ -406,16 +406,21 @@ meta_monitor_manager_calculate_monitor_mode_scale (MetaMonitorManager *manager,
monitor_mode);
}
static void
meta_monitor_manager_get_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
float **scales,
int *n_scales)
float *
meta_monitor_manager_calculate_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
int *n_supported_scales)
{
MetaMonitorManagerClass *manager_class =
META_MONITOR_MANAGER_GET_CLASS (manager);
manager_class->get_supported_scales (manager, layout_mode, scales, n_scales);
return manager_class->calculate_supported_scales (manager,
layout_mode,
monitor,
monitor_mode,
n_supported_scales);
}
MetaMonitorManagerCapability
@ -1487,7 +1492,7 @@ meta_monitor_manager_legacy_handle_apply_configuration (MetaDBusDisplayConfig *
#define META_DISPLAY_CONFIG_MODE_FLAGS_PREFERRED (1 << 0)
#define META_DISPLAY_CONFIG_MODE_FLAGS_CURRENT (1 << 1)
#define MODE_FORMAT "(iiddu)"
#define MODE_FORMAT "(iiddadu)"
#define MODES_FORMAT "a" MODE_FORMAT
#define MONITOR_SPEC_FORMAT "(ssss)"
#define MONITOR_FORMAT "(" MONITOR_SPEC_FORMAT MODES_FORMAT "a{sv})"
@ -1504,11 +1509,8 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
MetaMonitorManager *manager = META_MONITOR_MANAGER (skeleton);
GVariantBuilder monitors_builder;
GVariantBuilder logical_monitors_builder;
GVariantBuilder supported_scales_builder;
GVariantBuilder properties_builder;
GList *l;
float *supported_scales;
int n_supported_scales;
int i;
MetaMonitorManagerCapability capabilities;
int max_screen_width, max_screen_height;
@ -1546,8 +1548,11 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
for (k = meta_monitor_get_modes (monitor); k; k = k->next)
{
MetaMonitorMode *monitor_mode = k->data;
GVariantBuilder supported_scales_builder;
MetaMonitorModeSpec *monitor_mode_spec;
int preferred_scale;
float preferred_scale;
float *supported_scales;
int n_supported_scales;
uint32_t flags = 0;
monitor_mode_spec = meta_monitor_mode_get_spec (monitor_mode);
@ -1555,6 +1560,20 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
meta_monitor_manager_calculate_monitor_mode_scale (manager,
monitor,
monitor_mode);
g_variant_builder_init (&supported_scales_builder,
G_VARIANT_TYPE ("ad"));
supported_scales =
meta_monitor_manager_calculate_supported_scales (manager,
manager->layout_mode,
monitor,
monitor_mode,
&n_supported_scales);
for (i = 0; i < n_supported_scales; i++)
g_variant_builder_add (&supported_scales_builder, "d",
(double) supported_scales[i]);
g_free (supported_scales);
if (monitor_mode == current_mode)
flags |= META_DISPLAY_CONFIG_MODE_FLAGS_CURRENT;
if (monitor_mode == preferred_mode)
@ -1565,6 +1584,7 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
monitor_mode_spec->height,
monitor_mode_spec->refresh_rate,
(double) preferred_scale,
&supported_scales_builder,
flags);
}
@ -1632,14 +1652,6 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
NULL);
}
g_variant_builder_init (&supported_scales_builder, G_VARIANT_TYPE ("ad"));
meta_monitor_manager_get_supported_scales (manager,
manager->layout_mode,
&supported_scales,
&n_supported_scales);
for (i = 0; i < n_supported_scales; i++)
g_variant_builder_add (&supported_scales_builder, "d", supported_scales[i]);
g_variant_builder_init (&properties_builder, G_VARIANT_TYPE ("a{sv}"));
capabilities = meta_monitor_manager_get_capabilities (manager);
if ((capabilities & META_MONITOR_MANAGER_CAPABILITY_MIRRORING) == 0)
@ -1690,7 +1702,6 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
manager->serial,
g_variant_builder_end (&monitors_builder),
g_variant_builder_end (&logical_monitors_builder),
g_variant_builder_end (&supported_scales_builder),
g_variant_builder_end (&properties_builder));
return TRUE;
@ -1708,16 +1719,20 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
gboolean
meta_monitor_manager_is_scale_supported (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
float scale)
{
float *supported_scales;
g_autofree float *supported_scales = NULL;
int n_supported_scales;
int i;
meta_monitor_manager_get_supported_scales (manager,
layout_mode,
&supported_scales,
&n_supported_scales);
supported_scales =
meta_monitor_manager_calculate_supported_scales (manager,
layout_mode,
monitor,
monitor_mode,
&n_supported_scales);
for (i = 0; i < n_supported_scales; i++)
{
if (supported_scales[i] == scale)
@ -1740,15 +1755,6 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager,
float scale = logical_monitor_config->scale;
GList *k;
if (!meta_monitor_manager_is_scale_supported (manager,
config->layout_mode,
scale))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Scale not supported by backend");
return FALSE;
}
for (k = logical_monitor_config->monitor_configs; k; k = k->next)
{
MetaMonitorConfig *monitor_config = k->data;
@ -1773,6 +1779,18 @@ meta_monitor_manager_is_config_applicable (MetaMonitorManager *manager,
"Specified monitor mode not available");
return FALSE;
}
if (!meta_monitor_manager_is_scale_supported (manager,
config->layout_mode,
monitor,
monitor_mode,
scale))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Scale not supported by backend");
return FALSE;
}
}
}

View File

@ -1336,6 +1336,43 @@ meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
return calculate_scale (monitor, monitor_mode);
}
float *
meta_monitor_calculate_supported_scales (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
MetaMonitorScalesConstraint constraints,
int *n_supported_scales)
{
unsigned int i;
int width, height;
GArray *supported_scales;
static const float all_scales[] = {
1.0,
1.5,
2.0
};
meta_monitor_mode_get_resolution (monitor_mode, &width, &height);
supported_scales = g_array_new (FALSE, FALSE, sizeof (float));
for (i = 0; i < G_N_ELEMENTS (all_scales); i++)
{
float scale = all_scales[i];
if ((constraints & META_MONITOR_SCALES_CONSTRAINT_NO_FRAC) &&
fmodf (scale, 1.0) != 0.0)
continue;
if (fmodf (width, scale) != 0.0 || fmodf (height, scale) != 0.0)
continue;
g_array_append_val (supported_scales, scale);
}
*n_supported_scales = supported_scales->len;
return (float *) g_array_free (supported_scales, FALSE);
}
MetaMonitorModeSpec *
meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode)
{

View File

@ -53,6 +53,12 @@ typedef gboolean (* MetaMonitorModeFunc) (MetaMonitor *monitor,
gpointer user_data,
GError **error);
typedef enum _MetaMonitorScalesConstraint
{
META_MONITOR_SCALES_CONSTRAINT_NONE = 0,
META_MONITOR_SCALES_CONSTRAINT_NO_FRAC = (1 << 0),
} MetaMonitorScalesConstraint;
#define META_TYPE_MONITOR (meta_monitor_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaMonitor, meta_monitor, META, MONITOR, GObject)
@ -163,6 +169,11 @@ void meta_monitor_calculate_crtc_pos (MetaMonitor *monitor,
float meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode);
float * meta_monitor_calculate_supported_scales (MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
MetaMonitorScalesConstraint constraints,
int *n_supported_scales);
MetaMonitorModeSpec * meta_monitor_mode_get_spec (MetaMonitorMode *monitor_mode);
void meta_monitor_mode_get_resolution (MetaMonitorMode *monitor_mode,

View File

@ -52,17 +52,6 @@
#define ALL_TRANSFORMS_MASK ((1 << ALL_TRANSFORMS) - 1)
#define SYNC_TOLERANCE 0.01 /* 1 percent */
static float supported_scales_kms_logical[] = {
1.0,
1.5,
2.0
};
static float supported_scales_kms_physical[] = {
1.0,
2.0
};
typedef struct
{
drmModeConnector *connector;
@ -1852,23 +1841,28 @@ meta_monitor_manager_kms_calculate_monitor_mode_scale (MetaMonitorManager *manag
return meta_monitor_calculate_mode_scale (monitor, monitor_mode);
}
static void
meta_monitor_manager_kms_get_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
float **scales,
int *n_scales)
static float *
meta_monitor_manager_kms_calculate_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
int *n_supported_scales)
{
MetaMonitorScalesConstraint constraints =
META_MONITOR_SCALES_CONSTRAINT_NONE;
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
*scales = supported_scales_kms_logical;
*n_scales = G_N_ELEMENTS (supported_scales_kms_logical);
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
*scales = supported_scales_kms_physical;
*n_scales = G_N_ELEMENTS (supported_scales_kms_physical);
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
break;
}
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints,
n_supported_scales);
}
static MetaMonitorManagerCapability
@ -1973,7 +1967,7 @@ meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
manager_class->is_transform_handled = meta_monitor_manager_kms_is_transform_handled;
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_kms_calculate_monitor_mode_scale;
manager_class->get_supported_scales = meta_monitor_manager_kms_get_supported_scales;
manager_class->calculate_supported_scales = meta_monitor_manager_kms_calculate_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_kms_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_kms_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_kms_get_default_layout_mode;

View File

@ -54,10 +54,6 @@
* for the reasoning */
#define DPI_FALLBACK 96.0
static float supported_scales_xrandr[] = {
1.0, 2.0
};
struct _MetaMonitorManagerXrandr
{
MetaMonitorManager parent_instance;
@ -1799,14 +1795,19 @@ meta_monitor_manager_xrandr_calculate_monitor_mode_scale (MetaMonitorManager *ma
return meta_monitor_calculate_mode_scale (monitor, monitor_mode);
}
static void
meta_monitor_manager_xrandr_get_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
float **scales,
int *n_scales)
static float *
meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
int *n_supported_scales)
{
*scales = supported_scales_xrandr;
*n_scales = G_N_ELEMENTS (supported_scales_xrandr);
MetaMonitorScalesConstraint constraints;
constraints = META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints,
n_supported_scales);
}
static MetaMonitorManagerCapability
@ -1913,7 +1914,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
#endif
manager_class->is_transform_handled = meta_monitor_manager_xrandr_is_transform_handled;
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_xrandr_calculate_monitor_mode_scale;
manager_class->get_supported_scales = meta_monitor_manager_xrandr_get_supported_scales;
manager_class->calculate_supported_scales = meta_monitor_manager_xrandr_calculate_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode;

View File

@ -307,7 +307,6 @@
@serial: configuration serial
@monitors: available monitors
@logical_monitors: current logical monitor configuration
@supported_scales: scaling factors supported by the display server
@properties: display configuration properties
@monitors represent connected physical monitors
@ -316,11 +315,12 @@
* s vendor: vendor name
* s product: product name
* s serial: product serial
* a(iidu) modes: available modes
* a(iiddadu) modes: available modes
* i width: width in physical pixels
* i height: height in physical pixels
* d refresh rate: refresh rate
* d preferred scale: scale preferred as per calculations
* ad supported scales: scales supported by this mode
* u flags: mode flags (see below)
* a{sv} properties: optional properties, including:
- "width-mm" (i): physical width of monitor in millimeters
@ -366,10 +366,6 @@
7: 270° flipped
@supported_scales is an ordered list of floating point numbers representing
scale factors of logical monitors supported by the display server.
@layout_mode current layout mode represents the way logical monitors
are layed out on the screen. Possible modes include:
@ -408,9 +404,8 @@
-->
<method name="GetCurrentState">
<arg name="serial" direction="out" type="u" />
<arg name="monitors" direction="out" type="a((ssss)a(iiddu)a{sv})" />
<arg name="monitors" direction="out" type="a((ssss)a(iiddadu)a{sv})" />
<arg name="logical_monitors" direction="out" type="a(iiduba(ssss)a{sv})" />
<arg name="supported_scales" direction="out" type="ad" />
<arg name="properties" direction="out" type="a{sv}" />
</method>

View File

@ -24,17 +24,6 @@
#include "backends/meta-backend-private.h"
#include "backends/meta-monitor-config-manager.h"
static float supported_scales_test_logical[] = {
1.0,
1.5,
2.0
};
static float supported_scales_test_physical[] = {
1.0,
2.0
};
struct _MetaMonitorManagerTest
{
MetaMonitorManager parent;
@ -420,23 +409,28 @@ meta_monitor_manager_test_calculate_monitor_mode_scale (MetaMonitorManager *mana
return output_test->scale;
}
static void
meta_monitor_manager_test_get_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
float **scales,
int *n_scales)
static float *
meta_monitor_manager_test_calculate_supported_scales (MetaMonitorManager *manager,
MetaLogicalMonitorLayoutMode layout_mode,
MetaMonitor *monitor,
MetaMonitorMode *monitor_mode,
int *n_supported_scales)
{
MetaMonitorScalesConstraint constraints =
META_MONITOR_SCALES_CONSTRAINT_NONE;
switch (layout_mode)
{
case META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL:
*scales = supported_scales_test_logical;
*n_scales = G_N_ELEMENTS (supported_scales_test_logical);
break;
case META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL:
*scales = supported_scales_test_physical;
*n_scales = G_N_ELEMENTS (supported_scales_test_physical);
constraints |= META_MONITOR_SCALES_CONSTRAINT_NO_FRAC;
break;
}
return meta_monitor_calculate_supported_scales (monitor, monitor_mode,
constraints,
n_supported_scales);
}
static gboolean
@ -525,7 +519,7 @@ meta_monitor_manager_test_class_init (MetaMonitorManagerTestClass *klass)
manager_class->tiled_monitor_removed = meta_monitor_manager_test_tiled_monitor_removed;
manager_class->is_transform_handled = meta_monitor_manager_test_is_transform_handled;
manager_class->calculate_monitor_mode_scale = meta_monitor_manager_test_calculate_monitor_mode_scale;
manager_class->get_supported_scales = meta_monitor_manager_test_get_supported_scales;
manager_class->calculate_supported_scales = meta_monitor_manager_test_calculate_supported_scales;
manager_class->get_capabilities = meta_monitor_manager_test_get_capabilities;
manager_class->get_max_screen_size = meta_monitor_manager_test_get_max_screen_size;
manager_class->get_default_layout_mode = meta_monitor_manager_test_get_default_layout_mode;