diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-01-24 18:10:15 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2010-01-24 18:10:15 -0500 |
commit | a341fa016c54948af4fc76cde864f460f962f9db (patch) | |
tree | e03749a18af66b568b5872298cdc29eded71b877 | |
parent | 450cc8136d5c3c84407b3c621006a1fa6b092085 (diff) |
Use FBOs instead of eagle-specific API
-rw-r--r-- | Makefile.in | 7 | ||||
-rw-r--r-- | gears.c | 96 | ||||
-rw-r--r-- | image.c | 12 | ||||
-rw-r--r-- | terminal.c | 2 | ||||
-rw-r--r-- | wayland-system-compositor.c | 111 | ||||
-rw-r--r-- | window.c | 32 | ||||
-rw-r--r-- | window.h | 2 |
7 files changed, 130 insertions, 132 deletions
diff --git a/Makefile.in b/Makefile.in index cc66c61..3f666e2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,14 +5,15 @@ exec_prefix = @exec_prefix@ udev_rules_dir = @sysconfdir@/udev/rules.d 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 \ event-loop.o \ connection.o \ wayland-util.o \ @@ -33,13 +34,13 @@ wayland-system-compositor : \ wayland-system-compositor.o \ evdev.o \ cairo-util.o \ 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 screenshot : screenshot.o wayland-glib.o terminal : terminal.o window.o wayland-glib.o cairo-util.o image : image.o window.o wayland-glib.o cairo-util.o @@ -51,13 +52,13 @@ image : LDLIBS += @GDK_PIXBUF_LIBS@ view : CFLAGS += @POPPLER_CFLAGS@ 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} install $(libs) @libdir@ install wayland-server.pc wayland.pc @libdir@/pkgconfig install wayland-util.h wayland-client.h @includedir@ @@ -29,12 +29,13 @@ #include <math.h> #include <time.h> #include <cairo.h> #include <glib.h> #include <cairo-drm.h> +#define GL_GLEXT_PROTOTYPES #include <GL/gl.h> #include <eagle.h> #include "wayland-util.h" #include "wayland-client.h" #include "wayland-glib.h" @@ -49,20 +50,19 @@ struct gears { struct display *d; struct wl_compositor *compositor; 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 { GLfloat material[4]; GLfloat inner_radius; GLfloat outer_radius; @@ -255,25 +255,26 @@ resize_window(struct gears *gears) gears->rectangle.height = 300; } window_set_child_size(gears->window, &gears->rectangle); 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; } static void resize_handler(struct window *window, void *data) { @@ -305,56 +306,53 @@ static void handle_acknowledge(void *data, struct wl_compositor *compositor, uint32_t key, uint32_t frame) { 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 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; } static const struct wl_compositor_listener compositor_listener = { handle_acknowledge, 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; int i; udev = udev_new(); @@ -370,24 +368,35 @@ gears_create(struct display *display) if (gears->display == NULL) die("failed to create egl display\n"); 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); make_gear(&gear_templates[i]); glEndList(); } @@ -403,16 +412,19 @@ gears_create(struct display *display) glEnable(GL_CULL_FACE); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); 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); window_set_keyboard_focus_handler(gears->window, keyboard_focus_handler, gears); wl_compositor_add_listener(gears->compositor, @@ -181,13 +181,13 @@ image_draw(struct image *image) g_object_unref(pb); window_copy_surface(image->window, &rectangle, image->surface); - wl_compositor_commit(image->compositor, image->key); + window_commit(image->window, image->key); } static gboolean image_idle_redraw(void *data) { struct image *image = data; @@ -214,12 +214,21 @@ resize_handler(struct window *window, void *data) struct image *image = 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, uint32_t key, uint32_t frame) { struct image *image = data; @@ -271,12 +280,13 @@ image_create(struct display *display, uint32_t key, const char *filename) * allocation scheme here. Or maybe just a real toolkit. */ image->key = key + 100; image->redraw_scheduled = 1; 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); image_draw(image); return image; @@ -224,13 +224,13 @@ terminal_draw(struct terminal *terminal) rectangle.height = terminal->height * extents.height + 2 * terminal->margin; window_set_child_size(terminal->window, &rectangle); } window_draw(terminal->window); terminal_draw_contents(terminal); - wl_compositor_commit(terminal->compositor, 0); + window_commit(terminal->window, 0); } static gboolean idle_redraw(void *data) { struct terminal *terminal = data; diff --git a/wayland-system-compositor.c b/wayland-system-compositor.c index 74b7f0a..851398c 100644 --- a/wayland-system-compositor.c +++ b/wayland-system-compositor.c @@ -66,19 +66,19 @@ struct wlsc_listener { struct wlsc_output { struct wl_object base; 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; }; struct wlsc_input_device { struct wl_object base; @@ -99,13 +99,13 @@ struct wlsc_input_device { struct wlsc_compositor { struct wl_compositor base; struct wl_visual argb_visual, premultiplied_argb_visual, rgb_visual; EGLDisplay display; EGLContext context; - EGLConfig config; + GLuint fbo; struct wl_display *wl_display; struct wl_list output_list; struct wl_list input_device_list; struct wl_list surface_list; @@ -607,22 +607,17 @@ repaint_output(struct wlsc_output *output) struct wlsc_compositor *ec = output->compositor; struct wlsc_surface *es; struct wlsc_input_device *eid; 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); glTranslatef(-output->width / 2, -output->height / 2, -s / 2); @@ -647,13 +642,17 @@ repaint_output(struct wlsc_output *output) eid = container_of(eid->link.next, struct wlsc_input_device, link); } 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); } static void @@ -734,14 +733,14 @@ surface_attach(struct wl_client *client, glBindTexture(GL_TEXTURE_2D, es->texture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 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); } static void surface_map(struct wl_client *client, struct wl_surface *surface, @@ -759,42 +758,12 @@ static void surface_copy(struct wl_client *client, struct wl_surface *surface, int32_t dst_x, int32_t dst_y, 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 surface_damage(struct wl_client *client, struct wl_surface *surface, int32_t x, int32_t y, int32_t width, int32_t height) @@ -1135,20 +1104,12 @@ on_drm_input(int fd, uint32_t mask, void *data) drmHandleEvent(fd, &evctx); } 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; ec->display = eglCreateDisplayNative(device); if (ec->display == NULL) { @@ -1158,21 +1119,26 @@ init_egl(struct wlsc_compositor *ec, struct udev_device *device) if (!eglInitialize(ec->display, &major, &minor)) { fprintf(stderr, "failed to initialize display\n"); 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 = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, on_drm_input, ec); @@ -1194,13 +1160,13 @@ create_output_for_connector(struct wlsc_compositor *ec, drmModeRes *resources, drmModeConnector *connector) { struct wlsc_output *output; drmModeEncoder *encoder; drmModeModeInfo *mode; - uint32_t name, handle, stride; + GLint handle, stride; int i, ret, fd; fd = eglGetDisplayFD(ec->display); output = malloc(sizeof *output); if (output == NULL) @@ -1240,35 +1206,39 @@ create_output_for_connector(struct wlsc_compositor *ec, output->connector_id, encoder->encoder_id, mode->name); 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); return -1; } } 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); if (ret) { fprintf(stderr, "failed to set mode: %m\n"); return -1; @@ -1276,17 +1246,12 @@ create_output_for_connector(struct wlsc_compositor *ec, output->base.interface = &wl_output_interface; wl_display_add_object(ec->wl_display, &output->base); 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; } static int @@ -63,12 +63,13 @@ struct window { struct wl_input_device *grab_device; struct wl_input_device *keyboard_device; uint32_t name; 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; window_keyboard_focus_handler_t keyboard_focus_handler; void *user_data; }; @@ -110,12 +111,23 @@ window_attach_surface(struct window *window) window->allocation.x - window->margin, window->allocation.y - window->margin, window->allocation.width, 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) { cairo_t *cr; int border = 2, radius = 5; cairo_text_extents_t extents; @@ -207,38 +219,36 @@ window_draw_decorations(struct window *window) cairo_fill(cr); } else { cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); cairo_fill(cr); } cairo_destroy(cr); - - window_attach_surface(window); } static void window_draw_fullscreen(struct window *window) { window->cairo_surface = cairo_drm_surface_create(window->display->device, CAIRO_CONTENT_COLOR_ALPHA, window->allocation.width, window->allocation.height); - - window_attach_surface(window); } void window_draw(struct window *window) { if (window->cairo_surface != NULL) cairo_surface_destroy(window->cairo_surface); if (window->fullscreen) window_draw_fullscreen(window); else window_draw_decorations(window); + + window->new_surface = 1; } static void window_handle_acknowledge(void *data, struct wl_compositor *compositor, uint32_t key, uint32_t frame) @@ -248,19 +258,17 @@ window_handle_acknowledge(void *data, /* The acknowledge event means that the server * processed our last commit request and we can now * 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 window_handle_frame(void *data, struct wl_compositor *compositor, uint32_t frame, uint32_t timestamp) @@ -582,13 +590,13 @@ window_copy(struct window *window, uint32_t name, uint32_t stride) { cairo_surface_t *surface; 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); cr = cairo_create (window->cairo_surface); cairo_set_source_surface (cr, @@ -57,12 +57,14 @@ struct window * window_create(struct display *display, const char *title, int32_t x, int32_t y, int32_t width, int32_t height); 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 window_set_child_size(struct window *window, struct rectangle *rectangle); void |