Unpremultiply cairo surface data.
authorKristian Høgsberg <krh@redhat.com>
Sun, 2 Nov 2008 20:50:55 +0000 (15:50 -0500)
committerKristian Høgsberg <krh@redhat.com>
Thu, 6 Nov 2008 15:53:02 +0000 (10:53 -0500)
flower.c
pointer.c

index 46deb05..cc8d985 100644 (file)
--- a/flower.c
+++ b/flower.c
 static const char gem_device[] = "/dev/dri/card0";
 static const char socket_name[] = "\0wayland";
 
+static void
+unpremultiply_data(uint8_t *data, int width, int height, int stride)
+{
+       unsigned int i, j;
+       uint8_t *row;
+
+       for (j = 0; j < height; j++) {
+               row = data + j * stride;
+
+               for (i = 0; i < width; i++) {
+                       uint8_t *b = &row[i * 4];
+                       uint32_t pixel;
+                       uint8_t  alpha;
+
+                       memcpy (&pixel, b, sizeof (uint32_t));
+                       alpha = (pixel & 0xff000000) >> 24;
+                       if (alpha == 0) {
+                               b[0] = b[1] = b[2] = b[3] = 0;
+                       } else {
+                               b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+                               b[1] = (((pixel & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
+                               b[2] = (((pixel & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
+                               b[3] = alpha;
+                       }
+               }
+       }
+}
+
 static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
 {
        struct drm_i915_gem_create create;
        struct drm_gem_flink flink;
        struct drm_i915_gem_pwrite pwrite;
        int32_t width, height, stride;
+       void *data;
 
        width = cairo_image_surface_get_width(surface);
        height = cairo_image_surface_get_height(surface);
        stride = cairo_image_surface_get_stride(surface);
+       data = cairo_image_surface_get_data(surface);
+
+       unpremultiply_data(data, width, height, stride);
 
        memset(&create, 0, sizeof(create));
        create.size = height * stride;
@@ -40,8 +72,7 @@ static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
        pwrite.handle = create.handle;
        pwrite.offset = 0;
        pwrite.size = height * stride;
-       pwrite.data_ptr = (uint64_t) (uintptr_t)
-               cairo_image_surface_get_data(surface);
+       pwrite.data_ptr = (uint64_t) (uintptr_t) data;
        if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
                fprintf(stderr, "gem pwrite failed: %m\n");
                return 0;
@@ -149,7 +180,7 @@ int main(int argc, char *argv[])
 {
        struct wl_display *display;
        struct wl_surface *surface;
-       const int x = 200, y = 200, width = 200, height = 200;
+       const int x = 512, y = 384, width = 200, height = 200;
        int fd, i, ret;
        uint32_t name, mask;
        cairo_surface_t *s;
@@ -198,13 +229,13 @@ int main(int argc, char *argv[])
        wl_surface_attach(surface, name, width, height,
                          cairo_image_surface_get_stride(s));
 
-       i = 0;
+       i = ts.tv_nsec;
        while (ret = poll(p, 2, -1), ret >= 0) {
                if (p[1].revents & POLLIN) {
                        read(p[1].fd, &expires, sizeof expires);
                        wl_surface_map(surface, 
-                                      x + cos(i / 30.0) * 200,
-                                      y + sin(i / 31.0) * 200,
+                                      x + cos(i / 31.0) * 400 - width / 2,
+                                      y + sin(i / 27.0) * 300 - height / 2,
                                       width, height);
                        i++;
                        continue;
index 9571358..ec9f0a3 100644 (file)
--- a/pointer.c
+++ b/pointer.c
 static const char gem_device[] = "/dev/dri/card0";
 static const char socket_name[] = "\0wayland";
 
+static void
+unpremultiply_data(uint8_t *data, int width, int height, int stride)
+{
+       unsigned int i, j;
+       uint8_t *row;
+
+       for (j = 0; j < height; j++) {
+               row = data + j * stride;
+
+               for (i = 0; i < width; i++) {
+                       uint8_t *b = &row[i * 4];
+                       uint32_t pixel;
+                       uint8_t  alpha;
+
+                       memcpy (&pixel, b, sizeof (uint32_t));
+                       alpha = (pixel & 0xff000000) >> 24;
+                       if (alpha == 0) {
+                               b[0] = b[1] = b[2] = b[3] = 0;
+                       } else {
+                               b[0] = (((pixel & 0xff0000) >> 16) * 255 + alpha / 2) / alpha;
+                               b[1] = (((pixel & 0x00ff00) >>  8) * 255 + alpha / 2) / alpha;
+                               b[2] = (((pixel & 0x0000ff) >>  0) * 255 + alpha / 2) / alpha;
+                               b[3] = alpha;
+                       }
+               }
+       }
+}
+
 static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
 {
        struct drm_i915_gem_create create;
        struct drm_gem_flink flink;
        struct drm_i915_gem_pwrite pwrite;
        int32_t width, height, stride;
+       void *data;
 
        width = cairo_image_surface_get_width(surface);
        height = cairo_image_surface_get_height(surface);
        stride = cairo_image_surface_get_stride(surface);
+       data = cairo_image_surface_get_data(surface);
+
+       unpremultiply_data(data, width, height, stride);
 
        memset(&create, 0, sizeof(create));
        create.size = height * stride;
@@ -37,8 +69,7 @@ static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
        pwrite.handle = create.handle;
        pwrite.offset = 0;
        pwrite.size = height * stride;
-       pwrite.data_ptr = (uint64_t) (uintptr_t)
-               cairo_image_surface_get_data(surface);
+       pwrite.data_ptr = (uint64_t) (uintptr_t) data;
        if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
                fprintf(stderr, "gem pwrite failed: %m\n");
                return 0;
@@ -68,7 +99,7 @@ static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
 static void *
 draw_pointer(int width, int height)
 {
-       const int d = 2, end = 4, tx = 2, ty = 6, dx = 5, dy = 4;
+       const int d = 2, end = 4, tx = 2, ty = 6, dx = 4, dy = 4;
        cairo_surface_t *surface;
        cairo_t *cr;