From 8525a5036243212987b48eaf354d921e1d3e528a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 14 Jan 2011 16:20:21 -0500 Subject: [PATCH] Move buffer creation and buffer details into drm.c and shm.c --- compositor/compositor-drm.c | 12 ++-- compositor/compositor-wayland.c | 14 +---- compositor/compositor-x11.c | 9 +-- compositor/compositor.c | 118 +++++++++++++++++++++++----------------- compositor/compositor.h | 22 +++----- compositor/drm.c | 28 ++++++++-- compositor/shm.c | 6 ++ 7 files changed, 118 insertions(+), 91 deletions(-) diff --git a/compositor/compositor-drm.c b/compositor/compositor-drm.c index a082923..6df6b34 100644 --- a/compositor/compositor-drm.c +++ b/compositor/compositor-drm.c @@ -354,7 +354,13 @@ drm_compositor_create(struct wl_display *display, int connector) fprintf(stderr, "failed to initialize egl\n"); return NULL; } - + + ec->base.destroy = drm_destroy; + ec->base.authenticate = drm_authenticate; + ec->base.present = drm_compositor_present; + ec->base.create_buffer = wlsc_drm_buffer_create; + ec->base.focus = 1; + /* Can't init base class until we have a current egl context */ if (wlsc_compositor_init(&ec->base, display) < 0) return NULL; @@ -371,10 +377,6 @@ drm_compositor_create(struct wl_display *display, int connector) wl_event_loop_add_fd(loop, ec->base.drm.fd, WL_EVENT_READABLE, on_drm_input, ec); ec->tty = tty_create(&ec->base); - ec->base.destroy = drm_destroy; - ec->base.authenticate = drm_authenticate; - ec->base.present = drm_compositor_present; - ec->base.focus = 1; return &ec->base; } diff --git a/compositor/compositor-wayland.c b/compositor/compositor-wayland.c index a7a7874..ed8a2ba 100644 --- a/compositor/compositor-wayland.c +++ b/compositor/compositor-wayland.c @@ -278,9 +278,7 @@ wayland_compositor_create_output(struct wayland_compositor *c, static struct wl_buffer * create_invisible_pointer(struct wayland_compositor *c) { - struct wlsc_drm_buffer *wlsc_buffer; struct wl_buffer *buffer; - int name, stride; struct wl_visual *visual; GLuint texture; const int width = 1, height = 1; @@ -294,18 +292,8 @@ create_invisible_pointer(struct wayland_compositor *c) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); visual = wl_display_get_premultiplied_argb_visual(c->parent.display); - wlsc_buffer = wlsc_drm_buffer_create(&c->base, width, height, visual); + buffer = c->base.create_buffer(&c->base, width, height, visual, data); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, wlsc_buffer->image); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, - GL_RGBA, GL_UNSIGNED_BYTE, data); - - eglExportDRMImageMESA(c->base.display, wlsc_buffer->image, - &name, NULL, &stride); - - buffer = wl_drm_create_buffer(c->parent.drm, name, - width, height, - stride, visual); return buffer; } diff --git a/compositor/compositor-x11.c b/compositor/compositor-x11.c index 722bd94..7e7c8ca 100644 --- a/compositor/compositor-x11.c +++ b/compositor/compositor-x11.c @@ -676,6 +676,11 @@ x11_compositor_create(struct wl_display *display, int width, int height) if (x11_compositor_init_egl(c) < 0) return NULL; + c->base.destroy = x11_destroy; + c->base.authenticate = x11_authenticate; + c->base.present = x11_compositor_present; + c->base.create_buffer = wlsc_drm_buffer_create; + /* Can't init base class until we have a current egl context */ if (wlsc_compositor_init(&c->base, display) < 0) return NULL; @@ -693,9 +698,5 @@ x11_compositor_create(struct wl_display *display, int width, int height) WL_EVENT_READABLE, x11_compositor_handle_event, c); - c->base.destroy = x11_destroy; - c->base.authenticate = x11_authenticate; - c->base.present = x11_compositor_present; - return &c->base; } diff --git a/compositor/compositor.c b/compositor/compositor.c index 1e6f2ef..df73b60 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -188,33 +188,76 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client) wlsc_compositor_schedule_repaint(compositor); } -static int -texture_from_png(const char *filename, int width, int height) +static struct wl_buffer * +create_buffer_from_png(struct wlsc_compositor *ec, + const char *filename, int width, int height) { GdkPixbuf *pixbuf; GError *error = NULL; - void *data; - GLenum format; + int stride, i, n_channels; + unsigned char *pixels, *end, *argb_pixels, *s, *d; + struct wl_buffer *buffer; pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, width, height, FALSE, &error); if (error != NULL) - return -1; + return NULL; - data = gdk_pixbuf_get_pixels(pixbuf); + stride = gdk_pixbuf_get_rowstride(pixbuf); + pixels = gdk_pixbuf_get_pixels(pixbuf); + n_channels = gdk_pixbuf_get_n_channels(pixbuf); - if (gdk_pixbuf_get_has_alpha(pixbuf)) - format = GL_RGBA; - else - format = GL_RGB; + argb_pixels = malloc (height * width * 4); + if (argb_pixels == NULL) { + gdk_pixbuf_unref(pixbuf); + return NULL; + } - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, - format, GL_UNSIGNED_BYTE, data); + if (n_channels == 4) { + for (i = 0; i < height; i++) { + s = pixels + i * stride; + end = s + width * 4; + d = argb_pixels + i * width * 4; + while (s < end) { + unsigned int t; + +#define MULT(_d,c,a,t) \ + do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) + + MULT(d[0], s[2], s[3], t); + MULT(d[1], s[1], s[3], t); + MULT(d[2], s[0], s[3], t); + d[3] = s[3]; + s += 4; + d += 4; + } + } + } else if (n_channels == 3) { + for (i = 0; i < height; i++) { + s = pixels + i * stride; + end = s + width * 3; + d = argb_pixels + i * width * 4; + while (s < end) { + d[0] = s[2]; + d[1] = s[1]; + d[2] = s[0]; + d[3] = 0xff; + s += 3; + d += 4; + } + } + } gdk_pixbuf_unref(pixbuf); - return 0; + buffer = ec->create_buffer(ec, width, height, + &ec->compositor.premultiplied_argb_visual, + argb_pixels); + + free(argb_pixels); + + return buffer; } static const struct { @@ -238,25 +281,15 @@ static void create_pointer_images(struct wlsc_compositor *ec) { int i, count; - GLuint texture; const int width = 32, height = 32; - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - count = ARRAY_LENGTH(pointer_images); ec->pointer_buffers = malloc(count * sizeof *ec->pointer_buffers); for (i = 0; i < count; i++) { ec->pointer_buffers[i] = - wlsc_drm_buffer_create(ec, width, height, - &ec->compositor.argb_visual); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, - ec->pointer_buffers[i]->image); - texture_from_png(pointer_images[i].filename, width, height); + create_buffer_from_png(ec, + pointer_images[i].filename, + width, height); } } @@ -264,37 +297,20 @@ static struct wlsc_surface * background_create(struct wlsc_output *output, const char *filename) { struct wlsc_surface *background; - GdkPixbuf *pixbuf; - GError *error = NULL; - void *data; - GLenum format; + struct wlsc_compositor *ec = output->compositor; + struct wl_buffer *buffer; background = wlsc_surface_create(output->compositor, - &output->compositor->compositor.rgb_visual, + &ec->compositor.premultiplied_argb_visual, output->x, output->y, output->width, output->height); if (background == NULL) return NULL; - pixbuf = gdk_pixbuf_new_from_file_at_scale(filename, - output->width, - output->height, - FALSE, &error); - if (error != NULL) { - free(background); - return NULL; - } - - data = gdk_pixbuf_get_pixels(pixbuf); - - if (gdk_pixbuf_get_has_alpha(pixbuf)) - format = GL_RGBA; - else - format = GL_RGB; - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, - output->width, output->height, 0, - format, GL_UNSIGNED_BYTE, data); + buffer = create_buffer_from_png(output->compositor, + filename, + output->width, output->height); + buffer->attach(buffer, &background->surface); return background; } @@ -500,7 +516,7 @@ wlsc_input_device_set_pointer_image(struct wlsc_input_device *device, (struct wlsc_compositor *) device->input_device.compositor; wlsc_input_device_attach(device, - &compositor->pointer_buffers[type]->buffer, + compositor->pointer_buffers[type], pointer_images[type].hotspot_x, pointer_images[type].hotspot_y); } diff --git a/compositor/compositor.h b/compositor/compositor.h index 277f8cd..dd7f534 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -77,21 +77,10 @@ struct wlsc_drm { char *filename; }; -struct wlsc_drm_buffer { - struct wl_buffer buffer; - EGLImageKHR image; -}; - struct wlsc_shm { struct wl_object object; }; -struct wlsc_shm_buffer { - struct wl_buffer buffer; - int32_t stride; - void *data; -}; - struct wlsc_compositor { struct wl_compositor compositor; @@ -101,7 +90,7 @@ struct wlsc_compositor { EGLContext context; GLuint fbo, vbo; GLuint proj_uniform, tex_uniform; - struct wlsc_drm_buffer **pointer_buffers; + struct wl_buffer **pointer_buffers; struct wl_display *wl_display; /* We implement the shell interface. */ @@ -125,6 +114,10 @@ struct wlsc_compositor { void (*destroy)(struct wlsc_compositor *ec); int (*authenticate)(struct wlsc_compositor *c, uint32_t id); void (*present)(struct wlsc_compositor *c); + struct wl_buffer *(*create_buffer)(struct wlsc_compositor *c, + int32_t width, int32_t height, + struct wl_visual *visual, + const void *data); }; #define MODIFIER_CTRL (1 << 8) @@ -163,9 +156,10 @@ wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs); void wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor); -struct wlsc_drm_buffer * +struct wl_buffer * wlsc_drm_buffer_create(struct wlsc_compositor *ec, - int width, int height, struct wl_visual *visual); + int width, int height, + struct wl_visual *visual, const void *data); int wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display); diff --git a/compositor/drm.c b/compositor/drm.c index 0c3b129..9e25d33 100644 --- a/compositor/drm.c +++ b/compositor/drm.c @@ -22,6 +22,11 @@ #include "compositor.h" +struct wlsc_drm_buffer { + struct wl_buffer buffer; + EGLImageKHR image; +}; + static void drm_authenticate(struct wl_client *client, struct wl_drm *drm_base, uint32_t id) @@ -197,12 +202,13 @@ wlsc_drm_init(struct wlsc_compositor *ec, int fd, const char *filename) return 0; } -struct wlsc_drm_buffer * -wlsc_drm_buffer_create(struct wlsc_compositor *ec, - int width, int height, struct wl_visual *visual) +struct wl_buffer * +wlsc_drm_buffer_create(struct wlsc_compositor *ec, int width, int height, + struct wl_visual *visual, const void *data) { struct wlsc_drm_buffer *buffer; EGLImageKHR image; + GLuint texture; EGLint image_attribs[] = { EGL_WIDTH, 0, @@ -222,5 +228,19 @@ wlsc_drm_buffer_create(struct wlsc_compositor *ec, buffer = wlsc_drm_buffer_create_for_image(ec, image, width, height, visual); - return buffer; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, buffer->image); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, + GL_BGRA_EXT, GL_UNSIGNED_BYTE, data); + + glDeleteTextures(1, &texture); + + return &buffer->buffer; } diff --git a/compositor/shm.c b/compositor/shm.c index 52585f8..62eca2c 100644 --- a/compositor/shm.c +++ b/compositor/shm.c @@ -24,6 +24,12 @@ #include "compositor.h" +struct wlsc_shm_buffer { + struct wl_buffer buffer; + int32_t stride; + void *data; +}; + static void destroy_buffer(struct wl_resource *resource, struct wl_client *client) { -- 2.7.4