Use FBOs instead of eagle-specific API
authorKristian Høgsberg <krh@bitplanet.net>
Sun, 24 Jan 2010 23:10:15 +0000 (18:10 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Sun, 24 Jan 2010 23:10:15 +0000 (18:10 -0500)
Makefile.in
gears.c
image.c
terminal.c
wayland-system-compositor.c
window.c
window.h

index cc66c61b8ecb21be06c1c842d4c8a20ae41a143c..3f666e2585a79c8ba4fd8fa54fe133fe9a87f844 100644 (file)
@@ -8,8 +8,9 @@ libs = libwayland-server.so libwayland.so
 egl_clients = gears
 cairo_clients = flower screenshot terminal image view
 compositors = wayland-system-compositor
+clients = $(egl_clients) $(cairo_clients)
 
-all : $(libs) $(compositors) $(egl_clients) $(cairo_clients)
+all : $(libs) $(compositors) $(clients)
 
 libwayland-server.so :                         \
        wayland.o                               \
@@ -36,7 +37,7 @@ wayland-system-compositor :                   \
        wayland-util.o
 
 wayland-system-compositor : CFLAGS += @EGL_COMPOSITOR_CFLAGS@
-wayland-system-compositor : LDLIBS += -L. -lwayland-server @EGL_COMPOSITOR_LIBS@ -rdynamic -lrt
+wayland-system-compositor : LDLIBS += ./libwayland-server.so @EGL_COMPOSITOR_LIBS@ -rdynamic -lrt
 
 flower : flower.o wayland-glib.o
 gears : gears.o window.o wayland-glib.o cairo-util.o
@@ -54,7 +55,7 @@ view : LDLIBS += @POPPLER_LIBS@
 $(egl_clients) : CFLAGS += @EGL_CLIENT_CFLAGS@
 $(egl_clients) : LDLIBS += -L. -lwayland @EGL_CLIENT_LIBS@ -lrt
 $(cairo_clients) : CFLAGS += @CAIRO_CLIENT_CFLAGS@
-$(cairo_clients) : LDLIBS += -L. -lwayland @CAIRO_CLIENT_LIBS@ -lrt
+$(cairo_clients) : LDLIBS += ./libwayland.so @CAIRO_CLIENT_LIBS@ -lrt
 
 install : $(libs) $(compositors)
        install -d @libdir@ @libdir@/pkgconfig ${udev_rules_dir}
diff --git a/gears.c b/gears.c
index def1f99ccb0bce69989a21a1e3a250e582072d14..9a8d503cef612ae8dab21052242f6ae1c4afc037 100644 (file)
--- a/gears.c
+++ b/gears.c
@@ -32,6 +32,7 @@
 #include <glib.h>
 #include <cairo-drm.h>
 
+#define GL_GLEXT_PROTOTYPES
 #include <GL/gl.h>
 #include <eagle.h>
 
@@ -52,14 +53,13 @@ struct gears {
        struct rectangle rectangle;
 
        EGLDisplay display;
-       EGLConfig config;
-       EGLSurface surface;
        EGLContext context;
        int resized;
        GLfloat angle;
        cairo_surface_t *cairo_surface;
 
        GLint gear_list[3];
+       GLuint fbo, color_rbo, depth_rbo;
 };
 
 struct gear_template {
@@ -258,19 +258,20 @@ resize_window(struct gears *gears)
 
        window_draw(gears->window);
 
-       if (gears->surface != NULL)
-               eglDestroySurface(gears->display, gears->surface);
+       glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->color_rbo);
+       glRenderbufferStorage(GL_RENDERBUFFER_EXT,
+                             GL_RGBA,
+                             gears->rectangle.width,
+                             gears->rectangle.height);
 
-       gears->surface = eglCreateSurface(gears->display,
-                                         gears->config,
-                                         gears->rectangle.width,
-                                         gears->rectangle.height,
-                                         1, NULL);
-
-       eglMakeCurrent(gears->display,
-                      gears->surface, gears->surface, gears->context);
+       glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->depth_rbo);
+       glRenderbufferStorage(GL_RENDERBUFFER_EXT,
+                             GL_DEPTH_COMPONENT,
+                             gears->rectangle.width,
+                             gears->rectangle.height);
 
        glViewport(0, 0, gears->rectangle.width, gears->rectangle.height);
+
        gears->resized = 0;
 }
 
@@ -308,13 +309,12 @@ handle_acknowledge(void *data,
 {
        struct gears *gears = data;
 
-       if (key != 0)
-               return;
+       if (key == 10) {
+               if (gears->resized)
+                       resize_window(gears);
 
-       if (gears->resized)
-               resize_window(gears);
-
-       draw_gears(gears);
+               draw_gears(gears);
+       }
 }
 
 static void
@@ -322,14 +322,20 @@ handle_frame(void *data,
             struct wl_compositor *compositor,
             uint32_t frame, uint32_t timestamp)
 {
-       struct gears *gears = data;
-       uint32_t name, handle, stride;
-
-       eglGetColorBuffer(gears->surface, 0, &name, &handle, &stride);
+       struct gears *gears = data;
+       GLint name, stride;
+
+       glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->color_rbo);
+       glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
+                                    GL_RENDERBUFFER_STRIDE_INTEL,
+                                    &stride);
+       glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
+                                    GL_RENDERBUFFER_NAME_INTEL,
+                                    &name);
        
        window_copy(gears->window, &gears->rectangle, name, stride);
 
-       wl_compositor_commit(gears->compositor, 0);
+       window_commit(gears->window, 10);
 
        gears->angle = (GLfloat) (timestamp % 8192) * 360 / 8192.0;
 }
@@ -339,19 +345,11 @@ static const struct wl_compositor_listener compositor_listener = {
        handle_frame,
 };
 
-static const EGLint config_attribs[] = {
-       EGL_DEPTH_SIZE, 24,
-       EGL_CONFIG_CAVEAT, EGL_NONE,
-       EGL_RED_SIZE, 8,
-       EGL_NONE                
-};
-
 static struct gears *
 gears_create(struct display *display)
 {
        const int x = 200, y = 200, width = 450, height = 500;
-       EGLint major, minor, count;
-       EGLConfig configs[64];
+       EGLint major, minor;
        struct udev *udev;
        struct udev_device *device;
        struct gears *gears;
@@ -373,18 +371,29 @@ gears_create(struct display *display)
        if (!eglInitialize(gears->display, &major, &minor))
                die("failed to initialize display\n");
 
-       if (!eglGetConfigs(gears->display, configs, 64, &count))
-               die("failed to get configs\n");
-
-       if (!eglChooseConfig(gears->display, config_attribs, &gears->config, 1, NULL))
-               die("failed to pick a config\n");
-
-       gears->context = eglCreateContext(gears->display, gears->config, NULL, NULL);
+       gears->context = eglCreateContext(gears->display, NULL, NULL, NULL);
        if (gears->context == NULL)
                die("failed to create context\n");
 
-       resize_window(gears);
-
+       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(1, &gears->color_rbo);
+       glBindRenderbuffer(GL_RENDERBUFFER_EXT, gears->color_rbo);
+       glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT,
+                                 GL_COLOR_ATTACHMENT0_EXT,
+                                 GL_RENDERBUFFER_EXT,
+                                 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);
@@ -406,10 +415,13 @@ gears_create(struct display *display)
        glEnable(GL_DEPTH_TEST);
        glClearColor(0, 0, 0, 0.92);
 
+       if (glCheckFramebufferStatus (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE)
+               fprintf(stderr, "framebuffer incomplete\n");
+
        gears->compositor = display_get_compositor(display);
 
+       resize_window(gears);
        draw_gears(gears);
-
        handle_frame(gears, gears->compositor, 0, 0);
 
        window_set_resize_handler(gears->window, resize_handler, gears);
diff --git a/image.c b/image.c
index e38da0ffd5db61e65c03151a1a48cb9aa695366f..3f206fc19855c01c245a5b4a9c150ef23132f688 100644 (file)
--- a/image.c
+++ b/image.c
@@ -184,7 +184,7 @@ image_draw(struct image *image)
                            &rectangle,
                            image->surface);
 
-       wl_compositor_commit(image->compositor, image->key);
+       window_commit(image->window, image->key);
 }
 
 static gboolean
@@ -216,6 +216,15 @@ resize_handler(struct window *window, void *data)
        image_schedule_redraw(image);
 }
 
+static void
+keyboard_focus_handler(struct window *window,
+                      struct wl_input_device *device, void *data)
+{
+       struct image *image = data;
+
+       image_schedule_redraw(image);
+}
+
 static void
 handle_acknowledge(void *data,
                   struct wl_compositor *compositor,
@@ -274,6 +283,7 @@ image_create(struct display *display, uint32_t key, const char *filename)
 
        image->compositor = display_get_compositor(display);
        window_set_resize_handler(image->window, resize_handler, image);
+       window_set_keyboard_focus_handler(image->window, keyboard_focus_handler, image);
 
        wl_compositor_add_listener(image->compositor, &compositor_listener, image);
 
index 05cdaa1c415bacf481778e45ad71592e208e01f5..b4800d5fe5951ee73de6376048c0d24ec04053ec 100644 (file)
@@ -227,7 +227,7 @@ terminal_draw(struct terminal *terminal)
 
        window_draw(terminal->window);
        terminal_draw_contents(terminal);
-       wl_compositor_commit(terminal->compositor, 0);
+       window_commit(terminal->window, 0);
 }
 
 static gboolean
index 74b7f0a8c3d770360eff7cdcceddb59e29f0336c..851398c4c6dddf3b4973333ffdf7d3e4c374b254 100644 (file)
@@ -69,13 +69,13 @@ struct wlsc_output {
        struct wl_list link;
        struct wlsc_compositor *compositor;
        struct wlsc_surface *background;
-       EGLSurface surface;
        int32_t x, y, width, height;
 
        drmModeModeInfo mode;
        uint32_t crtc_id;
        uint32_t connector_id;
 
+       GLuint rbo[2];
        uint32_t fb_id[2];
        uint32_t current;       
 };
@@ -102,7 +102,7 @@ struct wlsc_compositor {
 
        EGLDisplay display;
        EGLContext context;
-       EGLConfig config;
+       GLuint fbo;
        struct wl_display *wl_display;
 
        struct wl_list output_list;
@@ -610,16 +610,11 @@ repaint_output(struct wlsc_output *output)
        double s = 3000;
        int fd;
 
-       if (!eglMakeCurrent(ec->display, output->surface, output->surface, ec->context)) {
-               fprintf(stderr, "failed to make context current\n");
-               return;
-       }
-
        glViewport(0, 0, output->width, output->height);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glFrustum(-output->width / s, output->width / s,
-                 output->height / s, -output->height / s, 1, 2 * s);
+                 -output->height / s, output->height / s, 1, 2 * s);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glClearColor(0, 0, 0, 1);
@@ -650,7 +645,11 @@ repaint_output(struct wlsc_output *output)
 
        fd = eglGetDisplayFD(ec->display);
        output->current ^= 1;
-       eglBindColorBuffer(ec->display, output->surface, output->current);
+
+       glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT,
+                                 GL_COLOR_ATTACHMENT0_EXT,
+                                 GL_RENDERBUFFER_EXT,
+                                 output->rbo[output->current]);
        drmModePageFlip(fd, output->crtc_id,
                        output->fb_id[output->current ^ 1],
                        DRM_MODE_PAGE_FLIP_EVENT, output);
@@ -737,8 +736,8 @@ surface_attach(struct wl_client *client,
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-       glTextureExternalMESA(GL_TEXTURE_2D, GL_RGBA, 4,
-                             width, height, stride / 4, name);
+       glTextureExternalINTEL(GL_TEXTURE_2D, GL_RGBA, 4,
+                              width, height, stride / 4, name);
        
 }
 
@@ -762,36 +761,6 @@ surface_copy(struct wl_client *client,
             uint32_t name, uint32_t stride,
             int32_t x, int32_t y, int32_t width, int32_t height)
 {
-       struct wlsc_surface *es = (struct wlsc_surface *) surface;
-       GLuint fbo[2], rb;
-
-       glGenFramebuffers(2, fbo);
-
-       glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, fbo[1]);
-       glGenRenderbuffers(1, &rb);
-       glBindRenderbuffer(GL_RENDERBUFFER_EXT, rb);
-       glRenderbufferExternalMESA(GL_RENDERBUFFER_EXT,
-                                  GL_RGBA,
-                                  es->width, es->height,
-                                  stride / 4, name);
-       glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER_EXT,
-                                 GL_COLOR_ATTACHMENT0_EXT,
-                                 GL_RENDERBUFFER_EXT,
-                                 rb);
-
-       glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, fbo[0]);
-       glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT,
-                              GL_COLOR_ATTACHMENT0_EXT,
-                              GL_TEXTURE_2D, es->texture, 0);
-       
-       glBlitFramebuffer(x, y, x + width, y + height,
-                         dst_x, dst_y, dst_x+ width, dst_y + height,
-                         GL_COLOR_BUFFER_BIT, GL_NEAREST);
-
-       glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
-       glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
-       glDeleteRenderbuffers(1, &rb);
-       glDeleteFramebuffers(2, fbo);
 }
 
 static void
@@ -1138,14 +1107,6 @@ on_drm_input(int fd, uint32_t mask, void *data)
 static int
 init_egl(struct wlsc_compositor *ec, struct udev_device *device)
 {
-       static const EGLint config_attribs[] = {
-               EGL_DEPTH_SIZE,         0,
-               EGL_STENCIL_SIZE,       0,
-               EGL_CONFIG_CAVEAT,      EGL_NONE,
-               EGL_RED_SIZE,           8,
-               EGL_NONE                
-       };
-
        struct wl_event_loop *loop;
        EGLint major, minor;
        int fd;
@@ -1161,15 +1122,20 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device)
                return -1;
        }
 
-       if (!eglChooseConfig(ec->display, config_attribs, &ec->config, 1, NULL))
-               return -1;
-
-       ec->context = eglCreateContext(ec->display, ec->config, NULL, NULL);
+       ec->context = eglCreateContext(ec->display, NULL, NULL, NULL);
        if (ec->context == NULL) {
                fprintf(stderr, "failed to create context\n");
                return -1;
        }
 
+       if (!eglMakeCurrent(ec->display, EGL_NO_SURFACE, EGL_NO_SURFACE, ec->context)) {
+               fprintf(stderr, "failed to make context current\n");
+               return -1;
+       }
+
+       glGenFramebuffers(1, &ec->fbo);
+       glBindFramebuffer(GL_FRAMEBUFFER_EXT, ec->fbo);
+
        loop = wl_display_get_event_loop(ec->wl_display);
        fd = eglGetDisplayFD(ec->display);
        ec->drm_source =
@@ -1197,7 +1163,7 @@ create_output_for_connector(struct wlsc_compositor *ec,
        struct wlsc_output *output;
        drmModeEncoder *encoder;
        drmModeModeInfo *mode;
-       uint32_t name, handle, stride;
+       GLint handle, stride;
        int i, ret, fd;
 
        fd = eglGetDisplayFD(ec->display);
@@ -1243,21 +1209,21 @@ create_output_for_connector(struct wlsc_compositor *ec,
 
        drmModeFreeEncoder(encoder);
 
-       output->surface = eglCreateSurface(ec->display,
-                                          ec->config,
-                                          output->width,
-                                          output->height,
-                                          2, NULL);
-       if (output->surface == NULL) {
-               fprintf(stderr, "failed to create surface\n");
-               return -1;
-       }
-
+       glGenRenderbuffers(2, output->rbo);
        for (i = 0; i < 2; i++) {
-               eglGetColorBuffer(output->surface,
-                                 i, &name, &handle, &stride);
-
-               ret = drmModeAddFB(fd, mode->hdisplay, mode->vdisplay,
+               glBindRenderbuffer(GL_RENDERBUFFER_EXT, output->rbo[i]);
+               glRenderbufferStorage(GL_RENDERBUFFER_EXT,
+                                     GL_RGBA,
+                                     output->width,
+                                     output->height);
+               glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
+                                            GL_RENDERBUFFER_STRIDE_INTEL,
+                                            &stride);
+               glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT,
+                                            GL_RENDERBUFFER_HANDLE_INTEL,
+                                            &handle);
+
+               ret = drmModeAddFB(fd, output->width, output->height,
                                   32, 32, stride, handle, &output->fb_id[i]);
                if (ret) {
                        fprintf(stderr, "failed to add fb %d: %m\n", i);
@@ -1266,6 +1232,10 @@ create_output_for_connector(struct wlsc_compositor *ec,
        }
 
        output->current = 0;
+       glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT,
+                                 GL_COLOR_ATTACHMENT0_EXT,
+                                 GL_RENDERBUFFER_EXT,
+                                 output->rbo[output->current]);
        ret = drmModeSetCrtc(fd, output->crtc_id,
                             output->fb_id[output->current ^ 1], 0, 0,
                             &output->connector_id, 1, &output->mode);
@@ -1279,11 +1249,6 @@ create_output_for_connector(struct wlsc_compositor *ec,
        wl_display_add_global(ec->wl_display, &output->base, post_output_geometry);
        wl_list_insert(ec->output_list.prev, &output->link);
 
-       if (!eglMakeCurrent(ec->display, output->surface, output->surface, ec->context)) {
-               fprintf(stderr, "failed to make context current\n");
-               return -1;
-       }
-
        output->background = background_create(output, option_background);
 
        return 0;
index e27ff32c53991b25852dda94b5db1e073cf86edd..95f3e21dc6eaa4f27daecb619cda79d63c15f380 100644 (file)
--- a/window.c
+++ b/window.c
@@ -66,6 +66,7 @@ struct window {
        uint32_t modifiers;
 
        cairo_surface_t *cairo_surface, *pending_surface;
+       int new_surface;
 
        window_resize_handler_t resize_handler;
        window_key_handler_t key_handler;
@@ -113,6 +114,17 @@ window_attach_surface(struct window *window)
                       window->allocation.height);
 }
 
+void
+window_commit(struct window *window, uint32_t key)
+{
+       if (window->new_surface) {
+               window_attach_surface(window);
+               window->new_surface = 0;
+       }
+
+       wl_compositor_commit(window->display->compositor, key);
+}
+
 static void
 window_draw_decorations(struct window *window)
 {
@@ -210,8 +222,6 @@ window_draw_decorations(struct window *window)
                cairo_fill(cr);
        }
        cairo_destroy(cr);
-
-       window_attach_surface(window);
 }
 
 static void
@@ -222,8 +232,6 @@ window_draw_fullscreen(struct window *window)
                                         CAIRO_CONTENT_COLOR_ALPHA,
                                         window->allocation.width,
                                         window->allocation.height);
-
-       window_attach_surface(window);
 }
 
 void
@@ -236,6 +244,8 @@ window_draw(struct window *window)
                window_draw_fullscreen(window);
        else
                window_draw_decorations(window);
+
+       window->new_surface = 1;
 }
 
 static void
@@ -251,13 +261,11 @@ window_handle_acknowledge(void *data,
         * safely free the old window buffer if we resized and
         * render the next frame into our back buffer.. */
 
-       if (key == 0) {
-               pending = window->pending_surface;
-               window->pending_surface = NULL;
-               if (pending != window->cairo_surface)
-                       window_attach_surface(window);
-               cairo_surface_destroy(pending);
-       }
+       pending = window->pending_surface;
+       window->pending_surface = NULL;
+       if (pending != window->cairo_surface)
+               window_attach_surface(window);
+       cairo_surface_destroy(pending);
 }
 
 static void
@@ -585,7 +593,7 @@ window_copy(struct window *window,
        cairo_t *cr;
 
        surface = cairo_drm_surface_create_for_name (window->display->device,
-                                                    name, CAIRO_CONTENT_COLOR_ALPHA,
+                                                    name, CAIRO_FORMAT_ARGB32,
                                                     rectangle->width, rectangle->height,
                                                     stride);
 
index c4834001bc7ad4e3104c947147e3660fd202a136..78e7734f03ec2795cea1db17ef520439ccab7b23 100644 (file)
--- a/window.h
+++ b/window.h
@@ -60,6 +60,8 @@ window_create(struct display *display, const char *title,
 void
 window_draw(struct window *window);
 void
+window_commit(struct window *window, uint32_t key);
+void
 window_get_child_rectangle(struct window *window,
                           struct rectangle *rectangle);
 void