summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-02-09 21:48:32 +0100
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-02-09 21:48:32 +0100
commit0f49000905ff66d3b85598ad0e117ceebac229ad (patch)
tree12816624907b89eb426e2a929d1d425622aa5804
parent9dc8ec29c02e4cbabb6f3b126b1707c289f6444f (diff)
add cairo-egl-surface demo
-rw-r--r--cairo-egl-wayland-window-surface.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/cairo-egl-wayland-window-surface.c b/cairo-egl-wayland-window-surface.c
new file mode 100644
index 0000000..6e446d0
--- /dev/null
+++ b/cairo-egl-wayland-window-surface.c
@@ -0,0 +1,278 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#include <wayland-client.h>
+#include <wayland-egl.h>
+
+#include <EGL/egl.h>
+
+#include <cairo.h>
+#include <cairo-gl.h>
+
+struct display {
+ struct wl_display *display;
+ struct wl_egl_display *egl_display;
+ struct {
+ struct wl_compositor *compositor;
+ struct wl_shell *shell;
+ } interface;
+
+ struct {
+ EGLDisplay dpy;
+ EGLConfig conf;
+ EGLContext ctx;
+ } egl;
+ cairo_device_t *cairo_device;
+
+ uint32_t mask;
+};
+
+struct window {
+ struct display *display;
+ struct wl_surface *surface;
+ struct wl_egl_window *egl_window;
+
+ int width, height;
+
+ struct {
+ EGLSurface surf;
+ } egl;
+ cairo_surface_t *cairo_surface;
+};
+
+static void
+init_egl(struct display *display)
+{
+ EGLint major, minor;
+ EGLint num_config;
+ EGLint config_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 1,
+ EGL_GREEN_SIZE, 1,
+ EGL_BLUE_SIZE, 1,
+ EGL_DEPTH_SIZE, 1,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+ EGL_NONE
+ };
+
+ display->egl.dpy = eglGetDisplay(display->egl_display);
+ assert(display->egl.dpy);
+
+ assert(eglInitialize(display->egl.dpy, &major, &minor));
+
+ assert(eglBindAPI(EGL_OPENGL_API));
+ assert(eglChooseConfig(display->egl.dpy, config_attribs,
+ &display->egl.conf, 1, &num_config));
+ assert(num_config == 1);
+
+ display->egl.ctx = eglCreateContext(display->egl.dpy, display->egl.conf,
+ EGL_NO_CONTEXT, NULL);
+ assert(display->egl.ctx);
+
+ display->cairo_device = cairo_egl_device_create(display->egl.dpy,
+ display->egl.ctx);
+ assert(display->cairo_device);
+}
+
+static const cairo_user_data_key_t surface_data_key;
+
+static void
+egl_window_surface_data_destroy(void *p)
+{
+ struct window *window = p;
+ struct display *d = window->display;
+
+ eglDestroySurface(d->egl.dpy, window->egl.surf);
+ wl_egl_window_destroy(window->egl_window);
+}
+
+static void
+create_cairo_window_surface(struct display *display, struct window *window)
+{
+ struct wl_visual *visual;
+
+ visual = wl_display_get_premultiplied_argb_visual(display->display);
+ window->egl_window = wl_egl_window_create(display->egl_display,
+ window->surface,
+ window->width,
+ window->height,
+ visual);
+
+ window->egl.surf =
+ eglCreateWindowSurface(display->egl.dpy, display->egl.conf,
+ window->egl_window,
+ NULL);
+
+ window->cairo_surface =
+ cairo_gl_surface_create_for_egl(display->cairo_device,
+ window->egl.surf,
+ window->width,
+ window->height);
+
+ cairo_surface_set_user_data(window->cairo_surface, &surface_data_key,
+ window, egl_window_surface_data_destroy);
+
+}
+
+static void
+redraw(void *data, uint32_t time)
+{
+ struct window *window = data;
+ cairo_t *cr;
+ cairo_pattern_t *pattern;
+ int x,y;
+ int width = window->width;
+ int height = window->height;
+
+ cr = cairo_create(window->cairo_surface);
+
+ int speed_div = 100;
+
+ double pos = time % (speed_div * 360) * 1.0 / speed_div;
+#if 0
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba(cr, 1, 1, 1, 1);
+ cairo_paint(cr);
+
+ /* Quadrate im Hintergrund zeichnen */
+ for (x=0; x<10; x++)
+ for (y=0; y<10; y++)
+ cairo_rectangle(cr, x*10.0, y*10.0, 5, 5);
+ pattern = cairo_pattern_create_radial(50, 50, 5, 50, 50, 50);
+ cairo_pattern_add_color_stop_rgb(pattern, 0, 0.75, 0.15, 0.99);
+ cairo_pattern_add_color_stop_rgb(pattern, 0.9, 1, 1, 1);
+
+ cairo_set_source(cr, pattern);
+#else
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_set_source_rgba(cr, 0, 0, 0, 0);
+ cairo_paint(cr);
+
+ cairo_set_line_width(cr, 9);
+
+ cairo_set_source_rgb(cr, 0.69, 0.19, 0);
+ cairo_arc(cr, width/2, height/2,
+ (width < height ? width : height) / 2 - 10, pos, pos+M_PI);
+ cairo_stroke_preserve(cr);
+
+ cairo_set_source_rgb(cr, 0.3, 0.4, 0.6);
+#endif
+ cairo_fill(cr);
+ cairo_destroy(cr);
+
+ cairo_gl_surface_swapbuffers(window->cairo_surface);
+
+ wl_display_frame_callback(window->display->display, redraw, window);
+}
+
+enum window_location {
+ WINDOW_INTERIOR = 0,
+ WINDOW_RESIZING_TOP = 1,
+ WINDOW_RESIZING_BOTTOM = 2,
+ WINDOW_RESIZING_LEFT = 4,
+ WINDOW_RESIZING_TOP_LEFT = 5,
+ WINDOW_RESIZING_BOTTOM_LEFT = 6,
+ WINDOW_RESIZING_RIGHT = 8,
+ WINDOW_RESIZING_TOP_RIGHT = 9,
+ WINDOW_RESIZING_BOTTOM_RIGHT = 10,
+ WINDOW_RESIZING_MASK = 15,
+ WINDOW_EXTERIOR = 16,
+ WINDOW_TITLEBAR = 17,
+ WINDOW_CLIENT_AREA = 18,
+};
+
+static void
+handle_configure(void *data, struct wl_shell *shell,
+ uint32_t time, uint32_t edges,
+ struct wl_surface *surface,
+ int32_t width, int32_t height)
+{
+ struct window *window = wl_surface_get_user_data(surface);
+ int dx = 0;
+ int dy = 0;
+ int a_width, a_height;
+
+ wl_egl_window_get_attached_size(window->egl_window,
+ &a_width, &a_height);
+
+ if (edges & WINDOW_RESIZING_LEFT)
+ dx = a_width - width;
+
+ if (edges & WINDOW_RESIZING_TOP)
+ dy = a_height - height;
+
+ wl_egl_window_resize(window->egl_window, width, height, dx, dy);
+ cairo_gl_surface_set_size(window->cairo_surface, width, height);
+
+ window->width = width;
+ window->height = height;
+}
+
+static const struct wl_shell_listener wayland_shell_listener = {
+ handle_configure,
+};
+
+static void
+display_handle_global(struct wl_display *display, uint32_t id,
+ const char *interface, uint32_t version, void *data)
+{
+ struct display *d = data;
+
+ if (strcmp(interface, "compositor") == 0) {
+ d->interface.compositor = wl_compositor_create(display, id);
+ } else if (strcmp(interface, "shell") == 0) {
+ d->interface.shell = wl_shell_create(display, id);
+ wl_shell_add_listener(d->interface.shell, &wayland_shell_listener, d);
+ }
+}
+
+static int
+event_mask_update(uint32_t mask, void *data)
+{
+ struct display *d = data;
+
+ d->mask = mask;
+
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct display display = { 0 };
+ struct window window = { 0 };
+
+ window.display = &display;
+ window.width = 100;
+ window.height = 100;
+
+ display.display = wl_display_connect(NULL);
+ assert(display.display);
+
+ display.egl_display = wl_egl_display_create(display.display);
+ assert(display.egl_display);
+
+ wl_display_add_global_listener(display.display,
+ display_handle_global, &display);
+ /* process connection events */
+ wl_display_iterate(display.display, WL_DISPLAY_READABLE);
+
+ init_egl(&display);
+ window.surface =
+ wl_compositor_create_surface(display.interface.compositor);
+ wl_surface_set_user_data(window.surface, &window);
+ create_cairo_window_surface(&display, &window);
+
+ wl_surface_map_toplevel(window.surface);
+
+ wl_display_frame_callback(display.display, redraw, &window);
+
+ wl_display_get_fd(display.display, event_mask_update, &display);
+ while (true)
+ wl_display_iterate(display.display, display.mask);
+
+ return 0;
+}