From 1b2f4390f54ed9f5ed0f1440c2fd620ec06e1590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Sun, 2 Nov 2008 15:50:55 -0500 Subject: [PATCH] Unpremultiply cairo surface data. --- flower.c | 43 +++++++++++++++++++++++++++++++++++++------ pointer.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/flower.c b/flower.c index 46deb054..cc8d9855 100644 --- a/flower.c +++ b/flower.c @@ -18,16 +18,48 @@ 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; diff --git a/pointer.c b/pointer.c index 95713589..ec9f0a34 100644 --- a/pointer.c +++ b/pointer.c @@ -15,16 +15,48 @@ 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;