diff --git a/clients/screenshot.c b/clients/screenshot.c index 428befa7..1cccedf5 100644 --- a/clients/screenshot.c +++ b/clients/screenshot.c @@ -40,7 +40,6 @@ static struct wl_output *output; static struct wl_shm *shm; -static struct wl_visual *visual; static struct screenshooter *screenshooter; static int output_width, output_height; @@ -78,17 +77,11 @@ static void handle_global(struct wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) { - static int visual_count; - if (strcmp(interface, "wl_output") == 0) { output = wl_display_bind(display, id, &wl_output_interface); wl_output_add_listener(output, &output_listener, NULL); } else if (strcmp(interface, "wl_shm") == 0) { shm = wl_display_bind(display, id, &wl_shm_interface); - } else if (strcmp(interface, "wl_visual") == 0) { - if (visual_count++ == 1) - visual = wl_display_bind(display, id, - &wl_visual_interface); } else if (strcmp(interface, "screenshooter") == 0) { screenshooter = wl_display_bind(display, id, &screenshooter_interface); } @@ -124,7 +117,8 @@ create_shm_buffer(int width, int height, void **data_out) return NULL; } - buffer = wl_shm_create_buffer(shm, fd, width, height, stride, visual); + buffer = wl_shm_create_buffer(shm, fd, width, height, stride, + WL_SHM_FORMAT_XRGB32); close(fd); diff --git a/clients/simple-egl.c b/clients/simple-egl.c index ef69fc24..ec09d683 100644 --- a/clients/simple-egl.c +++ b/clients/simple-egl.c @@ -93,7 +93,7 @@ init_egl(struct display *display) }; static const EGLint config_attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, @@ -195,26 +195,22 @@ create_surface(struct window *window) struct display *display = window->display; struct wl_visual *visual; EGLBoolean ret; + static const EGLint surface_attribs[] = { + EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE, + EGL_NONE + }; - if (!display->premultiplied_argb_visual) - wl_display_roundtrip(display->display); - if (!display->premultiplied_argb_visual) { - fprintf(stderr, "premultiplied argb visual missing\n"); - exit(1); - } - window->surface = wl_compositor_create_surface(display->compositor); visual = display->premultiplied_argb_visual; window->native = wl_egl_window_create(window->surface, window->geometry.width, - window->geometry.height, - visual); + window->geometry.height); window->egl_surface = eglCreateWindowSurface(display->egl.dpy, display->egl.conf, window->native, - NULL); + surface_attribs); wl_shell_set_toplevel(display->shell, window->surface); @@ -288,25 +284,6 @@ static const struct wl_callback_listener frame_listener = { redraw }; -static void -compositor_handle_visual(void *data, - struct wl_compositor *compositor, - uint32_t id, uint32_t token) -{ - struct display *d = data; - - switch (token) { - case WL_COMPOSITOR_VISUAL_PREMULTIPLIED_ARGB32: - d->premultiplied_argb_visual = - wl_display_bind(d->display, id, &wl_visual_interface); - break; - } -} - -static const struct wl_compositor_listener compositor_listener = { - compositor_handle_visual, -}; - static void display_handle_global(struct wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) @@ -316,8 +293,6 @@ display_handle_global(struct wl_display *display, uint32_t id, if (strcmp(interface, "wl_compositor") == 0) { d->compositor = wl_display_bind(display, id, &wl_compositor_interface); - wl_compositor_add_listener(d->compositor, - &compositor_listener, d); } else if (strcmp(interface, "wl_shell") == 0) { d->shell = wl_display_bind(display, id, &wl_shell_interface); } diff --git a/clients/simple-shm.c b/clients/simple-shm.c index b7c6ea1c..a93c2033 100644 --- a/clients/simple-shm.c +++ b/clients/simple-shm.c @@ -34,7 +34,6 @@ struct display { struct wl_display *display; - struct wl_visual *xrgb_visual; struct wl_compositor *compositor; struct wl_shell *shell; struct wl_shm *shm; @@ -51,8 +50,7 @@ struct window { static struct wl_buffer * create_shm_buffer(struct display *display, - int width, int height, struct wl_visual *visual, - void **data_out) + int width, int height, uint32_t format, void **data_out) { char filename[] = "/tmp/wayland-shm-XXXXXX"; struct wl_buffer *buffer; @@ -82,7 +80,7 @@ create_shm_buffer(struct display *display, } buffer = wl_shm_create_buffer(display->shm, fd, - width, height, stride, visual); + width, height, stride, format); close(fd); @@ -95,17 +93,16 @@ static struct window * create_window(struct display *display, int width, int height) { struct window *window; - struct wl_visual *visual; window = malloc(sizeof *window); window->display = display; window->width = width; window->height = height; window->surface = wl_compositor_create_surface(display->compositor); - visual = display->xrgb_visual; window->buffer = create_shm_buffer(display, width, height, - visual, &window->data); + WL_SHM_FORMAT_XRGB32, + &window->data); wl_shell_set_toplevel(display->shell, window->surface); @@ -143,25 +140,6 @@ static const struct wl_callback_listener frame_listener = { redraw }; -static void -compositor_handle_visual(void *data, - struct wl_compositor *compositor, - uint32_t id, uint32_t token) -{ - struct display *d = data; - - switch (token) { - case WL_COMPOSITOR_VISUAL_XRGB32: - d->xrgb_visual = wl_display_bind(d->display, - id, &wl_visual_interface); - break; - } -} - -static const struct wl_compositor_listener compositor_listener = { - compositor_handle_visual, -}; - static void display_handle_global(struct wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) @@ -171,8 +149,6 @@ display_handle_global(struct wl_display *display, uint32_t id, if (strcmp(interface, "wl_compositor") == 0) { d->compositor = wl_display_bind(display, id, &wl_compositor_interface); - wl_compositor_add_listener(d->compositor, - &compositor_listener, d); } else if (strcmp(interface, "wl_shell") == 0) { d->shell = wl_display_bind(display, id, &wl_shell_interface); } else if (strcmp(interface, "wl_shm") == 0) { @@ -205,9 +181,6 @@ create_display(void) wl_display_get_fd(display->display, event_mask_update, display); - while (!display->xrgb_visual) - wl_display_roundtrip(display->display); - return display; } diff --git a/clients/window.c b/clients/window.c index a969cd8c..bc657908 100644 --- a/clients/window.c +++ b/clients/window.c @@ -62,11 +62,11 @@ struct display { struct wl_shell *shell; struct wl_shm *shm; struct wl_output *output; - struct wl_visual *argb_visual, *premultiplied_argb_visual, *rgb_visual; struct rectangle screen_allocation; int authenticated; EGLDisplay dpy; - EGLConfig conf; + EGLConfig rgb_config; + EGLConfig premul_argb_config; EGLContext ctx; cairo_device_t *device; int fd; @@ -211,12 +211,19 @@ egl_window_surface_data_destroy(void *p) static cairo_surface_t * display_create_egl_window_surface(struct display *display, struct wl_surface *surface, - struct wl_visual *visual, + uint32_t flags, struct rectangle *rectangle) { cairo_surface_t *cairo_surface; struct egl_window_surface_data *data; + EGLConfig config; + const EGLint *attribs; + static const EGLint premul_attribs[] = { + EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE, + EGL_NONE + }; + data = malloc(sizeof *data); if (data == NULL) return NULL; @@ -224,13 +231,20 @@ display_create_egl_window_surface(struct display *display, data->display = display; data->surface = surface; + if (flags & SURFACE_OPAQUE) { + config = display->rgb_config; + attribps = NULL; + } else { + config = display->premultiplied_argb_config; + attribs = premul_attribs; + } + data->window = wl_egl_window_create(surface, rectangle->width, - rectangle->height, - visual); + rectangle->height); - data->surf = eglCreateWindowSurface(display->dpy, display->conf, - data->window, NULL); + data->surf = eglCreateWindowSurface(display->dpy, config, + data->window, attribs); cairo_surface = cairo_gl_surface_create_for_egl(display->device, data->surf, @@ -280,12 +294,13 @@ display_get_image_for_egl_image_surface(struct display *display, static cairo_surface_t * display_create_egl_image_surface(struct display *display, - struct wl_visual *visual, + uint32_t flags, struct rectangle *rectangle) { struct egl_image_surface_data *data; EGLDisplay dpy = display->dpy; cairo_surface_t *surface; + EGLConfig config; data = malloc(sizeof *data); if (data == NULL) @@ -294,13 +309,17 @@ display_create_egl_image_surface(struct display *display, data->display = display; data->pixmap = wl_egl_pixmap_create(rectangle->width, - rectangle->height, - visual, 0); + rectangle->height, 0); if (data->pixmap == NULL) { free(data); return NULL; } + if (flags & SURFACE_OPAQUE) + config = display->rgb_config; + else + config = display->premultiplied_argb_config; + data->image = display->create_image(dpy, NULL, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer) data->pixmap, @@ -343,7 +362,6 @@ display_create_egl_image_surface_from_file(struct display *display, int stride, i; unsigned char *pixels, *p, *end; struct egl_image_surface_data *data; - struct wl_visual *visual; pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, rect->width, rect->height, @@ -428,7 +446,7 @@ display_create_shm_surface(struct display *display, struct rectangle *rectangle, uint32_t flags) { struct shm_surface_data *data; - struct wl_visual *visual; + uint32_t format; cairo_surface_t *surface; int stride, fd; char filename[] = "/tmp/wayland-shm-XXXXXX"; @@ -471,15 +489,15 @@ display_create_shm_surface(struct display *display, data, shm_surface_data_destroy); if (flags & SURFACE_OPAQUE) - visual = display->rgb_visual; + format = WL_SHM_FORMAT_XRGB32; else - visual = display->premultiplied_argb_visual; + format = WL_SHM_FORMAT_PREMULTIPLIED_ARGB32; data->data.buffer = wl_shm_create_buffer(display->shm, fd, rectangle->width, rectangle->height, - stride, visual); + stride, format); close(fd); @@ -562,13 +580,6 @@ display_create_surface(struct display *display, struct rectangle *rectangle, uint32_t flags) { - struct wl_visual *visual; - - if (flags & SURFACE_OPAQUE) - visual = display->rgb_visual; - else - visual = display->premultiplied_argb_visual; - if (check_size(rectangle) < 0) return NULL; #ifdef HAVE_CAIRO_EGL @@ -576,11 +587,11 @@ display_create_surface(struct display *display, if (surface) return display_create_egl_window_surface(display, surface, - visual, + flags, rectangle); else return display_create_egl_image_surface(display, - visual, + flags, rectangle); } #endif @@ -1570,32 +1581,6 @@ window_set_buffer_type(struct window *window, enum window_buffer_type type) window->buffer_type = type; } -static void -compositor_handle_visual(void *data, - struct wl_compositor *compositor, - uint32_t id, uint32_t token) -{ - struct display *d = data; - - switch (token) { - case WL_COMPOSITOR_VISUAL_ARGB32: - d->argb_visual = - wl_display_bind(d->display, id, &wl_visual_interface); - break; - case WL_COMPOSITOR_VISUAL_PREMULTIPLIED_ARGB32: - d->premultiplied_argb_visual = - wl_display_bind(d->display, id, &wl_visual_interface); - break; - case WL_COMPOSITOR_VISUAL_XRGB32: - d->rgb_visual = - wl_display_bind(d->display, id, &wl_visual_interface); - break; - } -} - -static const struct wl_compositor_listener compositor_listener = { - compositor_handle_visual, -}; static void display_handle_geometry(void *data, @@ -1770,8 +1755,6 @@ display_handle_global(struct wl_display *display, uint32_t id, if (strcmp(interface, "wl_compositor") == 0) { d->compositor = wl_display_bind(display, id, &wl_compositor_interface); - wl_compositor_add_listener(d->compositor, - &compositor_listener, d); } else if (strcmp(interface, "wl_output") == 0) { d->output = wl_display_bind(display, id, &wl_output_interface); wl_output_add_listener(d->output, &output_listener, d); @@ -1844,8 +1827,11 @@ init_egl(struct display *d) { EGLint major, minor; EGLint n; - static const EGLint cfg_attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT, + + static const EGLint premul_argb_cfg_attribs[] = { + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_PIXMAP_BIT | + EGL_VG_ALPHA_FORMAT_PRE_BIT, EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, @@ -1855,6 +1841,17 @@ init_egl(struct display *d) EGL_NONE }; + static const EGLint rgb_cfg_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, 0, + EGL_DEPTH_SIZE, 1, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_NONE + }; + setenv("EGL_PLATFORM", "wayland", 1); d->dpy = eglGetDisplay(d->display); if (!eglInitialize(d->dpy, &major, &minor)) { @@ -1867,12 +1864,19 @@ init_egl(struct display *d) return -1; } - if (!eglChooseConfig(d->dpy, cfg_attribs, &d->conf, 1, &n) || n != 1) { - fprintf(stderr, "failed to choose config\n"); + if (!eglChooseConfig(d->dpy, premul_argb_cfg_attribs, + &d->premul_argb_config, 1, &n) || n != 1) { + fprintf(stderr, "failed to choose premul argb config\n"); + return -1; + } + + if (!eglChooseConfig(d->dpy, rgb_cfg_attribs, + &d->rgb_config, 1, &n) || n != 1) { + fprintf(stderr, "failed to choose rgb config\n"); return -1; } - d->ctx = eglCreateContext(d->dpy, d->conf, EGL_NO_CONTEXT, NULL); + d->ctx = eglCreateContext(d->dpy, d->rgb_config, EGL_NO_CONTEXT, NULL); if (d->ctx == NULL) { fprintf(stderr, "failed to create context\n"); return -1; @@ -1950,14 +1954,6 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR"); d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR"); - if (!d->premultiplied_argb_visual || !d->rgb_visual) { - wl_display_roundtrip(d->display); - if (!d->premultiplied_argb_visual || !d->rgb_visual) { - fprintf(stderr, "failed to retreive visuals\n"); - return NULL; - } - } - create_pointer_surfaces(d); display_render_frame(d); @@ -1994,7 +1990,7 @@ display_get_egl_display(struct display *d) EGLConfig display_get_egl_config(struct display *d) { - return d->conf; + return d->rgb_config; } struct wl_shell * diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c index 128ce117..9755c0ad 100644 --- a/compositor/compositor-wayland.c +++ b/compositor/compositor-wayland.c @@ -46,7 +46,6 @@ struct wayland_compositor { struct wl_compositor *compositor; struct wl_shell *shell; struct wl_output *output; - struct wl_visual *visual; struct { int32_t x, y, width, height; @@ -104,6 +103,7 @@ wayland_compositor_init_egl(struct wayland_compositor *c) EGL_RED_SIZE, 1, EGL_GREEN_SIZE, 1, EGL_BLUE_SIZE, 1, + EGL_ALPHA_SIZE, 0, EGL_DEPTH_SIZE, 1, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE @@ -257,8 +257,7 @@ wayland_compositor_create_output(struct wayland_compositor *c, wl_surface_set_user_data(output->parent.surface, output); output->parent.egl_window = - wl_egl_window_create(output->parent.surface, - width, height, c->parent.visual); + wl_egl_window_create(output->parent.surface, width, height); if (!output->parent.egl_window) { fprintf(stderr, "failure to create wl_egl_window\n"); goto cleanup_output; @@ -462,25 +461,6 @@ display_add_input(struct wayland_compositor *c, uint32_t id) wl_input_device_set_user_data(input->input_device, input); } -static void -compositor_handle_visual(void *data, - struct wl_compositor *compositor, - uint32_t id, uint32_t token) -{ - struct wayland_compositor *c = data; - - switch (token) { - case WL_COMPOSITOR_VISUAL_ARGB32: - c->parent.visual = wl_display_bind(c->parent.display, - id, &wl_visual_interface); - break; - } -} - -static const struct wl_compositor_listener compositor_listener = { - compositor_handle_visual, -}; - static void display_handle_global(struct wl_display *display, uint32_t id, const char *interface, uint32_t version, void *data) @@ -490,8 +470,6 @@ display_handle_global(struct wl_display *display, uint32_t id, if (strcmp(interface, "wl_compositor") == 0) { c->parent.compositor = wl_display_bind(display, id, &wl_compositor_interface); - wl_compositor_add_listener(c->parent.compositor, - &compositor_listener, c); } else if (strcmp(interface, "wl_output") == 0) { c->parent.output = wl_display_bind(display, id, &wl_output_interface); diff --git a/compositor/compositor.c b/compositor/compositor.c index 3128543d..54962669 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -244,7 +244,7 @@ wlsc_surface_create(struct wlsc_compositor *compositor, surface->surface.resource.client = NULL; surface->compositor = compositor; - surface->visual = NULL; + surface->visual = WLSC_NONE_VISUAL; surface->image = EGL_NO_IMAGE_KHR; surface->saved_texture = 0; surface->x = x; @@ -308,8 +308,6 @@ WL_EXPORT void wlsc_surface_configure(struct wlsc_surface *surface, int x, int y, int width, int height) { - struct wlsc_compositor *compositor = surface->compositor; - wlsc_surface_damage_below(surface); surface->x = x; @@ -321,7 +319,7 @@ wlsc_surface_configure(struct wlsc_surface *surface, wlsc_surface_damage(surface); pixman_region32_fini(&surface->opaque); - if (surface->visual == &compositor->compositor.rgb_visual) + if (surface->visual == WLSC_RGB_VISUAL) pixman_region32_init_rect(&surface->opaque, surface->x, surface->y, surface->width, surface->height); @@ -388,7 +386,18 @@ wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface) es->pitch, buffer->height, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, wl_shm_buffer_get_data(buffer)); - es->visual = buffer->visual; + + switch (wl_shm_buffer_get_format(buffer)) { + case WL_SHM_FORMAT_ARGB32: + es->visual = WLSC_ARGB_VISUAL; + break; + case WL_SHM_FORMAT_PREMULTIPLIED_ARGB32: + es->visual = WLSC_PREMUL_ARGB_VISUAL; + break; + case WL_SHM_FORMAT_XRGB32: + es->visual = WLSC_RGB_VISUAL; + break; + } surfaces_attached_to = buffer->user_data; @@ -402,7 +411,9 @@ wlsc_buffer_attach(struct wl_buffer *buffer, struct wl_surface *surface) buffer, NULL); ec->image_target_texture_2d(GL_TEXTURE_2D, es->image); - es->visual = buffer->visual; + + /* FIXME: we need to get the visual from the wl_buffer */ + es->visual = WLSC_PREMUL_ARGB_VISUAL; es->pitch = es->width; } } @@ -453,7 +464,7 @@ create_sprite_from_png(struct wlsc_compositor *ec, return NULL; } - sprite->visual = &ec->compositor.premultiplied_argb_visual; + sprite->visual = WLSC_PREMUL_ARGB_VISUAL; sprite->width = width; sprite->height = height; sprite->image = EGL_NO_IMAGE_KHR; @@ -646,14 +657,21 @@ wlsc_surface_draw(struct wlsc_surface *es, if (!pixman_region32_not_empty(&repaint)) return; - if (es->visual == &ec->compositor.argb_visual) { + switch (es->visual) { + case WLSC_ARGB_VISUAL: glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - } else if (es->visual == &ec->compositor.premultiplied_argb_visual) { + break; + case WLSC_PREMUL_ARGB_VISUAL: glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - } else { + break; + case WLSC_RGB_VISUAL: glDisable(GL_BLEND); + break; + default: + fprintf(stderr, "bogus visual\n"); + break; } if (es->transform == NULL) { @@ -760,10 +778,9 @@ fade_output(struct wlsc_output *output, surface.transform = NULL; if (tint <= 1.0) - surface.visual = - &compositor->compositor.premultiplied_argb_visual; + surface.visual = WLSC_PREMUL_ARGB_VISUAL; else - surface.visual = &compositor->compositor.rgb_visual; + surface.visual = WLSC_RGB_VISUAL; glUseProgram(compositor->solid_shader.program); glUniformMatrix4fv(compositor->solid_shader.proj_uniform, @@ -855,7 +872,7 @@ wlsc_output_repaint(struct wlsc_output *output) es = container_of(ec->surface_list.next, struct wlsc_surface, link); - if (es->visual == &ec->compositor.rgb_visual && + if (es->visual == WLSC_RGB_VISUAL && output->prepare_scanout_surface(output, es) == 0) { /* We're drawing nothing now, * draw the damaged regions later. */ @@ -1028,10 +1045,9 @@ surface_attach(struct wl_client *client, wl_list_insert(es->buffer->resource.destroy_listener_list.prev, &es->buffer_destroy_listener.link); - if (es->visual == NULL) + if (es->visual == WLSC_NONE_VISUAL) wl_list_insert(&es->compositor->surface_list, &es->link); - es->visual = buffer->visual; if (x != 0 || y != 0 || es->width != buffer->width || es->height != buffer->height) wlsc_surface_configure(es, es->x + x, es->y + y, diff --git a/compositor/compositor.h b/compositor/compositor.h index 38e35839..9f33a252 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -114,10 +114,17 @@ struct wlsc_input_device { struct wl_selection *selection; }; +enum wlsc_visual { + WLSC_NONE_VISUAL, + WLSC_ARGB_VISUAL, + WLSC_PREMUL_ARGB_VISUAL, + WLSC_RGB_VISUAL +}; + struct wlsc_sprite { GLuint texture; EGLImageKHR image; - struct wl_visual *visual; + uint32_t visual; int width; int height; }; @@ -248,7 +255,7 @@ struct wlsc_surface { struct wl_list link; struct wl_list buffer_link; struct wlsc_transform *transform; - struct wl_visual *visual; + uint32_t visual; struct wlsc_output *output; enum wlsc_surface_map_type map_type; struct wlsc_output *fullscreen_output;