Move buffer creation and buffer details into drm.c and shm.c
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 14 Jan 2011 21:20:21 +0000 (16:20 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 14 Jan 2011 21:20:21 +0000 (16:20 -0500)
compositor/compositor-drm.c
compositor/compositor-wayland.c
compositor/compositor-x11.c
compositor/compositor.c
compositor/compositor.h
compositor/drm.c
compositor/shm.c

index a082923..6df6b34 100644 (file)
@@ -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;
 }
index a7a7874..ed8a2ba 100644 (file)
@@ -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;
 }
 
index 722bd94..7e7c8ca 100644 (file)
@@ -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;
 }
index 1e6f2ef..df73b60 100644 (file)
@@ -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);
 }
index 277f8cd..dd7f534 100644 (file)
@@ -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);
index 0c3b129..9e25d33 100644 (file)
 
 #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;
 }
index 52585f8..62eca2c 100644 (file)
 
 #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)
 {