diff mbox

[Branch,~glmark2-dev/glmark2/trunk] Rev 267: NativeStateWayland: Add a Wayland backend to Canvas

Message ID 20130404180021.10538.95875.launchpad@ackee.canonical.com
State Accepted
Headers show

Commit Message

Jesse Barker April 4, 2013, 6 p.m. UTC
Merge authors:
  Rafal Mielniczuk (kruk87)
Related merge proposals:
  https://code.launchpad.net/~kruk87/glmark2/glmark2-wayland/+merge/156907
  proposed by: Rafal Mielniczuk (kruk87)
  review: Approve - Jesse Barker (jesse-barker)
------------------------------------------------------------
revno: 267 [merge]
committer: Jesse Barker <jesse.barker@linaro.org>
branch nick: trunk
timestamp: Thu 2013-04-04 10:59:10 -0700
message:
  NativeStateWayland: Add a Wayland backend to Canvas
added:
  src/native-state-wayland.cpp
  src/native-state-wayland.h
modified:
  src/main.cpp
  src/wscript_build
  wscript


--
lp:glmark2
https://code.launchpad.net/~glmark2-dev/glmark2/trunk

You are subscribed to branch lp:glmark2.
To unsubscribe from this branch go to https://code.launchpad.net/~glmark2-dev/glmark2/trunk/+edit-subscription
diff mbox

Patch

=== modified file 'src/main.cpp'
--- src/main.cpp	2013-03-05 15:48:10 +0000
+++ src/main.cpp	2013-04-03 16:53:35 +0000
@@ -43,6 +43,8 @@ 
 #include "native-state-drm.h"
 #elif GLMARK2_USE_MIR
 #include "native-state-mir.h"
+#elif GLMARK2_USE_WAYLAND
+#include "native-state-wayland.h"
 #endif
 
 #if GLMARK2_USE_EGL
@@ -196,6 +198,8 @@ 
     NativeStateDRM native_state;
 #elif GLMARK2_USE_MIR
     NativeStateMir native_state;
+#elif GLMARK2_USE_WAYLAND
+    NativeStateWayland native_state;
 #endif
 
 #if GLMARK2_USE_EGL

=== added file 'src/native-state-wayland.cpp'
--- src/native-state-wayland.cpp	1970-01-01 00:00:00 +0000
+++ src/native-state-wayland.cpp	2013-04-04 16:53:33 +0000
@@ -0,0 +1,261 @@ 
+/*
+ * Copyright © 2013 Rafal Mielniczuk
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 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 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 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
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Rafal Mielniczuk <rafal.mielniczuk2@gmail.com>
+ */
+
+#include "native-state-wayland.h"
+
+#include <cstring>
+#include <csignal>
+
+const struct wl_registry_listener NativeStateWayland::registry_listener_ = {
+    NativeStateWayland::registry_handle_global,
+    NativeStateWayland::registry_handle_global_remove
+};
+
+const struct wl_shell_surface_listener NativeStateWayland::shell_surface_listener_ = {
+    NativeStateWayland::shell_surface_handle_ping,
+    NativeStateWayland::shell_surface_handle_configure,
+    NativeStateWayland::shell_surface_handle_popup_done
+};
+
+const struct wl_output_listener NativeStateWayland::output_listener_ = {
+    NativeStateWayland::output_handle_geometry,
+    NativeStateWayland::output_handle_mode
+};
+
+volatile bool NativeStateWayland::should_quit_ = false;
+
+NativeStateWayland::NativeStateWayland() : display_(0), window_(0)
+{
+}
+
+NativeStateWayland::~NativeStateWayland()
+{
+    wl_shell_surface_destroy(window_->shell_surface);
+    wl_surface_destroy(window_->surface);
+    wl_egl_window_destroy(window_->native);
+    delete window_;
+
+    wl_shell_destroy(display_->shell);
+    for (OutputsVector::iterator it = display_->outputs.begin();
+         it != display_->outputs.end(); ++it) {
+
+        wl_output_destroy((*it)->output);
+        delete *it;
+    }
+    wl_compositor_destroy(display_->compositor);
+    wl_registry_destroy(display_->registry);
+    wl_display_flush(display_->display);
+    wl_display_disconnect(display_->display);
+    delete display_;
+}
+
+void
+NativeStateWayland::registry_handle_global(void *data, struct wl_registry *registry,
+                                           uint32_t id, const char *interface,
+                                           uint32_t /*version*/)
+{
+    NativeStateWayland *that = static_cast<NativeStateWayland *>(data);
+    if (strcmp(interface, "wl_compositor") == 0) {
+        that->display_->compositor =
+                static_cast<struct wl_compositor *>(
+                    wl_registry_bind(registry,
+                                     id, &wl_compositor_interface, 1));
+    } else if (strcmp(interface, "wl_shell") == 0) {
+        that->display_->shell =
+                static_cast<struct wl_shell *>(
+                    wl_registry_bind(registry,
+                                     id, &wl_shell_interface, 1));
+    } else if (strcmp(interface, "wl_output") == 0) {
+        struct my_output *my_output = new struct my_output;
+        memset(my_output, 0, sizeof(*my_output));
+        my_output->output =
+                static_cast<struct wl_output *>(
+                    wl_registry_bind(registry,
+                                     id, &wl_output_interface, 1));
+        that->display_->outputs.push_back(my_output);
+
+        wl_output_add_listener(my_output->output, &output_listener_, my_output);
+        wl_display_roundtrip(that->display_->display);
+    }
+}
+
+void
+NativeStateWayland::registry_handle_global_remove(void * /*data*/,
+                                                  struct wl_registry * /*registry*/,
+                                                  uint32_t /*name*/)
+{
+}
+
+void
+NativeStateWayland::output_handle_geometry(void * /*data*/, struct wl_output * /*wl_output*/,
+                                           int32_t /*x*/, int32_t /*y*/, int32_t /*physical_width*/,
+                                           int32_t /*physical_height*/, int32_t /*subpixel*/,
+                                           const char * /*make*/, const char * /*model*/,
+                                           int32_t /*transform*/)
+{
+}
+
+void
+NativeStateWayland::output_handle_mode(void *data, struct wl_output * /*wl_output*/,
+                                       uint32_t /*flags*/, int32_t width, int32_t height,
+                                       int32_t refresh)
+{
+    struct my_output *my_output = static_cast<struct my_output *>(data);
+    my_output->width = width;
+    my_output->height = height;
+    my_output->refresh = refresh;
+}
+
+void
+NativeStateWayland::shell_surface_handle_ping(void * /*data*/, struct wl_shell_surface *shell_surface,
+                                              uint32_t serial)
+{
+    wl_shell_surface_pong(shell_surface, serial);
+}
+
+void
+NativeStateWayland::shell_surface_handle_popup_done(void * /*data*/,
+                                                    struct wl_shell_surface * /*shell_surface*/)
+{
+}
+
+void
+NativeStateWayland::shell_surface_handle_configure(void *data, struct wl_shell_surface * /*shell_surface*/,
+                                                   uint32_t /*edges*/, int32_t width, int32_t height)
+{
+    NativeStateWayland *that = static_cast<NativeStateWayland *>(data);
+    that->window_->properties.width = width;
+    that->window_->properties.height = height;
+    wl_egl_window_resize(that->window_->native, width, height, 0, 0);
+}
+
+bool
+NativeStateWayland::init_display()
+{
+    struct sigaction sa;
+    sa.sa_handler = &NativeStateWayland::quit_handler;
+    sa.sa_flags = 0;
+    sigemptyset(&sa.sa_mask);
+
+    sigaction(SIGINT, &sa, NULL);
+    sigaction(SIGTERM, &sa, NULL);
+
+    display_ = new struct my_display;
+
+    if (!display_) {
+        return false;
+    }
+
+    display_->display = wl_display_connect(NULL);
+
+    if (!display_->display) {
+        return false;
+    }
+
+    display_->registry = wl_display_get_registry(display_->display);
+
+    wl_registry_add_listener(display_->registry, &registry_listener_, this);
+
+    wl_display_roundtrip(display_->display);
+
+    return true;
+}
+
+void*
+NativeStateWayland::display()
+{
+    return static_cast<void *>(display_->display);
+}
+
+bool
+NativeStateWayland::create_window(WindowProperties const& properties)
+{
+    struct my_output *output = 0;
+    if (!display_->outputs.empty()) output = display_->outputs.at(0);
+    window_ = new struct my_window;
+    window_->properties = properties;
+    window_->surface = wl_compositor_create_surface(display_->compositor);
+    if (window_->properties.fullscreen && output) {
+        window_->native = wl_egl_window_create(window_->surface,
+                                               output->width, output->height);
+        window_->properties.width = output->width;
+        window_->properties.height = output->height;
+    } else {
+        window_->native = wl_egl_window_create(window_->surface,
+                                               properties.width, properties.height);
+    }
+    window_->shell_surface = wl_shell_get_shell_surface(display_->shell,
+                                                        window_->surface);
+
+    if (window_->shell_surface) {
+        wl_shell_surface_add_listener(window_->shell_surface,
+                                      &shell_surface_listener_, this);
+    }
+
+    wl_shell_surface_set_title(window_->shell_surface, "glmark2");
+
+    if (window_->properties.fullscreen) {
+        wl_shell_surface_set_fullscreen(window_->shell_surface,
+                                        WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER,
+                                        output->refresh, output->output);
+    } else {
+        wl_shell_surface_set_toplevel(window_->shell_surface);
+    }
+
+    return true;
+}
+
+void*
+NativeStateWayland::window(WindowProperties &properties)
+{
+    if (window_) {
+        properties = window_->properties;
+        return window_->native;
+    }
+
+    return 0;
+}
+
+void
+NativeStateWayland::visible(bool /*v*/)
+{
+}
+
+bool
+NativeStateWayland::should_quit()
+{
+    return should_quit_;
+}
+
+void
+NativeStateWayland::flip()
+{
+    int ret = wl_display_dispatch(display_->display);
+    should_quit_ = (ret == -1) || should_quit_;
+}
+
+void
+NativeStateWayland::quit_handler(int /*signum*/)
+{
+    should_quit_ = true;
+}
+

=== added file 'src/native-state-wayland.h'
--- src/native-state-wayland.h	1970-01-01 00:00:00 +0000
+++ src/native-state-wayland.h	2013-04-04 16:53:33 +0000
@@ -0,0 +1,138 @@ 
+/*
+ * Copyright © 2013 Rafal Mielniczuk
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 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 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 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
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Rafal Mielniczuk <rafal.mielniczuk2@gmail.com>
+ */
+
+#ifndef GLMARK2_NATIVE_STATE_WAYLAND_H_
+#define GLMARK2_NATIVE_STATE_WAYLAND_H_
+
+#include <vector>
+#include <wayland-client.h>
+#include <wayland-egl.h>
+
+#include "native-state.h"
+
+class NativeStateWayland : public NativeState
+{
+public:
+    NativeStateWayland();
+    ~NativeStateWayland();
+
+    bool init_display();
+    void* display();
+    bool create_window(WindowProperties const& properties);
+    void* window(WindowProperties& properties);
+    void visible(bool v);
+    bool should_quit();
+    void flip();
+
+private:
+    static void quit_handler(int signum);
+
+    static const struct wl_registry_listener registry_listener_;
+    static const struct wl_shell_surface_listener shell_surface_listener_;
+    static const struct wl_output_listener output_listener_;
+
+    static void
+    registry_handle_global(void *data, struct wl_registry *registry,
+                           uint32_t id, const char *interface,
+                           uint32_t version);
+    static void
+    registry_handle_global_remove(void *data, struct wl_registry *registry,
+                                  uint32_t name);
+
+    static void
+    output_handle_geometry(void *data, struct wl_output *wl_output,
+                           int32_t x, int32_t y, int32_t physical_width,
+                           int32_t physical_height, int32_t subpixel,
+                           const char *make, const char *model,
+                           int32_t transform);
+
+    static void
+    output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
+             int32_t width, int32_t height, int32_t refresh);
+
+    static void
+    shell_surface_handle_ping(void *data, struct wl_shell_surface *shell_surface,
+                              uint32_t serial);
+    static void
+    shell_surface_handle_configure(void *data,
+                                   struct wl_shell_surface *shell_surface,
+                                   uint32_t edges,
+                                   int32_t width, int32_t height);
+    static void
+    shell_surface_handle_popup_done(void *data,
+                                    struct wl_shell_surface *shell_surface);
+
+    static void
+    keyboard_handle_keymap(void *data, struct wl_keyboard *wl_keyboard,
+                           uint32_t format, int32_t fd, uint32_t size);
+
+    static void
+    keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
+                          uint32_t serial, struct wl_surface *surface,
+                          struct wl_array *keys);
+
+    static void
+    keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
+                          uint32_t serial, struct wl_surface *surface);
+
+    static void
+    keyboard_handle_key(void *data, struct wl_keyboard *wl_keyboard,
+                        uint32_t serial, uint32_t time, uint32_t key,
+                        uint32_t state);
+
+    static void
+    keyboard_handle_modifiers(void *data, struct wl_keyboard *wl_keyboard,
+                              uint32_t serial, uint32_t mods_depressed,
+                              uint32_t mods_latched, uint32_t mods_locked,
+                              uint32_t group);
+
+    static void
+    seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
+                             uint32_t capabilities);
+
+    struct my_output {
+        wl_output *output;
+        int32_t width, height;
+        int32_t refresh;
+    };
+
+    typedef std::vector<struct my_output *> OutputsVector;
+
+    struct my_display {
+        wl_display *display;
+        wl_registry *registry;
+        wl_compositor *compositor;
+        wl_shell *shell;
+        OutputsVector outputs;
+    } *display_;
+
+    struct my_window {
+        WindowProperties properties;
+        struct wl_surface *surface;
+        struct wl_egl_window *native;
+        struct wl_shell_surface *shell_surface;
+    } *window_;
+
+    static volatile bool should_quit_;
+};
+
+#endif /* GLMARK2_NATIVE_STATE_WAYLAND_H_ */

=== modified file 'src/wscript_build'
--- src/wscript_build	2013-03-05 15:48:10 +0000
+++ src/wscript_build	2013-04-03 16:29:31 +0000
@@ -14,7 +14,9 @@ 
   'drm-gl' : ['canvas-generic.cpp', 'native-state-drm.cpp', 'gl-state-egl.cpp'],
   'drm-glesv2' : ['canvas-generic.cpp', 'native-state-drm.cpp', 'gl-state-egl.cpp'],
   'mir-gl' : ['canvas-generic.cpp', 'native-state-mir.cpp', 'gl-state-egl.cpp'],
-  'mir-glesv2' : ['canvas-generic.cpp', 'native-state-mir.cpp', 'gl-state-egl.cpp']
+  'mir-glesv2' : ['canvas-generic.cpp', 'native-state-mir.cpp', 'gl-state-egl.cpp'],
+  'wayland-gl' : ['canvas-generic.cpp', 'native-state-wayland.cpp', 'gl-state-egl.cpp'],
+  'wayland-glesv2' : ['canvas-generic.cpp', 'native-state-wayland.cpp', 'gl-state-egl.cpp']
 }
 flavor_uselibs = {
   'x11-gl' : ['x11', 'gl', 'matrix-gl'],
@@ -22,7 +24,9 @@ 
   'drm-gl' : ['drm', 'gbm', 'egl', 'gl', 'matrix-gl'],
   'drm-glesv2' : ['drm', 'gbm', 'egl', 'glesv2', 'matrix-gl'],
   'mir-gl' : ['mirclient', 'egl', 'gl', 'matrix-gl'],
-  'mir-glesv2' : ['mirclient', 'egl', 'glesv2', 'matrix-gl']
+  'mir-glesv2' : ['mirclient', 'egl', 'glesv2', 'matrix-gl'],
+  'wayland-gl' : ['wayland-client', 'wayland-egl', 'egl', 'gl', 'matrix-gl'],
+  'wayland-glesv2' : ['wayland-client', 'wayland-egl', 'egl', 'glesv2', 'matrix-gl']
 }
 flavor_defines = {
   'x11-gl' : ['GLMARK2_USE_X11', 'GLMARK2_USE_GL', 'GLMARK2_USE_GLX'],
@@ -30,7 +34,9 @@ 
   'drm-gl' : ['GLMARK2_USE_DRM', 'GLMARK2_USE_GL', 'GLMARK2_USE_EGL', '__GBM__'],
   'drm-glesv2' : ['GLMARK2_USE_DRM', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL', '__GBM__'],
   'mir-gl' : ['GLMARK2_USE_MIR', 'GLMARK2_USE_GL', 'GLMARK2_USE_EGL'],
-  'mir-glesv2' : ['GLMARK2_USE_MIR', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL']
+  'mir-glesv2' : ['GLMARK2_USE_MIR', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL'],
+  'wayland-gl' : ['GLMARK2_USE_WAYLAND', 'GLMARK2_USE_GL', 'GLMARK2_USE_EGL'],
+  'wayland-glesv2' : ['GLMARK2_USE_WAYLAND', 'GLMARK2_USE_GLESv2', 'GLMARK2_USE_EGL']
 }
 
 includes = ['.', 'scene-ideas', 'scene-terrain']

=== modified file 'wscript'
--- wscript	2013-03-05 15:48:10 +0000
+++ wscript	2013-04-03 16:29:31 +0000
@@ -17,7 +17,9 @@ 
     'drm-gl' : 'glmark2-drm',
     'drm-glesv2' : 'glmark2-es2-drm',
     'mir-gl' : 'glmark2-mir',
-    'mir-glesv2' : 'glmark2-es2-mir'
+    'mir-glesv2' : 'glmark2-es2-mir',
+    'wayland-gl' : 'glmark2-wayland',
+    'wayland-glesv2' : 'glmark2-es2-wayland'
 }
 FLAVORS_STR = ", ".join(FLAVORS.keys())
 
@@ -104,7 +106,9 @@ 
                 ('glesv2', 'glesv2', list_contains(Options.options.flavors, 'glesv2$')),
                 ('libdrm','drm', list_contains(Options.options.flavors, 'drm')),
                 ('gbm','gbm', list_contains(Options.options.flavors, 'drm')),
-                ('mirclient','mirclient', list_contains(Options.options.flavors, 'mir'))]
+                ('mirclient','mirclient', list_contains(Options.options.flavors, 'mir')),
+                ('wayland-client','wayland-client', list_contains(Options.options.flavors, 'wayland')),
+                ('wayland-egl','wayland-egl', list_contains(Options.options.flavors, 'wayland'))]
     for (pkg, uselib, mandatory) in opt_pkgs:
         ctx.check_cfg(package = pkg, uselib_store = uselib,
                       args = '--cflags --libs', mandatory = mandatory)