77db999339
Added support for Mir, now clutter can natively draw on MirSurfaces. This depends on latest cogl git. Run your clutter apps using CLUTTER_BACKEND=mir Signed-off-by: Emmanuele Bassi <ebassi@gnome.org>
232 lines
6.7 KiB
C
232 lines
6.7 KiB
C
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Copyright (C) 2014 Canonical Ltd.
|
|
*
|
|
* 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:
|
|
* Marco Trevisan <marco.trevisan@canonical.com>
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "clutter-debug.h"
|
|
#include "clutter-main.h"
|
|
#include "clutter-stage-private.h"
|
|
|
|
#include "mir/clutter-backend-mir-priv.h"
|
|
#include "mir/clutter-backend-mir.h"
|
|
#include "mir/clutter-device-manager-mir.h"
|
|
#include "mir/clutter-event-mir.h"
|
|
#include "mir/clutter-stage-mir.h"
|
|
#include "mir/clutter-mir.h"
|
|
|
|
#define clutter_backend_mir_get_type _clutter_backend_mir_get_type
|
|
|
|
G_DEFINE_TYPE (ClutterBackendMir, clutter_backend_mir, CLUTTER_TYPE_BACKEND);
|
|
|
|
static MirConnection *_foreign_connection = NULL;
|
|
static gboolean _no_event_dispatch = FALSE;
|
|
|
|
static gboolean
|
|
clutter_backend_mir_post_parse (ClutterBackend *backend,
|
|
GError **error)
|
|
{
|
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
|
|
|
backend_mir->mir_connection = _foreign_connection;
|
|
if (backend_mir->mir_connection == NULL)
|
|
backend_mir->mir_connection = mir_connect_sync (NULL, "Clutter");
|
|
|
|
if (!mir_connection_is_valid (backend_mir->mir_connection))
|
|
{
|
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
CLUTTER_INIT_ERROR_BACKEND,
|
|
"Failed to open Mir display socket %s",
|
|
mir_connection_get_error_message (backend_mir->mir_connection));
|
|
mir_connection_release (backend_mir->mir_connection);
|
|
return FALSE;
|
|
}
|
|
|
|
g_object_set (clutter_settings_get_default (), "font-dpi", 96 * 1024, NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static CoglRenderer *
|
|
clutter_backend_mir_get_renderer (ClutterBackend *backend,
|
|
GError **error)
|
|
{
|
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
|
CoglRenderer *renderer;
|
|
|
|
CLUTTER_NOTE (BACKEND, "Creating a new Mir renderer");
|
|
|
|
renderer = cogl_renderer_new ();
|
|
|
|
cogl_renderer_set_winsys_id (renderer, COGL_WINSYS_ID_EGL_MIR);
|
|
cogl_mir_renderer_set_foreign_connection (renderer,
|
|
backend_mir->mir_connection);
|
|
|
|
return renderer;
|
|
}
|
|
|
|
static CoglDisplay *
|
|
clutter_backend_mir_get_display (ClutterBackend *backend,
|
|
CoglRenderer *renderer,
|
|
CoglSwapChain *swap_chain,
|
|
GError **error)
|
|
{
|
|
CoglOnscreenTemplate *onscreen_template = NULL;
|
|
CoglDisplay *display;
|
|
|
|
onscreen_template = cogl_onscreen_template_new (swap_chain);
|
|
|
|
if (!cogl_renderer_check_onscreen_template (renderer,
|
|
onscreen_template,
|
|
error))
|
|
goto error;
|
|
|
|
display = cogl_display_new (renderer, onscreen_template);
|
|
|
|
return display;
|
|
|
|
error:
|
|
if (onscreen_template)
|
|
cogl_object_unref (onscreen_template);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
on_mir_event_cb (CoglMirEvent *mir_event,
|
|
void *data)
|
|
{
|
|
ClutterBackend *backend = data;
|
|
_clutter_mir_handle_event (backend, mir_event->surface, mir_event->event);
|
|
}
|
|
|
|
void
|
|
_clutter_events_mir_init (ClutterBackend *backend)
|
|
{
|
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
|
CoglRenderer *cogl_renderer = backend->cogl_renderer;
|
|
|
|
backend->device_manager = _clutter_device_manager_mir_new (backend);
|
|
|
|
if (_no_event_dispatch)
|
|
return;
|
|
|
|
cogl_mir_renderer_add_event_listener (cogl_renderer, on_mir_event_cb, backend);
|
|
backend_mir->mir_source = _clutter_event_source_mir_new ();
|
|
}
|
|
|
|
|
|
static void
|
|
clutter_backend_mir_init (ClutterBackendMir *backend_mir)
|
|
{
|
|
}
|
|
|
|
static void
|
|
clutter_backend_mir_dispose (GObject *gobject)
|
|
{
|
|
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
|
ClutterBackendMir *backend_mir = CLUTTER_BACKEND_MIR (backend);
|
|
CoglRenderer *cogl_renderer = backend->cogl_renderer;
|
|
|
|
g_clear_object (&backend->device_manager);
|
|
g_clear_pointer (&backend_mir->mir_source, g_source_unref);
|
|
cogl_mir_renderer_remove_event_listener (cogl_renderer, on_mir_event_cb,
|
|
backend);
|
|
|
|
G_OBJECT_CLASS (clutter_backend_mir_parent_class)->dispose (gobject);
|
|
}
|
|
|
|
static void
|
|
clutter_backend_mir_class_init (ClutterBackendMirClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
|
|
|
gobject_class->dispose = clutter_backend_mir_dispose;
|
|
|
|
backend_class->stage_window_type = CLUTTER_TYPE_STAGE_MIR;
|
|
|
|
backend_class->post_parse = clutter_backend_mir_post_parse;
|
|
backend_class->get_renderer = clutter_backend_mir_get_renderer;
|
|
backend_class->get_display = clutter_backend_mir_get_display;
|
|
}
|
|
|
|
/**
|
|
* clutter_mir_set_connection
|
|
* @connection: pointer to a mir connection
|
|
*
|
|
* Sets the display connection Clutter should use; must be called
|
|
* before clutter_init(), clutter_init_with_args() or other functions
|
|
* pertaining Clutter's initialization process.
|
|
*
|
|
* If you are parsing the command line arguments by retrieving Clutter's
|
|
* #GOptionGroup with clutter_get_option_group() and calling
|
|
* g_option_context_parse() yourself, you should also call
|
|
* clutter_mir_set_connection() before g_option_context_parse().
|
|
*
|
|
* Since: 1.22
|
|
*/
|
|
void
|
|
clutter_mir_set_connection (MirConnection *connection)
|
|
{
|
|
g_return_if_fail (mir_connection_is_valid (connection));
|
|
|
|
if (_clutter_context_is_initialized ())
|
|
{
|
|
g_warning ("%s() can only be used before calling clutter_init()",
|
|
G_STRFUNC);
|
|
return;
|
|
}
|
|
|
|
_foreign_connection = connection;
|
|
}
|
|
|
|
/**
|
|
* clutter_mir_disable_event_retrieval:
|
|
*
|
|
* Disables the dispatch of the events in the main loop.
|
|
*
|
|
* This is useful for integrating Clutter with another library that will do the
|
|
* event dispatch;
|
|
*
|
|
* This function can only be called before calling clutter_init().
|
|
*
|
|
* This function should not be normally used by applications.
|
|
*
|
|
* Since: 1.22
|
|
*/
|
|
void
|
|
clutter_mir_disable_event_retrieval (void)
|
|
{
|
|
if (_clutter_context_is_initialized ())
|
|
{
|
|
g_warning ("%s() can only be used before calling clutter_init()",
|
|
G_STRFUNC);
|
|
return;
|
|
}
|
|
|
|
_no_event_dispatch = TRUE;
|
|
}
|