/* * Copyright © 2011 Alberto Ruiz * Copyright © 2011 Codethink Ltd. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting documentation, and * that the name of the copyright holders not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The copyright holders make no representations * about the suitability of this software for any purpose. It is provided "as * is" without express or implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #define FALSE 0 #define TRUE 1 struct client_info { uint32_t mask; struct wl_compositor *comp; struct wl_egl_display *native; struct wl_egl_window *window; struct wl_display *disp; EGLDisplay egl_display; EGLSurface egl_surface; EGLConfig conf; EGLContext context; struct wl_surface *surface; cairo_device_t *cr_device; cairo_surface_t *cr_surface; int run; }; void wl_egl_init (struct client_info *info) { EGLint major, minor; EGLint n; static const EGLint config_attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, EGL_ALPHA_SIZE, 1, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE }; info->egl_display = eglGetDisplay(info->native); eglInitialize(info->egl_display, &major, &minor); eglBindAPI(EGL_OPENGL_API); eglChooseConfig(info->egl_display, config_attribs, &info->conf, 1, &n); info->context = eglCreateContext(info->egl_display, info->conf, EGL_NO_CONTEXT, NULL); eglMakeCurrent(info->egl_display, NULL, NULL, info->context); info->cr_device = cairo_egl_device_create(info->egl_display, info->context); return; } static int event_mask_update (uint32_t mask, void *data) { ((struct client_info*)data)->mask = mask; return 0; } /* This callback is called by wl_display_frame_callback and performs cairo operations * over the window surface to then swap buffers and show the results in the client window */ static void redraw(struct wl_surface *surface, void *data, uint32_t time) { struct client_info *info = (struct client_info*)data; cairo_t *cr; cr = cairo_create (info->cr_surface); cairo_set_line_width (cr, 1.0); cairo_rectangle (cr, 0.25, 0.25, 70.0, 70.0); cairo_set_source_rgb (cr, (time % 9 + 1) * 0.1, (time % 5 + 1) * 0.1, (time % 3 + 1) * 0.3); cairo_fill (cr); cairo_destroy (cr); cairo_gl_surface_swapbuffers(info->cr_surface); /* We need to call wl_display_frame_callback again if we want to redraw the surface past this point */ } static void display_handle_global (struct wl_display *disp, uint32_t id, const char *iface, uint32_t version, void *data) { struct client_info* info = (struct client_info*)data; fprintf (stderr, "- WAYLAND DISPLAY INTERFACE: %s\n", iface); if (!strcmp(iface, "compositor")) info->comp = wl_compositor_create (disp, id); } /* This callback is called when the connection with the display server * is finished and gets hold of the compositor object to create a window * surface. */ static void sync_handle (void *data) { struct wl_visual *visual; struct client_info *info = (struct client_info*)data; if (!info->comp) { fprintf (stderr, "No compositor object was found\n"); info->run = FALSE; return; } /* The compositor is now available, we crate a window surface */ info->surface = wl_compositor_create_surface(info->comp); visual = wl_display_get_premultiplied_argb_visual(info->disp); info->window = wl_egl_window_create(info->egl_display, info->surface, 100, 100, visual); info->egl_surface = eglCreateWindowSurface(info->egl_display, info->conf, info->window, NULL); eglMakeCurrent(info->egl_display, info->egl_surface, info->egl_surface, info->context); info->cr_surface = cairo_gl_surface_create_for_egl(info->cr_device, info->egl_surface, 100, 100); wl_surface_map_toplevel(info->surface); wl_display_frame_callback(info->disp, info->surface, redraw, info); } int main (int argc, char** argv) { struct client_info info = {0}; struct wl_display *disp = wl_display_connect (NULL); info.run = TRUE; info.disp = disp; wl_display_add_global_listener(disp, display_handle_global, &info); info.native = wl_egl_display_create(disp); wl_egl_init (&info); wl_display_get_fd (disp, event_mask_update, &info); wl_display_sync_callback(disp, sync_handle, &info); while (info.run) wl_display_iterate (disp, info.mask); return 0; }