gears: Use wayland egl surface instead of images
authorBenjamin Franzke <benjaminfranzke@googlemail.com>
Fri, 18 Feb 2011 22:00:55 +0000 (23:00 +0100)
committerBenjamin Franzke <benjaminfranzke@googlemail.com>
Thu, 17 Mar 2011 14:55:25 +0000 (15:55 +0100)
clients/gears.c
clients/window.c
clients/window.h

index 2df79c3..e64ff3e 100644 (file)
 #include <unistd.h>
 #include <math.h>
 #include <time.h>
-#include <cairo.h>
 #include <glib.h>
 
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
 #include <GL/gl.h>
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
@@ -51,14 +48,11 @@ struct gears {
        struct display *d;
 
        EGLDisplay display;
+       EGLDisplay config;
        EGLContext context;
        GLfloat angle;
-       cairo_surface_t *cairo_surface;
 
        GLint gear_list[3];
-       GLuint fbo, color_rbo[2], depth_rbo;
-       cairo_surface_t *surface[2];
-       int current;
 };
 
 struct gear_template {
@@ -203,55 +197,27 @@ make_gear(const struct gear_template *t)
 }
 
 static void
-allocate_buffer(struct gears *gears)
-{
-       EGLImageKHR image;
-       struct rectangle allocation;
-
-       window_draw(gears->window);
-
-       gears->surface[gears->current] = window_get_surface(gears->window);
-#ifdef HAVE_CAIRO_EGL
-       image = display_get_image_for_egl_image_surface(gears->display,
-                                                       gears->surface[gears->current]);
-#else /* XXX: hack to make Wayland compile, even if this example doesn't run */
-       die("gears cannot allocate buffer: it was compiled without cairo-gl\n");
-       return;
-#endif
-       if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context))
-               die("faile to make context current\n");
-
-       glBindRenderbuffer(GL_RENDERBUFFER_EXT,
-                          gears->color_rbo[gears->current]);
-       glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
-
-       glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo);
-       window_get_child_allocation(gears->window, &allocation);
-       glRenderbufferStorage(GL_RENDERBUFFER_EXT,
-                             GL_DEPTH_COMPONENT,
-                             allocation.width + 20 + 32,
-                             allocation.height + 60 + 32);
-}
-
-static void
 draw_gears(struct gears *gears)
 {
        GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+       struct rectangle window_allocation;
        struct rectangle allocation;
 
-       if (gears->surface[gears->current] == NULL)
-               allocate_buffer(gears);
-
-       glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT,
-                                 GL_COLOR_ATTACHMENT0_EXT,
-                                 GL_RENDERBUFFER_EXT,
-                                 gears->color_rbo[gears->current]);
+       window_draw(gears->window);
 
        window_get_child_allocation(gears->window, &allocation);
-       glViewport(allocation.x, allocation.y,
-                  allocation.width, allocation.height);
-       glScissor(allocation.x, allocation.y,
+       window_get_allocation(gears->window, &window_allocation);
+
+       display_acquire_window_surface(gears->d,
+                                      gears->window,
+                                      gears->context);
+       
+       glViewport(allocation.x,
+                  window_allocation.height - allocation.height - allocation.x,
                   allocation.width, allocation.height);
+       glScissor(allocation.x,
+                 window_allocation.height - allocation.height - allocation.y,
+                 allocation.width, allocation.height);
 
        glEnable(GL_SCISSOR_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -286,7 +252,7 @@ draw_gears(struct gears *gears)
 
        glFlush();
 
-       window_set_surface(gears->window, gears->surface[gears->current]);
+       display_release(gears->d);
        window_flush(gears->window);
 }
 
@@ -296,11 +262,6 @@ resize_handler(struct window *window,
 {
        struct gears *gears = data;
 
-       cairo_surface_destroy(gears->surface[0]);
-       gears->surface[0] = NULL;
-       cairo_surface_destroy(gears->surface[1]);
-       gears->surface[1] = NULL;
-
        /* Constrain child size to be square and at least 300x300 */
        if (width > height)
                height = width;
@@ -338,8 +299,6 @@ frame_callback(void *data, uint32_t time)
 {
        struct gears *gears = data;
 
-       gears->current = 1 - gears->current;
-
        gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
 
        window_schedule_redraw(gears->window);
@@ -359,7 +318,6 @@ gears_create(struct display *display)
        gears->d = display;
        gears->window = window_create(display, width, height);
        window_set_title(gears->window, "Wayland Gears");
-       window_set_buffer_type(gears->window, WINDOW_BUFFER_TYPE_EGL_IMAGE);
 
        gears->display = display_get_egl_display(gears->d);
        if (gears->display == NULL)
@@ -367,24 +325,16 @@ gears_create(struct display *display)
 
        eglBindAPI(EGL_OPENGL_API);
 
-       gears->context = eglCreateContext(gears->display,
-                                         NULL, EGL_NO_CONTEXT, NULL);
+       gears->config = display_get_egl_config(gears->d);
+
+       gears->context = eglCreateContext(gears->display, gears->config,
+                                         EGL_NO_CONTEXT, NULL);
        if (gears->context == NULL)
                die("failed to create context\n");
 
        if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context))
                die("faile to make context current\n");
 
-       glGenFramebuffers(1, &gears->fbo);
-       glBindFramebuffer(GL_FRAMEBUFFER_EXT, gears->fbo);
-
-       glGenRenderbuffers(2, gears->color_rbo);
-       glGenRenderbuffers(1, &gears->depth_rbo);
-       glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo);
-       glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT,
-                                 GL_DEPTH_ATTACHMENT_EXT,
-                                 GL_RENDERBUFFER_EXT,
-                                 gears->depth_rbo);
        for (i = 0; i < 3; i++) {
                gears->gear_list[i] = glGenLists(1);
                glNewList(gears->gear_list[i], GL_COMPILE);
index 4792710..6e7ef9b 100644 (file)
@@ -870,7 +870,10 @@ window_draw_decorations(struct window *window)
 
        cairo_destroy(cr);
 
+       /* FIXME: this breakes gears, fix cairo? */
+#if 0 
        cairo_device_flush (window->display->device);
+#endif
 }
 
 void
@@ -1261,6 +1264,13 @@ static const struct wl_shell_listener shell_listener = {
 };
 
 void
+window_get_allocation(struct window *window,
+                     struct rectangle *allocation)
+{
+       *allocation = window->allocation;
+}
+
+void
 window_get_child_allocation(struct window *window,
                            struct rectangle *allocation)
 {
@@ -1850,6 +1860,12 @@ display_get_egl_display(struct display *d)
        return d->dpy;
 }
 
+EGLConfig
+display_get_egl_config(struct display *d)
+{
+       return d->conf;
+}
+
 struct wl_shell *
 display_get_shell(struct display *display)
 {
@@ -1857,6 +1873,35 @@ display_get_shell(struct display *display)
 }
 
 void
+display_acquire_window_surface(struct display *display,
+                              struct window *window,
+                              EGLContext ctx)
+{
+       struct egl_window_surface_data *data;
+
+       if (!window->cairo_surface)
+               return;
+
+       if (!ctx)
+               ctx = display->ctx;
+
+       data = cairo_surface_get_user_data(window->cairo_surface,
+                                          &surface_data_key);
+
+       cairo_device_acquire(display->device);
+       if (!eglMakeCurrent(display->dpy, data->surf, data->surf, ctx))
+               fprintf(stderr, "failed to make surface current\n");
+}
+
+void
+display_release(struct display *display)
+{
+       if (!eglMakeCurrent(display->dpy, NULL, NULL, display->ctx))
+               fprintf(stderr, "failed to make context current\n");
+       cairo_device_release(display->device);
+}
+
+void
 display_run(struct display *d)
 {
        g_main_loop_run(d->loop);
index c1c5212..538ff07 100644 (file)
@@ -26,6 +26,7 @@
 #include <X11/extensions/XKBcommon.h>
 #include <glib.h>
 #include <wayland-client.h>
+#include <cairo.h>
 
 struct window;
 
@@ -55,6 +56,16 @@ display_get_shell(struct display *display);
 EGLDisplay
 display_get_egl_display(struct display *d);
 
+EGLConfig
+display_get_egl_config(struct display *d);
+
+void
+display_acquire_window_surface(struct display *display,
+                              struct window *window,
+                              EGLContext ctx);
+void
+display_release(struct display *display);
+
 #ifdef HAVE_CAIRO_EGL
 EGLImageKHR
 display_get_image_for_egl_image_surface(struct display *display,
@@ -142,6 +153,11 @@ window_move(struct window *window, struct input *input, uint32_t time);
 
 void
 window_draw(struct window *window);
+
+void
+window_get_allocation(struct window *window,
+                     struct rectangle *allocation);
+
 void
 window_get_child_allocation(struct window *window,
                            struct rectangle *allocation);