summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Spilsbury <sam.spilsbury@canonical.com>2011-06-13 20:09:50 +0800
committerSam Spilsbury <sam.spilsbury@canonical.com>2011-06-13 20:09:50 +0800
commit1d2841bfff3f7508ddb563ec8b7bbb091106e4a5 (patch)
treef6a029192eb71c0fb8ed764b8a5398ac69414c20
parent026af775173e46a3a8acc2535e637502f605b326 (diff)
downloadcompositionkit-1d2841bfff3f7508ddb563ec8b7bbb091106e4a5.tar.gz
compositionkit-1d2841bfff3f7508ddb563ec8b7bbb091106e4a5.tar.bz2
Added CompositionKit Service, this will be the Controller
for the CompositionKit infrastructure
-rw-r--r--CMakeLists.txt21
-rw-r--r--ckservice/ckservice-main.c628
2 files changed, 649 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9a315b1..86a0a89 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -26,6 +26,7 @@ option (BUILD_X11_COMPOSITOR "Build X11 Composition Backend" OFF)
option (BUILD_DRM_COMPOSITOR "Build DRM Composition Backend" OFF)
option (BUILD_WAYLAND_COMPOSITOR "Build Wayland Composition Backend" OFF)
option (BUILD_OPENWFD_COMPOSITOR "Build OpenWF Composition Backend" OFF)
+option (BUILD_COMPOSITIONKIT_SERVICE "Build CompositionKit Service" OFF)
cmake_minimum_required(VERSION 2.8)
@@ -174,3 +175,23 @@ include_directories (${COMPOSITIONKIT_INCLUDE_DIRS} ${compositionkit_BINARY_DIR}
link_directories (${COMPOSITIONKIT_LIBRARY_DIRS})
add_executable (compositionkit ${COMPOSITIONKIT_SRCS})
target_link_libraries (compositionkit ${COMPOSITIONKIT_LIBRARIES})
+
+if (BUILD_COMPOSITIONKIT_SERVICE)
+
+ pkg_check_modules (COMPOSITIONKIT_SERVICE gobject-2.0 gio-2.0 gtk+-2.0 gthread-2.0 x11)
+
+ if (COMPOSITIONKIT_SERVICE_FOUND)
+
+ include_directories (${COMPOSITIONKIT_SERVICE_INCLUDE_DIRS})
+ link_directories (${COMPOSITIONKIT_SERVICE_LIBRARY_DIRS})
+ add_executable (ckservice
+ ckservice/ckservice-main.c)
+ target_link_libraries (ckservice ${COMPOSITIONKIT_SERVICE_LIBRARIES})
+
+ else (COMPOSITIONKIT_SERVICE_FOUND)
+
+ set (BUILD_COMPOSITIONKIT_SERVICE OFF)
+
+ endif (COMPOSITIONKIT_SERVICE_FOUND)
+
+endif (BUILD_COMPOSITIONKIT_SERVICE)
diff --git a/ckservice/ckservice-main.c b/ckservice/ckservice-main.c
new file mode 100644
index 0000000..c01b0bd
--- /dev/null
+++ b/ckservice/ckservice-main.c
@@ -0,0 +1,628 @@
+/*
+ * Copyright © 2010 Canonical Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#ifndef _COMPOSITIONKIT_SERVICE_H_
+#define _COMPOSITIONKIT_SERVICE_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _CompositionKitService CompositionKitService;
+typedef struct _CompositionKitServiceClass CompositionKitServiceClass;
+typedef struct _CompositionKitServicePrivate CompositionKitServicePrivate;
+typedef struct _CompositionKitSurface CompositionKitSurface;
+typedef struct _CompositionKitShader CompositionKitShader;
+typedef struct _CompositionKitUniform CompositionKitUniform;
+typedef struct _CompositionKitAttribute CompositionKitAttribute;
+
+struct _CompositionKitService
+{
+ GObject parent;
+ CompositionKitServicePrivate *priv;
+};
+
+struct _CompositionKitServiceClass
+{
+ GObjectClass parent_class;
+};
+
+static CompositionKitService *static_service = NULL;
+
+struct _CompositionKitServicePrivate
+{
+ GList *surfaces;
+};
+
+struct _CompositionKitSurface
+{
+ gint id;
+ GList *shaders;
+};
+
+typedef enum
+{
+ SHADER_TYPE_FRAGMENT = 0,
+ SHADER_TYPE_VERTEX
+} CKShaderType;
+
+struct _CompositionKitUniform
+{
+ gchar *name;
+ gchar *type;
+ GVariant *data;
+};
+
+struct _CompositionKitAttribute
+{
+ gchar *name;
+ gchar *type;
+ GVariant *data;
+};
+
+struct _CompositionKitShader
+{
+ gchar *name;
+ CKShaderType type;
+ gchar *source;
+ GList *uniforms;
+ GList *attributes;
+};
+
+#define COMPOSITIONKIT_TYPE_SERVICE (compositionkit_service_get_type ())
+
+#define COMPOSITIONKIT_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
+ COMPOSITIONKIT_TYPE_SERVICE, CompositionKitService))
+
+#define COMPOSITIONKIT_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),\
+ COMPOSITIONKIT_TYPE_SERVICE, CompositionKitServiceClass))
+
+#define COMPOSITIONKIT_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),\
+ COMPOSITIONKIT_TYPE_SERVICE))
+
+#define COMPOSITIONKIT_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),\
+ COMPOSITIONKIT_TYPE_SERVICE))
+
+#define COMPOSITIONKIT_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\
+ COMPOSITIONKIT_TYPE_SERVICE, CompositionKitServiceClass))
+
+G_DEFINE_TYPE (CompositionKitService, compositionkit_service, G_TYPE_OBJECT);
+
+#define GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), COMPOSITIONKIT_TYPE_SERVICE, CompositionKitServicePrivate))
+
+G_END_DECLS
+
+#endif
+
+/* Forwards */
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data);
+
+
+static const GDBusInterfaceVTable interface_vtable =
+{
+ handle_method_call,
+ NULL,
+ NULL
+};
+
+
+/* Methods */
+
+static gint
+find_surface_by_id (gconstpointer a,
+ gconstpointer b)
+{
+ CompositionKitSurface *cks = (CompositionKitSurface *) a;
+ gint *req_id = (gint *) b;
+
+ return cks->id == *req_id ? 0 : 1;
+}
+
+static gint
+find_shader_by_name (gconstpointer a,
+ gconstpointer b)
+{
+ CompositionKitShader *cks = (CompositionKitShader *) a;
+ gchar *req_name = (gchar *) b;
+
+ return g_strcmp0 (cks->name, req_name);
+}
+
+static GVariant *
+list_shaders (CompositionKitSurface *surface)
+{
+ GList *list = surface->shaders;
+ GVariantBuilder builder;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(as)"));
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("as"));
+ GVariant *return_value;
+
+ while (list)
+ {
+ g_variant_builder_add (&builder, "s", ((CompositionKitShader *) list->data)->name);
+ list = g_list_next (list);
+ }
+
+ g_variant_builder_close (&builder);
+ return g_variant_builder_end (&builder);
+}
+
+static GVariant *
+list_surfaces (CompositionKitService *service)
+{
+ GList *list = service->priv->surfaces;
+ GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE ("ai"));
+ GVariant *return_value;
+
+ if (!list)
+ {
+ g_variant_builder_unref (builder);
+ return NULL;
+ }
+
+ while (list)
+ {
+ g_variant_builder_add (builder, "i", ((CompositionKitSurface *) list->data)->id);
+ list = g_list_next (list);
+ }
+
+ return_value = g_variant_new ("(ai)", builder);
+ g_variant_builder_unref (builder);
+
+ return return_value;
+}
+
+void
+delete_uniform (CompositionKitUniform *uniform)
+{
+ if (uniform->name)
+ g_free (uniform->name);
+
+ if (uniform->type)
+ g_free (uniform->type);
+
+ if (uniform->data)
+ g_variant_unref (uniform->data);
+
+ g_free (uniform);
+}
+
+void
+delete_attribute (CompositionKitAttribute *attribute)
+{
+ if (attribute->name)
+ g_free (attribute->name);
+
+ if (attribute->type)
+ g_free (attribute->type);
+
+ if (attribute->data)
+ g_variant_unref (attribute->data);
+
+ g_free (attribute);
+}
+
+void
+delete_shader (CompositionKitShader *shader)
+{
+ GList *iter;
+
+ if (shader->name)
+ g_free (shader->name);
+
+ if (shader->source)
+ g_free (shader->source);
+
+ iter = shader->uniforms;
+
+ while (iter)
+ {
+ CompositionKitUniform *uniform = (CompositionKitUniform *) iter;
+ delete_uniform (uniform);
+ iter = g_list_remove_link (iter, iter);
+ }
+
+ iter = shader->attributes;
+
+ while (iter)
+ {
+ CompositionKitAttribute *attribute = (CompositionKitAttribute *) iter;
+ delete_attribute (attribute);
+ iter = g_list_remove_link (iter, iter);
+ }
+
+ g_free (shader);
+}
+
+void
+delete_surface (CompositionKitSurface *surface)
+{
+ GList *iter = surface->shaders;
+
+ while (iter)
+ {
+ CompositionKitShader *shader = (CompositionKitShader *) iter;
+ delete_shader (shader);
+ iter = g_list_remove_link (iter, iter);
+ }
+
+ g_free (surface);
+}
+
+CompositionKitSurface *
+new_surface (gint id)
+{
+ CompositionKitSurface *cks = g_new0 (CompositionKitSurface, 1);
+
+ cks->id = id;
+ cks->shaders = NULL;
+
+ return cks;
+}
+
+CompositionKitShader *
+new_shader (const gchar *name, gint shader_type, gint parent_surface)
+{
+ CompositionKitShader *cks = g_new0 (CompositionKitShader, 1);
+
+ cks->name = g_strdup (name);
+ cks->type = shader_type;
+ cks->source = NULL;
+ cks->uniforms = NULL;
+ cks->attributes = NULL;
+}
+
+CompositionKitUniform *
+new_uniform (const gchar *name, const gchar *type)
+{
+ CompositionKitUniform *cku = g_new0 (CompositionKitUniform, 1);
+
+ cku->name = g_strdup (name);
+ cku->type = g_strdup (type);
+ cku->data = NULL;
+
+ return cku;
+}
+
+CompositionKitAttribute *
+new_attribute (const gchar *name, const gchar *type)
+{
+ CompositionKitAttribute *cka = g_new0 (CompositionKitAttribute, 1);
+
+ cka->name = g_strdup (name);
+ cka->type = g_strdup (type);
+ cka->data = NULL;
+
+ return cka;
+}
+
+static void
+handle_method_call (GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ CompositionKitService *service = COMPOSITIONKIT_SERVICE (user_data);
+
+ if (g_strcmp0 (method_name, "ListSurfaces") == 0)
+ {
+ GVariant *surfaces = list_surfaces (service);
+ if (surfaces)
+ {
+ g_dbus_method_invocation_return_value (invocation,
+ surfaces);
+ g_variant_unref (surfaces);
+ }
+ else
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No Surfaces");
+ }
+ else if (g_strcmp0 (method_name, "ListShaders") == 0)
+ {
+ guint32 id;
+ GList *list = service->priv->surfaces;
+
+ g_variant_get (parameters, "(i)", &id, NULL);
+ list = g_list_find_custom (list, &id, find_surface_by_id);
+
+ if (list)
+ {
+ GVariant *shaders = list_shaders ((CompositionKitSurface *) list->data);
+ g_dbus_method_invocation_return_value (invocation,
+ shaders);
+ g_variant_unref (shaders);
+ }
+ else
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "Surface 0x%x not found", id);
+ }
+ else if (g_strcmp0 (method_name, "AddSurface") == 0)
+ {
+ guint32 id;
+
+ g_variant_get (parameters, "(i)", &id, NULL);
+
+ if (id)
+ {
+ CompositionKitSurface *surf = new_surface (id);
+ service->priv->surfaces = g_list_append (service->priv->surfaces, (gpointer) surf);
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "ID 0x%x not valid", id);
+ }
+ }
+ else if (g_strcmp0 (method_name, "AddShader") == 0)
+ {
+ guint32 id;
+ gchar *string;
+ GList *list;
+
+ g_variant_get (parameters, "(si)", &string, &id, NULL);
+
+ list = g_list_find_custom (service->priv->surfaces, &id, find_surface_by_id);
+
+ if (list)
+ {
+ CompositionKitSurface *surf = (CompositionKitSurface *) list->data;
+ CompositionKitShader *shader = new_shader (string, SHADER_TYPE_FRAGMENT, surf->id);
+
+ surf->shaders = g_list_append (surf->shaders, (gpointer) shader);
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "ID 0x%x not valid for shader %s", id, string);
+ }
+
+ if (string)
+ g_free (string);
+ }
+ else if (g_strcmp0 (method_name, "RemoveShader") == 0)
+ {
+ guint32 id;
+ gchar *string;
+ GList *list;
+
+ g_variant_get (parameters, "(si)", &string, &id, NULL);
+
+ list = g_list_find_custom (service->priv->surfaces, &id, find_surface_by_id);
+
+ if (list)
+ {
+ CompositionKitSurface *surface = (CompositionKitSurface *) list->data;
+ GList *siter;
+
+ siter = g_list_find_custom (surface->shaders, string, find_shader_by_name);
+
+ if (siter)
+ {
+ CompositionKitShader *shader = (CompositionKitShader *) siter->data;
+ delete_shader (shader);
+ surface->shaders = g_list_remove_link (surface->shaders, siter);
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "No shader %s for id %i\n", string, id);
+ }
+ }
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "ID %i not valid for shader %s\n", id, string);
+ }
+
+ if (string)
+ g_free (string);
+ }
+ else if (g_strcmp0 (method_name, "RemoveSurface") == 0)
+ {
+ guint32 id;
+ GList *list;
+
+ g_variant_get (parameters, "(i)", &id, NULL);
+
+ list = g_list_find_custom (service->priv->surfaces, &id, find_surface_by_id);
+
+ if (list)
+ {
+ CompositionKitSurface *surface = (CompositionKitSurface *) list->data;
+ delete_surface (surface);
+ service->priv->surfaces = g_list_remove_link (service->priv->surfaces, list);
+ g_dbus_method_invocation_return_value (invocation, NULL);
+ }
+ else
+ {
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, "ID %i not valid\n", id);
+ }
+ }
+}
+
+/*
+ * GObject stuff
+ */
+
+static void
+compositionkit_service_class_dispose (GObject *object)
+{
+ CompositionKitServicePrivate *priv = COMPOSITIONKIT_SERVICE (object)->priv;
+ gint i;
+ GList *iter;
+
+ iter = priv->surfaces;
+ while (iter)
+ {
+ CompositionKitSurface *surface = (CompositionKitSurface *) iter;
+ GList *siter = surface->shaders;
+
+ while (siter)
+ {
+ delete_shader ((CompositionKitShader *) siter->data);
+ siter = surface->shaders = g_list_remove_link (siter, siter);
+ }
+ }
+ G_OBJECT_CLASS (compositionkit_service_parent_class)->dispose (object);
+}
+
+void
+compositionkit_service_class_init (CompositionKitServiceClass *klass)
+{
+ GObjectClass *obj_class = G_OBJECT_CLASS (klass);
+ obj_class->dispose = compositionkit_service_class_dispose;
+
+ g_type_class_add_private (obj_class, sizeof (CompositionKitServicePrivate));
+}
+
+void
+compositionkit_service_init (CompositionKitService *self)
+{
+ CompositionKitServicePrivate *priv;
+ priv = self->priv = GET_PRIVATE (self);
+}
+
+CompositionKitService *
+compositionkit_service_get_default ()
+{
+ if (static_service == NULL || !COMPOSITIONKIT_IS_SERVICE (static_service))
+ static_service = g_object_new (COMPOSITIONKIT_TYPE_SERVICE, NULL);
+
+ return static_service;
+}
+
+static GDBusNodeInfo *introspection_data = NULL;
+
+static const gchar introspection_xml[] =
+ "<node>"
+ " <interface name='com.canonical.CompositionKit.Service'>"
+ ""
+ " <method name='AddSurface'>"
+ " <arg type='i' name='id' direction='in'/>"
+ " </method>"
+ ""
+ " <method name='AddShader'>"
+ " <arg type='s' name='shader_name' direction='in'/>"
+ " <arg type='i' name='id' direction='in'/>"
+ " </method>"
+ ""
+ " <method name='RemoveShader'>"
+ " <arg type='s' name='shader_name' direction='in'/> "
+ " <arg type='i' name='id' direction='in'/> "
+ " </method>"
+ ""
+ " <method name='RemoveSurface'>"
+ " <arg type='i' name='id' direction='in'/> "
+ " </method>"
+ ""
+ " <method name='ListSurfaces'>"
+ " <arg type='ai' name='surfaces' direction='out'/>"
+ " </method>"
+ ""
+ " <method name='ListShaders'>"
+ " <arg type='i' name='id' direction='in'/>"
+ " <arg type='as' name='shaders' direction='out'/>"
+ " </method>"
+ ""
+ " </interface>"
+ "</node>";
+
+#define S_NAME "com.canonical.CompositionKit.Service"
+#define S_PATH "/com/canonical/CompositionKit"
+#define S_IFACE "com.canonical.CompositionKit.Service"
+
+static void
+on_bus_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ CompositionKitService *service = COMPOSITIONKIT_SERVICE (user_data);
+ guint reg_id;
+
+ reg_id = g_dbus_connection_register_object (connection,
+ S_PATH,
+ introspection_data->interfaces[0],
+ &interface_vtable,
+ service,
+ NULL,
+ NULL);
+
+ g_assert (reg_id > 0);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+}
+
+static void
+on_name_lost (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ CompositionKitService *service = COMPOSITIONKIT_SERVICE (user_data);
+
+ gtk_main_quit ();
+}
+
+gint
+main (gint argc, gchar **argv)
+{
+ CompositionKitService *service;
+ guint owner_id;
+
+ gtk_init (&argc, &argv);
+
+ service = compositionkit_service_get_default ();
+
+ introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+ g_assert (introspection_data != NULL);
+
+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ S_NAME,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ on_bus_acquired,
+ on_name_acquired,
+ on_name_lost,
+ service,
+ NULL);
+
+ gtk_main ();
+
+ g_bus_unown_name (owner_id);
+ g_dbus_node_info_unref (introspection_data);
+ g_object_unref (service);
+
+ return 0;
+}
+