diff options
author | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-02-09 21:48:32 +0100 |
---|---|---|
committer | Benjamin Franzke <benjaminfranzke@googlemail.com> | 2011-02-09 21:48:32 +0100 |
commit | 0f49000905ff66d3b85598ad0e117ceebac229ad (patch) | |
tree | 12816624907b89eb426e2a929d1d425622aa5804 | |
parent | 9dc8ec29c02e4cbabb6f3b126b1707c289f6444f (diff) |
add cairo-egl-surface demo
-rw-r--r-- | cairo-egl-wayland-window-surface.c | 278 |
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; +} |