10 #include "ecore_x_private.h"
13 #include <X11/extensions/XShm.h>
14 #include <X11/Xutil.h>
16 static int _ecore_x_image_shm_can = -1;
17 static int _ecore_x_image_err = 0;
20 _ecore_x_image_error_handler(Display *d __UNUSED__,
21 XErrorEvent *ev __UNUSED__)
23 _ecore_x_image_err = 1;
28 _ecore_x_image_shm_check(void)
31 XShmSegmentInfo shminfo;
34 if (_ecore_x_image_shm_can != -1)
37 XSync(_ecore_x_disp, False);
38 _ecore_x_image_err = 0;
40 xim = XShmCreateImage(_ecore_x_disp,
41 DefaultVisual(_ecore_x_disp,
42 DefaultScreen(_ecore_x_disp)),
43 DefaultDepth(_ecore_x_disp,
44 DefaultScreen(_ecore_x_disp)),
49 _ecore_x_image_shm_can = 0;
53 shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
55 if (shminfo.shmid == -1)
58 _ecore_x_image_shm_can = 0;
62 shminfo.readOnly = False;
63 shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
64 xim->data = shminfo.shmaddr;
66 if (xim->data == (char *)-1)
69 _ecore_x_image_shm_can = 0;
73 ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
74 XShmAttach(_ecore_x_disp, &shminfo);
75 XShmGetImage(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp),
76 xim, 0, 0, 0xffffffff);
77 XSync(_ecore_x_disp, False);
78 XSetErrorHandler((XErrorHandler)ph);
79 if (_ecore_x_image_err)
81 XShmDetach(_ecore_x_disp, &shminfo);
83 shmdt(shminfo.shmaddr);
84 shmctl(shminfo.shmid, IPC_RMID, 0);
85 _ecore_x_image_shm_can = 0;
89 XShmDetach(_ecore_x_disp, &shminfo);
91 shmdt(shminfo.shmaddr);
92 shmctl(shminfo.shmid, IPC_RMID, 0);
94 _ecore_x_image_shm_can = 1;
99 XShmSegmentInfo shminfo;
110 ecore_x_image_new(int w,
117 im = calloc(1, sizeof(Ecore_X_Image));
121 LOGFN(__FILE__, __LINE__, __FUNCTION__);
126 _ecore_x_image_shm_check();
127 im->shm = _ecore_x_image_shm_can;
132 ecore_x_image_free(Ecore_X_Image *im)
134 LOGFN(__FILE__, __LINE__, __FUNCTION__);
139 XShmDetach(_ecore_x_disp, &(im->shminfo));
140 XDestroyImage(im->xim);
141 shmdt(im->shminfo.shmaddr);
142 shmctl(im->shminfo.shmid, IPC_RMID, 0);
148 im->xim->data = NULL;
149 XDestroyImage(im->xim);
156 _ecore_x_image_shm_create(Ecore_X_Image *im)
158 im->xim = XShmCreateImage(_ecore_x_disp, im->vis, im->depth,
159 ZPixmap, NULL, &(im->shminfo),
164 im->shminfo.shmid = shmget(IPC_PRIVATE,
165 im->xim->bytes_per_line * im->xim->height,
167 if (im->shminfo.shmid == -1)
169 XDestroyImage(im->xim);
173 im->shminfo.readOnly = False;
174 im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0);
175 im->xim->data = im->shminfo.shmaddr;
176 if ((im->xim->data == (char *)-1) ||
179 shmdt(im->shminfo.shmaddr);
180 shmctl(im->shminfo.shmid, IPC_RMID, 0);
181 XDestroyImage(im->xim);
185 XShmAttach(_ecore_x_disp, &im->shminfo);
187 im->data = (unsigned char *)im->xim->data;
189 im->bpl = im->xim->bytes_per_line;
190 im->rows = im->xim->height;
191 if (im->xim->bits_per_pixel <= 8)
193 else if (im->xim->bits_per_pixel <= 16)
200 ecore_x_image_get(Ecore_X_Image *im,
201 Ecore_X_Drawable draw,
209 Eina_Bool ret = EINA_TRUE;
212 LOGFN(__FILE__, __LINE__, __FUNCTION__);
216 _ecore_x_image_shm_create(im);
221 _ecore_x_image_err = 0;
225 ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
226 if ((sx == 0) && (w == im->w))
228 im->xim->data = (char *)
229 im->data + (im->xim->bytes_per_line * sy) + (sx * im->bpp);
232 XGrabServer(_ecore_x_disp);
233 if (!XShmGetImage(_ecore_x_disp, draw, im->xim, x, y, 0xffffffff))
235 XUngrabServer(_ecore_x_disp);
238 // unavoidable thanks to mit-shm get api - tmp shm buf + copy into it
242 unsigned char *spixels, *sp, *pixels, *p;
243 int bpp, bpl, rows, sbpp, sbpl, srows;
246 tim = ecore_x_image_new(w, h, im->vis, im->depth);
249 ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h);
252 spixels = ecore_x_image_data_get(tim,
256 pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp);
257 if ((pixels) && (spixels))
259 p = pixels + (sy * bpl) + (sx * bpp);
261 for (r = srows; r > 0; r--)
270 ecore_x_image_free(tim);
274 XSetErrorHandler((XErrorHandler)ph);
275 if (_ecore_x_image_err)
280 printf("currently unimplemented ecore_x_image_get without shm\n");
288 ecore_x_image_put(Ecore_X_Image *im,
289 Ecore_X_Drawable draw,
300 LOGFN(__FILE__, __LINE__, __FUNCTION__);
304 memset(&gcv, 0, sizeof(gcv));
305 gcv.subwindow_mode = IncludeInferiors;
306 tgc = XCreateGC(_ecore_x_disp, draw, GCSubwindowMode, &gcv);
309 if (!im->xim) _ecore_x_image_shm_create(im);
311 XShmPutImage(_ecore_x_disp, draw, gc, im->xim, sx, sy, x, y, w, h, False);
312 if (tgc) ecore_x_gc_free(tgc);
316 ecore_x_image_data_get(Ecore_X_Image *im,
321 LOGFN(__FILE__, __LINE__, __FUNCTION__);
322 if (!im->xim) _ecore_x_image_shm_create(im);
323 if (!im->xim) return NULL;
324 if (bpl) *bpl = im->bpl;
325 if (rows) *rows = im->rows;
326 if (bpp) *bpp = im->bpp;
331 ecore_x_image_is_argb32_get(Ecore_X_Image *im)
333 Visual *vis = im->vis;
334 if (!im->xim) _ecore_x_image_shm_create(im);
335 if (((vis->class == TrueColor) ||
336 (vis->class == DirectColor)) &&
338 (vis->red_mask == 0xff0000) &&
339 (vis->green_mask == 0x00ff00) &&
340 (vis->blue_mask == 0x0000ff))
342 #ifdef WORDS_BIGENDIAN
343 if (im->xim->bitmap_bit_order == MSBFirst) return EINA_TRUE;
345 if (im->xim->bitmap_bit_order == LSBFirst) return EINA_TRUE;
352 ecore_x_image_to_argb_convert(void *src,
368 int n = 0, nret = 0, i, row;
369 unsigned int pal[256], r, g, b;
386 n = vis->map_entries;
388 ((vis->class == PseudoColor) ||
389 (vis->class == StaticColor) ||
390 (vis->class == GrayScale) ||
391 (vis->class == StaticGray)))
394 c = DefaultColormap(_ecore_x_disp,
395 DefaultScreen(_ecore_x_disp));
396 cols = alloca(n * sizeof(XColor));
397 for (i = 0; i < n; i++)
400 cols[i].flags = DoRed | DoGreen | DoBlue;
405 XQueryColors(_ecore_x_disp, c, cols, n);
406 for (i = 0; i < n; i++)
408 pal[i] = 0xff000000 |
409 ((cols[i].red >> 8) << 16) |
410 ((cols[i].green >> 8) << 8) |
411 ((cols[i].blue >> 8));
415 else if ((vis->class == TrueColor) ||
416 (vis->class == DirectColor))
418 if ((vis->red_mask == 0x00ff0000) &&
419 (vis->green_mask == 0x0000ff00) &&
420 (vis->blue_mask == 0x000000ff))
422 else if ((vis->red_mask == 0x000000ff) &&
423 (vis->green_mask == 0x0000ff00) &&
424 (vis->blue_mask == 0x00ff0000))
426 else if ((vis->red_mask == 0xff000000) &&
427 (vis->green_mask == 0x00ff0000) &&
428 (vis->blue_mask == 0x0000ff00))
430 else if ((vis->red_mask == 0x0000ff00) &&
431 (vis->green_mask == 0x00ff0000) &&
432 (vis->blue_mask == 0xff000000))
434 else if ((vis->red_mask == 0x0003f000) &&
435 (vis->green_mask == 0x00000fc0) &&
436 (vis->blue_mask == 0x0000003f))
438 else if ((vis->red_mask == 0x0000f800) &&
439 (vis->green_mask == 0x000007e0) &&
440 (vis->blue_mask == 0x0000001f))
442 else if ((vis->red_mask == 0x0000001f) &&
443 (vis->green_mask == 0x000007e0) &&
444 (vis->blue_mask == 0x0000f800))
446 else if ((vis->red_mask == 0x00007c00) &&
447 (vis->green_mask == 0x000003e0) &&
448 (vis->blue_mask == 0x0000001f))
453 for (row = 0; row < h; row++)
458 unsigned int *dp, *de;
460 dp = ((unsigned int *)(((unsigned char *)dst) +
461 ((dy + row) * dbpl))) + dx;
466 s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
480 s16 = ((unsigned short *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
486 r = (*s16 & 0xf800) << 8;
487 g = (*s16 & 0x07e0) << 5;
488 b = (*s16 & 0x001f) << 3;
489 r |= (r >> 5) & 0xff0000;
490 g |= (g >> 6) & 0x00ff00;
492 *dp = 0xff000000 | r | g | b;
500 r = (*s16 & 0x001f) << 19;
501 g = (*s16 & 0x07e0) << 5;
502 b = (*s16 & 0xf800) >> 8;
503 r |= (r >> 5) & 0xff0000;
504 g |= (g >> 6) & 0x00ff00;
506 *dp = 0xff000000 | r | g | b;
514 r = (*s16 & 0x7c00) << 9;
515 g = (*s16 & 0x03e0) << 6;
516 b = (*s16 & 0x001f) << 3;
517 r |= (r >> 5) & 0xff0000;
518 g |= (g >> 5) & 0x00ff00;
520 *dp = 0xff000000 | r | g | b;
533 s32 = ((unsigned int *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
539 *dp = 0xff000000 | *s32;
547 r = *s32 & 0x000000ff;
548 g = *s32 & 0x0000ff00;
549 b = *s32 & 0x00ff0000;
550 *dp = 0xff000000 | (r << 16) | (g) | (b >> 16);
558 *dp = 0xff000000 | (*s32 >> 8);
566 r = *s32 & 0x0000ff00;
567 g = *s32 & 0x00ff0000;
568 b = *s32 & 0xff000000;
569 *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24);
577 r = (*s32 & 0x3f000) << 6;
578 g = (*s32 & 0x00fc0) << 4;
579 b = (*s32 & 0x0003f) << 2;
580 r |= (r >> 6) & 0xff0000;
581 g |= (g >> 6) & 0x00ff00;
583 *dp = 0xff000000 | r | g | b;