Re: [PATCH] Prevent zero sized wl_egl_window

2014-02-13 Thread Pekka Paalanen
On Wed, 12 Feb 2014 16:21:11 -0800
Sinclair Yeh sinclair@intel.com wrote:

 It is illegal to create or resize a window to zero (or negative) width
 and/or height.  This patch prevents such a request from happening.
 ---
  src/egl/wayland/wayland-egl/wayland-egl.c | 6 ++
  1 file changed, 6 insertions(+)
 
 diff --git a/src/egl/wayland/wayland-egl/wayland-egl.c
 b/src/egl/wayland/wayland-egl/wayland-egl.c index 8bd49cf..ae78595
 100644 --- a/src/egl/wayland/wayland-egl/wayland-egl.c
 +++ b/src/egl/wayland/wayland-egl/wayland-egl.c
 @@ -9,6 +9,9 @@ wl_egl_window_resize(struct wl_egl_window *egl_window,
int width, int height,
int dx, int dy)
  {
 + if (width = 0 || height = 0)
 + return;
 +

The below seems fine, but I wonder if we could make this one cause an
error to be returned later where we can, rather than silently ignoring.
I'm not sure where or how, though.

Surely drivers have maximum size limits, too, those must be catched
somewhere already.

   egl_window-width  = width;
   egl_window-height = height;
   egl_window-dx = dx;
 @@ -24,6 +27,9 @@ wl_egl_window_create(struct wl_surface *surface,
  {
   struct wl_egl_window *egl_window;
  
 + if (width = 0 || height = 0)
 + return NULL;
 +
   egl_window = malloc(sizeof *egl_window);
   if (!egl_window)
   return NULL;

Thanks,
pq
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH] Prevent zero sized wl_egl_window

2014-02-13 Thread Yeh, Sinclair
 The below seems fine, but I wonder if we could make this one cause an
 error to be returned later where we can, rather than silently ignoring.
 I'm not sure where or how, though.

Would it make sense to change wl_egl_window_resize() so that it return a
value?  Either that, or it should be documented somewhere in the API
spec that setting width/height =0 will be ignored.


 
 Surely drivers have maximum size limits, too, those must be catched
 somewhere already.
 
  egl_window-width  = width;
  egl_window-height = height;
  egl_window-dx = dx;
  @@ -24,6 +27,9 @@ wl_egl_window_create(struct wl_surface *surface,
   {
  struct wl_egl_window *egl_window;
   
  +   if (width = 0 || height = 0)
  +   return NULL;
  +
  egl_window = malloc(sizeof *egl_window);
  if (!egl_window)
  return NULL;
 
 Thanks,
 pq
 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/wayland-devel

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput] Add a customizable log handler

2014-02-13 Thread Peter Hutterer
The previous log handler wasn't actually hooked up to anything. Add a public
API for the log handler with priority filtering, defaulting to priority
'error' and stderr as output stream.

And to keep the diff down and convenience up, provide a few simple wrappers
for logging. The generic is log_msg(), but let's use log_info, log_error, etc.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/libinput-private.h |   7 ++
 src/libinput-util.c|  20 --
 src/libinput.c |  62 ++
 src/libinput.h |  76 ++
 src/path.c |   4 +-
 test/Makefile.am   |   7 +-
 test/log.c | 169 +
 7 files changed, 322 insertions(+), 23 deletions(-)
 create mode 100644 test/log.c

diff --git a/src/libinput-private.h b/src/libinput-private.h
index 0d7de90..1fff7de 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -74,6 +74,13 @@ typedef void (*libinput_source_dispatch_t)(void *data);
 
 struct libinput_source;
 
+#define log_debug(...) log_msg(LIBINPUT_LOG_PRIORITY_DEBUG, __VA_ARGS__)
+#define log_info(...) log_msg(LIBINPUT_LOG_PRIORITY_INFO, __VA_ARGS__)
+#define log_error(...) log_msg(LIBINPUT_LOG_PRIORITY_ERROR, __VA_ARGS__)
+
+void
+log_msg(enum libinput_log_priority priority, const char *format, ...);
+
 int
 libinput_init(struct libinput *libinput,
  const struct libinput_interface *interface,
diff --git a/src/libinput-util.c b/src/libinput-util.c
index a3534e1..eeb9786 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -35,26 +35,6 @@
 #include libinput-util.h
 #include libinput-private.h
 
-static FILE *g_log_file = NULL;
-
-void
-set_logging_enabled(int enabled)
-{
-   g_log_file = enabled ? stdout : NULL;
-}
-
-void
-log_info(const char *format, ...)
-{
-   va_list ap;
-
-   if (g_log_file) {
-   va_start(ap, format);
-   vfprintf(g_log_file, format, ap);
-   va_end(ap);
-   }
-}
-
 void
 list_init(struct list *list)
 {
diff --git a/src/libinput.c b/src/libinput.c
index cfce2c5..b4879af 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -78,6 +78,68 @@ struct libinput_event_touch {
 };
 
 static void
+libinput_default_log_func(enum libinput_log_priority priority,
+ void *data,
+ const char *format, va_list args)
+{
+   const char *prefix;
+
+   switch(priority) {
+   case LIBINPUT_LOG_PRIORITY_DEBUG: prefix = debug; break;
+   case LIBINPUT_LOG_PRIORITY_INFO: prefix = info; break;
+   case LIBINPUT_LOG_PRIORITY_ERROR: prefix = error; break;
+   default: prefix=invalid priority; break;
+   }
+
+   fprintf(stderr, libinput %s: , prefix);
+   vfprintf(stderr, format, args);
+}
+
+struct log_data {
+   enum libinput_log_priority priority;
+   libinput_log_handler handler;
+   void *user_data;
+};
+
+static struct log_data log_data = {
+   .priority = LIBINPUT_LOG_PRIORITY_ERROR,
+   .handler = libinput_default_log_func,
+   .user_data = NULL,
+};
+
+void
+log_msg(enum libinput_log_priority priority, const char *format, ...)
+{
+   va_list args;
+
+   if (log_data.handler  log_data.priority = priority) {
+   va_start(args, format);
+   log_data.handler(priority, log_data.user_data, format, args);
+   va_end(args);
+   }
+}
+
+LIBINPUT_EXPORT void
+libinput_log_set_priority(enum libinput_log_priority priority)
+{
+   log_data.priority = priority;
+}
+
+LIBINPUT_EXPORT enum libinput_log_priority
+libinput_log_get_priority(void)
+{
+   return log_data.priority;
+}
+
+LIBINPUT_EXPORT void
+libinput_log_set_handler(libinput_log_handler log_handler,
+void *user_data)
+{
+   log_data.handler = log_handler;
+   log_data.user_data = user_data;
+}
+
+static void
 libinput_post_event(struct libinput *libinput,
struct libinput_event *event);
 
diff --git a/src/libinput.h b/src/libinput.h
index e87b2b7..6bf538a 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -42,6 +42,15 @@
 typedef int32_t li_fixed_t;
 
 /**
+ * Log priority for internal logging messages.
+ */
+enum libinput_log_priority {
+   LIBINPUT_LOG_PRIORITY_DEBUG = 10,
+   LIBINPUT_LOG_PRIORITY_INFO = 20,
+   LIBINPUT_LOG_PRIORITY_ERROR = 30,
+};
+
+/**
  * @ingroup device
  *
  * Capabilities on a device. A device may have one or more capabilities
@@ -875,6 +884,73 @@ void
 libinput_destroy(struct libinput *libinput);
 
 /**
+ * @ingroup base
+ *
+ * Set the global log priority. Messages with priorities equal to or
+ * higher than the argument will be printed to the current log handler.
+ *
+ * The default log priority is LIBINPUT_LOG_PRIORITY_ERROR.
+ *
+ * @param priority The minimum priority of log messages to print.
+ *
+ * @see libinput_log_set_handler
+ */
+void
+libinput_log_set_priority(enum libinput_log_priority 

[RFC v3] Fullscreen shell

2014-02-13 Thread Jason Ekstrand
This RFC is for the third version of my fullscreen shell implementation.
The contents of this RFC are:

* A new wl_fullscreen_shell protocol
* A weston shell that provides wl_fullscreen_shell
* Additions to the Wayland backend for Weston to take advantage of
  wl_fullscreen_shell
* Additions to weston-simple-shm and weston-fullscreen to demonstrate the
  wl_fullscreen_shell protocol.

This RFC improves the second version in a couple of ways:

* Changes the possible presentation modes to allow more options for clients
* Adds support in weston-fullscreen for fully testing wl_fullscreen_shell
* Various bugfixes

The previous version of this RFC can be found here:
http://lists.freedesktop.org/archives/wayland-devel/2013-October/011626.html

The original RFC can be found here:
http://lists.freedesktop.org/archives/wayland-devel/2013-August/010720.html

This RFC is primarily to provide a preview of the implementation, so I am
not going to spam the list with patches.  Instead, you can view it in its
entirety on my github:
https://github.com/jekstrand/weston/tree/fullscreen-shell-RFCv3

Immediately following this e-mail will be a fourth protocol-only RFC that
contains substantial changes to the modesetting portion of the protocol.
Feedback there is appreciated as well.

Thanks,
--Jason Ekstrand


Jason Ekstrand (11):
  Add a fullscreen shell protocol
  Generate/build the fullscreen shell protocol files
  Add a signal for when a seat updates its capabilities
  Add a wl_fullscreen_shell implementation
  simple-shm: Add fullscreen shell support
  toytoolkit: Only require xdg_shell if the window is not custom
  Add wl_fullscreen_shell support to weston-fullscreen
  compositor-wayland: Add support for running on top of
wl_fullscreen_shell
  compositor-wayland: Add a --sprawl option
  Automatically select the wayland backend if WAYLAND_SOCKET is set
  Properly handle running inside a compositor that does not provide
keymaps

 Makefile.am   |  32 +++
 clients/fullscreen.c  |  84 +-
 clients/simple-shm.c  |  31 ++-
 clients/window.c  |   2 +-
 configure.ac  |   8 +
 protocol/fullscreen-shell.xml |  70 +
 src/compositor-wayland.c  | 347 ---
 src/compositor.c  |   3 +-
 src/compositor.h  |   1 +
 src/fullscreen-shell.c| 626 ++
 src/input.c   |   2 +
 11 files changed, 1145 insertions(+), 61 deletions(-)
 create mode 100644 protocol/fullscreen-shell.xml
 create mode 100644 src/fullscreen-shell.c

-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[RFC v4] Fullscreen shell protocol

2014-02-13 Thread Jason Ekstrand
The following is yet another take on the fullscreen shell protocol.
Previous versions more-or-less followed the approach taken in wl_shell.
This version completely reworks the concept.  In particular, the protocol
is split into two use-cases.  The first is that of a simple client that
wants to present a surface or set of surfaces possibly with some scaling.
This happens through the present_surface request which looks similar to
that of wl_shell only without the modesetting.

The second use-case is of a client that wants more control over the
outputs.  In this case, the client uses the present_surface_for_mode
request to present the surface at a particular output mode.  This request
provides a more-or-less atomic modeset operation.  If the compositor can
satisfy the requested mode, then the mode is changed and the new surface is
presented.  Otherwise, the compositor harmlessly falls back to the
previously presented surface and the client is informed that the switch
failed.  This way, the surface is either displayed correctly or not at all.
Of course, a client is free to call present_surface_for_mode with the
currently presented surface and hope for the best.  However, this may
result in strange behavior and there is no reliable fallback if the mode
switch fails.

In particular, I would like feedback on the modesetting portion of this
protocol.  This is particularly targetted at compositors that want to run
inside weston or some other fullscreen compositor.  In the next week or so,
I will attempt to implement all this in weston and see how well it works.
However, I would also like to know how well this will work for other
compositors such as KWin or Hawaii.

Thanks for your feedback,
--Jason Ekstrand

= Protocol follows: =

protocol name=fullscreen_shell
  interface name=wl_fullscreen_shell version=1
description summary=Displays a single surface per output
  Displays a single surface per output.

  This interface provides a mechanism for a single client to display
  simple full-screen surfaces.  While there technically may be multiple
  clients bound to this interface, only one of those clients should be
  shown at a time.

  To present a surface, the client uses either the present_surface or
  present_surface_for_mode requests.  Presenting a surface takes effect
  on the next wl_surface.commit.  See the individual requests for
  details about scaling and mode switches.
  
  The client can have at most one surface per output at any time.
  Requesting a surface be presented on an output that already has a
  surface replaces the previously presented surface.  Presenting a null
  surface removes its content and effectively disables the output.
  Exactly what happens when an output is disabled is
  compositor-specific.  The same surface may be presented multiple
  outputs simultaneously.
/description

enum name=present_method
  description summary=different method to set the surface fullscreen
Hints to indicate to the compositor how to deal with a conflict
between the dimensions of the surface and the dimensions of the
output. The compositor is free to ignore this parameter.
  /description
  entry name=default value=0 summary=no preference, apply default 
policy/
  entry name=center value=1 summary=center the surface on the 
output/
  entry name=zoom value=2 summary=scale the surface, preserving 
aspect ratio, to the largest size that will fit on the output /
  entry name=zoom_crop value=3 summary=scale the surface, preserving 
aspect ratio, to fully fill the output cropping if needed /
  entry name=stretch value=4 summary=scale the surface to the size of 
the output ignoring aspect ratio /
/enum

request name=present_surface
  description summary=present surface for display
Present a surface on the given output.

If the output is null, the compositor will present the surface on
whatever display (or displays) it thinks best.  In particular, this
may replace any or all surfaces currently presented so it should
not be used in combination with placing surfaces on specific
outputs.

The method parameter is a hit to the compositor for how the surface
is to be presented.  In particular, it tells the compostior how to
handle a size mismatch between the presented surface and the
output.  The compositor is free to ignore this parameter.

The zoom, zoom_crop, and stretch methods imply a scaling
operation on the surface.  This will override any kind of output
scaling, so the buffer_scale property of the surface is effectively
ignored.
  /description
  arg name=surface type=object interface=wl_surface/
  arg name=method type=uint/
  arg name=output type=object interface=wl_output allow-null=true/
/request

request 

[PATCH 4/9] compositor: Add output-role_change_signal in clone mode

2014-02-13 Thread Xiong Zhang
When a output change role between master and slave in clone mode,
some work is needed, this signal is used to trigger this work.

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 desktop-shell/shell.c | 13 +
 src/compositor.c  |  1 +
 src/compositor.h  |  1 +
 3 files changed, 15 insertions(+)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 3831804..1e4a255 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -59,6 +59,7 @@ struct focus_state {
 struct shell_output {
struct desktop_shell  *shell;
struct weston_output  *output;
+   struct wl_listenerrole_change_listener;
struct wl_listenerdestroy_listener;
struct wl_listlink;
 };
@@ -5596,11 +5597,17 @@ handle_output_destroy(struct wl_listener *listener, 
void *data)
shell_reposition_views_on_output_destroy(output_listener);
 
wl_list_remove(output_listener-destroy_listener.link);
+   wl_list_remove(output_listener-role_change_listener.link);
wl_list_remove(output_listener-link);
free(output_listener);
 }
 
 static void
+handle_output_role_change(struct wl_listener *listener, void *data)
+{
+}
+
+static void
 create_shell_output(struct desktop_shell *shell,
struct weston_output *output)
 {
@@ -5615,6 +5622,11 @@ create_shell_output(struct desktop_shell *shell,
shell_output-destroy_listener.notify = handle_output_destroy;
wl_signal_add(output-destroy_signal,
  shell_output-destroy_listener);
+
+   shell_output-role_change_listener.notify = handle_output_role_change;
+   wl_signal_add(output-role_change_signal,
+ shell_output-role_change_listener);
+
wl_list_insert(shell-output_list.prev, shell_output-link);
 }
 
@@ -5697,6 +5709,7 @@ shell_destroy(struct wl_listener *listener, void *data)
 
wl_list_for_each_safe(shell_output, tmp, shell-output_list, link) {
wl_list_remove(shell_output-destroy_listener.link);
+   wl_list_remove(shell_output-role_change_listener.link);
wl_list_remove(shell_output-link);
free(shell_output);
}
diff --git a/src/compositor.c b/src/compositor.c
index 2c30334..5c0f67d 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -3283,6 +3283,7 @@ weston_output_init(struct weston_output *output, struct 
weston_compositor *c,
wl_signal_init(output-destroy_signal);
wl_list_init(output-animation_list);
wl_list_init(output-resource_list);
+   wl_signal_init(output-role_change_signal);
 
output-id = ffs(~output-compositor-output_id_pool) - 1;
output-compositor-output_id_pool |= 1  output-id;
diff --git a/src/compositor.h b/src/compositor.h
index 549d83d..0938078 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -216,6 +216,7 @@ struct weston_output {
char *master_output_name;
struct weston_output *master_output;
struct wl_list clone_output_list;
+   struct wl_signal role_change_signal;
 
void (*start_repaint_loop)(struct weston_output *output);
int (*repaint)(struct weston_output *output,
-- 
1.8.3.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH 5/9] compositor: Output unplug in clone mode

2014-02-13 Thread Xiong Zhang
If unplugged output is a slave output, no need to restore views.

If unplugged output is a master output which doesn't have slave
output related it, views will be restored the same as extend mode.

If unplugged output is a master output which have slave output
related it, one slave output will be upgraded to master output,
moving output following unplugged output isn't necessay,
views on unplugged output will be marked as dirty.

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 desktop-shell/shell.c |  13 ++-
 src/compositor-drm.c  | 103 +++---
 src/compositor.c  |  15 ++--
 src/compositor.h  |   1 +
 4 files changed, 122 insertions(+), 10 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 1e4a255..85987e5 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -5600,6 +5600,9 @@ handle_output_destroy(struct wl_listener *listener, void 
*data)
wl_list_remove(output_listener-role_change_listener.link);
wl_list_remove(output_listener-link);
free(output_listener);
+
+   /* Trigger compositor repaint */
+   weston_compositor_schedule_repaint(output_listener-output-compositor);
 }
 
 static void
@@ -5676,10 +5679,18 @@ setup_output_destroy_handler(struct weston_compositor 
*ec,
struct desktop_shell 
*shell)
 {
struct weston_output *output;
+   struct weston_output *clone_output;
 
wl_list_init(shell-output_list);
-   wl_list_for_each(output, ec-output_list, link)
+   wl_list_for_each(output, ec-output_list, link) {
create_shell_output(shell, output);
+   if (!output-is_slave) {
+   wl_list_for_each(clone_output,
+output-clone_output_list,
+link)
+   create_shell_output(shell, clone_output);
+   }
+   }
 
shell-output_create_listener.notify = handle_output_create;
wl_signal_add(ec-output_created_signal,
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 1d8c983..842710f 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -1217,6 +1217,8 @@ drm_assign_planes(struct weston_output *output)
 
 static void
 drm_output_fini_pixman(struct drm_output *output);
+static void
+drm_output_destroy_with_slave(struct drm_output *output);
 
 static void
 drm_output_destroy(struct weston_output *output_base)
@@ -1259,6 +1261,15 @@ drm_output_destroy(struct weston_output *output_base)
weston_plane_release(output-fb_plane);
weston_plane_release(output-cursor_plane);
 
+   if (!output-base.is_slave 
+   !wl_list_empty(output-base.clone_output_list)) {
+   drm_output_destroy_with_slave(output);
+
+   /* One slave is upgraded to master, Don't move
+* the following output.*/
+   output_base.dont_move = 1;
+   }
+
weston_output_destroy(output-base);
 
free(output);
@@ -2420,6 +2431,73 @@ drm_output_add_slave(struct drm_compositor *ec)
}
 }
 
+/* The output with max width will be new_master. */
+static struct weston_output *
+find_new_master(struct weston_output *master)
+{
+   struct weston_output *new_master, *output;
+   int32_t max_width = 0;
+
+   new_master = NULL;
+   wl_list_for_each(output, master-clone_output_list,
+link) {
+   if (output-current_mode-width  max_width) {
+   max_width = output-current_mode-width;
+   new_master = output;
+   }
+   }
+
+   return new_master;
+}
+
+/* If a master is unplugged, a output will be chosen from
+ * master-clone_output_list to replace the unplugged master.*/
+static void
+drm_output_destroy_with_slave(struct drm_output *output)
+{
+   struct weston_output *new_master, *tmp;
+   struct drm_output *clone_output, *next;
+   intoffset, move;
+
+   new_master = find_new_master(output-base);
+
+   /* When old master's width is different from new master's
+* width, move the output following the old master. */
+   offset = output-base.width - new_master-width;
+   if (offset != 0) {
+   move = 0;
+   wl_list_for_each(tmp, new_master-compositor-output_list,
+link) {
+   if (move == 1)
+   weston_output_move(tmp,
+   tmp-x - offset, tmp-y);
+
+   if (tmp == output-base)
+   move = 1;
+   }
+   }
+
+   wl_list_remove(new_master-link);
+   wl_list_insert(output-base.link.prev,
+  new_master-link);
+   new_master-is_slave = 0;
+
+   /* Link the remained clone output to new 

[PATCH 2/9] compositor: Output repaint in clone mode

2014-02-13 Thread Xiong Zhang
Because slave output doesn't in compositor-output_list,
the output-repaint()is called from master output only.
When master output repaint,all the slave output should
repaint also.

Slave output share fb with master output,when both slave and
master have finished page flip, the fb obj can be released.

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 src/compositor-drm.c | 112 ++-
 src/compositor.c |   3 +-
 2 files changed, 112 insertions(+), 3 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 6773226..ce85aec 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -155,6 +155,7 @@ struct drm_output {
 
uint32_t transform;
int scale, mm_width, mm_height;
+   uint32_t page_flip_count;
 
struct gbm_surface *surface;
struct gbm_bo *cursor_bo[2];
@@ -591,8 +592,9 @@ drm_output_repaint(struct weston_output *output_base,
struct drm_sprite *s;
struct drm_mode *mode;
int ret = 0;
+   struct drm_output *clone_output;
 
-   if (output-destroy_pending)
+   if (output-destroy_pending || output-base.is_slave)
return -1;
 
if (!output-next)
@@ -612,6 +614,25 @@ drm_output_repaint(struct weston_output *output_base,
goto err_pageflip;
}
output_base-set_dpms(output_base, WESTON_DPMS_ON);
+
+   wl_list_for_each(clone_output, output-base.clone_output_list,
+base.link) {
+   mode = container_of(clone_output-base.current_mode,
+   struct drm_mode, base);
+
+   ret = drmModeSetCrtc(compositor-drm.fd,
+clone_output-crtc_id,
+output-next-fb_id, 0, 0,
+clone_output-connector_id, 1,
+mode-mode_info);
+   if (ret) {
+   weston_log(set mode failed:%m\n);
+   goto err_pageflip;
+   }
+
+   clone_output-base.set_dpms(clone_output-base,
+   WESTON_DPMS_ON);
+   }
}
 
if (drmModePageFlip(compositor-drm.fd, output-crtc_id,
@@ -622,6 +643,23 @@ drm_output_repaint(struct weston_output *output_base,
}
 
output-page_flip_pending = 1;
+   output-page_flip_count++;
+
+   /* clone output repaint*/
+   wl_list_for_each(clone_output, output-base.clone_output_list,
+base.link) {
+   if (drmModePageFlip(compositor-drm.fd,
+   clone_output-crtc_id,
+   output-next-fb_id,
+   DRM_MODE_PAGE_FLIP_EVENT,
+   clone_output)  0) {
+   weston_log(queueing pageflip failed:%m\n);
+   goto err_pageflip;
+   }
+
+   clone_output-page_flip_pending = 1;
+   output-page_flip_count++;
+   }
 
drm_output_set_cursor(output);
 
@@ -691,8 +729,9 @@ drm_output_start_repaint_loop(struct weston_output 
*output_base)
uint32_t fb_id;
uint32_t msec;
struct timespec ts;
+   struct drm_output *clone_output;
 
-   if (output-destroy_pending)
+   if (output-destroy_pending || output-base.is_slave)
return;
 
if (!output-current) {
@@ -707,6 +746,22 @@ drm_output_start_repaint_loop(struct weston_output 
*output_base)
weston_log(queueing pageflip failed: %m\n);
goto finish_frame;
}
+   output-page_flip_count++;
+
+   /* clone output repaint*/
+   wl_list_for_each(clone_output, output-base.clone_output_list,
+base.link) {
+   if (drmModePageFlip(compositor-drm.fd,
+   clone_output-crtc_id,
+   fb_id,
+   DRM_MODE_PAGE_FLIP_EVENT,
+   clone_output)  0) {
+   weston_log(queueing pageflip failed:%m\n);
+   goto finish_frame;
+   }
+
+   output-page_flip_count++;
+   }
 
return;
 
@@ -745,8 +800,22 @@ page_flip_handler(int fd, unsigned int frame,
  unsigned int sec, unsigned int usec, void *data)
 {
struct drm_output *output = (struct drm_output *) data;
+   struct drm_output *master_output;
uint32_t msecs;
 
+   if (output-base.is_slave) {
+   master_output = (struct drm_output *)output-base.master_output;
+   master_output-page_flip_count--;
+   

[PATCH 1/9] compositor-drm: Add per connector clone mode support

2014-02-13 Thread Xiong Zhang
Add a clone option in output section of weston.ini

Master output will be in compositor-output_list.
Slave output won't be in compositor-output_list, while it is in
master-clone_output_list.

Slave output's current mode size should be smaller than master
output's mode size, or else the mode setting for slave output
will fail. So slave output's mode will be adjusted when it is
necessary.

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 src/compositor-drm.c | 189 ---
 src/compositor.c |  15 +++-
 src/compositor.h |   5 ++
 weston.ini.in|   2 +
 4 files changed, 185 insertions(+), 26 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index e45f47d..6773226 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -87,6 +87,7 @@ struct drm_compositor {
uint32_t connector_allocator;
struct wl_listener session_listener;
uint32_t format;
+   struct wl_list clone_output_list;
 
/* we need these parameters in order to not fail drmModeAddFB2()
 * due to out of bounds dimensions, and then mistakenly set
@@ -152,6 +153,9 @@ struct drm_output {
int page_flip_pending;
int destroy_pending;
 
+   uint32_t transform;
+   int scale, mm_width, mm_height;
+
struct gbm_surface *surface;
struct gbm_bo *cursor_bo[2];
struct weston_plane cursor_plane;
@@ -1856,7 +1860,7 @@ static int
 create_output_for_connector(struct drm_compositor *ec,
drmModeRes *resources,
drmModeConnector *connector,
-   int x, int y, struct udev_device *drm_device)
+   struct udev_device *drm_device)
 {
struct drm_output *output;
struct drm_mode *drm_mode, *next, *preferred, *current, *configured, 
*best;
@@ -1870,6 +1874,8 @@ create_output_for_connector(struct drm_compositor *ec,
const char *type_name;
enum output_config config;
uint32_t transform;
+   int x, y;
+   struct weston_output *prev = NULL;
 
i = find_crtc_for_connector(ec, resources, connector);
if (i  0) {
@@ -1923,6 +1929,14 @@ create_output_for_connector(struct drm_compositor *ec,
setup_output_seat_constraint(ec, output-base, s);
free(s);
 
+   weston_config_section_get_string(section, clone, s, );
+   if (strcmp(s, ) != 0) {
+   output-base.is_slave = 1;
+   output-base.master_output_name = strdup(s);
+   }
+   wl_list_init(output-base.clone_output_list);
+   free(s);
+
output-crtc_id = resources-crtcs[i];
output-pipe = i;
ec-crtc_allocator |= (1  output-crtc_id);
@@ -2009,9 +2023,27 @@ create_output_for_connector(struct drm_compositor *ec,
 
output-base.current_mode-flags |= WL_OUTPUT_MODE_CURRENT;
 
-   weston_output_init(output-base, ec-base, x, y,
-  connector-mmWidth, connector-mmHeight,
-  transform, scale);
+   if (!output-base.is_slave) {
+   if (wl_list_empty(ec-base.output_list))
+   x = 0;
+   else {
+   prev = container_of(ec-base.output_list.prev,
+ struct weston_output,
+ link);
+   x = prev-x + prev-width;
+   }
+   y = 0;
+
+   weston_output_init(output-base, ec-base, x, y,
+  connector-mmWidth, connector-mmHeight,
+  transform, scale);
+   } else {
+   output-base.compositor = ec-base;
+   output-transform = transform;
+   output-scale = scale;
+   output-mm_width = connector-mmWidth;
+   output-mm_height = connector-mmHeight;
+   }
 
if (ec-use_pixman) {
if (drm_output_init_pixman(output, ec)  0) {
@@ -2034,7 +2066,10 @@ create_output_for_connector(struct drm_compositor *ec,
weston_log(Failed to initialize backlight\n);
}
 
-   wl_list_insert(ec-base.output_list.prev, output-base.link);
+   if (!output-base.is_slave)
+   wl_list_insert(ec-base.output_list.prev, output-base.link);
+   else
+   wl_list_insert(ec-clone_output_list.prev, output-base.link);
 
find_and_parse_output_edid(ec, output, connector);
if (connector-connector_type == DRM_MODE_CONNECTOR_LVDS)
@@ -2157,6 +2192,126 @@ destroy_sprites(struct drm_compositor *compositor)
}
 }
 
+/* Because slave and master output share the same frame buffer which
+ * is assigned according to master output's mode. If clone output's mode
+ * is larger than frame buffer's size, the mode setting for clone
+ * output will fail. Choosing a nearest mode below master output's mode */
+static int

[PATCH 3/9] compositor-drm: Deal with VT switch in clone mode

2014-02-13 Thread Xiong Zhang
When system do VT switch, slave output should use master
output's fb to restore mode.

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 src/compositor-drm.c | 38 +-
 1 file changed, 37 insertions(+), 1 deletion(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index ce85aec..1d8c983 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -2608,6 +2608,7 @@ drm_compositor_set_modes(struct drm_compositor 
*compositor)
struct drm_output *output;
struct drm_mode *drm_mode;
int ret;
+   struct drm_output *clone_output;
 
wl_list_for_each(output, compositor-base.output_list, base.link) {
if (!output-current) {
@@ -2628,9 +2629,33 @@ drm_compositor_set_modes(struct drm_compositor 
*compositor)
if (ret  0) {
weston_log(
failed to set mode %dx%d for output at %d,%d: 
%m\n,
-   drm_mode-base.width, drm_mode-base.height, 
+   drm_mode-base.width, drm_mode-base.height,
output-base.x, output-base.y);
}
+
+   if (!output-base.is_slave) {
+   wl_list_for_each(clone_output,
+output-base.clone_output_list,
+base.link) {
+   drm_mode = (struct drm_mode *)
+   clone_output-base.current_mode;
+   ret = drmModeSetCrtc(compositor-drm.fd,
+clone_output-crtc_id,
+output-current-fb_id,
+0, 0,
+
clone_output-connector_id,
+1,
+drm_mode-mode_info);
+   if (ret  0) {
+   weston_log(failed to set mode %dx%d
+   for output at %d,%d: %m\n,
+   drm_mode-base.width,
+   drm_mode-base.height,
+   clone_output-base.x,
+   clone_output-base.y);
+   }
+   }
+   }
}
 }
 
@@ -2641,6 +2666,7 @@ session_notify(struct wl_listener *listener, void *data)
struct drm_compositor *ec = data;
struct drm_sprite *sprite;
struct drm_output *output;
+   struct drm_output *clone_output;
 
if (ec-base.session_active) {
weston_log(activating session\n);
@@ -2666,6 +2692,16 @@ session_notify(struct wl_listener *listener, void *data)
wl_list_for_each(output, ec-base.output_list, base.link) {
output-base.repaint_needed = 0;
drmModeSetCursor(ec-drm.fd, output-crtc_id, 0, 0, 0);
+
+   if (!output-base.is_slave) {
+   wl_list_for_each(clone_output,
+
output-base.clone_output_list,
+base.link) {
+   drmModeSetCursor(ec-drm.fd,
+clone_output-crtc_id,
+0, 0, 0);
+   }
+   }
}
 
output = container_of(ec-base.output_list.next,
-- 
1.8.3.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH 6/9] compositor-drm: Abstract drm_output_set_mode()

2014-02-13 Thread Xiong Zhang
Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 src/compositor-drm.c | 81 +++-
 1 file changed, 29 insertions(+), 52 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 842710f..836f81d 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -583,6 +583,27 @@ drm_output_set_gamma(struct weston_output *output_base,
 }
 
 static int
+drm_output_set_mode(struct drm_output *output,
+   uint32_t fb_id)
+{
+   struct drm_compositor *compositor =
+   (struct drm_compositor *)output-base.compositor;
+   struct drm_mode *mode;
+   int ret = 0;
+
+   mode = container_of(output-base.current_mode,
+   struct drm_mode, base);
+   ret = drmModeSetCrtc(compositor-drm.fd, output-crtc_id,
+fb_id, 0, 0,
+output-connector_id, 1,
+mode-mode_info);
+   if (ret)
+   weston_log(set mode failed:%m\n);
+
+   return ret;
+}
+
+static int
 drm_output_repaint(struct weston_output *output_base,
   pixman_region32_t *damage)
 {
@@ -590,7 +611,6 @@ drm_output_repaint(struct weston_output *output_base,
struct drm_compositor *compositor =
(struct drm_compositor *) output-base.compositor;
struct drm_sprite *s;
-   struct drm_mode *mode;
int ret = 0;
struct drm_output *clone_output;
 
@@ -602,33 +622,18 @@ drm_output_repaint(struct weston_output *output_base,
if (!output-next)
return -1;
 
-   mode = container_of(output-base.current_mode, struct drm_mode, base);
if (!output-current ||
output-current-stride != output-next-stride) {
-   ret = drmModeSetCrtc(compositor-drm.fd, output-crtc_id,
-output-next-fb_id, 0, 0,
-output-connector_id, 1,
-mode-mode_info);
-   if (ret) {
-   weston_log(set mode failed: %m\n);
+   if (drm_output_set_mode(output, output-next-fb_id))
goto err_pageflip;
-   }
+
output_base-set_dpms(output_base, WESTON_DPMS_ON);
 
wl_list_for_each(clone_output, output-base.clone_output_list,
 base.link) {
-   mode = container_of(clone_output-base.current_mode,
-   struct drm_mode, base);
-
-   ret = drmModeSetCrtc(compositor-drm.fd,
-clone_output-crtc_id,
-output-next-fb_id, 0, 0,
-clone_output-connector_id, 1,
-mode-mode_info);
-   if (ret) {
-   weston_log(set mode failed:%m\n);
+   if (drm_output_set_mode(clone_output,
+   output-next-fb_id))
goto err_pageflip;
-   }
 
clone_output-base.set_dpms(clone_output-base,
WESTON_DPMS_ON);
@@ -2699,8 +2704,6 @@ static void
 drm_compositor_set_modes(struct drm_compositor *compositor)
 {
struct drm_output *output;
-   struct drm_mode *drm_mode;
-   int ret;
struct drm_output *clone_output;
 
wl_list_for_each(output, compositor-base.output_list, base.link) {
@@ -2714,40 +2717,14 @@ drm_compositor_set_modes(struct drm_compositor 
*compositor)
continue;
}
 
-   drm_mode = (struct drm_mode *) output-base.current_mode;
-   ret = drmModeSetCrtc(compositor-drm.fd, output-crtc_id,
-output-current-fb_id, 0, 0,
-output-connector_id, 1,
-drm_mode-mode_info);
-   if (ret  0) {
-   weston_log(
-   failed to set mode %dx%d for output at %d,%d: 
%m\n,
-   drm_mode-base.width, drm_mode-base.height,
-   output-base.x, output-base.y);
-   }
+   drm_output_set_mode(output, output-current-fb_id);
 
if (!output-base.is_slave) {
wl_list_for_each(clone_output,
 output-base.clone_output_list,
-base.link) {
-   drm_mode = (struct drm_mode *)
-   clone_output-base.current_mode;
-   ret = drmModeSetCrtc(compositor-drm.fd,
- 

[PATCH 9/9] shell: set_fullscreen and set_maximized in clone mode

2014-02-13 Thread Xiong Zhang
if the assigned output is slave, change the assigned output to
associated master output

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 desktop-shell/shell.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 2bc1856..0edefbd 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -2372,8 +2372,11 @@ shell_surface_set_fullscreen(struct wl_client *client,
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
struct weston_output *output;
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
+   if (output-is_slave)
+   output = output-master_output;
+   }
else
output = NULL;
 
@@ -2477,9 +2480,11 @@ shell_surface_set_maximized(struct wl_client *client,
struct shell_surface *shsurf = wl_resource_get_user_data(resource);
struct weston_output *output;
 
-   if (output_resource)
+   if (output_resource) {
output = wl_resource_get_user_data(output_resource);
-   else
+   if (output-is_slave)
+   output = output-master_output;
+   } else
output = NULL;
 
shell_surface_set_parent(shsurf, NULL);
-- 
1.8.3.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH 7/9] compositor: Hot plug a output in clone mode

2014-02-13 Thread Xiong Zhang
If adding output is a slave output, this slave output share the fb
with master output.

If adding output is a master output, loop the output_list to find
its slave output. If it has slave output, this slave output will
change role from master to slave.

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 clients/desktop-shell.c |   2 +
 desktop-shell/shell.c   |  26 +++
 src/compositor-drm.c| 120 +++-
 3 files changed, 147 insertions(+), 1 deletion(-)

diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
index a0c6b6d..3389ad5 100644
--- a/clients/desktop-shell.c
+++ b/clients/desktop-shell.c
@@ -1232,6 +1232,8 @@ create_output(struct desktop *desktop, uint32_t id)
 * in which case we can't create the panel and background just yet */
if (desktop-shell)
output_init(output, desktop);
+
+   desktop-painted = 0;
 }
 
 static void
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 85987e5..096d618 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -59,6 +59,7 @@ struct focus_state {
 struct shell_output {
struct desktop_shell  *shell;
struct weston_output  *output;
+   uint32_t mark_dirty;
struct wl_listenerrole_change_listener;
struct wl_listenerdestroy_listener;
struct wl_listlink;
@@ -3853,12 +3854,24 @@ desktop_shell_set_grab_surface(struct wl_client *client,
 }
 
 static void
+shell_reposition_views_on_output_destroy(struct shell_output *shell_output);
+
+static void
 desktop_shell_desktop_ready(struct wl_client *client,
struct wl_resource *resource)
 {
struct desktop_shell *shell = wl_resource_get_user_data(resource);
+   struct shell_output *shell_output;
 
shell_fade_startup(shell);
+
+   wl_list_for_each(shell_output, shell-output_list, link) {
+   if (shell_output-mark_dirty == 0)
+   continue;
+
+   shell_reposition_views_on_output_destroy(shell_output);
+   shell_output-mark_dirty = 0;
+   }
 }
 
 static const struct desktop_shell_interface desktop_shell_implementation = {
@@ -5608,6 +5621,19 @@ handle_output_destroy(struct wl_listener *listener, void 
*data)
 static void
 handle_output_role_change(struct wl_listener *listener, void *data)
 {
+   struct shell_output *shell_output =
+   container_of(listener, struct shell_output,
+role_change_listener);
+   struct weston_output *output = (struct weston_output *)data;
+
+   /* Output change from master to slave. */
+   if (output-is_slave)
+   /* Mark views on this old master as dirty.
+* But we will use new master as target output,
+* At this point, new master doesn't have panel view
+* and background view. So the desktop shell doesn't ready.
+* So we delay the mark dirty work until desktop shell ready. */
+   shell_output-mark_dirty = 1;
 }
 
 static void
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 836f81d..037c142 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -809,6 +809,13 @@ page_flip_handler(int fd, unsigned int frame,
uint32_t msecs;
 
if (output-base.is_slave) {
+   /* This is a delayed page flip event, after this output
+* changed from master to slave. */
+   if (output-page_flip_count) {
+   output-page_flip_count--;
+   goto finish_frame;
+   }
+
master_output = (struct drm_output *)output-base.master_output;
master_output-page_flip_count--;
output-page_flip_pending = 0;
@@ -832,6 +839,7 @@ page_flip_handler(int fd, unsigned int frame,
 
output-page_flip_pending = 0;
 
+finish_frame:
if (output-destroy_pending)
drm_output_destroy(output-base);
else if (!output-vblank_pending) {
@@ -2409,6 +2417,10 @@ drm_output_add_slave(struct drm_compositor *ec)
found = 1;

wl_list_insert(master_output-base.clone_output_list.prev,
   clone_output-base.link);
+
+   if (master_output-current)
+   drm_output_set_mode(clone_output,
+   master_output-current-fb_id);
}
 
break;
@@ -2503,6 +2515,105 @@ drm_output_destroy_with_slave(struct drm_output *output)
wl_signal_emit(new_master-role_change_signal, new_master);
 }
 
+/* First a slave output is discoveryed but associated master isn't found
+ * this slave output will be upgraded to master output;
+ * Second the master output is hot plugged, the original slave output
+ * 

[PATCH 8/9] compositor: Handle background and panel surface in clone mode

2014-02-13 Thread Xiong Zhang
The background and panel view of slave output can't exist on
layer_list and view_list, otherwise panel is mess.

When unplugging a master, one slave may become master, the slave's
background and panel view should be moved to view_list.

When plugging a master, one old master may become slave, the old
master's background and panel view should be removed from view_list

Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
---
 desktop-shell/shell.c | 70 +--
 1 file changed, 57 insertions(+), 13 deletions(-)

diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index 096d618..2bc1856 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -60,6 +60,8 @@ struct shell_output {
struct desktop_shell  *shell;
struct weston_output  *output;
uint32_t mark_dirty;
+   struct weston_view*panel_view;
+   struct weston_view*background_view;
struct wl_listenerrole_change_listener;
struct wl_listenerdestroy_listener;
struct wl_listlink;
@@ -2066,15 +2068,16 @@ static int
 get_output_panel_height(struct desktop_shell *shell,
struct weston_output *output)
 {
-   struct weston_view *view;
+   struct shell_output *shell_output;
int panel_height = 0;
 
if (!output)
return 0;
 
-   wl_list_for_each(view, shell-panel_layer.view_list, layer_link) {
-   if (view-surface-output == output) {
-   panel_height = view-surface-height;
+   wl_list_for_each(shell_output, shell-output_list, link) {
+   if (shell_output-output == output) {
+   panel_height =
+   shell_output-panel_view-surface-height;
break;
}
}
@@ -3654,7 +3657,8 @@ configure_static_view(struct weston_view *ev, struct 
weston_layer *layer)
 
weston_view_set_position(ev, ev-output-x, ev-output-y);
 
-   if (wl_list_empty(ev-layer_link)) {
+   if (wl_list_empty(ev-layer_link) 
+   !ev-output-is_slave) {
wl_list_insert(layer-view_list, ev-layer_link);
weston_compositor_schedule_repaint(ev-surface-compositor);
}
@@ -3681,6 +3685,7 @@ desktop_shell_set_background(struct wl_client *client,
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
struct weston_view *view, *next;
+   struct shell_output *shell_output;
 
if (surface-configure) {
wl_resource_post_error(surface_resource,
@@ -3697,6 +3702,12 @@ desktop_shell_set_background(struct wl_client *client,
surface-configure_private = shell;
surface-output = wl_resource_get_user_data(output_resource);
view-output = surface-output;
+
+   wl_list_for_each(shell_output, shell-output_list, link) {
+   if (shell_output-output == view-output)
+   shell_output-background_view = view;
+   }
+
desktop_shell_send_configure(resource, 0,
 surface_resource,
 surface-output-width,
@@ -3724,6 +3735,7 @@ desktop_shell_set_panel(struct wl_client *client,
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
struct weston_view *view, *next;
+   struct shell_output *shell_output;
 
if (surface-configure) {
wl_resource_post_error(surface_resource,
@@ -3740,6 +3752,12 @@ desktop_shell_set_panel(struct wl_client *client,
surface-configure_private = shell;
surface-output = wl_resource_get_user_data(output_resource);
view-output = surface-output;
+
+   wl_list_for_each(shell_output, shell-output_list, link) {
+   if (shell_output-output == view-output)
+   shell_output-panel_view = view;
+   }
+
desktop_shell_send_configure(resource, 0,
 surface_resource,
 surface-output-width,
@@ -5625,15 +5643,30 @@ handle_output_role_change(struct wl_listener *listener, 
void *data)
container_of(listener, struct shell_output,
 role_change_listener);
struct weston_output *output = (struct weston_output *)data;
+   struct desktop_shell *shell = shell_output-shell;
 
/* Output change from master to slave. */
-   if (output-is_slave)
+   if (output-is_slave) {
+   wl_list_remove(shell_output-background_view-layer_link);
+   wl_list_init(shell_output-background_view-layer_link);
+   wl_list_remove(shell_output-panel_view-layer_link);
+   wl_list_init(shell_output-panel_view-layer_link);
+
/* Mark views on this old master as dirty.
 * But we will use new master as 

Re: [RFC v4] Fullscreen shell protocol

2014-02-13 Thread Pekka Paalanen
Hi Jason

On Thu, 13 Feb 2014 22:37:53 -0600
Jason Ekstrand ja...@jlekstrand.net wrote:

 The following is yet another take on the fullscreen shell protocol.
 Previous versions more-or-less followed the approach taken in wl_shell.
 This version completely reworks the concept.  In particular, the protocol
 is split into two use-cases.  The first is that of a simple client that
 wants to present a surface or set of surfaces possibly with some scaling.
 This happens through the present_surface request which looks similar to
 that of wl_shell only without the modesetting.
 
 The second use-case is of a client that wants more control over the
 outputs.  In this case, the client uses the present_surface_for_mode
 request to present the surface at a particular output mode.  This request
 provides a more-or-less atomic modeset operation.  If the compositor can
 satisfy the requested mode, then the mode is changed and the new surface is
 presented.  Otherwise, the compositor harmlessly falls back to the
 previously presented surface and the client is informed that the switch
 failed.  This way, the surface is either displayed correctly or not at all.
 Of course, a client is free to call present_surface_for_mode with the
 currently presented surface and hope for the best.  However, this may
 result in strange behavior and there is no reliable fallback if the mode
 switch fails.
 
 In particular, I would like feedback on the modesetting portion of this
 protocol.  This is particularly targetted at compositors that want to run
 inside weston or some other fullscreen compositor.  In the next week or so,
 I will attempt to implement all this in weston and see how well it works.
 However, I would also like to know how well this will work for other
 compositors such as KWin or Hawaii.
 
 Thanks for your feedback,
 --Jason Ekstrand
 
 = Protocol follows: =
 
 protocol name=fullscreen_shell
   interface name=wl_fullscreen_shell version=1

This interface should have a destructor request IMO. It's not stricly
required, but I think it would be consistent (I think all global
interfaces need an explicit destructor request) and more future-proof.

 description summary=Displays a single surface per output
   Displays a single surface per output.
 
   This interface provides a mechanism for a single client to display
   simple full-screen surfaces.  While there technically may be multiple
   clients bound to this interface, only one of those clients should be
   shown at a time.
 
   To present a surface, the client uses either the present_surface or
   present_surface_for_mode requests.  Presenting a surface takes effect
   on the next wl_surface.commit.  See the individual requests for
   details about scaling and mode switches.
   
   The client can have at most one surface per output at any time.
   Requesting a surface be presented on an output that already has a
   surface replaces the previously presented surface.  Presenting a null
   surface removes its content and effectively disables the output.
   Exactly what happens when an output is disabled is
   compositor-specific.  The same surface may be presented multiple
   outputs simultaneously.

If the same surface is presented on multiple outputs, should the client
have a way to say which output is to be considered the surface's main
output, where e.g. presentation feedback is synced to?

Maybe also note explicitly, that once a surface has been presented on
an output, it stays on that output until explicitly removed, or output
is unplugged? So that simple attach+damage+commit can be used to update
the content, if that is the intention.

 /description
 
 enum name=present_method
   description summary=different method to set the surface fullscreen
   Hints to indicate to the compositor how to deal with a conflict
   between the dimensions of the surface and the dimensions of the
   output. The compositor is free to ignore this parameter.
   /description
   entry name=default value=0 summary=no preference, apply default 
 policy/
   entry name=center value=1 summary=center the surface on the 
 output/
   entry name=zoom value=2 summary=scale the surface, preserving 
 aspect ratio, to the largest size that will fit on the output /
   entry name=zoom_crop value=3 summary=scale the surface, 
 preserving aspect ratio, to fully fill the output cropping if needed /
   entry name=stretch value=4 summary=scale the surface to the size 
 of the output ignoring aspect ratio /
 /enum
 
 request name=present_surface
   description summary=present surface for display
   Present a surface on the given output.
 
   If the output is null, the compositor will present the surface on
   whatever display (or displays) it thinks best.  In particular, this
   may replace any or all surfaces currently presented so it should
   not be used 

Re: [PATCH 2/9] compositor: Output repaint in clone mode

2014-02-13 Thread Pekka Paalanen
On Fri, 14 Feb 2014 15:17:37 +0800
Xiong Zhang xiong.y.zh...@intel.com wrote:

 Because slave output doesn't in compositor-output_list,
 the output-repaint()is called from master output only.
 When master output repaint,all the slave output should
 repaint also.
 
 Slave output share fb with master output,when both slave and
 master have finished page flip, the fb obj can be released.

Hi,

ok, so core's finish_frame will be called when all flips of a master
output and its slaves have completed. If the refresh rates of these
outputs are different, I think it means that the perceived frame rate
(the frequency at which finish_frame is called) will fluctuate over
time. That will have very interesting consequences for presentation
prediction and feedback.

OTOH, the future will bring dynamically varied refresh rate monitors,
so client's should be prepared for fluctuations in the apparent vblank
frequency anyway.

I'm not claiming your patch creates a problem, I think we can cope with
it, but it will be interesting nevertheless. Just pointing out we
should keep this in mind.

We may need to tweak finish_frame calling logic a bit, so that it gets
the flip completion timestamp of the master output, and not whatever
output was the last one. But that will only be a concern when the
presentation extension lands. I think... unless we care about the
timestamp carried by the frame callbacks.


Thanks,
pq


 Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
 ---
  src/compositor-drm.c | 112 
 ++-
  src/compositor.c |   3 +-
  2 files changed, 112 insertions(+), 3 deletions(-)
 
 diff --git a/src/compositor-drm.c b/src/compositor-drm.c
 index 6773226..ce85aec 100644
 --- a/src/compositor-drm.c
 +++ b/src/compositor-drm.c
 @@ -155,6 +155,7 @@ struct drm_output {
  
   uint32_t transform;
   int scale, mm_width, mm_height;
 + uint32_t page_flip_count;
  
   struct gbm_surface *surface;
   struct gbm_bo *cursor_bo[2];
 @@ -591,8 +592,9 @@ drm_output_repaint(struct weston_output *output_base,
   struct drm_sprite *s;
   struct drm_mode *mode;
   int ret = 0;
 + struct drm_output *clone_output;
  
 - if (output-destroy_pending)
 + if (output-destroy_pending || output-base.is_slave)
   return -1;
  
   if (!output-next)
 @@ -612,6 +614,25 @@ drm_output_repaint(struct weston_output *output_base,
   goto err_pageflip;
   }
   output_base-set_dpms(output_base, WESTON_DPMS_ON);
 +
 + wl_list_for_each(clone_output, output-base.clone_output_list,
 +  base.link) {
 + mode = container_of(clone_output-base.current_mode,
 + struct drm_mode, base);
 +
 + ret = drmModeSetCrtc(compositor-drm.fd,
 +  clone_output-crtc_id,
 +  output-next-fb_id, 0, 0,
 +  clone_output-connector_id, 1,
 +  mode-mode_info);
 + if (ret) {
 + weston_log(set mode failed:%m\n);
 + goto err_pageflip;
 + }
 +
 + clone_output-base.set_dpms(clone_output-base,
 + WESTON_DPMS_ON);
 + }
   }
  
   if (drmModePageFlip(compositor-drm.fd, output-crtc_id,
 @@ -622,6 +643,23 @@ drm_output_repaint(struct weston_output *output_base,
   }
  
   output-page_flip_pending = 1;
 + output-page_flip_count++;
 +
 + /* clone output repaint*/
 + wl_list_for_each(clone_output, output-base.clone_output_list,
 +  base.link) {
 + if (drmModePageFlip(compositor-drm.fd,
 + clone_output-crtc_id,
 + output-next-fb_id,
 + DRM_MODE_PAGE_FLIP_EVENT,
 + clone_output)  0) {
 + weston_log(queueing pageflip failed:%m\n);
 + goto err_pageflip;
 + }
 +
 + clone_output-page_flip_pending = 1;
 + output-page_flip_count++;
 + }
  
   drm_output_set_cursor(output);
  
 @@ -691,8 +729,9 @@ drm_output_start_repaint_loop(struct weston_output 
 *output_base)
   uint32_t fb_id;
   uint32_t msec;
   struct timespec ts;
 + struct drm_output *clone_output;
  
 - if (output-destroy_pending)
 + if (output-destroy_pending || output-base.is_slave)
   return;
  
   if (!output-current) {
 @@ -707,6 +746,22 @@ drm_output_start_repaint_loop(struct weston_output 
 *output_base)
   weston_log(queueing pageflip failed: %m\n);
   goto finish_frame;
   }
 + output-page_flip_count++;
 +
 +  

Re: [PATCH 5/9] compositor: Output unplug in clone mode

2014-02-13 Thread Pekka Paalanen
On Fri, 14 Feb 2014 15:17:40 +0800
Xiong Zhang xiong.y.zh...@intel.com wrote:

 If unplugged output is a slave output, no need to restore views.
 
 If unplugged output is a master output which doesn't have slave
 output related it, views will be restored the same as extend mode.
 
 If unplugged output is a master output which have slave output
 related it, one slave output will be upgraded to master output,
 moving output following unplugged output isn't necessay,
 views on unplugged output will be marked as dirty.
 
 Signed-off-by: Xiong Zhang xiong.y.zh...@intel.com
 ---
  desktop-shell/shell.c |  13 ++-
  src/compositor-drm.c  | 103 
 +++---
  src/compositor.c  |  15 ++--
  src/compositor.h  |   1 +
  4 files changed, 122 insertions(+), 10 deletions(-)
 
 diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
 index 1e4a255..85987e5 100644
 --- a/desktop-shell/shell.c
 +++ b/desktop-shell/shell.c
 @@ -5600,6 +5600,9 @@ handle_output_destroy(struct wl_listener *listener, 
 void *data)
   wl_list_remove(output_listener-role_change_listener.link);
   wl_list_remove(output_listener-link);
   free(output_listener);
 +
 + /* Trigger compositor repaint */
 + weston_compositor_schedule_repaint(output_listener-output-compositor);
  }
  
  static void
 @@ -5676,10 +5679,18 @@ setup_output_destroy_handler(struct weston_compositor 
 *ec,
   struct desktop_shell 
 *shell)
  {
   struct weston_output *output;
 + struct weston_output *clone_output;
  
   wl_list_init(shell-output_list);
 - wl_list_for_each(output, ec-output_list, link)
 + wl_list_for_each(output, ec-output_list, link) {
   create_shell_output(shell, output);
 + if (!output-is_slave) {
 + wl_list_for_each(clone_output,
 +  output-clone_output_list,
 +  link)
 + create_shell_output(shell, clone_output);
 + }
 + }
  
   shell-output_create_listener.notify = handle_output_create;
   wl_signal_add(ec-output_created_signal,
 diff --git a/src/compositor-drm.c b/src/compositor-drm.c
 index 1d8c983..842710f 100644
 --- a/src/compositor-drm.c
 +++ b/src/compositor-drm.c
 @@ -1217,6 +1217,8 @@ drm_assign_planes(struct weston_output *output)
  
  static void
  drm_output_fini_pixman(struct drm_output *output);
 +static void
 +drm_output_destroy_with_slave(struct drm_output *output);
  
  static void
  drm_output_destroy(struct weston_output *output_base)
 @@ -1259,6 +1261,15 @@ drm_output_destroy(struct weston_output *output_base)
   weston_plane_release(output-fb_plane);
   weston_plane_release(output-cursor_plane);
  
 + if (!output-base.is_slave 
 + !wl_list_empty(output-base.clone_output_list)) {
 + drm_output_destroy_with_slave(output);
 +
 + /* One slave is upgraded to master, Don't move
 +  * the following output.*/
 + output_base.dont_move = 1;
 + }
 +
   weston_output_destroy(output-base);
  
   free(output);
 @@ -2420,6 +2431,73 @@ drm_output_add_slave(struct drm_compositor *ec)
   }
  }
  
 +/* The output with max width will be new_master. */
 +static struct weston_output *
 +find_new_master(struct weston_output *master)
 +{
 + struct weston_output *new_master, *output;
 + int32_t max_width = 0;
 +
 + new_master = NULL;
 + wl_list_for_each(output, master-clone_output_list,
 +  link) {
 + if (output-current_mode-width  max_width) {
 + max_width = output-current_mode-width;
 + new_master = output;
 + }
 + }
 +
 + return new_master;
 +}
 +
 +/* If a master is unplugged, a output will be chosen from
 + * master-clone_output_list to replace the unplugged master.*/
 +static void
 +drm_output_destroy_with_slave(struct drm_output *output)
 +{
 + struct weston_output *new_master, *tmp;
 + struct drm_output *clone_output, *next;
 + intoffset, move;
 +
 + new_master = find_new_master(output-base);
 +
 + /* When old master's width is different from new master's
 +  * width, move the output following the old master. */
 + offset = output-base.width - new_master-width;
 + if (offset != 0) {
 + move = 0;
 + wl_list_for_each(tmp, new_master-compositor-output_list,
 +  link) {
 + if (move == 1)
 + weston_output_move(tmp,
 + tmp-x - offset, tmp-y);
 +
 + if (tmp == output-base)
 + move = 1;
 + }
 + }
 +
 + wl_list_remove(new_master-link);
 + wl_list_insert(output-base.link.prev,
 +