1 #include "ecore_xcb_private.h"
4 #include <xcb/xcb_event.h>
9 xcb_shm_segment_info_t shminfo;
18 /* local function prototypes */
19 static void _ecore_xcb_image_shm_check(void);
20 static void _ecore_xcb_image_shm_create(Ecore_X_Image *im);
21 static xcb_format_t *_ecore_xcb_image_find_format(const xcb_setup_t *setup, uint8_t depth);
24 static int _ecore_xcb_image_shm_can = -1;
27 ecore_x_image_new(int w, int h, Ecore_X_Visual vis, int depth)
31 LOGFN(__FILE__, __LINE__, __FUNCTION__);
33 if (!(im = calloc(1, sizeof(Ecore_X_Image)))) return NULL;
38 _ecore_xcb_image_shm_check();
39 im->shm = _ecore_xcb_image_shm_can;
44 ecore_x_image_free(Ecore_X_Image *im)
46 LOGFN(__FILE__, __LINE__, __FUNCTION__);
53 xcb_shm_detach(_ecore_xcb_conn, im->shminfo.shmseg);
54 xcb_image_destroy(im->xim);
55 shmdt(im->shminfo.shmaddr);
56 shmctl(im->shminfo.shmid, IPC_RMID, 0);
61 if (im->xim->data) free(im->xim->data);
63 xcb_image_destroy(im->xim);
71 ecore_x_image_get(Ecore_X_Image *im, Ecore_X_Drawable draw, int x, int y, int sx, int sy, int w, int h)
73 Eina_Bool ret = EINA_TRUE;
75 LOGFN(__FILE__, __LINE__, __FUNCTION__);
79 if (!im->xim) _ecore_xcb_image_shm_create(im);
80 if (!im->xim) return EINA_FALSE;
82 if ((sx == 0) && (w == im->w))
84 im->xim->data = (uint8_t *)im->data + (im->xim->stride * sy) +
90 if (!xcb_image_shm_get(_ecore_xcb_conn, draw, im->xim,
91 im->shminfo, x, y, 0xffffffff))
93 DBG("\tImage Shm Get Failed");
97 ecore_x_sync(); // needed
103 tim = ecore_x_image_new(w, h, im->vis, im->depth);
106 ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h);
109 unsigned char *spixels, *pixels;
110 int sbpp = 0, sbpl = 0, srows = 0;
111 int bpp = 0, bpl = 0, rows = 0;
114 ecore_x_image_data_get(tim, &sbpl, &srows, &sbpp);
115 pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp);
116 if ((spixels) && (pixels))
118 unsigned char *p, *sp;
121 p = (pixels + (sy * bpl) + (sx * bpp));
123 for (r = srows; r > 0; r--)
131 ecore_x_image_free(tim);
140 xcb_image_get(_ecore_xcb_conn, draw, x, y, w, h,
141 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP);
142 if (!im->xim) ret = EINA_FALSE;
144 ecore_x_sync(); // needed
148 im->data = (unsigned char *)im->xim->data;
149 im->bpl = im->xim->stride;
150 im->rows = im->xim->height;
151 if (im->xim->bpp <= 8)
153 else if (im->xim->bpp <= 16)
164 ecore_x_image_data_get(Ecore_X_Image *im, int *bpl, int *rows, int *bpp)
166 LOGFN(__FILE__, __LINE__, __FUNCTION__);
168 if (!im) return NULL;
169 if (!im->xim) _ecore_xcb_image_shm_create(im);
170 if (!im->xim) return NULL;
172 if (bpl) *bpl = im->bpl;
173 if (rows) *rows = im->rows;
174 if (bpp) *bpp = im->bpp;
180 ecore_x_image_put(Ecore_X_Image *im, Ecore_X_Drawable draw, Ecore_X_GC gc, int x, int y, int sx, int sy, int w, int h)
184 LOGFN(__FILE__, __LINE__, __FUNCTION__);
188 uint32_t mask, values[1];
190 tgc = xcb_generate_id(_ecore_xcb_conn);
191 mask = XCB_GC_SUBWINDOW_MODE;
192 values[0] = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS;
193 xcb_create_gc(_ecore_xcb_conn, tgc, draw, mask, values);
196 if (!im->xim) _ecore_xcb_image_shm_create(im);
200 xcb_shm_put_image(_ecore_xcb_conn, draw, gc, im->xim->width,
201 im->xim->height, sx, sy, w, h, x, y,
202 im->xim->depth, im->xim->format, 0,
204 im->xim->data - im->shminfo.shmaddr);
205 // xcb_image_shm_put(_ecore_xcb_conn, draw, gc, im->xim,
206 // im->shminfo, sx, sy, x, y, w, h, 0);
208 xcb_image_put(_ecore_xcb_conn, draw, gc, im->xim, sx, sy, 0);
211 if (tgc) ecore_x_gc_free(tgc);
216 ecore_x_image_is_argb32_get(Ecore_X_Image *im)
218 xcb_visualtype_t *vis;
220 LOGFN(__FILE__, __LINE__, __FUNCTION__);
222 vis = (xcb_visualtype_t *)im->vis;
223 if (!im->xim) _ecore_xcb_image_shm_create(im);
225 if (((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) ||
226 (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) &&
227 (im->depth >= 24) && (vis->red_mask == 0xff0000) &&
228 (vis->green_mask == 0x00ff00) && (vis->blue_mask == 0x0000ff))
230 #ifdef WORDS_BIGENDIAN
231 if (im->xim->byte_order == XCB_IMAGE_ORDER_LSB_FIRST)
234 if (im->xim->byte_order == XCB_IMAGE_ORDER_MSB_FIRST)
243 ecore_x_image_to_argb_convert(void *src, int sbpp, int sbpl, Ecore_X_Colormap c, Ecore_X_Visual v, int x, int y, int w, int h, unsigned int *dst, int dbpl, int dx, int dy)
245 xcb_visualtype_t *vis;
247 int n = 0, nret = 0, i, row, mode = 0;
248 unsigned int pal[256], r, g, b;
262 LOGFN(__FILE__, __LINE__, __FUNCTION__);
266 vis = (xcb_visualtype_t *)v;
267 n = vis->colormap_entries;
269 ((vis->_class == XCB_VISUAL_CLASS_PSEUDO_COLOR) ||
270 (vis->_class == XCB_VISUAL_CLASS_STATIC_COLOR) ||
271 (vis->_class == XCB_VISUAL_CLASS_GRAY_SCALE) ||
272 (vis->_class == XCB_VISUAL_CLASS_STATIC_GRAY)))
274 xcb_query_colors_cookie_t cookie;
275 xcb_query_colors_reply_t *reply;
279 c = (xcb_colormap_t)((xcb_screen_t *)
280 _ecore_xcb_screen)->default_colormap;
283 cols = alloca(n * sizeof(uint32_t));
284 for (i = 0; i < n; i++)
287 cookie = xcb_query_colors_unchecked(_ecore_xcb_conn, c, n, cols);
288 reply = xcb_query_colors_reply(_ecore_xcb_conn, cookie, NULL);
291 xcb_rgb_iterator_t iter;
294 iter = xcb_query_colors_colors_iterator(reply);
295 ret = xcb_query_colors_colors(reply);
298 for (i = 0; iter.rem; xcb_rgb_next(&iter), i++)
300 pal[i] = 0xff000000 |
301 ((iter.data->red >> 8) << 16) |
302 ((iter.data->green >> 8) << 8) |
303 ((iter.data->blue >> 8));
310 else if ((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) ||
311 (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR))
313 if ((vis->red_mask == 0x00ff0000) &&
314 (vis->green_mask == 0x0000ff00) &&
315 (vis->blue_mask == 0x000000ff))
317 else if ((vis->red_mask == 0x000000ff) &&
318 (vis->green_mask == 0x0000ff00) &&
319 (vis->blue_mask == 0x00ff0000))
321 else if ((vis->red_mask == 0xff000000) &&
322 (vis->green_mask == 0x00ff0000) &&
323 (vis->blue_mask == 0x0000ff00))
325 else if ((vis->red_mask == 0x0000ff00) &&
326 (vis->green_mask == 0x00ff0000) &&
327 (vis->blue_mask == 0xff000000))
329 else if ((vis->red_mask == 0x0003f000) &&
330 (vis->green_mask == 0x00000fc0) &&
331 (vis->blue_mask == 0x0000003f))
333 else if ((vis->red_mask == 0x0000f800) &&
334 (vis->green_mask == 0x000007e0) &&
335 (vis->blue_mask == 0x0000001f))
337 else if ((vis->red_mask == 0x0000001f) &&
338 (vis->green_mask == 0x000007e0) &&
339 (vis->blue_mask == 0x0000f800))
341 else if ((vis->red_mask == 0x00007c00) &&
342 (vis->green_mask == 0x000003e0) &&
343 (vis->blue_mask == 0x0000001f))
348 for (row = 0; row < h; row++)
352 unsigned int *s32, *dp, *de;
354 dp = ((unsigned int *)(((unsigned char *)dst) +
355 ((dy + row) * dbpl))) + dx;
360 s8 = ((unsigned char *)(((unsigned char *)src) +
361 ((y + row) * sbpl))) + x;
374 s16 = ((unsigned short *)(((unsigned char *)src) +
375 ((y + row) * sbpl))) + x;
381 r = (*s16 & 0xf800) << 8;
382 g = (*s16 & 0x07e0) << 5;
383 b = (*s16 & 0x001f) << 3;
384 r |= (r >> 5) & 0xff0000;
385 g |= (g >> 6) & 0x00ff00;
387 *dp = 0xff000000 | r | g | b;
394 r = (*s16 & 0x001f) << 19;
395 g = (*s16 & 0x07e0) << 5;
396 b = (*s16 & 0xf800) >> 8;
397 r |= (r >> 5) & 0xff0000;
398 g |= (g >> 6) & 0x00ff00;
400 *dp = 0xff000000 | r | g | b;
407 r = (*s16 & 0x7c00) << 9;
408 g = (*s16 & 0x03e0) << 6;
409 b = (*s16 & 0x001f) << 3;
410 r |= (r >> 5) & 0xff0000;
411 g |= (g >> 5) & 0x00ff00;
413 *dp = 0xff000000 | r | g | b;
424 s32 = ((unsigned int *)(((unsigned char *)src) +
425 ((y + row) * sbpl))) + x;
431 *dp = 0xff000000 | *s32;
438 r = *s32 & 0x000000ff;
439 g = *s32 & 0x0000ff00;
440 b = *s32 & 0x00ff0000;
441 *dp = 0xff000000 | (r << 16) | (g) | (b >> 16);
448 *dp = 0xff000000 | (*s32 >> 8);
455 r = *s32 & 0x0000ff00;
456 g = *s32 & 0x00ff0000;
457 b = *s32 & 0xff000000;
458 *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24);
465 r = (*s32 & 0x3f000) << 6;
466 g = (*s32 & 0x00fc0) << 4;
467 b = (*s32 & 0x0003f) << 2;
468 r |= (r >> 6) & 0xff0000;
469 g |= (g >> 6) & 0x00ff00;
471 *dp = 0xff000000 | r | g | b;
489 /* local functions */
491 _ecore_xcb_image_shm_check(void)
493 // xcb_shm_query_version_reply_t *reply;
494 xcb_shm_segment_info_t shminfo;
495 xcb_shm_get_image_cookie_t cookie;
496 xcb_shm_get_image_reply_t *ireply;
497 xcb_image_t *img = 0;
500 if (_ecore_xcb_image_shm_can != -1) return;
503 /* xcb_shm_query_version_reply(_ecore_xcb_conn, */
504 /* xcb_shm_query_version(_ecore_xcb_conn), NULL); */
507 /* _ecore_xcb_image_shm_can = 0; */
511 /* if ((reply->major_version < 1) || */
512 /* ((reply->major_version == 1) && (reply->minor_version == 0))) */
514 /* _ecore_xcb_image_shm_can = 0; */
521 depth = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth;
523 ecore_x_sync(); // needed
525 img = _ecore_xcb_image_create_native(1, 1, XCB_IMAGE_FORMAT_Z_PIXMAP,
526 depth, NULL, ~0, NULL);
529 _ecore_xcb_image_shm_can = 0;
534 shmget(IPC_PRIVATE, img->stride * img->height, (IPC_CREAT | 0666));
535 if (shminfo.shmid == (uint32_t)-1)
537 xcb_image_destroy(img);
538 _ecore_xcb_image_shm_can = 0;
542 shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
543 img->data = shminfo.shmaddr;
544 if (img->data == (uint8_t *)-1)
546 xcb_image_destroy(img);
547 _ecore_xcb_image_shm_can = 0;
551 shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn);
552 xcb_shm_attach(_ecore_xcb_conn, shminfo.shmseg, shminfo.shmid, 0);
555 xcb_shm_get_image(_ecore_xcb_conn,
556 ((xcb_screen_t *)_ecore_xcb_screen)->root,
557 0, 0, img->width, img->height,
558 0xffffffff, img->format,
559 shminfo.shmseg, img->data - shminfo.shmaddr);
561 ecore_x_sync(); // needed
563 ireply = xcb_shm_get_image_reply(_ecore_xcb_conn, cookie, NULL);
566 _ecore_xcb_image_shm_can = 1;
570 _ecore_xcb_image_shm_can = 0;
572 xcb_shm_detach(_ecore_xcb_conn, shminfo.shmseg);
573 xcb_image_destroy(img);
574 shmdt(shminfo.shmaddr);
575 shmctl(shminfo.shmid, IPC_RMID, 0);
579 _ecore_xcb_image_shm_create(Ecore_X_Image *im)
582 _ecore_xcb_image_create_native(im->w, im->h, XCB_IMAGE_FORMAT_Z_PIXMAP,
583 im->depth, NULL, ~0, NULL);
584 if (!im->xim) return;
586 im->shminfo.shmid = shmget(IPC_PRIVATE, im->xim->size, (IPC_CREAT | 0666));
587 if (im->shminfo.shmid == (uint32_t)-1)
589 xcb_image_destroy(im->xim);
593 im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0);
594 im->xim->data = im->shminfo.shmaddr;
595 if ((!im->xim->data) || (im->xim->data == (uint8_t *)-1))
597 DBG("Shm Create No Image Data");
598 xcb_image_destroy(im->xim);
599 shmdt(im->shminfo.shmaddr);
600 shmctl(im->shminfo.shmid, IPC_RMID, 0);
604 im->shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn);
605 xcb_shm_attach(_ecore_xcb_conn, im->shminfo.shmseg, im->shminfo.shmid, 0);
607 im->data = (unsigned char *)im->xim->data;
608 im->bpl = im->xim->stride;
609 im->rows = im->xim->height;
610 if (im->xim->bpp <= 8)
612 else if (im->xim->bpp <= 16)
619 _ecore_xcb_image_create_native(int w, int h, xcb_image_format_t format, uint8_t depth, void *base, uint32_t bytes, uint8_t *data)
621 static uint8_t dpth = 0;
622 static xcb_format_t *fmt = NULL;
623 const xcb_setup_t *setup;
624 xcb_image_format_t xif;
626 /* NB: We cannot use xcb_image_create_native as it only creates images
627 * using MSB_FIRST, so this routine recreates that function and uses
628 * the endian-ness of the server setup */
629 setup = xcb_get_setup(_ecore_xcb_conn);
632 if ((xif == XCB_IMAGE_FORMAT_Z_PIXMAP) && (depth == 1))
633 xif = XCB_IMAGE_FORMAT_XY_PIXMAP;
638 fmt = _ecore_xcb_image_find_format(setup, depth);
644 case XCB_IMAGE_FORMAT_XY_BITMAP:
645 if (depth != 1) return 0;
646 case XCB_IMAGE_FORMAT_XY_PIXMAP:
647 case XCB_IMAGE_FORMAT_Z_PIXMAP:
648 return xcb_image_create(w, h, xif,
650 fmt->depth, fmt->bits_per_pixel,
651 setup->bitmap_format_scanline_unit,
652 setup->image_byte_order,
653 setup->bitmap_format_bit_order,
662 static xcb_format_t *
663 _ecore_xcb_image_find_format(const xcb_setup_t *setup, uint8_t depth)
665 xcb_format_t *fmt, *fmtend;
667 fmt = xcb_setup_pixmap_formats(setup);
668 fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
669 for (; fmt != fmtend; ++fmt)
670 if (fmt->depth == depth)