[mutter/wip/wayland-kms: 696/697] Integrate the monitor manager with wayland
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland-kms: 696/697] Integrate the monitor manager with wayland
- Date: Mon, 19 Aug 2013 13:36:19 +0000 (UTC)
commit 43e1b004866ce682a10da114c8e9431f09088c43
Author: Giovanni Campagna <gcampagn redhat com>
Date: Mon Aug 19 11:12:42 2013 +0200
Integrate the monitor manager with wayland
Use the right backend when running as a wayland compositor,
export the data to wayland clients, and use it to keep the stage
appropriately sized.
src/compositor/compositor.c | 32 ++++--
src/core/monitor.c | 11 ++-
src/core/screen.c | 5 +-
src/wayland/meta-wayland-private.h | 22 +----
src/wayland/meta-wayland-stage.c | 1 +
src/wayland/meta-wayland.c | 228 +++++++++++++++++++++++++++---------
6 files changed, 208 insertions(+), 91 deletions(-)
---
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index 3240fc0..7991ce1 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -733,6 +733,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
{
wayland_compositor = meta_wayland_compositor_get_default ();
info->stage = wayland_compositor->stage;
+
+ meta_screen_get_size (screen, &width, &height);
+ clutter_actor_set_size (info->stage, width, height);
}
else
{
@@ -1481,18 +1484,25 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
guint width,
guint height)
{
+ MetaDisplay *display = meta_screen_get_display (screen);
+ MetaCompScreen *info = meta_screen_get_compositor_data (screen);
+
if (meta_is_wayland_compositor ())
{
- /* It's not clear at the moment how we will be dealing with screen
- * resizing as a Wayland compositor so for now just abort if we
- * hit this code. */
- g_critical ("Unexpected call to meta_compositor_sync_screen_size() "
- "when running as a wayland compositor");
+ /* FIXME: when we support a sliced stage, this is the place to do it
+ But! This is not the place to apply KMS config, here we only
+ notify Clutter/Cogl/GL that the framebuffer sizes changed.
+
+ And because for now clutter does not do sliced, we use one
+ framebuffer the size of the whole screen, and when running on
+ bare metal MetaMonitorManager will do the necessary tricks to
+ show the right portions on the right screens.
+ */
+
+ clutter_actor_set_size (info->stage, width, height);
}
else
{
- MetaDisplay *display = meta_screen_get_display (screen);
- MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Display *xdisplay;
Window xwin;
@@ -1503,11 +1513,11 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
-
- meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
- meta_screen_get_screen_number (screen),
- width, height);
}
+
+ meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
+ meta_screen_get_screen_number (screen),
+ width, height);
}
static void
diff --git a/src/core/monitor.c b/src/core/monitor.c
index d81ff15..3542b1f 100644
--- a/src/core/monitor.c
+++ b/src/core/monitor.c
@@ -475,6 +475,15 @@ make_logical_config (MetaMonitorManager *manager)
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
}
+static GType
+get_default_backend (void)
+{
+ if (meta_is_wayland_compositor ())
+ return META_TYPE_MONITOR_MANAGER; /* FIXME: KMS */
+ else
+ return META_TYPE_MONITOR_MANAGER_XRANDR;
+}
+
static MetaMonitorManager *
meta_monitor_manager_new (void)
{
@@ -484,7 +493,7 @@ meta_monitor_manager_new (void)
env = g_getenv ("META_DEBUG_MULTIMONITOR");
if (env == NULL)
- type = META_TYPE_MONITOR_MANAGER_XRANDR;
+ type = get_default_backend ();
else if (strcmp (env, "xrandr") == 0)
type = META_TYPE_MONITOR_MANAGER_XRANDR;
else
diff --git a/src/core/screen.c b/src/core/screen.c
index b8870da..ee91329 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -675,8 +675,9 @@ meta_screen_new (MetaDisplay *display,
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->rect.x = screen->rect.y = 0;
-
- meta_monitor_manager_initialize ();
+
+ if (!meta_is_wayland_compositor ())
+ meta_monitor_manager_initialize ();
manager = meta_monitor_manager_get ();
g_signal_connect (manager, "monitors-changed",
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index f23d933..1dad985 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -113,26 +113,6 @@ typedef struct
typedef struct
{
- guint32 flags;
- int width;
- int height;
- int refresh;
-} MetaWaylandMode;
-
-typedef struct
-{
- struct wl_object wayland_output;
- int x;
- int y;
- int width_mm;
- int height_mm;
- /* XXX: with sliced stages we'd reference a CoglFramebuffer here. */
-
- GList *modes;
-} MetaWaylandOutput;
-
-typedef struct
-{
GSource source;
GPollFD pfd;
struct wl_display *display;
@@ -154,7 +134,7 @@ struct _MetaWaylandCompositor
struct wl_event_loop *wayland_loop;
GMainLoop *init_loop;
ClutterActor *stage;
- GList *outputs;
+ GHashTable *outputs;
GSource *wayland_event_source;
GList *surfaces;
struct wl_list frame_callbacks;
diff --git a/src/wayland/meta-wayland-stage.c b/src/wayland/meta-wayland-stage.c
index f7d28d4..48fe8e7 100644
--- a/src/wayland/meta-wayland-stage.c
+++ b/src/wayland/meta-wayland-stage.c
@@ -55,6 +55,7 @@ meta_wayland_stage_class_init (MetaWaylandStageClass *klass)
static void
meta_wayland_stage_init (MetaWaylandStage *self)
{
+ clutter_stage_set_user_resizable (CLUTTER_STAGE (self), FALSE);
}
ClutterActor *
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index bb25697..ecbfd4d 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -53,6 +53,7 @@
#include <meta/main.h>
#include "frame.h"
#include "meta-weston-launch.h"
+#include "monitor-private.h"
static MetaWaylandCompositor _meta_wayland_compositor;
@@ -642,84 +643,186 @@ meta_wayland_compositor_create_region (struct wl_client *wayland_client,
region->region = cairo_region_create ();
}
+typedef struct {
+ MetaOutput *output;
+ struct wl_global *global;
+ int x, y;
+ enum wl_output_transform transform;
+
+ GList *resources;
+} MetaWaylandOutput;
+
+static void
+output_resource_destroy (struct wl_resource *res)
+{
+ MetaWaylandOutput *wayland_output;
+
+ wayland_output = wl_resource_get_user_data (res);
+ wayland_output->resources = g_list_remove (wayland_output->resources, res);
+}
+
static void
bind_output (struct wl_client *client,
void *data,
guint32 version,
guint32 id)
{
- MetaWaylandOutput *output = data;
- struct wl_resource *resource =
- wl_resource_create (client, &wl_output_interface, version, id);
- GList *l;
+ MetaWaylandOutput *wayland_output = data;
+ MetaOutput *output = wayland_output->output;
+ struct wl_resource *resource;
+ guint mode_flags;
+
+ resource = wl_resource_create (client, &wl_output_interface, version, id);
+ wayland_output->resources = g_list_prepend (wayland_output->resources, resource);
+
+ wl_resource_set_user_data (resource, wayland_output);
+ wl_resource_set_destructor (resource, output_resource_destroy);
+
+ meta_verbose ("Binding output %p/%s (%u, %u, %u, %u) x %f\n",
+ output, output->name,
+ output->crtc->rect.x, output->crtc->rect.y,
+ output->crtc->rect.width, output->crtc->rect.height,
+ output->crtc->current_mode->refresh_rate);
wl_resource_post_event (resource,
WL_OUTPUT_GEOMETRY,
- output->x, output->y,
+ (int)output->crtc->rect.x,
+ (int)output->crtc->rect.y,
output->width_mm,
output->height_mm,
- 0, /* subpixel: unknown */
- "unknown", /* make */
- "unknown"); /* model */
+ /* Cogl values reflect XRandR values,
+ and so does wayland */
+ output->subpixel_order,
+ output->vendor,
+ output->product,
+ output->crtc->transform);
+
+ g_assert (output->crtc->current_mode != NULL);
+
+ mode_flags = WL_OUTPUT_MODE_CURRENT;
+ if (output->crtc->current_mode == output->preferred_mode)
+ mode_flags |= WL_OUTPUT_MODE_PREFERRED;
+
+ wl_resource_post_event (resource,
+ WL_OUTPUT_MODE,
+ mode_flags,
+ (int)output->crtc->current_mode->width,
+ (int)output->crtc->current_mode->height,
+ (int)output->crtc->current_mode->refresh_rate);
+
+ if (version >= 2)
+ wl_resource_post_event (resource,
+ WL_OUTPUT_DONE);
+}
+
+static void
+wayland_output_destroy_notify (gpointer data)
+{
+ MetaWaylandOutput *wayland_output = data;
+ GList *resources;
+
+ /* Make sure the destructors don't mess with the list */
+ resources = wayland_output->resources;
+ wayland_output->resources = NULL;
+
+ wl_global_destroy (wayland_output->global);
+ g_list_free (resources);
+
+ g_slice_free (MetaWaylandOutput, wayland_output);
+}
+
+static void
+wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
+ MetaOutput *output)
+{
+ GList *iter;
+ guint mode_flags;
- for (l = output->modes; l; l = l->next)
+ g_assert (output->crtc->current_mode != NULL);
+
+ mode_flags = WL_OUTPUT_MODE_CURRENT;
+ if (output->crtc->current_mode == output->preferred_mode)
+ mode_flags |= WL_OUTPUT_MODE_PREFERRED;
+
+ for (iter = wayland_output->resources; iter; iter = iter->next)
{
- MetaWaylandMode *mode = l->data;
+ struct wl_resource *resource = iter->data;
+
+ if (wayland_output->x != output->crtc->rect.x ||
+ wayland_output->y != output->crtc->rect.y ||
+ wayland_output->transform != output->crtc->transform)
+ {
+ wl_resource_post_event (resource,
+ WL_OUTPUT_GEOMETRY,
+ (int)output->crtc->rect.x,
+ (int)output->crtc->rect.y,
+ output->width_mm,
+ output->height_mm,
+ output->subpixel_order,
+ output->vendor,
+ output->product,
+ output->crtc->transform);
+ }
+
wl_resource_post_event (resource,
WL_OUTPUT_MODE,
- mode->flags,
- mode->width,
- mode->height,
- mode->refresh);
+ mode_flags,
+ (int)output->crtc->current_mode->width,
+ (int)output->crtc->current_mode->height,
+ (int)output->crtc->current_mode->refresh_rate);
}
+
+ /* It's very important that we change the output pointer here, as
+ the old structure is about to be freed by MetaMonitorManager */
+ wayland_output->output = output;
+ wayland_output->x = output->crtc->rect.x;
+ wayland_output->y = output->crtc->rect.y;
+ wayland_output->transform = output->crtc->transform;
}
-static void
-meta_wayland_compositor_create_output (MetaWaylandCompositor *compositor,
- int x,
- int y,
- int width,
- int height,
- int width_mm,
- int height_mm)
-{
- MetaWaylandOutput *output = g_slice_new0 (MetaWaylandOutput);
- MetaWaylandMode *mode;
- float final_width, final_height;
-
- /* XXX: eventually we will support sliced stages and an output should
- * correspond to a slice/CoglFramebuffer, but for now we only support
- * one output so we make sure it always matches the size of the stage
- */
- clutter_actor_set_size (compositor->stage, width, height);
+static GHashTable *
+meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
+ MetaMonitorManager *monitors)
+{
+ MetaOutput *outputs;
+ unsigned int i, n_outputs;
+ GHashTable *new_table;
- /* Read back the actual size we were given.
- * XXX: This really needs re-thinking later though so we know the
- * correct output geometry to use. */
- clutter_actor_get_size (compositor->stage, &final_width, &final_height);
- width = final_width;
- height = final_height;
+ outputs = meta_monitor_manager_get_outputs (monitors, &n_outputs);
+ new_table = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
- output->wayland_output.interface = &wl_output_interface;
+ for (i = 0; i < n_outputs; i++)
+ {
+ MetaOutput *output = &outputs[i];
+ MetaWaylandOutput *wayland_output;
- output->x = x;
- output->y = y;
- output->width_mm = width_mm;
- output->height_mm = height_mm;
+ /* wayland does not expose disabled outputs */
+ if (output->crtc == NULL)
+ {
+ g_hash_table_remove (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
+ continue;
+ }
- wl_global_create (compositor->wayland_display,
- &wl_output_interface, 2,
- output, bind_output);
+ wayland_output = g_hash_table_lookup (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
- mode = g_slice_new0 (MetaWaylandMode);
- mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
- mode->width = width;
- mode->height = height;
- mode->refresh = 60;
+ if (wayland_output)
+ {
+ g_hash_table_steal (compositor->outputs, GSIZE_TO_POINTER (output->output_id));
+ }
+ else
+ {
+ wayland_output = g_slice_new0 (MetaWaylandOutput);
+ wayland_output->global = wl_global_create (compositor->wayland_display,
+ &wl_output_interface, 2,
+ wayland_output, bind_output);
+ }
- output->modes = g_list_prepend (output->modes, mode);
+ wayland_output_update_for_output (wayland_output, output);
+ g_hash_table_insert (new_table, GSIZE_TO_POINTER (output->output_id), wayland_output);
+ }
- compositor->outputs = g_list_prepend (compositor->outputs, output);
+ g_hash_table_destroy (compositor->outputs);
+ return new_table;
}
const static struct wl_compositor_interface meta_wayland_compositor_interface = {
@@ -1458,6 +1561,13 @@ on_evdev_device_open (const char *path,
path, flags, error);
}
+static void
+on_monitors_changed (MetaMonitorManager *monitors,
+ MetaWaylandCompositor *compositor)
+{
+ compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
+}
+
void
meta_wayland_init (void)
{
@@ -1467,6 +1577,7 @@ meta_wayland_init (void)
CoglContext *cogl_context;
CoglRenderer *cogl_renderer;
int weston_launch_fd;
+ MetaMonitorManager *monitors;
memset (compositor, 0, sizeof (MetaWaylandCompositor));
@@ -1563,8 +1674,15 @@ meta_wayland_init (void)
dup2 (fd, STDIN_FILENO);
}
+ meta_monitor_manager_initialize ();
+ monitors = meta_monitor_manager_get ();
+ g_signal_connect (monitors, "monitors-changed",
+ G_CALLBACK (on_monitors_changed), compositor);
+
+ compositor->outputs = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
+ compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
+
compositor->stage = meta_wayland_stage_new ();
- clutter_stage_set_user_resizable (CLUTTER_STAGE (compositor->stage), FALSE);
g_signal_connect_after (compositor->stage, "paint",
G_CALLBACK (paint_finished_cb), compositor);
g_signal_connect (compositor->stage, "destroy",
@@ -1590,8 +1708,6 @@ meta_wayland_init (void)
compositor, /* hook_data */
NULL /* data_destroy */);
- meta_wayland_compositor_create_output (compositor, 0, 0, 1024, 600, 222, 125);
-
if (wl_global_create (compositor->wayland_display,
&wl_shell_interface, 1,
compositor, bind_shell) == NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]