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