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;