DisplayConfig: make the dummy backend writable

Add a number of dummy outputs and modes to the dummy backend,
and implement the writing bits.
The only visible effect is that you can change the screen size,
which resizes the output window.
This commit is contained in:
Giovanni Campagna 2013-07-23 10:07:52 +02:00
parent 33c0c1dc18
commit 1e3aad2d8c
2 changed files with 241 additions and 31 deletions

View File

@ -73,6 +73,9 @@ struct _MetaOutput
MetaOutput **possible_clones; MetaOutput **possible_clones;
unsigned int n_possible_clones; unsigned int n_possible_clones;
/* Used when changing configuration */
gboolean dirty;
/* The low-level bits used to build the high-level info /* The low-level bits used to build the high-level info
in MetaMonitorInfo in MetaMonitorInfo

View File

@ -126,9 +126,22 @@ static int signals[SIGNALS_LAST];
G_DEFINE_TYPE (MetaMonitorManager, meta_monitor_manager, G_TYPE_OBJECT); G_DEFINE_TYPE (MetaMonitorManager, meta_monitor_manager, G_TYPE_OBJECT);
static void invalidate_logical_config (MetaMonitorManager *manager);
static void static void
make_dummy_monitor_config (MetaMonitorManager *manager) make_dummy_monitor_config (MetaMonitorManager *manager)
{ {
/* The dummy monitor config has:
- one enabled output, LVDS, primary, at 0x0 and 1024x768
- one free CRTC
- two disabled outputs
- three modes, 1024x768, 800x600 and 640x480
- no clones are possible (use different CRTCs)
Low-level IDs should be assigned sequentially, to
mimick what XRandR and KMS do
*/
manager->backend = META_BACKEND_DUMMY; manager->backend = META_BACKEND_DUMMY;
manager->max_screen_width = 65535; manager->max_screen_width = 65535;
@ -136,18 +149,28 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
manager->screen_width = 1024; manager->screen_width = 1024;
manager->screen_height = 768; manager->screen_height = 768;
manager->modes = g_new0 (MetaMonitorMode, 1); manager->modes = g_new0 (MetaMonitorMode, 3);
manager->n_modes = 1; manager->n_modes = 3;
manager->modes[0].mode_id = 1; manager->modes[0].mode_id = 1;
manager->modes[0].width = manager->screen_width; manager->modes[0].width = 1024;
manager->modes[0].height = manager->screen_height; manager->modes[0].height = 768;
manager->modes[0].refresh_rate = 60.0; manager->modes[0].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 1); manager->modes[1].mode_id = 2;
manager->n_crtcs = 1; manager->modes[1].width = 800;
manager->modes[1].height = 600;
manager->modes[1].refresh_rate = 60.0;
manager->crtcs[0].crtc_id = 2; manager->modes[2].mode_id = 3;
manager->modes[2].width = 640;
manager->modes[2].height = 480;
manager->modes[2].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 2);
manager->n_crtcs = 2;
manager->crtcs[0].crtc_id = 4;
manager->crtcs[0].rect.x = 0; manager->crtcs[0].rect.x = 0;
manager->crtcs[0].rect.y = 0; manager->crtcs[0].rect.y = 0;
manager->crtcs[0].rect.width = manager->modes[0].width; manager->crtcs[0].rect.width = manager->modes[0].width;
@ -156,11 +179,20 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
manager->crtcs[0].dirty = FALSE; manager->crtcs[0].dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL; manager->crtcs[0].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 1); manager->crtcs[1].crtc_id = 5;
manager->n_outputs = 1; manager->crtcs[1].rect.x = 0;
manager->crtcs[1].rect.y = 0;
manager->crtcs[1].rect.width = 0;
manager->crtcs[1].rect.height = 0;
manager->crtcs[1].current_mode = NULL;
manager->crtcs[1].dirty = FALSE;
manager->crtcs[1].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 3);
manager->n_outputs = 3;
manager->outputs[0].crtc = &manager->crtcs[0]; manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].output_id = 3; manager->outputs[0].output_id = 6;
manager->outputs[0].name = g_strdup ("LVDS"); manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("unknown"); manager->outputs[0].vendor = g_strdup ("unknown");
manager->outputs[0].product = g_strdup ("unknown"); manager->outputs[0].product = g_strdup ("unknown");
@ -169,14 +201,61 @@ make_dummy_monitor_config (MetaMonitorManager *manager)
manager->outputs[0].height_mm = 125; manager->outputs[0].height_mm = 125;
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN; manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[0].preferred_mode = &manager->modes[0]; manager->outputs[0].preferred_mode = &manager->modes[0];
manager->outputs[0].n_modes = 1; manager->outputs[0].n_modes = 3;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1); manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 3);
manager->outputs[0].modes[0] = &manager->modes[0]; manager->outputs[0].modes[0] = &manager->modes[0];
manager->outputs[0].n_possible_crtcs = 1; manager->outputs[0].modes[1] = &manager->modes[1];
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1); manager->outputs[0].modes[2] = &manager->modes[2];
manager->outputs[0].n_possible_crtcs = 2;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 2);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0]; manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].possible_crtcs[1] = &manager->crtcs[1];
manager->outputs[0].n_possible_clones = 0; manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0); manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[1].crtc = NULL;
manager->outputs[1].output_id = 7;
manager->outputs[1].name = g_strdup ("HDMI");
manager->outputs[1].vendor = g_strdup ("unknown");
manager->outputs[1].product = g_strdup ("unknown");
manager->outputs[1].serial = g_strdup ("");
manager->outputs[1].width_mm = 510;
manager->outputs[1].height_mm = 287;
manager->outputs[1].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[1].preferred_mode = &manager->modes[0];
manager->outputs[1].n_modes = 3;
manager->outputs[1].modes = g_new0 (MetaMonitorMode *, 3);
manager->outputs[1].modes[0] = &manager->modes[0];
manager->outputs[1].modes[1] = &manager->modes[1];
manager->outputs[1].modes[2] = &manager->modes[2];
manager->outputs[1].n_possible_crtcs = 2;
manager->outputs[1].possible_crtcs = g_new0 (MetaCRTC *, 2);
manager->outputs[1].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[1].possible_crtcs[1] = &manager->crtcs[1];
manager->outputs[1].n_possible_clones = 0;
manager->outputs[1].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[2].crtc = NULL;
manager->outputs[2].output_id = 8;
manager->outputs[2].name = g_strdup ("VGA");
manager->outputs[2].vendor = g_strdup ("unknown");
manager->outputs[2].product = g_strdup ("unknown");
manager->outputs[2].serial = g_strdup ("");
manager->outputs[2].width_mm = 309;
manager->outputs[2].height_mm = 174;
manager->outputs[2].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[2].preferred_mode = &manager->modes[0];
manager->outputs[2].n_modes = 3;
manager->outputs[2].modes = g_new0 (MetaMonitorMode *, 3);
manager->outputs[2].modes[0] = &manager->modes[0];
manager->outputs[2].modes[1] = &manager->modes[1];
manager->outputs[2].modes[2] = &manager->modes[2];
manager->outputs[2].n_possible_crtcs = 2;
manager->outputs[2].possible_crtcs = g_new0 (MetaCRTC *, 2);
manager->outputs[2].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[2].possible_crtcs[1] = &manager->crtcs[1];
manager->outputs[2].n_possible_clones = 0;
manager->outputs[2].possible_clones = g_new0 (MetaOutput *, 0);
} }
#ifdef HAVE_RANDR #ifdef HAVE_RANDR
@ -1082,7 +1161,10 @@ apply_config_xrandr (MetaMonitorManager *manager,
MetaCRTC *crtc = &manager->crtcs[i]; MetaCRTC *crtc = &manager->crtcs[i];
if (crtc->dirty) if (crtc->dirty)
{
crtc->dirty = FALSE;
continue; continue;
}
if (crtc->current_mode == NULL) if (crtc->current_mode == NULL)
continue; continue;
@ -1098,6 +1180,117 @@ apply_config_xrandr (MetaMonitorManager *manager,
} }
#endif #endif
static void
apply_config_dummy (MetaMonitorManager *manager,
GVariantIter *crtcs,
GVariantIter *outputs)
{
GVariant *nested_outputs, *properties;
guint crtc_id, output_id, transform;
int new_mode, x, y;
unsigned i;
int screen_width = 0, screen_height = 0;
while (g_variant_iter_loop (crtcs, "(uiiiu@aua{sv})",
&crtc_id, &new_mode, &x, &y,
&transform, &nested_outputs, NULL))
{
MetaCRTC *crtc = &manager->crtcs[crtc_id];
crtc->dirty = TRUE;
if (new_mode == -1)
{
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
else
{
MetaMonitorMode *mode;
MetaOutput *output;
int i, n_outputs;
guint output_id;
mode = &manager->modes[new_mode];
crtc->rect.x = x;
crtc->rect.y = y;
crtc->rect.width = mode->width;
crtc->rect.height = mode->height;
crtc->current_mode = mode;
screen_width = MAX (screen_width, x + mode->width);
screen_height = MAX (screen_height, y + mode->height);
n_outputs = g_variant_n_children (nested_outputs);
for (i = 0; i < n_outputs; i++)
{
g_variant_get_child (nested_outputs, i, "u", &output_id);
output = &manager->outputs[output_id];
output->dirty = TRUE;
output->crtc = crtc;
}
}
}
while (g_variant_iter_loop (outputs, "(u@a{sv})",
&output_id, &properties))
{
MetaOutput *output = &manager->outputs[output_id];
gboolean primary, presentation;
if (g_variant_lookup (properties, "primary", "b", &primary))
output->is_primary = primary;
if (g_variant_lookup (properties, "presentation", "b", &presentation))
output->is_presentation = presentation;
}
/* Disable CRTCs not mentioned in the list */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
crtc->logical_monitor = NULL;
if (crtc->dirty)
{
crtc->dirty = FALSE;
continue;
}
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
/* Disable outputs not mentioned in the list */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->dirty)
{
output->dirty = FALSE;
continue;
}
output->crtc = NULL;
output->is_primary = FALSE;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
invalidate_logical_config (manager);
}
static gboolean static gboolean
handle_apply_configuration (MetaDBusDisplayConfig *skeleton, handle_apply_configuration (MetaDBusDisplayConfig *skeleton,
GDBusMethodInvocation *invocation, GDBusMethodInvocation *invocation,
@ -1129,14 +1322,6 @@ handle_apply_configuration (MetaDBusDisplayConfig *skeleton,
return TRUE; return TRUE;
} }
if (manager->backend != META_BACKEND_XRANDR)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_NOT_SUPPORTED,
"Changing configuration is not supported by the backend");
return TRUE;
}
/* Validate all arguments */ /* Validate all arguments */
g_variant_iter_init (&crtc_iter, crtcs); g_variant_iter_init (&crtc_iter, crtcs);
while (g_variant_iter_loop (&crtc_iter, "(uiiiuaua{sv})", while (g_variant_iter_loop (&crtc_iter, "(uiiiuaua{sv})",
@ -1246,7 +1431,19 @@ handle_apply_configuration (MetaDBusDisplayConfig *skeleton,
g_variant_iter_init (&crtc_iter, crtcs); g_variant_iter_init (&crtc_iter, crtcs);
g_variant_iter_init (&output_iter, outputs); g_variant_iter_init (&output_iter, outputs);
if (manager->backend == META_BACKEND_COGL)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_NOT_SUPPORTED,
"Changing configuration is not supported by the backend");
return TRUE;
}
if (manager->backend == META_BACKEND_XRANDR)
apply_config_xrandr (manager, &crtc_iter, &output_iter); apply_config_xrandr (manager, &crtc_iter, &output_iter);
else
apply_config_dummy (manager, &crtc_iter, &output_iter);
meta_dbus_display_config_complete_apply_configuration (skeleton, invocation); meta_dbus_display_config_complete_apply_configuration (skeleton, invocation);
return TRUE; return TRUE;
@ -1352,13 +1549,28 @@ meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
*height = manager->screen_height; *height = manager->screen_height;
} }
static void
invalidate_logical_config (MetaMonitorManager *manager)
{
MetaMonitorInfo *old_monitor_infos;
old_monitor_infos = manager->monitor_infos;
manager->serial++;
make_logical_config (manager);
g_signal_emit (manager, signals[MONITORS_CHANGED], 0);
g_free (old_monitor_infos);
}
gboolean gboolean
meta_monitor_manager_handle_xevent (MetaMonitorManager *manager, meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event) XEvent *event)
{ {
MetaOutput *old_outputs; MetaOutput *old_outputs;
MetaCRTC *old_crtcs; MetaCRTC *old_crtcs;
MetaMonitorInfo *old_monitor_infos;
MetaMonitorMode *old_modes; MetaMonitorMode *old_modes;
int n_old_outputs; int n_old_outputs;
@ -1374,17 +1586,12 @@ meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
/* Save the old structures, so they stay valid during the update */ /* Save the old structures, so they stay valid during the update */
old_outputs = manager->outputs; old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs; n_old_outputs = manager->n_outputs;
old_monitor_infos = manager->monitor_infos;
old_modes = manager->modes; old_modes = manager->modes;
old_crtcs = manager->crtcs; old_crtcs = manager->crtcs;
manager->serial ++;
read_current_config (manager); read_current_config (manager);
make_logical_config (manager); invalidate_logical_config (manager);
g_signal_emit (manager, signals[MONITORS_CHANGED], 0);
g_free (old_monitor_infos);
free_output_array (old_outputs, n_old_outputs); free_output_array (old_outputs, n_old_outputs);
g_free (old_modes); g_free (old_modes);
g_free (old_crtcs); g_free (old_crtcs);