summaryrefslogtreecommitdiff
path: root/cogl/winsys
diff options
context:
space:
mode:
authorMarco Trevisan (Treviño) <mail@3v1n0.net>2014-11-17 15:49:20 +0100
committerMarco Trevisan (Treviño) <mail@3v1n0.net>2014-11-17 15:49:20 +0100
commit672eff0c6cd36c7bef2fd60997443502221a9e85 (patch)
tree474d038b53bc0fee7d8ed626b6a639607fd9375e /cogl/winsys
parentbf3954ebe346758bdcf5e626b898d5d82534b504 (diff)
cogl: add Mir EGL platform
Diffstat (limited to 'cogl/winsys')
-rw-r--r--cogl/winsys/cogl-winsys-egl-mir-private.h39
-rw-r--r--cogl/winsys/cogl-winsys-egl-mir.c447
2 files changed, 486 insertions, 0 deletions
diff --git a/cogl/winsys/cogl-winsys-egl-mir-private.h b/cogl/winsys/cogl-winsys-egl-mir-private.h
new file mode 100644
index 00000000..b11b29cb
--- /dev/null
+++ b/cogl/winsys/cogl-winsys-egl-mir-private.h
@@ -0,0 +1,39 @@
+/*
+ * Cogl
+ *
+ * A Low-Level GPU Graphics and Utilities API
+ *
+ * Copyright (C) 2011 Canonical Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *
+ */
+
+#ifndef __COGL_WINSYS_EGL_MIR_PRIVATE_H
+#define __COGL_WINSYS_EGL_MIR_PRIVATE_H
+
+#include "cogl-winsys-private.h"
+
+const CoglWinsysVtable *
+_cogl_winsys_egl_mir_get_vtable (void);
+
+#endif /* __COGL_WINSYS_EGL_MIR_PRIVATE_H */
diff --git a/cogl/winsys/cogl-winsys-egl-mir.c b/cogl/winsys/cogl-winsys-egl-mir.c
new file mode 100644
index 00000000..01f0f714
--- /dev/null
+++ b/cogl/winsys/cogl-winsys-egl-mir.c
@@ -0,0 +1,447 @@
+/*
+ * Cogl
+ *
+ * A Low-Level GPU Graphics and Utilities API
+ *
+ * Copyright (C) 2014 Canonical Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ *
+ * Authors:
+ * Marco Trevisan <marco.trevisan@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <mir_toolkit/mir_client_library.h>
+#include <string.h>
+#include <errno.h>
+
+#include "cogl-winsys-egl-mir-private.h"
+#include "cogl-winsys-egl-private.h"
+#include "cogl-renderer-private.h"
+#include "cogl-onscreen-private.h"
+#include "cogl-error-private.h"
+
+static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
+
+static const CoglWinsysVtable *parent_vtable;
+
+typedef struct _CoglRendererMir
+{
+ MirConnection *mir_connection;
+} CoglRendererMir;
+
+typedef struct _CoglDisplayMir
+{
+ MirSurface *dummy_mir_surface;
+} CoglDisplayMir;
+
+typedef struct _CoglOnscreenMir
+{
+ MirSurface *mir_surface;
+ MirSurfaceState last_state;
+} CoglOnscreenMir;
+
+
+static MirPixelFormat
+_mir_connection_get_valid_format (MirConnection *connection)
+{
+ MirPixelFormat formats[mir_pixel_formats];
+ guint valid_formats;
+ guint f;
+
+ mir_connection_get_available_surface_formats(connection, formats,
+ mir_pixel_formats,
+ &valid_formats);
+
+ for (f = 0; f < valid_formats; f++)
+ {
+ switch (formats[f])
+ {
+ case mir_pixel_format_abgr_8888:
+ case mir_pixel_format_xbgr_8888:
+ case mir_pixel_format_argb_8888:
+ case mir_pixel_format_xrgb_8888:
+ return formats[f];
+ default:
+ continue;
+ }
+ }
+
+ return mir_pixel_format_invalid;
+}
+
+static void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererMir *mir_renderer = egl_renderer->platform;
+
+ if (egl_renderer->edpy)
+ eglTerminate (egl_renderer->edpy);
+
+ if (mir_connection_is_valid (mir_renderer->mir_connection))
+ mir_connection_release (mir_renderer->mir_connection);
+
+ g_slice_free (CoglRendererMir, egl_renderer->platform);
+ g_slice_free (CoglRendererEGL, egl_renderer);
+}
+
+static CoglBool
+_cogl_winsys_renderer_connect (CoglRenderer *renderer,
+ CoglError **error)
+{
+ CoglRendererEGL *egl_renderer;
+ CoglRendererMir *mir_renderer;
+ MirEGLNativeDisplayType mir_native_dpy;
+
+ renderer->winsys = g_slice_new0 (CoglRendererEGL);
+ egl_renderer = renderer->winsys;
+ mir_renderer = g_slice_new0 (CoglRendererMir);
+ egl_renderer->platform = mir_renderer;
+
+ egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable;
+
+ mir_renderer->mir_connection = mir_connect_sync (NULL, __PRETTY_FUNCTION__);
+ if (!mir_connection_is_valid (mir_renderer->mir_connection))
+ {
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "Failed to connect mir display");
+ goto error;
+ }
+
+ mir_native_dpy =
+ mir_connection_get_egl_native_display (mir_renderer->mir_connection);
+ egl_renderer->edpy =
+ eglGetDisplay (mir_native_dpy);
+
+ if (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
+ goto error;
+
+ return TRUE;
+
+error:
+ _cogl_winsys_renderer_disconnect (renderer);
+ return FALSE;
+}
+
+static CoglBool
+_cogl_winsys_egl_display_setup (CoglDisplay *display,
+ CoglError **error)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayMir *mir_display;
+
+ mir_display = g_slice_new0 (CoglDisplayMir);
+ egl_display->platform = mir_display;
+
+ return TRUE;
+}
+
+static void
+_cogl_winsys_egl_display_destroy (CoglDisplay *display)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+
+ g_slice_free (CoglDisplayMir, egl_display->platform);
+}
+
+static CoglBool
+make_dummy_surface (CoglDisplay *display,
+ CoglError **error)
+{
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererMir *mir_renderer = egl_renderer->platform;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayMir *mir_display = egl_display->platform;
+ MirEGLNativeWindowType dummy_mir_egl_native_window;
+ MirSurfaceParameters surfaceparm;
+ const char *error_message;
+
+ surfaceparm.name = "CoglDummySurface";
+ surfaceparm.width = 1;
+ surfaceparm.height = 1;
+ surfaceparm.pixel_format = _mir_connection_get_valid_format (mir_renderer->mir_connection);
+ surfaceparm.buffer_usage = mir_buffer_usage_hardware;
+ surfaceparm.output_id = mir_display_output_id_invalid;
+
+ mir_display->dummy_mir_surface =
+ mir_connection_create_surface_sync (mir_renderer->mir_connection, &surfaceparm);
+ if (!mir_display->dummy_mir_surface)
+ {
+ error_message= "Failed to create a dummy mir surface";
+ goto fail;
+ }
+
+ dummy_mir_egl_native_window =
+ mir_surface_get_egl_native_window (mir_display->dummy_mir_surface);
+ if (!dummy_mir_egl_native_window)
+ {
+ error_message= "Failed to get a dummy mir native egl surface";
+ goto fail;
+ }
+
+ egl_display->dummy_surface =
+ eglCreateWindowSurface (egl_renderer->edpy,
+ egl_display->egl_config,
+ (EGLNativeWindowType) dummy_mir_egl_native_window,
+ NULL);
+ if (egl_display->dummy_surface == EGL_NO_SURFACE)
+ {
+ error_message= "Unable to create dummy window surface";
+ goto fail;
+ }
+
+ return TRUE;
+
+ fail:
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "%s", error_message);
+
+ return FALSE;
+}
+
+static CoglBool
+_cogl_winsys_egl_context_created (CoglDisplay *display,
+ CoglError **error)
+{
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglDisplayEGL *egl_display = display->winsys;
+
+ if ((egl_renderer->private_features &
+ COGL_EGL_WINSYS_FEATURE_SURFACELESS_CONTEXT) == 0 &&
+ !make_dummy_surface(display, error))
+ return FALSE;
+
+ if (!_cogl_winsys_egl_make_current (display,
+ egl_display->dummy_surface,
+ egl_display->dummy_surface,
+ egl_display->egl_context))
+ {
+ _cogl_set_error (error,
+ COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "%s",
+ "Unable to eglMakeCurrent with dummy surface");
+ }
+
+ return TRUE;
+}
+
+static void
+_cogl_winsys_egl_cleanup_context (CoglDisplay *display)
+{
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayMir *mir_display = egl_display->platform;
+
+ if (egl_display->dummy_surface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface (egl_renderer->edpy, egl_display->dummy_surface);
+ egl_display->dummy_surface = EGL_NO_SURFACE;
+ }
+
+ if (mir_display->dummy_mir_surface)
+ {
+ mir_surface_release (mir_display->dummy_mir_surface, NULL, NULL);
+ mir_display->dummy_mir_surface = NULL;
+ }
+}
+
+static CoglBool
+_cogl_winsys_egl_context_init (CoglContext *context,
+ CoglError **error)
+{
+ COGL_FLAGS_SET (context->features,
+ COGL_FEATURE_ID_ONSCREEN_MULTIPLE, TRUE);
+ COGL_FLAGS_SET (context->winsys_features,
+ COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
+ TRUE);
+
+ return TRUE;
+}
+
+static CoglBool
+_cogl_winsys_egl_onscreen_init (CoglOnscreen *onscreen,
+ EGLConfig egl_config,
+ CoglError **error)
+{
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglOnscreenMir *mir_onscreen;
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = framebuffer->context;
+ CoglRenderer *renderer = context->display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererMir *mir_renderer = egl_renderer->platform;
+ MirEGLNativeWindowType mir_egl_native_window;
+ MirSurfaceParameters surfaceparm;
+
+ mir_onscreen = g_slice_new0 (CoglOnscreenMir);
+ egl_onscreen->platform = mir_onscreen;
+
+ surfaceparm.name = "CoglSurface";
+ surfaceparm.width = cogl_framebuffer_get_width (framebuffer);
+ surfaceparm.height = cogl_framebuffer_get_height (framebuffer);
+ surfaceparm.pixel_format = _mir_connection_get_valid_format (mir_renderer->mir_connection);
+ surfaceparm.buffer_usage = mir_buffer_usage_hardware;
+ surfaceparm.output_id = mir_display_output_id_invalid;
+
+ mir_onscreen->mir_surface =
+ mir_connection_create_surface_sync (mir_renderer->mir_connection, &surfaceparm);
+
+ mir_onscreen->last_state = mir_surface_get_state (mir_onscreen->mir_surface);
+
+ if (!mir_surface_is_valid (mir_onscreen->mir_surface))
+ {
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Error while creating mir surface for CoglOnscreen");
+ return FALSE;
+ }
+
+ mir_egl_native_window = mir_surface_get_egl_native_window (mir_onscreen->mir_surface);
+ if (!mir_egl_native_window)
+ {
+ _cogl_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Error while getting mir egl native window "
+ "for CoglOnscreen");
+ return FALSE;
+ }
+
+ egl_onscreen->egl_surface =
+ eglCreateWindowSurface (egl_renderer->edpy,
+ egl_config,
+ (EGLNativeWindowType) mir_egl_native_window,
+ NULL);
+
+ return TRUE;
+}
+
+static void
+_cogl_winsys_egl_onscreen_deinit (CoglOnscreen *onscreen)
+{
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglOnscreenMir *mir_onscreen = egl_onscreen->platform;
+
+ if (mir_onscreen->mir_surface)
+ {
+ mir_surface_release (mir_onscreen->mir_surface, NULL, NULL);
+ mir_onscreen->mir_surface = NULL;
+ }
+
+ mir_onscreen->last_state = mir_surface_state_unknown;
+
+ g_slice_free (CoglOnscreenMir, mir_onscreen);
+}
+
+static void
+_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen,
+ CoglBool visibility)
+{
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglOnscreenMir *mir_onscreen = egl_onscreen->platform;
+ MirSurfaceState new_state, current_state;
+
+ current_state = mir_surface_get_state (mir_onscreen->mir_surface);
+
+ if ((visibility && current_state != mir_surface_state_minimized) ||
+ (!visibility && current_state == mir_surface_state_minimized))
+ {
+ return;
+ }
+
+ if (!visibility)
+ {
+ new_state = mir_surface_state_minimized;
+ mir_onscreen->last_state = current_state;
+ }
+ else
+ {
+ new_state = mir_onscreen->last_state;
+ }
+
+ mir_surface_set_state (mir_onscreen->mir_surface, new_state);
+}
+
+MirSurface *
+cogl_mir_onscreen_get_surface (CoglOnscreen *onscreen)
+{
+ CoglOnscreenEGL *egl_onscreen;
+ CoglOnscreenMir *mir_onscreen;
+
+ cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), NULL);
+
+ egl_onscreen = onscreen->winsys;
+ mir_onscreen = egl_onscreen->platform;
+
+ return mir_onscreen->mir_surface;
+}
+
+static const CoglWinsysEGLVtable
+_cogl_winsys_egl_vtable =
+ {
+ .display_setup = _cogl_winsys_egl_display_setup,
+ .display_destroy = _cogl_winsys_egl_display_destroy,
+ .context_created = _cogl_winsys_egl_context_created,
+ .cleanup_context = _cogl_winsys_egl_cleanup_context,
+ .context_init = _cogl_winsys_egl_context_init,
+ .onscreen_init = _cogl_winsys_egl_onscreen_init,
+ .onscreen_deinit = _cogl_winsys_egl_onscreen_deinit
+ };
+
+const CoglWinsysVtable *
+_cogl_winsys_egl_mir_get_vtable (void)
+{
+ static CoglBool vtable_inited = FALSE;
+ static CoglWinsysVtable vtable;
+
+ if (!vtable_inited)
+ {
+ /* The EGL_MIR winsys is a subclass of the EGL winsys so we
+ start by copying its vtable */
+
+ parent_vtable = _cogl_winsys_egl_get_vtable ();
+ vtable = *parent_vtable;
+
+ vtable.id = COGL_WINSYS_ID_EGL_MIR;
+ vtable.name = "EGL_MIR";
+
+ vtable.renderer_connect = _cogl_winsys_renderer_connect;
+ vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect;
+
+ vtable.onscreen_set_visibility =
+ _cogl_winsys_onscreen_set_visibility;
+
+ vtable_inited = TRUE;
+ }
+
+ return &vtable;
+}