blob: 94c7b037c8d59da2920dce08f19902d29d0661e2 [file] [log] [blame]
Kristian Høgsberg2f2cfae2008-11-08 22:46:30 -05001#include <stdint.h>
2#include <stdlib.h>
3#include <string.h>
4#include <stdio.h>
5#include <i915_drm.h>
6#include <sys/ioctl.h>
7#include <math.h>
8#include <cairo.h>
9#include "cairo-util.h"
10
11struct buffer *
12buffer_create(int fd, int width, int height, int stride)
13{
14 struct buffer *buffer;
15 struct drm_i915_gem_create create;
16 struct drm_gem_flink flink;
17
18 buffer = malloc(sizeof *buffer);
19 buffer->width = width;
20 buffer->height = height;
21 buffer->stride = stride;
22
23 memset(&create, 0, sizeof(create));
24 create.size = height * stride;
25
26 if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create) != 0) {
27 fprintf(stderr, "gem create failed: %m\n");
28 free(buffer);
29 return NULL;
30 }
31
32 flink.handle = create.handle;
33 if (ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) {
34 fprintf(stderr, "gem flink failed: %m\n");
35 free(buffer);
36 return 0;
37 }
38
39 buffer->handle = flink.handle;
40 buffer->name = flink.name;
41
42 return buffer;
43}
44
45int
46buffer_destroy(struct buffer *buffer, int fd)
47{
48 struct drm_gem_close close;
49
50 close.handle = buffer->handle;
51 if (ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close) < 0) {
52 fprintf(stderr, "gem close failed: %m\n");
53 return -1;
54 }
55
56 free(buffer);
57
58 return 0;
59}
60
61int
62buffer_data(struct buffer *buffer, int fd, void *data)
63{
64 struct drm_i915_gem_pwrite pwrite;
65
66 pwrite.handle = buffer->handle;
67 pwrite.offset = 0;
68 pwrite.size = buffer->height * buffer->stride;
69 pwrite.data_ptr = (uint64_t) (uintptr_t) data;
70
71 if (ioctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &pwrite) < 0) {
72 fprintf(stderr, "gem pwrite failed: %m\n");
73 return -1;
74 }
75
76 return 0;
77}
78
79struct buffer *
80buffer_create_from_cairo_surface(int fd, cairo_surface_t *surface)
81{
82 struct buffer *buffer;
83 int32_t width, height, stride;
84 void *data;
85
86 width = cairo_image_surface_get_width(surface);
87 height = cairo_image_surface_get_height(surface);
88 stride = cairo_image_surface_get_stride(surface);
89 data = cairo_image_surface_get_data(surface);
90
91 buffer = buffer_create(fd, width, height, stride);
92 if (buffer == NULL)
93 return NULL;
94
95 if (buffer_data(buffer, fd, data) < 0) {
96 buffer_destroy(buffer, fd);
97 return NULL;
98 }
99
100 return buffer;
101}
102
103void
Kristian Høgsberg10bdd292008-11-08 23:27:27 -0500104blur_surface(cairo_surface_t *surface, int margin)
Kristian Høgsberg2f2cfae2008-11-08 22:46:30 -0500105{
106 cairo_surface_t *tmp;
107 int32_t width, height, stride, x, y, z, w;
108 uint8_t *src, *dst;
109 uint32_t *s, *d, a, p;
Kristian Høgsberg10bdd292008-11-08 23:27:27 -0500110 int i, j, k, size = 17, half;
Kristian Høgsberg2f2cfae2008-11-08 22:46:30 -0500111 uint8_t kernel[100];
112 double f;
113
114 width = cairo_image_surface_get_width(surface);
115 height = cairo_image_surface_get_height(surface);
116 stride = cairo_image_surface_get_stride(surface);
117 src = cairo_image_surface_get_data(surface);
118
119 tmp = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
120 dst = cairo_image_surface_get_data(tmp);
121
122 half = size / 2;
123 a = 0;
124 for (i = 0; i < size; i++) {
125 f = (i - half);
126 kernel[i] = exp(- f * f / 30.0) * 80;
127 a += kernel[i];
128 }
129
130 for (i = 0; i < height; i++) {
131 s = (uint32_t *) (src + i * stride);
132 d = (uint32_t *) (dst + i * stride);
133 for (j = 0; j < width; j++) {
Kristian Høgsberg10bdd292008-11-08 23:27:27 -0500134 if (margin < j && j < width - margin &&
135 margin < i && i < height - margin)
136 continue;
Kristian Høgsberg2f2cfae2008-11-08 22:46:30 -0500137 x = 0;
138 y = 0;
139 z = 0;
140 w = 0;
141 for (k = 0; k < size; k++) {
142 if (j - half + k < 0 || j - half + k >= width)
143 continue;
144 p = s[j - half + k];
145
146 x += (p >> 24) * kernel[k];
147 y += ((p >> 16) & 0xff) * kernel[k];
148 z += ((p >> 8) & 0xff) * kernel[k];
149 w += (p & 0xff) * kernel[k];
150 }
151 d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
152 }
153 }
154
155 for (i = 0; i < height; i++) {
156 s = (uint32_t *) (dst + i * stride);
157 d = (uint32_t *) (src + i * stride);
158 for (j = 0; j < width; j++) {
Kristian Høgsberg10bdd292008-11-08 23:27:27 -0500159 if (margin <= j && j < width - margin &&
160 margin <= i && i < height - margin)
161 continue;
Kristian Høgsberg2f2cfae2008-11-08 22:46:30 -0500162 x = 0;
163 y = 0;
164 z = 0;
165 w = 0;
166 for (k = 0; k < size; k++) {
167 if (i - half + k < 0 || i - half + k >= height)
168 continue;
169 s = (uint32_t *) (dst + (i - half + k) * stride);
170 p = s[j];
171
172 x += (p >> 24) * kernel[k];
173 y += ((p >> 16) & 0xff) * kernel[k];
174 z += ((p >> 8) & 0xff) * kernel[k];
175 w += (p & 0xff) * kernel[k];
176 }
177 d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
178 }
179 }
180
181 cairo_surface_destroy(tmp);
182}