diff --git a/clutter/Makefile.am b/clutter/Makefile.am index d9846aebf..2d9137cfd 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -580,6 +580,25 @@ egl_source_h = \ egl_source_h_priv = $(srcdir)/egl/clutter-backend-eglnative.h egl_source_c = $(srcdir)/egl/clutter-backend-eglnative.c +# Wayland backend rules +if SUPPORT_WAYLAND +backend_source_h_priv += \ + $(srcdir)/evdev/clutter-xkb-utils.h \ + $(srcdir)/wayland/clutter-backend-wayland.h \ + $(srcdir)/wayland/clutter-stage-wayland.h \ + $(srcdir)/wayland/clutter-event-wayland.h \ + $(srcdir)/wayland/clutter-input-device-wayland.h \ + $(srcdir)/wayland/clutter-device-manager-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 \ + $(srcdir)/wayland/clutter-device-manager-wayland.c +endif # SUPPORT_WAYLAND + if SUPPORT_EGL backend_source_h += $(egl_source_h) backend_source_c += $(egl_source_c) @@ -633,36 +652,6 @@ clutter-osx-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc pc_files += clutter-osx-$(CLUTTER_API_VERSION).pc 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) - -clutter-wayland-$(CLUTTER_API_VERSION).pc: clutter-$(CLUTTER_API_VERSION).pc - $(QUIET_GEN)cp -f $< $(@F) - -pc_files += clutter-wayland-$(CLUTTER_API_VERSION).pc - -compat_libs += \ - libclutter-wayland-$(CLUTTER_API_VERSION).so \ - $(NULL) -endif # SUPPORT_WAYLAND - # cally cally_sources_h = \ $(srcdir)/cally/cally-actor.h \ diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index a108fbb0d..06f4125c7 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -74,6 +74,9 @@ /* XXX - should probably warn, here */ #include "tslib/clutter-event-tslib.h" #endif +#ifdef CLUTTER_INPUT_WAYLAND +#include "wayland/clutter-device-manager-wayland.h" +#endif G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT); @@ -496,6 +499,14 @@ clutter_backend_real_init_events (ClutterBackend *backend) _clutter_events_tslib_init (backend); } else +#endif +#ifdef CLUTTER_INPUT_WAYLAND + if (clutter_check_windowing_backend (CLUTTER_WINDOWING_WAYLAND) && + (input_backend == NULL || input_backend == I_(CLUTTER_INPUT_WAYLAND))) + { + _clutter_events_wayland_init (backend); + } + else #endif if (input_backend != NULL) { diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 4ab31a906..cd3388018 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -3,7 +3,7 @@ * * An OpenGL based 'interactive canvas' library. * - * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2010, 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 @@ -35,252 +35,110 @@ #include -#include -#include -#include - -#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-main.h" #include "clutter-stage-private.h" -static ClutterBackendWayland *backend_singleton = NULL; +#include "wayland/clutter-backend-wayland.h" +#include "wayland/clutter-device-manager-wayland.h" +#include "wayland/clutter-event-wayland.h" +#include "wayland/clutter-stage-wayland.h" +#include "cogl/clutter-stage-cogl.h" -G_DEFINE_TYPE (ClutterBackendWayland, _clutter_backend_wayland, CLUTTER_TYPE_BACKEND); +#include -static gboolean -clutter_backend_wayland_pre_parse (ClutterBackend *backend, - GError **error) -{ - return TRUE; -} +#include + +#define clutter_backend_wayland_get_type _clutter_backend_wayland_get_type + +G_DEFINE_TYPE (ClutterBackendWayland, clutter_backend_wayland, CLUTTER_TYPE_BACKEND); static void -drm_handle_device (void *data, struct wl_drm *drm, const char *device) +clutter_backend_wayland_dispose (GObject *gobject) { - ClutterBackendWayland *backend_wayland = data; - backend_wayland->device_name = g_strdup (device); -} + ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (gobject); -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)) + if (backend_wayland->device_manager) { - clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_wayland->wrapper)); + g_object_unref (backend_wayland->device_manager); + backend_wayland->device_manager = NULL; } - stage_wayland->pending_allocation.width = width; - stage_wayland->pending_allocation.height = height; - stage_wayland->allocation = stage_wayland->pending_allocation; + G_OBJECT_CLASS (clutter_backend_wayland_parent_class)->dispose (gobject); +} - clutter_actor_set_size (CLUTTER_ACTOR (stage_wayland->wrapper), - width, height); +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_wayland->wrapper); + clutter_stage_ensure_viewport (stage_cogl->wrapper); } static const struct wl_shell_listener shell_listener = { - handle_configure, + handle_configure, }; static void display_handle_global (struct wl_display *display, uint32_t id, - const char *interface, + const char *interface, uint32_t version, void *data) { ClutterBackendWayland *backend_wayland = data; - if (strcmp (interface, "compositor") == 0) + if (strcmp (interface, "wl_compositor") == 0) + backend_wayland->wayland_compositor = + wl_display_bind (display, id, &wl_compositor_interface); + else if (strcmp (interface, "wl_input_device") == 0) { - backend_wayland->wayland_compositor = wl_compositor_create (display, id); + ClutterDeviceManager *device_manager = backend_wayland->device_manager; + _clutter_device_manager_wayland_add_input_group (device_manager, id); } - else if (strcmp (interface, "output") == 0) + else if (strcmp (interface, "wl_shell") == 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); + backend_wayland->wayland_shell = + wl_display_bind (display, id, &wl_shell_interface); 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); - } + else if (strcmp (interface, "wl_shm") == 0) + backend_wayland->wayland_shm = + wl_display_bind (display, id, &wl_shm_interface); } -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) + GError **error) { ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - EGLBoolean status; /* 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"); + CLUTTER_INIT_ERROR_BACKEND, + "Failed to open Wayland display socket"); return FALSE; } @@ -288,340 +146,101 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend, _clutter_event_source_wayland_new (backend_wayland->wayland_display); g_source_attach (backend_wayland->wayland_source, NULL); + /* XXX: We require the device manager to exist as soon as we connect to the + * compositor and setup an event handler because we will immediately be + * notified of the available input devices which need to be associated with + * the device-manager. + * + * FIXME: At some point we could perhaps just collapse the + * _clutter_backend_post_parse(), and _clutter_backend_init_events() + * functions into one called something like _clutter_backend_init() which + * would allow the real backend to manage the precise order of + * initialization. + */ + backend_wayland->device_manager = + _clutter_device_manager_wayland_new (backend); + /* 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); - } + /* Wait until we have been notified about the compositor and shell objects */ + while (!(backend_wayland->wayland_compositor && + backend_wayland->wayland_shell)) + wl_display_roundtrip (backend_wayland->wayland_display); 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) +static CoglRenderer * +clutter_backend_wayland_get_renderer (ClutterBackend *backend, + GError **error) { ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); - const char *error_message; + CoglRenderer *renderer; - 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 + CLUTTER_NOTE (BACKEND, "Creating a new wayland renderer"); - 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; - } + renderer = cogl_renderer_new (); - CLUTTER_NOTE (BACKEND, "Created EGL Context"); - } + cogl_wayland_renderer_set_foreign_display (renderer, + backend_wayland->wayland_display); + cogl_wayland_renderer_set_foreign_compositor (renderer, + backend_wayland->wayland_compositor); + cogl_wayland_renderer_set_foreign_shell (renderer, + backend_wayland->wayland_shell); - 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; - } + return renderer; } -#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) +static CoglDisplay * +clutter_backend_wayland_get_display (ClutterBackend *backend, + CoglRenderer *renderer, + CoglSwapChain *swap_chain, + 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; + CoglOnscreenTemplate *onscreen_template = NULL; + CoglDisplay *display; - if (backend_wayland->egl_context != EGL_NO_CONTEXT) - return TRUE; + onscreen_template = cogl_onscreen_template_new (swap_chain); -#if defined(COGL_HAS_GL) - eglBindAPI (EGL_OPENGL_API); -#else - eglBindAPI (EGL_OPENGL_ES_API); -#endif - egl_extensions = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS); + /* XXX: I have some doubts that this is a good design. + * Conceptually should we be able to check an onscreen_template + * without more details about the CoglDisplay configuration? + */ + if (!cogl_renderer_check_onscreen_template (renderer, + onscreen_template, + error)) + goto error; - 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; - } + display = cogl_display_new (renderer, onscreen_template); - 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 display; - return status; +error: + if (onscreen_template) + cogl_object_unref (onscreen_template); + + return NULL; } 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_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 void -_clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass) +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; + gobject_class->dispose = clutter_backend_wayland_dispose; backend_class->stage_window_type = CLUTTER_TYPE_STAGE_WAYLAND; - 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->create_context = clutter_backend_wayland_create_context; - backend_class->redraw = clutter_backend_wayland_redraw; + backend_class->post_parse = clutter_backend_wayland_post_parse; + backend_class->get_renderer = clutter_backend_wayland_get_renderer; + backend_class->get_display = clutter_backend_wayland_get_display; } static void -_clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland) +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; -} - -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 index c36ecab84..53dd2e0c9 100644 --- a/clutter/wayland/clutter-backend-wayland.h +++ b/clutter/wayland/clutter-backend-wayland.h @@ -3,7 +3,7 @@ * * An OpenGL based 'interactive canvas' library. * - * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2010, 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 @@ -29,11 +29,8 @@ #include #include - -#include -#include - -#include "clutter-wayland.h" +#include +#include #include "clutter-backend-private.h" @@ -53,33 +50,16 @@ 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; + ClutterDeviceManager *device_manager; 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; + GSource *wayland_source; - PFNEGLGETDRMDISPLAYMESA get_drm_display; - PFNEGLCREATEDRMIMAGEMESA create_drm_image; - PFNEGLDESTROYIMAGEKHRPROC destroy_image; - PFNEGLEXPORTDRMIMAGEMESA export_drm_image; - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; + /* event timer */ + GTimer *event_timer; }; struct _ClutterBackendWaylandClass @@ -89,10 +69,6 @@ struct _ClutterBackendWaylandClass 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..75fdf21f1 --- /dev/null +++ b/clutter/wayland/clutter-device-manager-wayland.c @@ -0,0 +1,226 @@ +/* + * 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 . + * + * Authors: + * Emmanuele Bassi + * Robert Bragg + */ + +#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 "wayland/clutter-backend-wayland.h" +#include "clutter-debug.h" +#include "clutter-device-manager-private.h" +#include "clutter-private.h" + +#include "evdev/clutter-xkb-utils.h" + +#include + +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_device_manager_wayland_add_input_group (ClutterDeviceManager *manager, + uint32_t id) +{ + ClutterBackend *backend = _clutter_device_manager_get_backend (manager); + ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); + 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_display_bind (backend_wayland->wayland_display, id, + &wl_input_device_interface); + 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)); +} + +ClutterDeviceManager * +_clutter_device_manager_wayland_new (ClutterBackend *backend) +{ + return g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_WAYLAND, + "backend", backend, + NULL); +} + +void +_clutter_events_wayland_init (ClutterBackend *backend) +{ + ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend); + + /* XXX: We actually create the wayland device manager in the backend + * post_parse vfunc because that's the point where we connect to a compositor + * and that's also the point where we will be notified of input devices so we + * need the device-manager to exist early on. + * + * To be consistent with other clutter backends though we only associate the + * device manager with the backend when _clutter_events_wayland_init() is + * called in _clutter_backend_init_events(). This should still allow the + * runtime selection of an alternative input backend if desired and in that + * case the wayland device manager will be benign. + * + * FIXME: At some point we could perhaps collapse the + * _clutter_backend_post_parse(), and _clutter_backend_init_events() + * functions into one called something like _clutter_backend_init() which + * would allow the real backend to manage the precise order of + * initialization. + */ + + backend->device_manager = g_object_ref (backend_wayland->device_manager); +} + +void +_clutter_events_wayland_uninit (ClutterBackend *backend) +{ + g_object_unref (backend->device_manager); + backend->device_manager = NULL; +} diff --git a/clutter/wayland/clutter-device-manager-wayland.h b/clutter/wayland/clutter-device-manager-wayland.h new file mode 100644 index 000000000..6fc827300 --- /dev/null +++ b/clutter/wayland/clutter-device-manager-wayland.h @@ -0,0 +1,75 @@ +/* + * 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 . + * + * Authors: + * Robert Bragg + */ + +#ifndef __CLUTTER_DEVICE_MANAGER_WAYLAND_H__ +#define __CLUTTER_DEVICE_MANAGER_WAYLAND_H__ + +#include +#include + +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; + +ClutterDeviceManager * +_clutter_device_manager_wayland_new (ClutterBackend *backend); + +void +_clutter_device_manager_wayland_add_input_group (ClutterDeviceManager *manager, + uint32_t id); + +void +_clutter_events_wayland_init (ClutterBackend *backend); + +void +_clutter_events_wayland_uninit (ClutterBackend *backend); + +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..6067b21d7 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); + * writes 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..4ac6b7218 --- /dev/null +++ b/clutter/wayland/clutter-event-wayland.h @@ -0,0 +1,37 @@ +/* + * 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 + * . + + * Authors: + * Robert Bragg + */ + +#ifndef __CLUTTER_EVENT_WAYLAND_H__ +#define __CLUTTER_EVENT_WAYLAND_H__ + +#include +#include + +#include + +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..431efd5d7 100644 --- a/clutter/wayland/clutter-input-device-wayland.c +++ b/clutter/wayland/clutter-input-device-wayland.c @@ -37,48 +37,30 @@ #include "clutter-event-private.h" #include "clutter-private.h" #include "clutter-keysyms.h" -#include "clutter-xkb-utils.h" +#include "evdev/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,15 +220,15 @@ 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; - end = keys->data + keys->size; + end = (uint32_t *)((guint8 *)keys->data + keys->size); device->modifier_state = 0; for (k = keys->data; k < end; k++) device->modifier_state |= device->xkb->map->modmap[*k]; @@ -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..8fa195837 --- /dev/null +++ b/clutter/wayland/clutter-input-device-wayland.h @@ -0,0 +1,56 @@ +/* + * 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 + * . + + * Authors: + * Robert Bragg + */ + +#ifndef __CLUTTER_INPUT_DEVICE_WAYLAND_H__ +#define __CLUTTER_INPUT_DEVICE_WAYLAND_H__ + +#include +#include + +#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 index 022745ab9..0407bf757 100644 --- a/clutter/wayland/clutter-stage-wayland.c +++ b/clutter/wayland/clutter-stage-wayland.c @@ -28,660 +28,54 @@ #include "config.h" #endif -#include #include -#include -#include -#include -#include -#include -#include -#include #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 "clutter-stage-window.h" -#include "cogl/cogl-framebuffer-private.h" +#include -static void -wayland_swap_buffers (ClutterStageWayland *stage_wayland); +static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL; static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface); -enum -{ - PROP_0, - - PROP_BACKEND, - PROP_WRAPPER -}; - G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland, - _clutter_stage_wayland, - G_TYPE_OBJECT, + clutter_stage_wayland, + CLUTTER_TYPE_STAGE_COGL, 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; + ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window); + struct wl_surface *wl_surface; - 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; + clutter_stage_window_parent_iface->realize (stage_window); - stage_wayland->wayland_surface = - wl_compositor_create_surface (backend_wayland->wayland_compositor); - wl_surface_set_user_data (stage_wayland->wayland_surface, stage_wayland); + wl_surface = cogl_wayland_onscreen_get_surface (stage_cogl->onscreen); - stage_wayland->pick_buffer = - wayland_create_buffer (&stage_wayland->allocation); + wl_surface_set_user_data (wl_surface, stage_wayland); 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) +clutter_stage_wayland_init (ClutterStageWayland *stage_wayland) { - 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) { + clutter_stage_window_parent_iface = g_type_interface_peek_parent (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_set_property (GObject *gobject, - guint prop_id, - const GValue *value, - GParamSpec *pspec) +clutter_stage_wayland_class_init (ClutterStageWaylandClass *klass) { - ClutterStageWayland *self = CLUTTER_STAGE_WAYLAND (gobject); - - switch (prop_id) - { - case PROP_BACKEND: - self->backend = g_value_get_object (value); - break; - - case PROP_WRAPPER: - self->wrapper = g_value_get_object (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); - } -} - -static void -_clutter_stage_wayland_class_init (ClutterStageWaylandClass *klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - gobject_class->set_property = clutter_stage_wayland_set_property; - - g_object_class_override_property (gobject_class, PROP_BACKEND, "backend"); - g_object_class_override_property (gobject_class, PROP_WRAPPER, "wrapper"); -} - -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 index e92134b5a..58bb431f7 100644 --- a/clutter/wayland/clutter-stage-wayland.h +++ b/clutter/wayland/clutter-stage-wayland.h @@ -3,7 +3,7 @@ * * An OpenGL based 'interactive canvas' library. * - * Copyright (C) 2010 Intel Corporation. + * Copyright (C) 2010,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 @@ -34,14 +34,9 @@ #include #include -#define MESA_EGL_NO_X11_HEADERS -#include -#include +#include "cogl/clutter-stage-cogl.h" -#include "clutter-backend-wayland.h" - - -#define CLUTTER_TYPE_STAGE_WAYLAND (_clutter_stage_wayland_get_type ()) +#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)) @@ -51,64 +46,16 @@ 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; + ClutterStageCogl parent_instance; }; struct _ClutterStageWaylandClass { - GObjectClass parent_class; + ClutterStageCoglClass parent_class; }; -GType _clutter_stage_wayland_get_type (void) G_GNUC_CONST; - -void _clutter_stage_wayland_redraw (ClutterStageWayland *stage_wayland, - ClutterStage *stage); +GType clutter_stage_wayland_get_type (void) G_GNUC_CONST; #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 . - - * 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 - * <clutter/egl/clutter-wayland.h> - * to have access to the functions documented here. - */ - -#ifndef __CLUTTER_WAYLAND_H__ -#define __CLUTTER_WAYLAND_H__ - -#include - -#include -#include - -G_BEGIN_DECLS - -/** - * clutter_wayland_get_egl_display: - * - * Retrieves the EGLDisplay 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 46398dfa8..9b2cc3187 100644 --- a/configure.ac +++ b/configure.ac @@ -306,19 +306,23 @@ AS_IF([test "x$enable_gdk" = "xyes"], AS_IF([test "x$enable_wayland" = "xyes"], [ CLUTTER_BACKENDS="$CLUTTER_BACKENDS wayland" + CLUTTER_INPUT_BACKENDS="$CLUTTER_INPUT_BACKENDS wayland" experimental_backend="yes" SUPPORT_WAYLAND=1 - SUPPORT_EVDEV=1 - 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"], []) AC_DEFINE([HAVE_CLUTTER_WAYLAND], [1], [Have the Wayland backend]) + ], + [ + # The wayland headers introduce so much symbol shadowing that build + # logs become incomprehensible with -Wshadow so we only use it for + # non-wayland builds. + MAINTAINER_COMPILER_FLAGS="-Wshadow" ]) AS_IF([test "x$enable_cex100" = "xyes"], @@ -456,8 +460,7 @@ AM_CONDITIONAL(SUPPORT_WIN32, [test "x$SUPPORT_WIN32" = "x1"]) AM_CONDITIONAL(SUPPORT_CEX100, [test "x$SUPPORT_EGL_PLATFORM_GDL" = "x1"]) AM_CONDITIONAL(SUPPORT_WAYLAND, [test "x$SUPPORT_WAYLAND" = "x1"]) AM_CONDITIONAL(SUPPORT_STUB, [test "x$SUPPORT_WIN32" = "x1" -o \ - "x$SUPPORT_OSX" = "x1" -o \ - "x$SUPPORT_WAYLAND" = "x1"]) + "x$SUPPORT_OSX" = "x1"]) AM_CONDITIONAL(USE_COGL, [test "x$SUPPORT_COGL" = "x1"]) AM_CONDITIONAL(USE_TSLIB, [test "x$have_tslib" = "xyes"]) @@ -519,6 +522,9 @@ AS_IF([test "x$SUPPORT_EVDEV" = "x1"], AS_IF([test "x$SUPPORT_TSLIB" = "x1"], [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES #define CLUTTER_INPUT_TSLIB \"tslib\""]) +AS_IF([test "x$SUPPORT_WAYLAND" = "x1"], + [CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES +#define CLUTTER_INPUT_WAYLAND \"wayland\""]) # the 'null' input backend is special CLUTTER_CONFIG_DEFINES="$CLUTTER_CONFIG_DEFINES @@ -887,7 +893,8 @@ AC_ARG_ENABLE([maintainer-flags], [], [enable_maintainer_flags=maintainer_flags_default]) -MAINTAINER_COMPILER_FLAGS="-Wall -Wshadow -Wcast-align -Wuninitialized +MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS + -Wall -Wcast-align -Wuninitialized -Wno-strict-aliasing -Wempty-body -Wformat -Wformat-security -Winit-self -Wdeclaration-after-statement -Wvla diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 0bbcabbc9..b965b34ba 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -1352,12 +1352,6 @@ clutter_win32_get_stage_window clutter_win32_handle_event -
-clutter-wayland -Wayland Specific Support -clutter_wayland_get_egl_display -
-
clutter-gdk GDK Specific Support