From 84290d02ae77be353fffd49a534f26fa7123ea1e Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Wed, 2 Mar 2011 10:07:59 +0100 Subject: [PATCH] compositor-x11: Use an EGL Window Surface as output --- compositor/compositor-x11.c | 242 +++++++------------------------------------- configure.ac | 2 +- 2 files changed, 39 insertions(+), 205 deletions(-) diff --git a/compositor/compositor-x11.c b/compositor/compositor-x11.c index afe7adc..5631f69 100644 --- a/compositor/compositor-x11.c +++ b/compositor/compositor-x11.c @@ -31,18 +31,11 @@ #include #include -#include -#include - #include #include -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES #include -#include #include -#include #include "compositor.h" @@ -55,8 +48,6 @@ struct x11_compositor { xcb_connection_t *conn; xcb_screen_t *screen; xcb_cursor_t null_cursor; - int dri2_major; - int dri2_minor; struct wl_array keys; struct wl_event_source *xcb_source; struct { @@ -76,12 +67,8 @@ struct x11_compositor { struct x11_output { struct wlsc_output base; - xcb_xfixes_region_t region; xcb_window_t window; - GLuint rbo; - EGLImageKHR image; - xcb_rectangle_t damage[16]; - int damage_count; + EGLSurface egl_surface; }; struct x11_input { @@ -107,98 +94,25 @@ x11_input_create(struct x11_compositor *c) } static int -dri2_connect(struct x11_compositor *c) -{ - xcb_xfixes_query_version_reply_t *xfixes_query; - xcb_xfixes_query_version_cookie_t xfixes_query_cookie; - xcb_dri2_query_version_reply_t *dri2_query; - xcb_dri2_query_version_cookie_t dri2_query_cookie; - xcb_dri2_connect_reply_t *connect; - xcb_dri2_connect_cookie_t connect_cookie; - xcb_generic_error_t *error; - char path[256]; - - xcb_prefetch_extension_data (c->conn, &xcb_xfixes_id); - xcb_prefetch_extension_data (c->conn, &xcb_dri2_id); - - xfixes_query_cookie = - xcb_xfixes_query_version(c->conn, - XCB_XFIXES_MAJOR_VERSION, - XCB_XFIXES_MINOR_VERSION); - - dri2_query_cookie = - xcb_dri2_query_version (c->conn, - XCB_DRI2_MAJOR_VERSION, - XCB_DRI2_MINOR_VERSION); - - connect_cookie = xcb_dri2_connect_unchecked (c->conn, - c->screen->root, - XCB_DRI2_DRIVER_TYPE_DRI); - - xfixes_query = - xcb_xfixes_query_version_reply (c->conn, - xfixes_query_cookie, &error); - if (xfixes_query == NULL || - error != NULL || xfixes_query->major_version < 2) { - free(error); - return -1; - } - free(xfixes_query); - - dri2_query = - xcb_dri2_query_version_reply (c->conn, - dri2_query_cookie, &error); - if (dri2_query == NULL || error != NULL) { - fprintf(stderr, "DRI2: failed to query version\n"); - free(error); - return EGL_FALSE; - } - c->dri2_major = dri2_query->major_version; - c->dri2_minor = dri2_query->minor_version; - free(dri2_query); - - connect = xcb_dri2_connect_reply (c->conn, - connect_cookie, NULL); - if (connect == NULL || - connect->driver_name_length + connect->device_name_length == 0) { - fprintf(stderr, "DRI2: failed to connect, DRI2 version: %u.%u\n", - c->dri2_major, c->dri2_minor); - return -1; - } - -#ifdef XCB_DRI2_CONNECT_DEVICE_NAME_BROKEN - { - char *driver_name, *device_name; - - driver_name = xcb_dri2_connect_driver_name (connect); - device_name = driver_name + - ((connect->driver_name_length + 3) & ~3); - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - device_name); - } -#else - snprintf(path, sizeof path, "%.*s", - xcb_dri2_connect_device_name_length (connect), - xcb_dri2_connect_device_name (connect)); -#endif - free(connect); - return 0; -} - -static int x11_compositor_init_egl(struct x11_compositor *c) { EGLint major, minor; + EGLint n; const char *extensions; + 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_ES2_BIT, + EGL_NONE + }; static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - if (dri2_connect(c) < 0) - return -1; - c->base.display = eglGetDisplay(c->dpy); if (c->base.display == NULL) { fprintf(stderr, "failed to create display\n"); @@ -220,8 +134,13 @@ x11_compositor_init_egl(struct x11_compositor *c) fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n"); return -1; } + if (!eglChooseConfig(c->base.display, config_attribs, + &c->base.config, 1, &n) || n == 0) { + fprintf(stderr, "failed to choose config: %d\n", n); + return -1; + } - c->base.context = eglCreateContext(c->base.display, NULL, + c->base.context = eglCreateContext(c->base.display, c->base.config, EGL_NO_CONTEXT, context_attribs); if (c->base.context == NULL) { fprintf(stderr, "failed to create context\n"); @@ -242,19 +161,16 @@ x11_compositor_present(struct wlsc_compositor *base) { struct x11_compositor *c = (struct x11_compositor *) base; struct x11_output *output; - xcb_dri2_copy_region_cookie_t cookie; struct timeval tv; uint32_t msec; - glFlush(); - wl_list_for_each(output, &c->base.output_list, base.link) { - cookie = xcb_dri2_copy_region_unchecked(c->conn, - output->window, - output->region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); - free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL)); + if (!eglMakeCurrent(c->base.display, output->egl_surface, + output->egl_surface, c->base.context)) { + fprintf(stderr, "failed to make current\n"); + continue; + } + eglSwapBuffers(c->base.display, output->egl_surface); } gettimeofday(&tv, NULL); @@ -326,14 +242,9 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height) static const char name[] = "Wayland Compositor"; static const char class[] = "wayland-1\0Wayland Compositor"; struct x11_output *output; - xcb_dri2_dri2_buffer_t *buffers; - xcb_dri2_get_buffers_reply_t *reply; - xcb_dri2_get_buffers_cookie_t cookie; xcb_screen_iterator_t iter; xcb_rectangle_t rectangle; struct wm_normal_hints normal_hints; - unsigned int attachments[] = - { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT}; uint32_t mask = XCB_CW_EVENT_MASK | XCB_CW_CURSOR; uint32_t values[2] = { XCB_EVENT_MASK_KEY_PRESS | @@ -350,20 +261,13 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height) 0 }; - EGLint attribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_STRIDE_MESA, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_NONE - }; - output = malloc(sizeof *output); if (output == NULL) return -1; memset(output, 0, sizeof *output); - wlsc_output_init(&output->base, &c->base, 0, 0, width, height, 0); + wlsc_output_init(&output->base, &c->base, 0, 0, width, height, + WL_OUTPUT_FLIPPED); values[1] = c->null_cursor; output->window = xcb_generate_id(c->conn); @@ -410,86 +314,27 @@ x11_compositor_create_output(struct x11_compositor *c, int width, int height) rectangle.y = 0; rectangle.width = width; rectangle.height = height; - output->region = xcb_generate_id(c->conn); - xcb_xfixes_create_region(c->conn, output->region, 1, &rectangle); - - xcb_dri2_create_drawable (c->conn, output->window); x11_output_set_wm_protocols(output); - cookie = xcb_dri2_get_buffers_unchecked (c->conn, - output->window, - 1, 1, attachments); - reply = xcb_dri2_get_buffers_reply (c->conn, cookie, NULL); - if (reply == NULL) - return -1; - buffers = xcb_dri2_get_buffers_buffers (reply); - if (buffers == NULL) + output->egl_surface = + eglCreateWindowSurface(c->base.display, c->base.config, + output->window, NULL); + if (!output->egl_surface) { + fprintf(stderr, "failed to create window surface\n"); return -1; - - if (reply->count != 1) { - fprintf(stderr, - "got wrong number of buffers (%d)\n", reply->count); + } + if (!eglMakeCurrent(c->base.display, output->egl_surface, + output->egl_surface, c->base.context)) { + fprintf(stderr, "failed to make surface current\n"); return -1; } - attribs[1] = reply->width; - attribs[3] = reply->height; - attribs[5] = buffers[0].pitch / 4; - output->image = - eglCreateImageKHR(c->base.display, - EGL_NO_CONTEXT, - EGL_DRM_BUFFER_MESA, - (EGLClientBuffer) buffers[0].name, - attribs); - free(reply); - - glGenRenderbuffers(1, &output->rbo); - glBindRenderbuffer(GL_RENDERBUFFER, output->rbo); - - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - output->image); - - glFramebufferRenderbuffer(GL_FRAMEBUFFER, - GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, - output->rbo); - wl_list_insert(c->base.output_list.prev, &output->base.link); return 0; } -static void -idle_repaint(void *data) -{ - struct x11_output *output = data; - struct x11_compositor *c = - (struct x11_compositor *) output->base.compositor; - xcb_xfixes_region_t region; - xcb_dri2_copy_region_cookie_t cookie; - - if (output->damage_count <= ARRAY_SIZE(output->damage)) { - region = xcb_generate_id(c->conn); - xcb_xfixes_create_region(c->conn, region, - output->damage_count, output->damage); - } else { - region = output->region; - } - - cookie = xcb_dri2_copy_region_unchecked(c->conn, - output->window, - region, - XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, - XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); - - if (region != output->region) - xcb_xfixes_destroy_region(c->conn, region); - - free(xcb_dri2_copy_region_reply(c->conn, cookie, NULL)); - output->damage_count = 0; -} - static struct x11_output * x11_compositor_find_output(struct x11_compositor *c, xcb_window_t window) { @@ -518,7 +363,6 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) xcb_keymap_notify_event_t *keymap_notify; xcb_focus_in_event_t *focus_in; xcb_expose_event_t *expose; - xcb_rectangle_t *r; xcb_atom_t atom; uint32_t *k; int i, set; @@ -560,18 +404,11 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) case XCB_EXPOSE: expose = (xcb_expose_event_t *) event; - output = x11_compositor_find_output(c, expose->window); - if (output->damage_count == 0) - wl_event_loop_add_idle(loop, - idle_repaint, output); + + /* FIXME: schedule output repaint */ + /* output = x11_compositor_find_output(c, expose->window); */ - r = &output->damage[output->damage_count++]; - if (output->damage_count > 16) - break; - r->x = expose->x; - r->y = expose->y; - r->width = expose->width; - r->height = expose->height; + wlsc_compositor_schedule_repaint(&c->base); break; case XCB_ENTER_NOTIFY: @@ -731,9 +568,6 @@ x11_compositor_create(struct wl_display *display, int width, int height) c->base.present = x11_compositor_present; c->base.create_buffer = wlsc_drm_buffer_create; - glGenFramebuffers(1, &c->base.fbo); - glBindFramebuffer(GL_FRAMEBUFFER, c->base.fbo); - /* Can't init base class until we have a current egl context */ if (wlsc_compositor_init(&c->base, display) < 0) return NULL; diff --git a/configure.ac b/configure.ac index 3ed83b1..402509b 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ AC_PROG_RANLIB PKG_PROG_PKG_CONFIG() PKG_CHECK_MODULES(COMPOSITOR, - [wayland-server wayland-client wayland-egl egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] pixman-1 x11 x11-xcb xcb-dri2 xcb-xfixes) + [wayland-server wayland-client wayland-egl egl >= 7.10 glesv2 gdk-pixbuf-2.0 libudev >= 136 libdrm >= 2.4.23] pixman-1 x11 x11-xcb) PKG_CHECK_MODULES(SIMPLE_CLIENT, [egl >= 7.10 glesv2 wayland-client wayland-egl]) PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 gl cairo >= 1.10.0 gdk-pixbuf-2.0 glib-2.0 gobject-2.0 xkbcommon]) PKG_CHECK_MODULES(POPPLER, [poppler-glib gdk-2.0 gio-2.0], -- 2.7.4