diff options
author | Robert Bragg <robert@linux.intel.com> | 2011-05-09 22:45:33 +0100 |
---|---|---|
committer | Robert Bragg <robert@linux.intel.com> | 2011-10-26 15:55:05 +0100 |
commit | 755a52b3d97b24247375c2c0fdcfece760ab7610 (patch) | |
tree | c47e36fc6b53072b284bd9552a0d2bf13b6cb196 | |
parent | 81a82867e1cbd0b7a4da0ae518b9b1719974ad60 (diff) | |
download | clutter-755a52b3d97b24247375c2c0fdcfece760ab7610.tar.gz |
Updates wayland support
This updates Wayland support in line with upstream changes to the Wayland
API and protocol.
-rw-r--r-- | clutter/Makefile.am | 35 | ||||
-rw-r--r-- | clutter/cogl/clutter-backend-cogl.c | 127 | ||||
-rw-r--r-- | clutter/cogl/clutter-backend-cogl.h | 9 | ||||
-rw-r--r-- | clutter/cogl/clutter-stage-cogl.c | 8 | ||||
-rw-r--r-- | clutter/evdev/clutter-xkb-utils.h | 8 | ||||
-rw-r--r-- | clutter/wayland/clutter-backend-wayland.c | 672 | ||||
-rw-r--r-- | clutter/wayland/clutter-backend-wayland.h | 98 | ||||
-rw-r--r-- | clutter/wayland/clutter-device-manager-wayland.c | 195 | ||||
-rw-r--r-- | clutter/wayland/clutter-device-manager-wayland.h | 71 | ||||
-rw-r--r-- | clutter/wayland/clutter-event-wayland.c | 6 | ||||
-rw-r--r-- | clutter/wayland/clutter-event-wayland.h | 38 | ||||
-rw-r--r-- | clutter/wayland/clutter-input-device-wayland.c | 152 | ||||
-rw-r--r-- | clutter/wayland/clutter-input-device-wayland.h | 57 | ||||
-rw-r--r-- | clutter/wayland/clutter-stage-wayland.c | 650 | ||||
-rw-r--r-- | clutter/wayland/clutter-stage-wayland.h | 114 | ||||
-rw-r--r-- | clutter/wayland/clutter-wayland.h | 61 | ||||
-rw-r--r-- | configure.ac | 12 | ||||
-rw-r--r-- | doc/reference/clutter/clutter-sections.txt | 6 |
18 files changed, 581 insertions, 1738 deletions
diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 461e7d103..943f7be5a 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -495,6 +495,20 @@ if SUPPORT_CEX100 backend_source_h += $(cex_h) endif # SUPPORT_CEX100 +# Wayland backend rules +if SUPPORT_WAYLAND +backend_source_h_priv += \ + $(srcdir)/evdev/clutter-xkb-utils.h \ + $(srcdir)/wayland/clutter-event-wayland.h \ + $(srcdir)/wayland/clutter-device-manager-wayland.h + +backend_source_c += \ + $(srcdir)/evdev/clutter-xkb-utils.c \ + $(srcdir)/wayland/clutter-event-wayland.c \ + $(srcdir)/wayland/clutter-input-device-wayland.c \ + $(srcdir)/wayland/clutter-device-manager-wayland.c +endif # SUPPORT_WAYLAND + if SUPPORT_EGL backend_source_h += $(cogl_source_h) $(egl_source_h) backend_source_c += $(cogl_source_c) @@ -540,27 +554,6 @@ clutterosx_includedir = $(clutter_includedir)/osx clutterosx_include_HEADERS = $(osx_source_h) endif # SUPPORT_OSX -# Wayland backend rules -if SUPPORT_WAYLAND -backend_source_h += \ - $(srcdir)/wayland/clutter-wayland.h - -backend_source_h_priv += \ - $(srcdir)/evdev/clutter-xkb-utils.h \ - $(srcdir)/wayland/clutter-backend-wayland.h \ - $(srcdir)/wayland/clutter-stage-wayland.h - -backend_source_c += \ - $(srcdir)/evdev/clutter-xkb-utils.c \ - $(srcdir)/wayland/clutter-backend-wayland.c \ - $(srcdir)/wayland/clutter-stage-wayland.c \ - $(srcdir)/wayland/clutter-event-wayland.c \ - $(srcdir)/wayland/clutter-input-device-wayland.c - -clutterwayland_includedir = $(clutter_includedir)/wayland -clutterwayland_include_HEADERS = $(wayland_source_h) -endif # SUPPORT_WAYLAND - # cally cally_sources_h = \ $(srcdir)/cally/cally-actor.h \ diff --git a/clutter/cogl/clutter-backend-cogl.c b/clutter/cogl/clutter-backend-cogl.c index 1ca885025..fdfbf38f2 100644 --- a/clutter/cogl/clutter-backend-cogl.c +++ b/clutter/cogl/clutter-backend-cogl.c @@ -54,6 +54,10 @@ #ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT #include "clutter-cex100.h" #endif +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT +#include "wayland/clutter-device-manager-wayland.h" +#include "wayland/clutter-event-wayland.h" +#endif static ClutterBackendCogl *backend_singleton = NULL; @@ -110,10 +114,76 @@ clutter_backend_cogl_pre_parse (ClutterBackend *backend, return TRUE; } +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT +static void +handle_configure (void *data, + struct wl_shell *shell, + uint32_t timestamp, + uint32_t edges, + struct wl_surface *surface, + int32_t width, + int32_t height) +{ + ClutterStageCogl *stage_cogl = wl_surface_get_user_data (surface); + CoglFramebuffer *fb = COGL_FRAMEBUFFER (stage_cogl->onscreen); + + if (cogl_framebuffer_get_width (fb) != width || + cogl_framebuffer_get_height (fb) != height) + clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_cogl->wrapper)); + + clutter_actor_set_size (CLUTTER_ACTOR (stage_cogl->wrapper), + width, height); + + /* the resize process is complete, so we can ask the stage + * to set up the GL viewport with the new size + */ + clutter_stage_ensure_viewport (stage_cogl->wrapper); +} + +static const struct wl_shell_listener shell_listener = { + handle_configure, +}; + +static void +display_handle_global (struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, + void *data) +{ + ClutterBackendCogl *backend_cogl = data; + + if (strcmp (interface, "wl_compositor") == 0) + backend_cogl->wayland_compositor = wl_compositor_create (display, id, 1); + else if (strcmp (interface, "wl_input_device") == 0) + _clutter_wayland_add_input_group (backend_cogl, id); + else if (strcmp (interface, "wl_shell") == 0) + { + backend_cogl->wayland_shell = wl_shell_create (display, id, 1); + wl_shell_add_listener (backend_cogl->wayland_shell, + &shell_listener, backend_cogl); + } + else if (strcmp (interface, "wl_shm") == 0) + backend_cogl->wayland_shm = wl_shm_create (display, id, 1); +} + +static int +event_mask_update_cb (uint32_t mask, void *user_data) +{ + ClutterBackendCogl *backend_cogl = user_data; + backend_cogl->wayland_event_mask = mask; + return 0; +} +#endif + static gboolean clutter_backend_cogl_post_parse (ClutterBackend *backend, GError **error) { +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend); +#endif + #ifdef COGL_HAS_X11_SUPPORT ClutterBackendClass *parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class); @@ -124,6 +194,37 @@ clutter_backend_cogl_post_parse (ClutterBackend *backend, return TRUE; #endif +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + + /* TODO: expose environment variable/commandline option for this... */ + backend_cogl->wayland_display = wl_display_connect (NULL); + if (!backend_cogl->wayland_display) + { + g_set_error (error, CLUTTER_INIT_ERROR, + CLUTTER_INIT_ERROR_BACKEND, + "Failed to open Wayland display socket"); + return FALSE; + } + + backend_cogl->wayland_source = + _clutter_event_source_wayland_new (backend_cogl->wayland_display); + g_source_attach (backend_cogl->wayland_source, NULL); + + /* Set up listener so we'll catch all events. */ + wl_display_add_global_listener (backend_cogl->wayland_display, + display_handle_global, + backend_cogl); + + wl_display_get_fd (backend_cogl->wayland_display, + event_mask_update_cb, backend_cogl); + + /* Wait until we have been notified about the compositor object */ + while (!backend_cogl->wayland_compositor) + wl_display_iterate (backend_cogl->wayland_display, + backend_cogl->wayland_event_mask); + +#endif + g_atexit (clutter_backend_at_exit); return TRUE; @@ -137,7 +238,12 @@ clutter_backend_cogl_get_device_manager (ClutterBackend *backend) if (G_UNLIKELY (backend_cogl->device_manager == NULL)) { -#ifdef HAVE_EVDEV +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + backend_cogl->device_manager = + g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND, + "backend", backend_cogl, + NULL); +#elif defined (HAVE_EVDEV) backend_cogl->device_manager = g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV, "backend", backend_cogl, @@ -159,6 +265,9 @@ clutter_backend_cogl_init_events (ClutterBackend *backend) #ifdef HAVE_EVDEV _clutter_events_evdev_init (CLUTTER_BACKEND (backend)); #endif +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + _clutter_events_wayland_init (backend); +#endif #ifdef COGL_HAS_X11_SUPPORT /* Chain up to the X11 backend */ CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class)-> @@ -179,7 +288,7 @@ static void clutter_backend_cogl_dispose (GObject *gobject) { ClutterBackend *backend = CLUTTER_BACKEND (gobject); -#ifdef HAVE_TSLIB +#if defined (HAVE_TSLIB) || defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT) ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (gobject); #endif @@ -204,6 +313,9 @@ clutter_backend_cogl_dispose (GObject *gobject) backend_cogl->event_timer = NULL; } #endif +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + _clutter_events_wayland_uninit (backend_cogl); +#endif } static GObject * @@ -291,8 +403,10 @@ static gboolean clutter_backend_cogl_create_context (ClutterBackend *backend, GError **error) { -#ifdef COGL_HAS_XLIB_SUPPORT +#if defined (COGL_HAS_XLIB_SUPPORT) ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend); +#elif defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT) + ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend); #endif CoglSwapChain *swap_chain = NULL; CoglOnscreenTemplate *onscreen_template = NULL; @@ -301,9 +415,14 @@ clutter_backend_cogl_create_context (ClutterBackend *backend, return TRUE; backend->cogl_renderer = cogl_renderer_new (); -#ifdef COGL_HAS_XLIB_SUPPORT +#if defined (COGL_HAS_XLIB_SUPPORT) cogl_xlib_renderer_set_foreign_display (backend->cogl_renderer, backend_x11->xdpy); +#elif defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT) + cogl_renderer_wayland_set_foreign_display (backend->cogl_renderer, + backend_cogl->wayland_display); + cogl_renderer_wayland_set_foreign_compositor (backend->cogl_renderer, + backend_cogl->wayland_compositor); #endif if (!cogl_renderer_connect (backend->cogl_renderer, error)) goto error; diff --git a/clutter/cogl/clutter-backend-cogl.h b/clutter/cogl/clutter-backend-cogl.h index c1563d390..7ea926772 100644 --- a/clutter/cogl/clutter-backend-cogl.h +++ b/clutter/cogl/clutter-backend-cogl.h @@ -75,6 +75,15 @@ struct _ClutterBackendCogl #endif /* COGL_HAS_X11_SUPPORT */ +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + struct wl_display *wayland_display; + struct wl_compositor *wayland_compositor; + struct wl_shell *wayland_shell; + struct wl_shm *wayland_shm; + uint32_t wayland_event_mask; + GSource *wayland_source; +#endif + CoglContext *cogl_context; gboolean can_blit_sub_buffer; diff --git a/clutter/cogl/clutter-stage-cogl.c b/clutter/cogl/clutter-stage-cogl.c index 0acec4bef..be42827cb 100644 --- a/clutter/cogl/clutter-stage-cogl.c +++ b/clutter/cogl/clutter-stage-cogl.c @@ -104,6 +104,9 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) #ifdef COGL_HAS_XLIB_SUPPORT ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); #endif +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + struct wl_surface *wl_surface; +#endif ClutterBackend *backend; CoglFramebuffer *framebuffer; GError *error = NULL; @@ -153,6 +156,11 @@ clutter_stage_cogl_realize (ClutterStageWindow *stage_window) * will be ignored, so we need to make sure the stage size is * updated to this size. */ +#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT + wl_surface = cogl_wayland_onscreen_get_surface (stage_cogl->onscreen); + wl_input_device_set_user_data (wl_surface, stage_cogl); +#endif + if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT)) { stage_cogl->swap_callback_id = diff --git a/clutter/evdev/clutter-xkb-utils.h b/clutter/evdev/clutter-xkb-utils.h index 34e65c616..527d187ec 100644 --- a/clutter/evdev/clutter-xkb-utils.h +++ b/clutter/evdev/clutter-xkb-utils.h @@ -22,12 +22,16 @@ * Damien Lespiau <damien.lespiau@intel.com> */ -#include <X11/extensions/XKBcommon.h> - #include "clutter-stage.h" #include "clutter-event.h" #include "clutter-input-device.h" +/* Make sure to include this last because it will typedef KeyCode if + * X.h hasn't already been included, but if X.h gets included + * afterwards it doesn't have a guard to stop it redeclaring the + * typedef. */ +#include <X11/extensions/XKBcommon.h> + ClutterEvent * _clutter_key_event_new_from_evdev (ClutterInputDevice *device, ClutterStage *stage, struct xkb_desc *xkb, diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c deleted file mode 100644 index 56c23a251..000000000 --- a/clutter/wayland/clutter-backend-wayland.c +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Matthew Allum - * Robert Bragg - * Kristian Høgsberg - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> - -#include <errno.h> - -#include <wayland-util.h> -#include <wayland-client.h> -#include <xf86drm.h> - -#include "clutter-backend-wayland.h" -#include "clutter-stage-wayland.h" -#include "clutter-wayland.h" - -#include "clutter-debug.h" -#include "clutter-main.h" -#include "clutter-private.h" -#include "clutter-stage-private.h" - -static ClutterBackendWayland *backend_singleton = NULL; - -G_DEFINE_TYPE (ClutterBackendWayland, _clutter_backend_wayland, CLUTTER_TYPE_BACKEND); - -static void -clutter_backend_at_exit (void) -{ - if (backend_singleton) - g_object_run_dispose (G_OBJECT (backend_singleton)); -} - -static gboolean -clutter_backend_wayland_pre_parse (ClutterBackend *backend, - GError **error) -{ - return TRUE; -} - -static void -drm_handle_device (void *data, struct wl_drm *drm, const char *device) -{ - ClutterBackendWayland *backend_wayland = data; - backend_wayland->device_name = g_strdup (device); -} - -static void -drm_handle_authenticated (void *data, struct wl_drm *drm) -{ - ClutterBackendWayland *backend_wayland = data; - backend_wayland->authenticated = 1; -} - -static const struct wl_drm_listener drm_listener = -{ - drm_handle_device, - drm_handle_authenticated -}; - -static void -display_handle_geometry (void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - ClutterBackendWayland *backend_wayland = data; - - backend_wayland->screen_allocation.x = x; - backend_wayland->screen_allocation.y = y; - backend_wayland->screen_allocation.width = width; - backend_wayland->screen_allocation.height = height; -} - -static const struct wl_output_listener output_listener = -{ - display_handle_geometry, -}; - - -static void -handle_configure (void *data, struct wl_shell *shell, - uint32_t timestamp, uint32_t edges, - struct wl_surface *surface, - int32_t width, int32_t height) -{ - ClutterStageWayland *stage_wayland; - - stage_wayland = wl_surface_get_user_data (surface); - - if ((stage_wayland->allocation.width != width) || - (stage_wayland->allocation.height != height)) - { - clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_wayland->wrapper)); - } - - stage_wayland->pending_allocation.width = width; - stage_wayland->pending_allocation.height = height; - stage_wayland->allocation = stage_wayland->pending_allocation; - - clutter_actor_set_size (CLUTTER_ACTOR (stage_wayland->wrapper), - width, height); - - /* the resize process is complete, so we can ask the stage - * to set up the GL viewport with the new size - */ - clutter_stage_ensure_viewport (stage_wayland->wrapper); -} - -static const struct wl_shell_listener shell_listener = { - handle_configure, -}; - -static void -display_handle_global (struct wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, - void *data) -{ - ClutterBackendWayland *backend_wayland = data; - - if (strcmp (interface, "compositor") == 0) - { - backend_wayland->wayland_compositor = wl_compositor_create (display, id); - } - else if (strcmp (interface, "output") == 0) - { - backend_wayland->wayland_output = wl_output_create (display, id); - wl_output_add_listener (backend_wayland->wayland_output, - &output_listener, backend_wayland); - } - else if (strcmp (interface, "input_device") == 0) - { - _clutter_backend_add_input_device (backend_wayland, id); - } - else if (strcmp (interface, "shell") == 0) - { - backend_wayland->wayland_shell = wl_shell_create (display, id); - wl_shell_add_listener (backend_wayland->wayland_shell, - &shell_listener, backend_wayland); - } - else if (strcmp (interface, "drm") == 0) - { - backend_wayland->wayland_drm = wl_drm_create (display, id); - wl_drm_add_listener (backend_wayland->wayland_drm, - &drm_listener, backend_wayland); - } - else if (strcmp (interface, "shm") == 0) - { - backend_wayland->wayland_shm = wl_shm_create (display, id); - } -} - -static gboolean -try_get_display (ClutterBackendWayland *backend_wayland, GError **error) -{ - EGLDisplay edpy = EGL_NO_DISPLAY; - int drm_fd; - - drm_fd = open (backend_wayland->device_name, O_RDWR); - - backend_wayland->get_drm_display = - (PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA"); - - if (backend_wayland->get_drm_display != NULL && drm_fd >= 0) - edpy = backend_wayland->get_drm_display (drm_fd); - - if (edpy == EGL_NO_DISPLAY) - edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - if (edpy == EGL_NO_DISPLAY) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to open EGLDisplay"); - return FALSE; - } - - backend_wayland->edpy = edpy; - backend_wayland->drm_fd = drm_fd; - - return TRUE; -} - -static gboolean -try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error) -{ - drm_magic_t magic; - const gchar *exts, *glexts; - - if (backend_wayland->drm_fd < 0) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to open drm device"); - return FALSE; - } - - glexts = glGetString(GL_EXTENSIONS); - exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); - - if (!cogl_clutter_check_extension ("EGL_KHR_image_base", exts) || - !cogl_clutter_check_extension ("EGL_MESA_drm_image", exts) || - !cogl_clutter_check_extension ("GL_OES_EGL_image", glexts)) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Missing EGL extensions"); - return FALSE; - } - - backend_wayland->create_drm_image = - (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA"); - backend_wayland->destroy_image = - (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR"); - backend_wayland->export_drm_image = - (PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA"); - backend_wayland->image_target_texture_2d = - (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES"); - - if (backend_wayland->create_drm_image == NULL || - backend_wayland->destroy_image == NULL || - backend_wayland->export_drm_image == NULL || - backend_wayland->image_target_texture_2d == NULL) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Missing EGL extensions"); - return FALSE; - } - - if (drmGetMagic (backend_wayland->drm_fd, &magic)) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to get drm magic"); - return FALSE; - } - - wl_drm_authenticate (backend_wayland->wayland_drm, magic); - wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE); - while (!backend_wayland->authenticated) - wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); - - return TRUE; -}; - -static gboolean -clutter_backend_wayland_post_parse (ClutterBackend *backend, - GError **error) -{ - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - EGLBoolean status; - - g_atexit (clutter_backend_at_exit); - - /* TODO: expose environment variable/commandline option for this... */ - backend_wayland->wayland_display = wl_display_connect (NULL); - if (!backend_wayland->wayland_display) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Failed to open Wayland display socket"); - return FALSE; - } - - backend_wayland->wayland_source = - _clutter_event_source_wayland_new (backend_wayland->wayland_display); - g_source_attach (backend_wayland->wayland_source, NULL); - - /* Set up listener so we'll catch all events. */ - wl_display_add_global_listener (backend_wayland->wayland_display, - display_handle_global, - backend_wayland); - - /* Process connection events. */ - wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE); - - if (!try_get_display(backend_wayland, error)) - return FALSE; - - status = eglInitialize (backend_wayland->edpy, - &backend_wayland->egl_version_major, - &backend_wayland->egl_version_minor); - if (status != EGL_TRUE) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Unable to Initialize EGL"); - return FALSE; - } - - CLUTTER_NOTE (BACKEND, "EGL Reports version %i.%i", - backend_wayland->egl_version_major, - backend_wayland->egl_version_minor); - - backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error); - - if (!backend_wayland->drm_enabled) { - if (backend_wayland->wayland_shm == NULL) - return FALSE; - - g_debug("Could not enable DRM buffers, falling back to SHM buffers"); - g_clear_error(error); - } - - return TRUE; -} - -#if defined(COGL_HAS_GL) -#define _COGL_RENDERABLE_BIT EGL_OPENGL_BIT -#elif defined(COGL_HAS_GLES2) -#define _COGL_GLES_VERSION 2 -#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES2_BIT -#elif defined(COGL_HAS_GLES1) -#define _COGL_GLES_VERSION 1 -#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES_BIT -#endif - -static gboolean -make_dummy_surface (ClutterBackendWayland *backend_wayland) -{ - static const EGLint attrs[] = { - EGL_WIDTH, 1, - EGL_HEIGHT, 1, - EGL_RENDERABLE_TYPE, _COGL_RENDERABLE_BIT, - EGL_NONE }; - EGLint num_configs; - - eglGetConfigs(backend_wayland->edpy, - &backend_wayland->egl_config, 1, &num_configs); - if (num_configs < 1) - return FALSE; - - backend_wayland->egl_surface = - eglCreatePbufferSurface(backend_wayland->edpy, - backend_wayland->egl_config, - attrs); - - if (backend_wayland->egl_surface == EGL_NO_SURFACE) - return FALSE; - - return TRUE; -} - -static gboolean -try_create_context (ClutterBackend *backend, - int retry_cookie, - gboolean *try_fallback, - GError **error) -{ - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - const char *error_message; - - if (backend_wayland->egl_context == EGL_NO_CONTEXT) - { -#if defined(COGL_HAS_GL) - static const EGLint *attribs = NULL; -#else - static const EGLint attribs[] = - { EGL_CONTEXT_CLIENT_VERSION, _COGL_GLES_VERSION, EGL_NONE }; -#endif - - backend_wayland->egl_context = - eglCreateContext (backend_wayland->edpy, - backend_wayland->egl_config, - EGL_NO_CONTEXT, - attribs); - if (backend_wayland->egl_context == EGL_NO_CONTEXT) - { - error_message = "Unable to create a suitable EGL context"; - goto fail; - } - - CLUTTER_NOTE (BACKEND, "Created EGL Context"); - } - - if (!eglMakeCurrent (backend_wayland->edpy, - backend_wayland->egl_surface, - backend_wayland->egl_surface, - backend_wayland->egl_context)) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Unable to MakeCurrent"); - return FALSE; - } - - return TRUE; - -fail: - { - *try_fallback = FALSE; - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "%s", error_message); - return FALSE; - } -} - -#if defined(COGL_HAS_GL) -#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_opengl" -#elif defined(COGL_HAS_GLES1) -#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles1" -#elif defined(COGL_HAS_GLES2) -#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles2" -#endif - -static gboolean -clutter_backend_wayland_create_context (ClutterBackend *backend, - GError **error) -{ - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - const gchar *egl_extensions = NULL; - gboolean status; - int retry_cookie; - gboolean try_fallback; - GError *try_error = NULL; - - if (backend_wayland->egl_context != EGL_NO_CONTEXT) - return TRUE; - -#if defined(COGL_HAS_GL) - eglBindAPI (EGL_OPENGL_API); -#else - eglBindAPI (EGL_OPENGL_ES_API); -#endif - egl_extensions = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); - - if (!cogl_clutter_check_extension (_COGL_SURFACELESS_EXTENSION, egl_extensions)) - { - g_debug("Could not find the " _COGL_SURFACELESS_EXTENSION - " extension; falling back to binding a dummy surface"); - if (!make_dummy_surface(backend_wayland)) - { - g_set_error (error, CLUTTER_INIT_ERROR, - CLUTTER_INIT_ERROR_BACKEND, - "Could not create dummy surface"); - return FALSE; - } - } - else - { - backend_wayland->egl_config = NULL; - backend_wayland->egl_surface = EGL_NO_SURFACE; - } - - retry_cookie = 0; - while (!(status = try_create_context (backend, - retry_cookie, - &try_fallback, - &try_error)) && - try_fallback) - { - g_warning ("Failed to create context: %s\nWill try fallback...", - try_error->message); - g_error_free (try_error); - try_error = NULL; - retry_cookie++; - } - if (!status) - g_propagate_error (error, try_error); - - return status; -} - -static void -clutter_backend_wayland_ensure_context (ClutterBackend *backend, - ClutterStage *stage) -{ -} - -static void -clutter_backend_wayland_redraw (ClutterBackend *backend, - ClutterStage *stage) -{ - ClutterStageWindow *impl; - - impl = _clutter_stage_get_window (stage); - if (!impl) - return; - - g_assert (CLUTTER_IS_STAGE_WAYLAND (impl)); - - _clutter_stage_wayland_redraw (CLUTTER_STAGE_WAYLAND (impl), stage); -} - -static void -clutter_backend_wayland_init_events (ClutterBackend *backend) -{ -} - -static void -clutter_backend_wayland_finalize (GObject *gobject) -{ - if (backend_singleton) - backend_singleton = NULL; - - G_OBJECT_CLASS (_clutter_backend_wayland_parent_class)->finalize (gobject); -} - -static void -clutter_backend_wayland_dispose (GObject *gobject) -{ - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (gobject); - - /* We chain up before disposing our own resources so that - ClutterBackend will destroy all of the stages before we destroy - the egl context. Otherwise the actors may try to make GL calls - during destruction which causes a crash */ - G_OBJECT_CLASS (_clutter_backend_wayland_parent_class)->dispose (gobject); - - if (backend_wayland->egl_context) - { - eglDestroyContext (backend_wayland->edpy, backend_wayland->egl_context); - backend_wayland->egl_context = NULL; - } - - if (backend_wayland->edpy) - { - eglTerminate (backend_wayland->edpy); - backend_wayland->edpy = 0; - } - - if (backend_wayland->drm_fd != -1) - { - close (backend_wayland->drm_fd); - backend_wayland->drm_fd = -1; - } -} - -static GObject * -clutter_backend_wayland_constructor (GType gtype, - guint n_params, - GObjectConstructParam *params) -{ - GObjectClass *parent_class; - GObject *retval; - - if (!backend_singleton) - { - parent_class = G_OBJECT_CLASS (_clutter_backend_wayland_parent_class); - retval = parent_class->constructor (gtype, n_params, params); - - backend_singleton = CLUTTER_BACKEND_WAYLAND (retval); - - return retval; - } - - g_warning ("Attempting to create a new backend object. This should " - "never happen, so we return the singleton instance."); - - return g_object_ref (backend_singleton); -} - -static ClutterFeatureFlags -clutter_backend_wayland_get_features (ClutterBackend *backend) -{ - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - ClutterFeatureFlags flags = 0; - - g_assert (backend_wayland->egl_context != NULL); - - flags |= - CLUTTER_FEATURE_STAGE_MULTIPLE | - CLUTTER_FEATURE_SWAP_EVENTS | - CLUTTER_FEATURE_SYNC_TO_VBLANK; - - CLUTTER_NOTE (BACKEND, "Checking features\n" - "GL_VENDOR: %s\n" - "GL_RENDERER: %s\n" - "GL_VERSION: %s\n" - "EGL_VENDOR: %s\n" - "EGL_VERSION: %s\n" - "EGL_EXTENSIONS: %s\n", - glGetString (GL_VENDOR), - glGetString (GL_RENDERER), - glGetString (GL_VERSION), - eglQueryString (backend_wayland->edpy, EGL_VENDOR), - eglQueryString (backend_wayland->edpy, EGL_VERSION), - eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS)); - - return flags; -} - -static ClutterStageWindow * -clutter_backend_wayland_create_stage (ClutterBackend *backend, - ClutterStage *wrapper, - GError **error) -{ - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - ClutterStageWindow *stage; - ClutterStageWayland *stage_wayland; - - stage = g_object_new (CLUTTER_TYPE_STAGE_WAYLAND, NULL); - - stage_wayland = CLUTTER_STAGE_WAYLAND (stage); - stage_wayland->backend = backend_wayland; - stage_wayland->wrapper = wrapper; - - return stage; -} - -static void -_clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass); - - gobject_class->constructor = clutter_backend_wayland_constructor; - gobject_class->dispose = clutter_backend_wayland_dispose; - gobject_class->finalize = clutter_backend_wayland_finalize; - - backend_class->pre_parse = clutter_backend_wayland_pre_parse; - backend_class->post_parse = clutter_backend_wayland_post_parse; - backend_class->get_features = clutter_backend_wayland_get_features; - backend_class->init_events = clutter_backend_wayland_init_events; - backend_class->create_stage = clutter_backend_wayland_create_stage; - backend_class->create_context = clutter_backend_wayland_create_context; - backend_class->ensure_context = clutter_backend_wayland_ensure_context; - backend_class->redraw = clutter_backend_wayland_redraw; -} - -static void -_clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland) -{ - backend_wayland->edpy = EGL_NO_DISPLAY; - backend_wayland->egl_context = EGL_NO_CONTEXT; - - backend_wayland->drm_fd = -1; -} - -GType -_clutter_backend_impl_get_type (void) -{ - return _clutter_backend_wayland_get_type (); -} - -EGLDisplay -clutter_wayland_get_egl_display (void) -{ - return backend_singleton->edpy; -} diff --git a/clutter/wayland/clutter-backend-wayland.h b/clutter/wayland/clutter-backend-wayland.h deleted file mode 100644 index c36ecab84..000000000 --- a/clutter/wayland/clutter-backend-wayland.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Matthew Allum - * Robert Bragg - * Kristian Høgsberg - */ - -#ifndef __CLUTTER_BACKEND_WAYLAND_H__ -#define __CLUTTER_BACKEND_WAYLAND_H__ - -#include <glib-object.h> -#include <clutter/clutter-event.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "clutter-wayland.h" - -#include "clutter-backend-private.h" - -G_BEGIN_DECLS - -#define CLUTTER_TYPE_BACKEND_WAYLAND (_clutter_backend_wayland_get_type ()) -#define CLUTTER_BACKEND_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_WAYLAND, ClutterBackendWayland)) -#define CLUTTER_IS_BACKEND_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_WAYLAND)) -#define CLUTTER_BACKEND_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_WAYLAND, ClutterBackendWaylandClass)) -#define CLUTTER_IS_BACKEND_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_WAYLAND)) -#define CLUTTER_BACKEND_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_WAYLAND, ClutterBackendWaylandClass)) - -typedef struct _ClutterBackendWayland ClutterBackendWayland; -typedef struct _ClutterBackendWaylandClass ClutterBackendWaylandClass; - -struct _ClutterBackendWayland -{ - ClutterBackend parent_instance; - - /* EGL Specific */ - EGLDisplay edpy; - EGLContext egl_context; - EGLConfig egl_config; - EGLSurface egl_surface; - - gint egl_version_major; - gint egl_version_minor; - - struct wl_display *wayland_display; - GSource *wayland_source; - struct wl_compositor *wayland_compositor; - struct wl_shell *wayland_shell; - struct wl_drm *wayland_drm; - struct wl_shm *wayland_shm; - char *device_name; - int authenticated; - struct wl_output *wayland_output; - ClutterGeometry screen_allocation; - int drm_fd; - gboolean drm_enabled; - - PFNEGLGETDRMDISPLAYMESA get_drm_display; - PFNEGLCREATEDRMIMAGEMESA create_drm_image; - PFNEGLDESTROYIMAGEKHRPROC destroy_image; - PFNEGLEXPORTDRMIMAGEMESA export_drm_image; - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; -}; - -struct _ClutterBackendWaylandClass -{ - ClutterBackendClass parent_class; -}; - -GType _clutter_backend_wayland_get_type (void) G_GNUC_CONST; - -GSource *_clutter_event_source_wayland_new(struct wl_display *display); -void _clutter_backend_add_input_device (ClutterBackendWayland *backend_wayland, - uint32_t id); - -G_END_DECLS - -#endif /* __CLUTTER_BACKEND_WAYLAND_H__ */ diff --git a/clutter/wayland/clutter-device-manager-wayland.c b/clutter/wayland/clutter-device-manager-wayland.c new file mode 100644 index 000000000..263a52f22 --- /dev/null +++ b/clutter/wayland/clutter-device-manager-wayland.c @@ -0,0 +1,195 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corp. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Emmanuele Bassi <ebassi@linux.intel.com> + * Robert Bragg <robert@linux.intel.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-input-device-wayland.h" +#include "clutter-device-manager-wayland.h" + +#include "clutter-backend.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-private.h" + +#include "evdev/clutter-xkb-utils.h" + +enum +{ + PROP_0 +}; + +G_DEFINE_TYPE (ClutterDeviceManagerWayland, + clutter_device_manager_wayland, + CLUTTER_TYPE_DEVICE_MANAGER); + +static void +clutter_device_manager_wayland_add_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerWayland *manager_wayland = CLUTTER_DEVICE_MANAGER_WAYLAND (manager); + ClutterInputDeviceType device_type; + gboolean is_pointer, is_keyboard; + + device_type = clutter_input_device_get_device_type (device); + is_pointer = (device_type == CLUTTER_POINTER_DEVICE) ? TRUE : FALSE; + is_keyboard = (device_type == CLUTTER_KEYBOARD_DEVICE) ? TRUE : FALSE; + + manager_wayland->devices = g_slist_prepend (manager_wayland->devices, device); + + if (is_pointer && manager_wayland->core_pointer == NULL) + manager_wayland->core_pointer = device; + + if (is_keyboard && manager_wayland->core_keyboard == NULL) + manager_wayland->core_keyboard = device; +} + +static void +clutter_device_manager_wayland_remove_device (ClutterDeviceManager *manager, + ClutterInputDevice *device) +{ + ClutterDeviceManagerWayland *manager_wayland = CLUTTER_DEVICE_MANAGER_WAYLAND (manager); + + manager_wayland->devices = g_slist_remove (manager_wayland->devices, device); +} + +static const GSList * +clutter_device_manager_wayland_get_devices (ClutterDeviceManager *manager) +{ + return CLUTTER_DEVICE_MANAGER_WAYLAND (manager)->devices; +} + +static ClutterInputDevice * +clutter_device_manager_wayland_get_core_device (ClutterDeviceManager *manager, + ClutterInputDeviceType type) +{ + ClutterDeviceManagerWayland *manager_wayland; + + manager_wayland = CLUTTER_DEVICE_MANAGER_WAYLAND (manager); + + switch (type) + { + case CLUTTER_POINTER_DEVICE: + return manager_wayland->core_pointer; + + case CLUTTER_KEYBOARD_DEVICE: + return manager_wayland->core_keyboard; + + case CLUTTER_EXTENSION_DEVICE: + default: + return NULL; + } + + return NULL; +} + +static ClutterInputDevice * +clutter_device_manager_wayland_get_device (ClutterDeviceManager *manager, + gint id) +{ + ClutterDeviceManagerWayland *manager_wayland = CLUTTER_DEVICE_MANAGER_WAYLAND (manager); + GSList *l; + + for (l = manager_wayland->devices; l != NULL; l = l->next) + { + ClutterInputDevice *device = l->data; + + if (clutter_input_device_get_device_id (device) == id) + return device; + } + + return NULL; +} + +static void +clutter_device_manager_wayland_class_init (ClutterDeviceManagerWaylandClass *klass) +{ + ClutterDeviceManagerClass *manager_class; + + manager_class = CLUTTER_DEVICE_MANAGER_CLASS (klass); + manager_class->add_device = clutter_device_manager_wayland_add_device; + manager_class->remove_device = clutter_device_manager_wayland_remove_device; + manager_class->get_devices = clutter_device_manager_wayland_get_devices; + manager_class->get_core_device = clutter_device_manager_wayland_get_core_device; + manager_class->get_device = clutter_device_manager_wayland_get_device; +} + +static void +clutter_device_manager_wayland_init (ClutterDeviceManagerWayland *self) +{ +} + +const char *option_xkb_layout = "us"; +const char *option_xkb_variant = ""; +const char *option_xkb_options = ""; + +void +_clutter_wayland_add_input_group (ClutterBackendCogl *backend_cogl, + uint32_t id) +{ + ClutterDeviceManager *manager = clutter_device_manager_get_default (); + ClutterInputDeviceWayland *device; + + device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_WAYLAND, + "id", id, + "device-type", CLUTTER_POINTER_DEVICE, + "name", "wayland device", + "enabled", TRUE, + NULL); + + device->input_device = + wl_input_device_create (backend_cogl->wayland_display, id, 1); + wl_input_device_add_listener (device->input_device, + &_clutter_input_device_wayland_listener, device); + wl_input_device_set_user_data (device->input_device, device); + + device->xkb = _clutter_xkb_desc_new (NULL, + option_xkb_layout, + option_xkb_variant, + option_xkb_options); + if (!device->xkb) + CLUTTER_NOTE (BACKEND, "Failed to compile keymap"); + + _clutter_device_manager_add_device (manager, CLUTTER_INPUT_DEVICE (device)); +} + +void +_clutter_events_wayland_init (ClutterBackendCogl *backend_cogl) +{ + CLUTTER_NOTE (EVENT, "Initializing evdev backend"); + + /* We just have to create the singleon here */ + clutter_device_manager_get_default (); +} + +void +_clutter_events_wayland_uninit (ClutterBackendCogl *backend_cogl) +{ + ClutterDeviceManager *manager; + + manager = clutter_device_manager_get_default (); + g_object_unref (manager); +} diff --git a/clutter/wayland/clutter-device-manager-wayland.h b/clutter/wayland/clutter-device-manager-wayland.h new file mode 100644 index 000000000..0c6a8bc6e --- /dev/null +++ b/clutter/wayland/clutter-device-manager-wayland.h @@ -0,0 +1,71 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corp. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Emmanuele Bassi <ebassi@linux.intel.com> + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_WAYLAND_H__ +#define __CLUTTER_DEVICE_MANAGER_WAYLAND_H__ + +#include <clutter/clutter-device-manager.h> +#include <clutter/cogl/clutter-backend-cogl.h> + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND (clutter_device_manager_wayland_get_type ()) +#define CLUTTER_DEVICE_MANAGER_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND, ClutterDeviceManagerWayland)) +#define CLUTTER_IS_DEVICE_MANAGER_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND)) +#define CLUTTER_DEVICE_MANAGER_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND, ClutterDeviceManagerWaylandClass)) +#define CLUTTER_IS_DEVICE_MANAGER_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND)) +#define CLUTTER_DEVICE_MANAGER_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND, ClutterDeviceManagerWaylandClass)) + +typedef struct _ClutterDeviceManagerWayland ClutterDeviceManagerWayland; +typedef struct _ClutterDeviceManagerWaylandClass ClutterDeviceManagerWaylandClass; + +struct _ClutterDeviceManagerWayland +{ + ClutterDeviceManager parent_instance; + + GSList *devices; + + ClutterInputDevice *core_pointer; + ClutterInputDevice *core_keyboard; +}; + +struct _ClutterDeviceManagerWaylandClass +{ + ClutterDeviceManagerClass parent_class; +}; + +GType clutter_device_manager_wayland_get_type (void) G_GNUC_CONST; + +void +_clutter_events_wayland_init (ClutterBackendCogl *backend_cogl); + +void +_clutter_events_wayland_uninit (ClutterBackendCogl *backend_cogl); + +void +_clutter_wayland_add_input_group (ClutterBackendCogl *backend_cogl, + uint32_t id); + +G_END_DECLS + +#endif /* __CLUTTER_DEVICE_MANAGER_WAYLAND_H__ */ diff --git a/clutter/wayland/clutter-event-wayland.c b/clutter/wayland/clutter-event-wayland.c index 23d9be41b..bb5163a24 100644 --- a/clutter/wayland/clutter-event-wayland.c +++ b/clutter/wayland/clutter-event-wayland.c @@ -55,10 +55,8 @@ clutter_event_source_wayland_prepare (GSource *base, gint *timeout) /* We have to add/remove the GPollFD if we want to update our * poll event mask dynamically. Instead, let's just flush all - * write on idle instead, which is what this amounts to. */ - - while (source->mask & WL_DISPLAY_WRITABLE) - wl_display_iterate (source->display, WL_DISPLAY_WRITABLE); + * write on idle. */ + wl_display_flush (source->display); retval = clutter_events_pending (); diff --git a/clutter/wayland/clutter-event-wayland.h b/clutter/wayland/clutter-event-wayland.h new file mode 100644 index 000000000..549b8f7a3 --- /dev/null +++ b/clutter/wayland/clutter-event-wayland.h @@ -0,0 +1,38 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + + * Authors: + * Robert Bragg + * Kristian Høgsberg + */ + +#ifndef __CLUTTER_EVENT_WAYLAND_H__ +#define __CLUTTER_EVENT_WAYLAND_H__ + +#include <glib-object.h> +#include <clutter/clutter-event.h> + +#include <wayland-client.h> + +GSource * +_clutter_event_source_wayland_new (struct wl_display *display); + +#endif /* __CLUTTER_EVENT_WAYLAND_H__ */ diff --git a/clutter/wayland/clutter-input-device-wayland.c b/clutter/wayland/clutter-input-device-wayland.c index 854ecddea..6243869a0 100644 --- a/clutter/wayland/clutter-input-device-wayland.c +++ b/clutter/wayland/clutter-input-device-wayland.c @@ -38,47 +38,29 @@ #include "clutter-private.h" #include "clutter-keysyms.h" #include "clutter-xkb-utils.h" +#include "clutter-input-device-wayland.h" -#include "clutter-stage-wayland.h" - -#define CLUTTER_TYPE_INPUT_DEVICE_WAYLAND (clutter_input_device_wayland_get_type ()) -#define CLUTTER_INPUT_DEVICE_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_WAYLAND, ClutterInputDeviceWayland)) -#define CLUTTER_IS_INPUT_DEVICE_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_WAYLAND)) - -typedef struct _ClutterInputDeviceWayland ClutterInputDeviceWayland; - -GType clutter_input_device_wayland_get_type (void) G_GNUC_CONST; +#include "cogl/clutter-stage-cogl.h" typedef struct _ClutterInputDeviceClass ClutterInputDeviceWaylandClass; -struct _ClutterInputDeviceWayland -{ - ClutterInputDevice device; - struct wl_input_device *input_device; - ClutterStageWayland *pointer_focus; - ClutterStageWayland *keyboard_focus; - uint32_t modifier_state; - int32_t x, y, surface_x, surface_y; - struct xkb_desc *xkb; -}; - G_DEFINE_TYPE (ClutterInputDeviceWayland, clutter_input_device_wayland, CLUTTER_TYPE_INPUT_DEVICE); static void -clutter_backend_wayland_handle_motion (void *data, - struct wl_input_device *input_device, - uint32_t _time, - int32_t x, int32_t y, - int32_t sx, int32_t sy) +clutter_wayland_handle_motion (void *data, + struct wl_input_device *input_device, + uint32_t _time, + int32_t x, int32_t y, + int32_t sx, int32_t sy) { ClutterInputDeviceWayland *device = data; - ClutterStageWayland *stage_wayland = device->pointer_focus; + ClutterStageCogl *stage_cogl = device->pointer_focus; ClutterEvent *event; event = clutter_event_new (CLUTTER_MOTION); - event->motion.stage = stage_wayland->wrapper; + event->motion.stage = stage_cogl->wrapper; event->motion.device = CLUTTER_INPUT_DEVICE (device); event->motion.time = _time; event->motion.modifier_state = 0; @@ -94,13 +76,13 @@ clutter_backend_wayland_handle_motion (void *data, } static void -clutter_backend_wayland_handle_button (void *data, - struct wl_input_device *input_device, - uint32_t _time, - uint32_t button, uint32_t state) +clutter_wayland_handle_button (void *data, + struct wl_input_device *input_device, + uint32_t _time, + uint32_t button, uint32_t state) { ClutterInputDeviceWayland *device = data; - ClutterStageWayland *stage_wayland = device->pointer_focus; + ClutterStageCogl *stage_cogl = device->pointer_focus; ClutterEvent *event; ClutterEventType type; @@ -110,7 +92,7 @@ clutter_backend_wayland_handle_button (void *data, type = CLUTTER_BUTTON_RELEASE; event = clutter_event_new (type); - event->button.stage = stage_wayland->wrapper; + event->button.stage = stage_cogl->wrapper; event->button.device = CLUTTER_INPUT_DEVICE (device); event->button.time = _time; event->button.x = device->surface_x; @@ -134,17 +116,17 @@ clutter_backend_wayland_handle_button (void *data, } static void -clutter_backend_wayland_handle_key (void *data, - struct wl_input_device *input_device, - uint32_t _time, - uint32_t key, uint32_t state) +clutter_wayland_handle_key (void *data, + struct wl_input_device *input_device, + uint32_t _time, + uint32_t key, uint32_t state) { ClutterInputDeviceWayland *device = data; - ClutterStageWayland *stage_wayland = device->keyboard_focus; + ClutterStageCogl *stage_cogl = device->keyboard_focus; ClutterEvent *event; event = _clutter_key_event_new_from_evdev ((ClutterInputDevice *) device, - stage_wayland->wrapper, + stage_cogl->wrapper, device->xkb, _time, key, state, &device->modifier_state); @@ -153,26 +135,26 @@ clutter_backend_wayland_handle_key (void *data, } static void -clutter_backend_wayland_handle_pointer_focus (void *data, - struct wl_input_device *input_device, - uint32_t _time, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy) +clutter_wayland_handle_pointer_focus (void *data, + struct wl_input_device *input_device, + uint32_t _time, + struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy) { ClutterInputDeviceWayland *device = data; - ClutterStageWayland *stage_wayland; + ClutterStageCogl *stage_cogl; ClutterEvent *event; if (device->pointer_focus) { - stage_wayland = device->pointer_focus; + stage_cogl = device->pointer_focus; event = clutter_event_new (CLUTTER_LEAVE); - event->crossing.stage = stage_wayland->wrapper; + event->crossing.stage = stage_cogl->wrapper; event->crossing.time = _time; event->crossing.x = sx; event->crossing.y = sy; - event->crossing.source = CLUTTER_ACTOR (stage_wayland->wrapper); + event->crossing.source = CLUTTER_ACTOR (stage_cogl->wrapper); event->crossing.device = CLUTTER_INPUT_DEVICE (device); _clutter_event_push (event, FALSE); @@ -183,18 +165,18 @@ clutter_backend_wayland_handle_pointer_focus (void *data, if (surface) { - stage_wayland = wl_surface_get_user_data (surface); + stage_cogl = wl_surface_get_user_data (surface); - device->pointer_focus = stage_wayland; + device->pointer_focus = stage_cogl; _clutter_input_device_set_stage (CLUTTER_INPUT_DEVICE (device), - stage_wayland->wrapper); + stage_cogl->wrapper); event = clutter_event_new (CLUTTER_MOTION); event->motion.time = _time; event->motion.x = sx; event->motion.y = sy; event->motion.modifier_state = device->modifier_state; - event->motion.source = CLUTTER_ACTOR (stage_wayland->wrapper); + event->motion.source = CLUTTER_ACTOR (stage_cogl->wrapper); event->motion.device = CLUTTER_INPUT_DEVICE (device); _clutter_event_push (event, FALSE); @@ -210,26 +192,26 @@ clutter_backend_wayland_handle_pointer_focus (void *data, } static void -clutter_backend_wayland_handle_keyboard_focus (void *data, - struct wl_input_device *input_device, - uint32_t _time, - struct wl_surface *surface, - struct wl_array *keys) +clutter_wayland_handle_keyboard_focus (void *data, + struct wl_input_device *input_device, + uint32_t _time, + struct wl_surface *surface, + struct wl_array *keys) { ClutterInputDeviceWayland *device = data; - ClutterStageWayland *stage_wayland; + ClutterStageCogl *stage_cogl; ClutterEvent *event; uint32_t *k, *end; if (device->keyboard_focus) { - stage_wayland = device->keyboard_focus; + stage_cogl = device->keyboard_focus; device->keyboard_focus = NULL; event = clutter_event_new (CLUTTER_STAGE_STATE); event->stage_state.time = _time; - event->stage_state.stage = stage_wayland->wrapper; - event->stage_state.stage = stage_wayland->wrapper; + event->stage_state.stage = stage_cogl->wrapper; + event->stage_state.stage = stage_cogl->wrapper; event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; event->stage_state.new_state = 0; @@ -238,11 +220,11 @@ clutter_backend_wayland_handle_keyboard_focus (void *data, if (surface) { - stage_wayland = wl_surface_get_user_data (surface); - device->keyboard_focus = stage_wayland; + stage_cogl = wl_surface_get_user_data (surface); + device->keyboard_focus = stage_cogl; event = clutter_event_new (CLUTTER_STAGE_STATE); - event->stage_state.stage = stage_wayland->wrapper; + event->stage_state.stage = stage_cogl->wrapper; event->stage_state.changed_mask = CLUTTER_STAGE_STATE_ACTIVATED; event->stage_state.new_state = CLUTTER_STAGE_STATE_ACTIVATED; @@ -255,12 +237,12 @@ clutter_backend_wayland_handle_keyboard_focus (void *data, } } -static const struct wl_input_device_listener input_device_listener = { - clutter_backend_wayland_handle_motion, - clutter_backend_wayland_handle_button, - clutter_backend_wayland_handle_key, - clutter_backend_wayland_handle_pointer_focus, - clutter_backend_wayland_handle_keyboard_focus, +const struct wl_input_device_listener _clutter_input_device_wayland_listener = { + clutter_wayland_handle_motion, + clutter_wayland_handle_button, + clutter_wayland_handle_key, + clutter_wayland_handle_pointer_focus, + clutter_wayland_handle_keyboard_focus, }; static void @@ -272,33 +254,3 @@ static void clutter_input_device_wayland_init (ClutterInputDeviceWayland *self) { } - -const char *option_xkb_layout = "us"; -const char *option_xkb_variant = ""; -const char *option_xkb_options = ""; - -void -_clutter_backend_add_input_device (ClutterBackendWayland *backend_wayland, - uint32_t id) -{ - ClutterInputDeviceWayland *device; - - device = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_WAYLAND, - "id", id, - "device-type", CLUTTER_POINTER_DEVICE, - "name", "wayland device", - NULL); - - device->input_device = - wl_input_device_create (backend_wayland->wayland_display, id); - wl_input_device_add_listener (device->input_device, - &input_device_listener, device); - wl_input_device_set_user_data (device->input_device, device); - - device->xkb = _clutter_xkb_desc_new (NULL, - option_xkb_layout, - option_xkb_variant, - option_xkb_options); - if (!device->xkb) - CLUTTER_NOTE (BACKEND, "Failed to compile keymap"); -} diff --git a/clutter/wayland/clutter-input-device-wayland.h b/clutter/wayland/clutter-input-device-wayland.h new file mode 100644 index 000000000..297337a1c --- /dev/null +++ b/clutter/wayland/clutter-input-device-wayland.h @@ -0,0 +1,57 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + + * Authors: + * Robert Bragg + * Kristian Høgsberg + */ + +#ifndef __CLUTTER_INPUT_DEVICE_WAYLAND_H__ +#define __CLUTTER_INPUT_DEVICE_WAYLAND_H__ + +#include <glib-object.h> +#include <clutter/clutter-event.h> + +#include "clutter-device-manager-private.h" +#include "cogl/clutter-stage-cogl.h" + +#define CLUTTER_TYPE_INPUT_DEVICE_WAYLAND (clutter_input_device_wayland_get_type ()) +#define CLUTTER_INPUT_DEVICE_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_INPUT_DEVICE_WAYLAND, ClutterInputDeviceWayland)) +#define CLUTTER_IS_INPUT_DEVICE_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_INPUT_DEVICE_WAYLAND)) + +typedef struct _ClutterInputDeviceWayland ClutterInputDeviceWayland; + +struct _ClutterInputDeviceWayland +{ + ClutterInputDevice device; + struct wl_input_device *input_device; + ClutterStageCogl *pointer_focus; + ClutterStageCogl *keyboard_focus; + uint32_t modifier_state; + int32_t x, y, surface_x, surface_y; + struct xkb_desc *xkb; +}; + +GType clutter_input_device_wayland_get_type (void) G_GNUC_CONST; + +extern const struct wl_input_device_listener _clutter_input_device_wayland_listener; + +#endif /* __CLUTTER_INPUT_DEVICE_WAYLAND_H__ */ diff --git a/clutter/wayland/clutter-stage-wayland.c b/clutter/wayland/clutter-stage-wayland.c deleted file mode 100644 index 427685155..000000000 --- a/clutter/wayland/clutter-stage-wayland.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Matthew Allum - * Robert Bragg - * Kristian Høgsberg - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <fcntl.h> -#include <glib.h> -#include <glib/gstdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <unistd.h> -#include <wayland-util.h> -#include <wayland-client.h> -#include <xf86drm.h> - -#include "clutter-stage-wayland.h" -#include "clutter-wayland.h" -#include "clutter-backend-wayland.h" - -#include "clutter-actor-private.h" -#include "clutter-debug.h" -#include "clutter-event.h" -#include "clutter-enum-types.h" -#include "clutter-feature.h" -#include "clutter-main.h" -#include "clutter-private.h" -#include "clutter-stage-private.h" - -#include "cogl/cogl-framebuffer-private.h" - -static void -wayland_swap_buffers (ClutterStageWayland *stage_wayland); - -static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); - -G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland, - _clutter_stage_wayland, - G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW, - clutter_stage_window_iface_init)); - -#if G_BYTE_ORDER == G_BIG_ENDIAN -#define VISUAL_ARGB_PRE COGL_PIXEL_FORMAT_ARGB_8888_PRE -#define VISUAL_ARGB COGL_PIXEL_FORMAT_ARGB_8888 -#define VISUAL_RGB COGL_PIXEL_FORMAT_RGB_888 -#elif G_BYTE_ORDER == G_LITTLE_ENDIAN -#define VISUAL_ARGB_PRE COGL_PIXEL_FORMAT_BGRA_8888_PRE -#define VISUAL_ARGB COGL_PIXEL_FORMAT_BGRA_8888 -#define VISUAL_RGB COGL_PIXEL_FORMAT_BGR_888 -#endif - -static struct wl_visual * -get_visual (struct wl_display *display, CoglPixelFormat format) -{ - switch (format) - { - case VISUAL_ARGB_PRE: - return wl_display_get_premultiplied_argb_visual (display); - case VISUAL_ARGB: - return wl_display_get_argb_visual (display); - case VISUAL_RGB: - return wl_display_get_rgb_visual (display); - default: - return NULL; - } -} -static ClutterStageWaylandWaylandBuffer * -wayland_create_shm_buffer (ClutterBackendWayland *backend_wayland, - cairo_rectangle_int_t *geom) -{ - ClutterStageWaylandWaylandBufferSHM *buffer; - struct wl_visual *visual; - CoglHandle tex; - CoglTextureFlags flags = COGL_TEXTURE_NONE; /* XXX: tweak flags? */ - CoglPixelFormat format = VISUAL_ARGB_PRE; - int fd; - gchar tmp[] = "/tmp/clutter-wayland-shm-XXXXXX"; - - buffer = g_slice_new (ClutterStageWaylandWaylandBufferSHM); - - buffer->buffer.type = BUFFER_TYPE_SHM; - - tex = cogl_texture_new_with_size ((unsigned int) geom->width, - (unsigned int) geom->height, - flags, format); - buffer->format = format; - buffer->stride = cogl_texture_get_rowstride(tex); - buffer->size = cogl_texture_get_data(tex, format, buffer->stride, NULL); - buffer->buffer.tex = tex; - - fd = g_mkstemp_full(tmp, O_RDWR, 0600); - ftruncate(fd, buffer->size); - buffer->data = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - - g_unlink(tmp); - - visual = get_visual (backend_wayland->wayland_display, format); - - buffer->buffer.wayland_buffer = - wl_shm_create_buffer (backend_wayland->wayland_shm, - fd, - geom->width, - geom->height, - buffer->stride, visual); - close(fd); - return &buffer->buffer; -} - -static ClutterStageWaylandWaylandBuffer * -wayland_create_drm_buffer (ClutterBackendWayland *backend_wayland, - cairo_rectangle_int_t *geom) -{ - EGLDisplay edpy = clutter_wayland_get_egl_display (); - struct wl_visual *visual; - EGLint name, stride; - ClutterStageWaylandWaylandBufferDRM *buffer; - EGLint image_attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - buffer = g_slice_new (ClutterStageWaylandWaylandBufferDRM); - - buffer->buffer.type = BUFFER_TYPE_DRM; - - image_attribs[1] = geom->width; - image_attribs[3] = geom->height; - buffer->drm_image = backend_wayland->create_drm_image (edpy, image_attribs); - glGenTextures (1, &buffer->texture); - glBindTexture (GL_TEXTURE_2D, buffer->texture); - backend_wayland->image_target_texture_2d (GL_TEXTURE_2D, buffer->drm_image); - - buffer->buffer.tex = cogl_texture_new_from_foreign (buffer->texture, - GL_TEXTURE_2D, - geom->width, - geom->height, - 0, - 0, - VISUAL_ARGB_PRE); - - backend_wayland->export_drm_image (edpy, buffer->drm_image, - &name, NULL, &stride); - visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE); - buffer->buffer.wayland_buffer = - wl_drm_create_buffer (backend_wayland->wayland_drm, - name, - geom->width, - geom->height, - stride, visual); - - return &buffer->buffer; -} - -static ClutterStageWaylandWaylandBuffer * -wayland_create_buffer (cairo_rectangle_int_t *geom) -{ - ClutterBackend *backend = clutter_get_default_backend (); - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - ClutterStageWaylandWaylandBuffer *buffer; - cairo_rectangle_int_t rect; - - if (backend_wayland->drm_enabled && - backend_wayland->wayland_drm != NULL) - buffer = wayland_create_drm_buffer (backend_wayland, geom); - else if (backend_wayland->wayland_shm != NULL) - buffer = wayland_create_shm_buffer (backend_wayland, geom); - else - return NULL; - - buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex); - - rect.x = geom->x; - rect.y = geom->y; - rect.width = geom->width; - rect.height = geom->height; - buffer->dirty_region = cairo_region_create_rectangle (&rect); - - return buffer; -} - -static void -wayland_free_shm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer) -{ - ClutterStageWaylandWaylandBufferSHM *buffer; - - buffer = (ClutterStageWaylandWaylandBufferSHM *)generic_buffer; - - munmap(buffer->data, buffer->size); - g_slice_free (ClutterStageWaylandWaylandBufferSHM, buffer); -} - -static void -wayland_free_drm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer) -{ - ClutterBackend *backend = clutter_get_default_backend (); - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - EGLDisplay edpy = clutter_wayland_get_egl_display (); - ClutterStageWaylandWaylandBufferDRM *buffer; - - buffer = (ClutterStageWaylandWaylandBufferDRM *)generic_buffer; - - glDeleteTextures (1, &buffer->texture); - backend_wayland->destroy_image (edpy, buffer->drm_image); - g_slice_free (ClutterStageWaylandWaylandBufferDRM, buffer); -} - -static void -wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer) -{ - cogl_handle_unref (buffer->tex); - wl_buffer_destroy (buffer->wayland_buffer); - cogl_handle_unref (buffer->offscreen); - - if (buffer->type == BUFFER_TYPE_DRM) - wayland_free_drm_buffer(buffer); - else if (buffer->type == BUFFER_TYPE_SHM) - wayland_free_shm_buffer(buffer); -} - -static void -clutter_stage_wayland_unrealize (ClutterStageWindow *stage_window) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - - if (stage_wayland->front_buffer) - { - wayland_free_buffer (stage_wayland->front_buffer); - stage_wayland->front_buffer = NULL; - } - - if (stage_wayland->back_buffer) - { - wayland_free_buffer (stage_wayland->back_buffer); - stage_wayland->back_buffer = NULL; - } - - wayland_free_buffer (stage_wayland->pick_buffer); -} - -static gboolean -clutter_stage_wayland_realize (ClutterStageWindow *stage_window) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - ClutterBackend *backend = clutter_get_default_backend (); - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - gfloat width, height; - - clutter_actor_get_size (CLUTTER_ACTOR (stage_wayland->wrapper), - &width, &height); - stage_wayland->pending_allocation.width = (gint)width; - stage_wayland->pending_allocation.height = (gint)height; - stage_wayland->allocation = stage_wayland->pending_allocation; - - stage_wayland->wayland_surface = - wl_compositor_create_surface (backend_wayland->wayland_compositor); - wl_surface_set_user_data (stage_wayland->wayland_surface, stage_wayland); - - stage_wayland->pick_buffer = - wayland_create_buffer (&stage_wayland->allocation); - - return TRUE; -} - -static int -clutter_stage_wayland_get_pending_swaps (ClutterStageWindow *stage_window) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - - return stage_wayland->pending_swaps; -} - -static void -clutter_stage_wayland_set_fullscreen (ClutterStageWindow *stage_window, - gboolean fullscreen) -{ - g_warning ("Stage of type '%s' do not support ClutterStage::set_fullscreen", - G_OBJECT_TYPE_NAME (stage_window)); -} - -static void -clutter_stage_wayland_set_title (ClutterStageWindow *stage_window, - const gchar *title) -{ - g_warning ("Stage of type '%s' do not support ClutterStage::set_title", - G_OBJECT_TYPE_NAME (stage_window)); -} - -static void -clutter_stage_wayland_set_cursor_visible (ClutterStageWindow *stage_window, - gboolean cursor_visible) -{ - g_warning ("Stage of type '%s' do not support ClutterStage::set_cursor_visible", - G_OBJECT_TYPE_NAME (stage_window)); -} - -static ClutterActor * -clutter_stage_wayland_get_wrapper (ClutterStageWindow *stage_window) -{ - return CLUTTER_ACTOR (CLUTTER_STAGE_WAYLAND (stage_window)->wrapper); -} - -static void -clutter_stage_wayland_show (ClutterStageWindow *stage_window, - gboolean do_raise) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - - clutter_actor_map (CLUTTER_ACTOR (stage_wayland->wrapper)); -} - -static void -clutter_stage_wayland_hide (ClutterStageWindow *stage_window) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - - clutter_actor_unmap (CLUTTER_ACTOR (stage_wayland->wrapper)); -} - -static void -clutter_stage_wayland_get_geometry (ClutterStageWindow *stage_window, - cairo_rectangle_int_t *geometry) -{ - if (geometry != NULL) - { - ClutterStageWayland *stage_wayland = - CLUTTER_STAGE_WAYLAND (stage_window); - - *geometry = stage_wayland->allocation; - } -} - -static void -clutter_stage_wayland_resize (ClutterStageWindow *stage_window, - gint width, - gint height) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - - fprintf (stderr, "resize %dx%d\n", width, height); - - stage_wayland->pending_allocation.width = width; - stage_wayland->pending_allocation.height = height; - - /* FIXME: Shouldn't the stage repaint everything when it gets resized? */ - cairo_region_union_rectangle (stage_wayland->repaint_region, - &stage_wayland->pending_allocation); -} - -#define CAIRO_REGION_FULL ((cairo_region_t *) 1) - -static gboolean -clutter_stage_wayland_has_redraw_clips (ClutterStageWindow *stage_window) -{ - return TRUE; -} - -static gboolean -clutter_stage_wayland_ignoring_redraw_clips (ClutterStageWindow *stage_window) -{ - return FALSE; -} - -static void -clutter_stage_wayland_add_redraw_clip (ClutterStageWindow *stage_window, - cairo_rectangle_int_t *stage_clip) -{ - ClutterStageWayland *stage_wayland = CLUTTER_STAGE_WAYLAND (stage_window); - cairo_rectangle_int_t rect; - - if (stage_clip == NULL) - rect = stage_wayland->allocation; - else - rect = stage_clip; - - if (stage_wayland->repaint_region == NULL) - stage_wayland->repaint_region = cairo_region_create_rectangle (&rect); - else - cairo_region_union_rectangle (stage_wayland->repaint_region, &rect); -} - -static void -clutter_stage_window_iface_init (ClutterStageWindowIface *iface) -{ - iface->realize = clutter_stage_wayland_realize; - iface->unrealize = clutter_stage_wayland_unrealize; - iface->get_pending_swaps = clutter_stage_wayland_get_pending_swaps; - iface->set_fullscreen = clutter_stage_wayland_set_fullscreen; - iface->set_title = clutter_stage_wayland_set_title; - iface->set_cursor_visible = clutter_stage_wayland_set_cursor_visible; - iface->get_wrapper = clutter_stage_wayland_get_wrapper; - iface->get_geometry = clutter_stage_wayland_get_geometry; - iface->resize = clutter_stage_wayland_resize; - iface->show = clutter_stage_wayland_show; - iface->hide = clutter_stage_wayland_hide; - - iface->add_redraw_clip = clutter_stage_wayland_add_redraw_clip; - iface->has_redraw_clips = clutter_stage_wayland_has_redraw_clips; - iface->ignoring_redraw_clips = clutter_stage_wayland_ignoring_redraw_clips; -} - -static void -_clutter_stage_wayland_class_init (ClutterStageWaylandClass *klass) -{ -} - -static void -_clutter_stage_wayland_init (ClutterStageWayland *stage_wayland) -{ - stage_wayland->allocation.x = 0; - stage_wayland->allocation.y = 0; - stage_wayland->allocation.width = 640; - stage_wayland->allocation.height = 480; - stage_wayland->save_allocation = stage_wayland->allocation; -} - -static void -wayland_frame_callback (void *data, uint32_t _time) -{ - ClutterStageWayland *stage_wayland = data; - - stage_wayland->pending_swaps--; -} - -static void -wayland_damage_buffer(ClutterStageWaylandWaylandBuffer *generic_buffer) -{ - ClutterStageWaylandWaylandBufferSHM *buffer; - int size; - - if (generic_buffer->type != BUFFER_TYPE_SHM) - return; - - buffer = (ClutterStageWaylandWaylandBufferSHM *)generic_buffer; - - size = cogl_texture_get_data(buffer->buffer.tex, buffer->format, - buffer->stride, NULL); - g_assert(size == (int)buffer->size); - - (void) cogl_texture_get_data(buffer->buffer.tex, buffer->format, - buffer->stride, buffer->data); - -} - -static void -wayland_swap_buffers (ClutterStageWayland *stage_wayland) -{ - ClutterBackend *backend = clutter_get_default_backend (); - ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - ClutterStageWaylandWaylandBuffer *buffer; - - buffer = stage_wayland->front_buffer; - stage_wayland->front_buffer = stage_wayland->back_buffer; - stage_wayland->back_buffer = buffer; - - wayland_damage_buffer(stage_wayland->front_buffer); - - wl_surface_attach (stage_wayland->wayland_surface, - stage_wayland->front_buffer->wayland_buffer, - /* 0,0 here is "relative to the old buffer," not absolute */ - 0, 0); - wl_surface_map_toplevel (stage_wayland->wayland_surface); - - stage_wayland->pending_swaps++; - wl_display_frame_callback (backend_wayland->wayland_display, - wayland_frame_callback, - stage_wayland); -} - -static void -_clutter_stage_wayland_repair_dirty(ClutterStageWayland *stage_wayland, - ClutterStage *stage) -{ - CoglMaterial *outline = NULL; - CoglHandle vbo; - float vertices[8], texcoords[8]; - CoglMatrix modelview; - cairo_region_t *dirty; - cairo_rectangle_int_t rect; - int i, count; - float width, height; - - dirty = stage_wayland->back_buffer->dirty_region; - stage_wayland->back_buffer->dirty_region = NULL; - cairo_region_subtract (dirty, stage_wayland->repaint_region); - width = stage_wayland->allocation.width; - height = stage_wayland->allocation.height; - - /* If this is the first time we render, there is no front buffer to - * copy back from, but then the dirty region not covered by the - * repaint should be empty, because we repaint the entire stage. - * - * assert(stage_wayland->front_buffer != NULL) || - * cairo_region_is_empty(dirty); - * - * FIXME: in test-rotate, the stage never queues a full repaint - * initially, it's restricted to the paint box of it's rotating - * children. - */ - - if (!stage_wayland->front_buffer) - return; - - outline = cogl_material_new (); - cogl_material_set_layer (outline, 0, stage_wayland->front_buffer->tex); - count = cairo_region_num_rectangles (dirty); - - for (i = 0; i < count; i++) - { - cairo_region_get_rectangle (dirty, i, &rect); - vbo = cogl_vertex_buffer_new (4); - - vertices[0] = rect.x - 1; - vertices[1] = rect.y - 1; - vertices[2] = rect.x + rect.width + 1; - vertices[3] = rect.y - 1; - vertices[4] = rect.x + rect.width + 1; - vertices[5] = rect.y + rect.height + 1; - vertices[6] = rect.x - 1; - vertices[7] = rect.y + rect.height + 1; - - cogl_vertex_buffer_add (vbo, - "gl_Vertex", - 2, /* n_components */ - COGL_ATTRIBUTE_TYPE_FLOAT, - FALSE, /* normalized */ - 0, /* stride */ - vertices); - - texcoords[0] = vertices[0] / width; - texcoords[1] = vertices[1] / height; - texcoords[2] = vertices[2] / width; - texcoords[3] = vertices[3] / height; - texcoords[4] = vertices[4] / width; - texcoords[5] = vertices[5] / height; - texcoords[6] = vertices[6] / width; - texcoords[7] = vertices[7] / height; - - cogl_vertex_buffer_add (vbo, - "gl_MultiTexCoord0", - 2, /* n_components */ - COGL_ATTRIBUTE_TYPE_FLOAT, - FALSE, /* normalized */ - 0, /* stride */ - texcoords); - - cogl_vertex_buffer_submit (vbo); - - cogl_push_matrix (); - cogl_matrix_init_identity (&modelview); - _clutter_actor_apply_modelview_transform (CLUTTER_ACTOR (stage), - &modelview); - cogl_set_modelview_matrix (&modelview); - cogl_set_source (outline); - cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_TRIANGLE_FAN, - 0 , 4); - cogl_pop_matrix (); - cogl_object_unref (vbo); - } - - cairo_region_destroy (dirty); -} - -void -_clutter_stage_wayland_repaint_region (ClutterStageWayland *stage_wayland, - ClutterStage *stage) -{ - cairo_rectangle_int_t rect; - int i, count; - - count = cairo_region_num_rectangles (stage_wayland->repaint_region); - for (i = 0; i < count; i++) - { - cairo_region_get_rectangle (stage_wayland->repaint_region, i, &rect); - - cogl_clip_push_window_rectangle (rect.x - 1, - rect.y - 1, - rect.width + 2, - rect.height + 2); - - /* FIXME: We should pass geom in as second arg, but some actors - * cull themselves a little to much. Disable for now.*/ - _clutter_stage_do_paint (stage, NULL); - - cogl_clip_pop (); - } -} - -void -_clutter_stage_wayland_redraw (ClutterStageWayland *stage_wayland, - ClutterStage *stage) -{ - stage_wayland->allocation = stage_wayland->pending_allocation; - - if (!stage_wayland->back_buffer) - { - stage_wayland->back_buffer = - wayland_create_buffer (&stage_wayland->allocation); - } - - cogl_set_framebuffer (stage_wayland->back_buffer->offscreen); - _clutter_stage_maybe_setup_viewport (stage_wayland->wrapper); - - _clutter_stage_wayland_repair_dirty (stage_wayland, stage); - - _clutter_stage_wayland_repaint_region (stage_wayland, stage); - - cogl_flush (); - glFlush (); - - wayland_swap_buffers (stage_wayland); - - if (stage_wayland->back_buffer) - stage_wayland->back_buffer->dirty_region = stage_wayland->repaint_region; - else - cairo_region_destroy (stage_wayland->repaint_region); - - stage_wayland->repaint_region = NULL; - - cogl_set_framebuffer (stage_wayland->pick_buffer->offscreen); - _clutter_stage_maybe_setup_viewport (stage_wayland->wrapper); -} diff --git a/clutter/wayland/clutter-stage-wayland.h b/clutter/wayland/clutter-stage-wayland.h deleted file mode 100644 index e92134b5a..000000000 --- a/clutter/wayland/clutter-stage-wayland.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Matthew Allum - * Robert Bragg - * Kristian Høgsberg - */ - -#ifndef __CLUTTER_STAGE_WAYLAND_H__ -#define __CLUTTER_STAGE_WAYLAND_H__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <glib-object.h> -#include <clutter/clutter-stage.h> - -#define MESA_EGL_NO_X11_HEADERS -#include <EGL/egl.h> -#include <EGL/eglext.h> - -#include "clutter-backend-wayland.h" - - -#define CLUTTER_TYPE_STAGE_WAYLAND (_clutter_stage_wayland_get_type ()) -#define CLUTTER_STAGE_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_WAYLAND, ClutterStageWayland)) -#define CLUTTER_IS_STAGE_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_WAYLAND)) -#define CLUTTER_STAGE_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_WAYLAND, ClutterStageWaylandClass)) -#define CLUTTER_IS_STAGE_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_WAYLAND)) -#define CLUTTER_STAGE_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_WAYLAND, ClutterStageWaylandClass)) - -typedef struct _ClutterStageWayland ClutterStageWayland; -typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass; - -#define BUFFER_TYPE_DRM 1 -#define BUFFER_TYPE_SHM 2 - -typedef struct _ClutterStageWaylandWaylandBuffer -{ - CoglHandle offscreen; - struct wl_buffer *wayland_buffer; - cairo_region_t *dirty_region; - CoglHandle tex; - guint type; -} ClutterStageWaylandWaylandBuffer; - -typedef struct _ClutterStageWaylandWaylandBufferDRM -{ - ClutterStageWaylandWaylandBuffer buffer; - EGLImageKHR drm_image; - GLuint texture; -} ClutterStageWaylandWaylandBufferDRM; - -typedef struct _ClutterStageWaylandWaylandBufferSHM -{ - ClutterStageWaylandWaylandBuffer buffer; - CoglPixelFormat format; - guint8 *data; - size_t size; - unsigned int stride; -} ClutterStageWaylandWaylandBufferSHM; - -struct _ClutterStageWayland -{ - GObject parent_instance; - - /* the stage wrapper */ - ClutterStage *wrapper; - - /* back pointer to the backend */ - ClutterBackendWayland *backend; - - cairo_rectangle_int_t allocation; - cairo_rectangle_int_t save_allocation; - cairo_rectangle_int_t pending_allocation; - struct wl_surface *wayland_surface; - int pending_swaps; - - ClutterStageWaylandWaylandBuffer *front_buffer; - ClutterStageWaylandWaylandBuffer *back_buffer; - ClutterStageWaylandWaylandBuffer *pick_buffer; - cairo_region_t *repaint_region; -}; - -struct _ClutterStageWaylandClass -{ - GObjectClass parent_class; -}; - -GType _clutter_stage_wayland_get_type (void) G_GNUC_CONST; - -void _clutter_stage_wayland_redraw (ClutterStageWayland *stage_wayland, - ClutterStage *stage); - -#endif /* __CLUTTER_STAGE_WAYLAND_H__ */ diff --git a/clutter/wayland/clutter-wayland.h b/clutter/wayland/clutter-wayland.h deleted file mode 100644 index 26b1680c8..000000000 --- a/clutter/wayland/clutter-wayland.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Clutter. - * - * An OpenGL based 'interactive canvas' library. - * - * Copyright (C) 2010 Intel Corporation. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see <http://www.gnu.org/licenses/>. - - * Authors: - * Matthew Allum - * Robert Bragg - * Kristian Høgsberg - */ - -/** - * SECTION:clutter-wayland - * @short_description: Wayland specific API - * - * The Wayland backend for Clutter provides some Wayland specific API - * - * You need to include - * <filename class="headerfile"><clutter/egl/clutter-wayland.h></filename> - * to have access to the functions documented here. - */ - -#ifndef __CLUTTER_WAYLAND_H__ -#define __CLUTTER_WAYLAND_H__ - -#include <glib.h> - -#include <EGL/egl.h> -#include <EGL/eglext.h> - -G_BEGIN_DECLS - -/** - * clutter_wayland_get_egl_display: - * - * Retrieves the <structname>EGLDisplay</structname> used by Clutter - * - * Return value: the EGL display - * - * Since: 1.6 - */ -EGLDisplay clutter_wayland_get_egl_display (void); - -G_END_DECLS - -#endif /* __CLUTTER_WAYLAND_H__ */ diff --git a/configure.ac b/configure.ac index 8545dbbab..1206e72b3 100644 --- a/configure.ac +++ b/configure.ac @@ -253,14 +253,15 @@ AS_CASE([$CLUTTER_FLAVOUR], CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_WAYLAND" SUPPORT_WAYLAND=1 + SUPPORT_EGL=1 - CLUTTER_WINSYS=wayland + CLUTTER_WINSYS=cogl CLUTTER_SONAME_INFIX=wayland PKG_CHECK_EXISTS([gl], [BACKEND_PC_FILES="$BACKEND_PC_FILES gl"], []) PKG_CHECK_EXISTS([egl], [BACKEND_PC_FILES="$BACKEND_PC_FILES egl"], []) - PKG_CHECK_EXISTS([wayland-client xkbcommon], - [BACKEND_PC_FILES="$BACKEND_PC_FILES wayland-client xkbcommon"], []) + PKG_CHECK_EXISTS([wayland-client wayland-egl xkbcommon], + [BACKEND_PC_FILES="$BACKEND_PC_FILES wayland-client wayland-egl xkbcommon"], []) ], [eglx], @@ -423,10 +424,9 @@ AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "x1"]) AM_CONDITIONAL(SUPPORT_OSX, [test "x$CLUTTER_WINSYS" = "xosx"]) AM_CONDITIONAL(SUPPORT_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"]) AM_CONDITIONAL(SUPPORT_CEX100, [test "x$SUPPORT_EGL_PLATFORM_GDL" = "x1"]) -AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$CLUTTER_WINSYS" = "xwayland"]) +AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$SUPPORT_WAYLAND" = "x1"]) AM_CONDITIONAL(SUPPORT_STUB, [test "x$CLUTTER_WINSYS" = "xwin32" -o \ - "x$CLUTTER_WINSYS" = "xosx" -o \ - "x$CLUTTER_WINSYS" = "xwayland"]) + "x$CLUTTER_WINSYS" = "xosx"]) AM_CONDITIONAL(USE_TSLIB, [test "x$have_tslib" = "xyes"]) AM_CONDITIONAL(SUPPORT_EVDEV, [test "x$have_evdev" = "xyes"]) diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 891968bfc..29d7c3b67 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1347,12 +1347,6 @@ clutter_win32_handle_event </SECTION> <SECTION> -<FILE>clutter-wayland</FILE> -<TITLE>Wayland Specific Support</TITLE> -clutter_wayland_get_egl_display -</SECTION> - -<SECTION> <FILE>clutter-version</FILE> <TITLE>Versioning Macros</TITLE> CLUTTER_MAJOR_VERSION |