1 // Manually created
2 module std.c.linux.X11.xcb.image;
3 version(USE_XCB):
4
5 import std.c.linux.X11.xcb.xcb;
6 import std.c.linux.X11.xcb.shm;
7 import std.c.linux.X11.xcb.xproto;
8 import std.c.stdlib;
9 import std.conv;
10
11 struct xcb_image_t
12 {
13 ushort width;
14 ushort height;
15 xcb_image_format_t format;
16 ubyte scanline_pad;
17 ubyte depth;
18 ubyte bpp;
19 ubyte unit;
20 uint plane_mask;
21 xcb_image_order_t byte_order;
22 xcb_image_order_t bit_order;
23 uint stride;
24 uint size;
25 void * base;
26 ubyte * data;
27 }
28
29 xcb_format_t *
30 find_format_by_depth (xcb_setup_t *setup, ubyte depth)
31 {
32 xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
33 xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
34 for(; fmt != fmtend; ++fmt)
35 if(fmt.depth == depth)
36 return fmt;
37 return null;
38 }
39
40
41 xcb_image_format_t
42 effective_format(xcb_image_format_t format, ubyte bpp)
43 {
44 if (format == XCB_IMAGE_FORMAT_Z_PIXMAP && bpp != 1)
45 return format;
46 return XCB_IMAGE_FORMAT_XY_PIXMAP;
47 }
48
49
50 int
51 format_valid (ubyte depth, ubyte bpp, ubyte unit,
52 xcb_image_format_t format, ubyte xpad)
53 {
54 xcb_image_format_t ef = effective_format(format, bpp);
55 if (depth > bpp)
56 return 0;
57 switch(ef) {
58 case XCB_IMAGE_FORMAT_XY_PIXMAP:
59 switch(unit) {
60 case 8:
61 case 16:
62 case 32:
63 break;
64 default:
65 return 0;
66 }
67 if (xpad < bpp)
68 return 0;
69 switch (xpad) {
70 case 8:
71 case 16:
72 case 32:
73 break;
74 default:
75 return 0;
76 }
77 break;
78 case XCB_IMAGE_FORMAT_Z_PIXMAP:
79 switch (bpp) {
80 case 4:
81 if (unit != 8)
82 return 0;
83 break;
84 case 8:
85 case 16:
86 case 24:
87 case 32:
88 if (unit != bpp)
89 return 0;
90 break;
91 default:
92 return 0;
93 }
94 break;
95 default:
96 return 0;
97 }
98 return 1;
99 }
100
101
102 int
103 image_format_valid (xcb_image_t *image) {
104 return format_valid(image.depth,
105 image.bpp,
106 image.unit,
107 image.format,
108 image.scanline_pad);
109 }
110
111 uint xcb_roundup(uint base,
112 uint pad
113 )
114 {
115 uint b = base + pad - 1;
116 /* faster if pad is a power of two */
117 if (((pad - 1) & pad) == 0)
118 return b & -pad;
119 return b - b % pad;
120 }
121
122 void
123 xcb_image_annotate (xcb_image_t *image)
124 {
125 xcb_image_format_t ef = effective_format(image.format, image.bpp);
126 switch (ef) {
127 case XCB_IMAGE_FORMAT_XY_PIXMAP:
128 image.stride = xcb_roundup(image.width, image.scanline_pad) >> 3;
129 image.size = image.height * image.stride * image.depth;
130 break;
131 case XCB_IMAGE_FORMAT_Z_PIXMAP:
132 image.stride = xcb_roundup(cast(uint)image.width *
133 cast(uint)image.bpp,
134 image.scanline_pad) >> 3;
135 image.size = image.height * image.stride;
136 break;
137 default:
138 assert(0);
139 }
140 }
141
142 xcb_image_t *
143 xcb_image_create_native (xcb_connection_t * c,
144 ushort width,
145 ushort height,
146 xcb_image_format_t format,
147 ubyte depth,
148 void * base,
149 uint bytes,
150 ubyte * data)
151 {
152 xcb_setup_t * setup = xcb_get_setup(c);
153 xcb_format_t * fmt;
154 xcb_image_format_t ef = format;
155
156 if (ef == XCB_IMAGE_FORMAT_Z_PIXMAP && depth == 1)
157 ef = XCB_IMAGE_FORMAT_XY_PIXMAP;
158 switch (ef) {
159 case XCB_IMAGE_FORMAT_XY_BITMAP:
160 if (depth != 1)
161 return null;
162 /* fall through */
163 goto case;
164 case XCB_IMAGE_FORMAT_XY_PIXMAP:
165 if (depth > 1) {
166 fmt = find_format_by_depth(setup, depth);
167 if (!fmt)
168 return null;
169 }
170 return xcb_image_create(width, height, format,
171 setup.bitmap_format_scanline_pad,
172 depth, depth, setup.bitmap_format_scanline_unit,
173 setup.image_byte_order,
174 setup.bitmap_format_bit_order,
175 base, bytes, data);
176 case XCB_IMAGE_FORMAT_Z_PIXMAP:
177 fmt = find_format_by_depth(setup, depth);
178 if (!fmt)
179 return null;
180 return xcb_image_create(width, height, format,
181 fmt.scanline_pad,
182 fmt.depth, fmt.bits_per_pixel, 0,
183 setup.image_byte_order,
184 XCB_IMAGE_ORDER_MSB_FIRST,
185 base, bytes, data);
186 default:
187 assert(0);
188 }
189 assert(0);
190 }
191
192 uint xcb_mask(uint n)
193 {
194 return n == 32 ? ~0 : (1 << n) - 1;
195 }
196
197 xcb_image_t *
198 xcb_image_create (ushort width,
199 ushort height,
200 xcb_image_format_t format,
201 ubyte xpad,
202 ubyte depth,
203 ubyte bpp,
204 ubyte unit,
205 xcb_image_order_t byte_order,
206 xcb_image_order_t bit_order,
207 void * base,
208 uint bytes,
209 ubyte * data)
210 {
211 xcb_image_t * image;
212
213 if (unit == 0) {
214 switch (format) {
215 case XCB_IMAGE_FORMAT_XY_BITMAP:
216 case XCB_IMAGE_FORMAT_XY_PIXMAP:
217 unit = 32;
218 break;
219 case XCB_IMAGE_FORMAT_Z_PIXMAP:
220 if (bpp == 1) {
221 unit = 32;
222 break;
223 }
224 if (bpp < 8) {
225 unit = 8;
226 break;
227 }
228 unit = bpp;
229 break;
230 default:
231 break;
232
233 }
234 }
235 if (!format_valid(depth, bpp, unit, format, xpad))
236 return null;
237 import std.c.stdlib;
238 image = cast(xcb_image_t*)malloc(xcb_image_t.sizeof);
239 if (image is null)
240 return null;
241 image.width = width;
242 image.height = height;
243 image.format = format;
244 image.scanline_pad = xpad;
245 image.depth = depth;
246 image.bpp = bpp;
247 image.unit = unit;
248 image.plane_mask = xcb_mask(depth);
249 image.byte_order = byte_order;
250 image.bit_order = bit_order;
251 xcb_image_annotate(image);
252
253 /*
254 * Ways this function can be called:
255 * * with data: we fail if bytes isn't
256 * large enough, else leave well enough alone.
257 * * with base and !data: if bytes is zero, we
258 * default; otherwise we fail if bytes isn't
259 * large enough, else fill in data
260 * * with !base and !data: we malloc storage
261 * for the data, save that address as the base,
262 * and fail if malloc does.
263 *
264 * When successful, we establish the invariant that data
265 * points at sufficient storage that may have been
266 * supplied, and base is set iff it should be
267 * auto-freed when the image is destroyed.
268 *
269 * Except as a special case when base = 0 && data == 0 &&
270 * bytes == ~0 we just return the image structure and let
271 * the caller deal with getting the allocation right.
272 */
273 if (!base && !data && bytes == ~0) {
274 image.base = null;
275 image.data = null;
276 return image;
277 }
278 if (!base && data && bytes == 0)
279 bytes = image.size;
280 image.base = base;
281 image.data = data;
282 if (!image.data) {
283 if (image.base) {
284 image.data = cast(ubyte*)image.base;
285 } else {
286 bytes = image.size;
287 image.base = malloc(bytes);
288 image.data = cast(ubyte*)image.base;
289 }
290 }
291 if (!image.data || bytes < image.size) {
292 free(image);
293 return null;
294 }
295 return image;
296 }
297
298
299 void
300 xcb_image_destroy (xcb_image_t *image)
301 {
302 if (image.base)
303 free (image.base);
304 free (image);
305 }
306
307 ubyte
308 xcb_aux_get_depth(xcb_connection_t *c,
309 xcb_screen_t *screen)
310 {
311 xcb_drawable_t drawable;
312 xcb_get_geometry_reply_t *geom;
313 ubyte depth;
314
315 drawable = screen.root;
316 geom = xcb_get_geometry_reply (c, xcb_get_geometry(c, drawable), null);
317
318 if (!geom) {
319 //Log.e("GetGeometry(root) failed");
320 exit (0);
321 }
322
323 depth = geom.depth;
324 free (geom);
325
326 return depth;
327 }
328
329 extern (C) int xcb_image_shm_get(xcb_connection_t * conn,
330 xcb_drawable_t draw,
331 xcb_image_t * image,
332 xcb_shm_segment_info_t shminfo,
333 ushort x,
334 ushort y,
335 uint plane_mask);
336 const XCB_ALL_PLANES = ~0;
337
338 extern (C) xcb_image_t *
339 xcb_image_shm_put (xcb_connection_t * conn,
340 xcb_drawable_t draw,
341 xcb_gcontext_t gc,
342 xcb_image_t * image,
343 xcb_shm_segment_info_t shminfo,
344 short src_x,
345 short src_y,
346 short dest_x,
347 short dest_y,
348 ushort src_width,
349 ushort src_height,
350 ubyte send_event);
351
352 /**
353 * @struct xcb_shm_segment_info_t
354 * A structure that stores the informations needed by the MIT Shm
355 * Extension.
356 */
357 struct xcb_shm_segment_info_t
358 {
359 xcb_shm_seg_t shmseg;
360 uint shmid;
361 ubyte *shmaddr;
362 }
363
364 alias int key_t;
365 extern (C) int shmget(key_t key, size_t size, int shmflg);
366 extern (C) int getpagesize();
367 extern (C) ubyte *shmat(int shmid, ubyte *shmaddr, int shmflg);
368 extern (C) int shmctl(int shmid, int cmd, void *buf);
369 const IPC_CREAT = octal!1000;
370 const IPC_PRIVATE = (cast(key_t) 0);
371 const IPC_RMID = 0;