19 #include "ecore_x_private.h"
22 #include <X11/extensions/XShm.h>
23 #include <X11/Xutil.h>
25 static int _ecore_x_image_shm_can = -1;
26 static int _ecore_x_image_err = 0;
29 _ecore_x_image_error_handler(Display *d EINA_UNUSED, XErrorEvent *ev)
31 _ecore_x_image_err = 1;
32 switch (ev->error_code)
34 case BadRequest: /* bad request code */
37 case BadValue: /* int parameter out of range */
40 case BadWindow: /* parameter not a Window */
43 case BadPixmap: /* parameter not a Pixmap */
46 case BadAtom: /* parameter not an Atom */
49 case BadCursor: /* parameter not a Cursor */
52 case BadFont: /* parameter not a Font */
55 case BadMatch: /* parameter mismatch */
58 case BadDrawable: /* parameter not a Pixmap or Window */
61 case BadAccess: /* depending on context */
64 case BadAlloc: /* insufficient resources */
67 case BadColor: /* no such colormap */
70 case BadGC: /* parameter not a GC */
73 case BadIDChoice: /* choice not in range or already used */
76 case BadName: /* font or color name doesn't exist */
79 case BadLength: /* Request length incorrect */
82 case BadImplementation: /* server is defective */
83 ERR("BadImplementation");
90 _ecore_x_image_shm_check(void)
93 XShmSegmentInfo shminfo;
96 if (_ecore_x_image_shm_can != -1)
97 return _ecore_x_image_shm_can;
99 if (!XShmQueryExtension(_ecore_x_disp))
101 _ecore_x_image_shm_can = 0;
102 return _ecore_x_image_shm_can;
105 XSync(_ecore_x_disp, False);
106 _ecore_x_image_err = 0;
108 xim = XShmCreateImage(_ecore_x_disp,
109 DefaultVisual(_ecore_x_disp,
110 DefaultScreen(_ecore_x_disp)),
111 DefaultDepth(_ecore_x_disp,
112 DefaultScreen(_ecore_x_disp)),
115 if (_ecore_xlib_sync) ecore_x_sync();
118 _ecore_x_image_shm_can = 0;
119 return _ecore_x_image_shm_can;
122 shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
124 if (shminfo.shmid == -1)
126 ERR("%s", strerror(errno));
128 _ecore_x_image_shm_can = 0;
129 return _ecore_x_image_shm_can;
132 shminfo.readOnly = False;
133 shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
134 xim->data = shminfo.shmaddr;
136 if (xim->data == (char *)-1)
139 _ecore_x_image_shm_can = 0;
140 return _ecore_x_image_shm_can;
143 ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
144 XShmAttach(_ecore_x_disp, &shminfo);
145 XShmGetImage(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp),
146 xim, 0, 0, 0xffffffff);
147 XSync(_ecore_x_disp, False);
148 XSetErrorHandler((XErrorHandler)ph);
149 if (_ecore_x_image_err)
151 XShmDetach(_ecore_x_disp, &shminfo);
153 shmdt(shminfo.shmaddr);
154 shmctl(shminfo.shmid, IPC_RMID, 0);
155 _ecore_x_image_shm_can = 0;
156 return _ecore_x_image_shm_can;
159 XShmDetach(_ecore_x_disp, &shminfo);
161 shmdt(shminfo.shmaddr);
162 shmctl(shminfo.shmid, IPC_RMID, 0);
164 _ecore_x_image_shm_can = 1;
165 return _ecore_x_image_shm_can;
168 struct _Ecore_X_Image
170 XShmSegmentInfo shminfo;
181 ecore_x_image_new(int w,
188 im = calloc(1, sizeof(Ecore_X_Image));
192 LOGFN(__FILE__, __LINE__, __FUNCTION__);
197 if (depth <= 8) im->bpp = 1;
198 else if (depth <= 16) im->bpp = 2;
199 else if (depth <= 24) im->bpp = 3;
201 _ecore_x_image_shm_check();
202 im->shm = _ecore_x_image_shm_can;
207 ecore_x_image_free(Ecore_X_Image *im)
209 LOGFN(__FILE__, __LINE__, __FUNCTION__);
214 XShmDetach(_ecore_x_disp, &(im->shminfo));
215 XDestroyImage(im->xim);
216 shmdt(im->shminfo.shmaddr);
217 shmctl(im->shminfo.shmid, IPC_RMID, 0);
223 im->xim->data = NULL;
224 XDestroyImage(im->xim);
231 _ecore_x_image_finalize(Ecore_X_Image *im)
233 im->data = (unsigned char *)im->xim->data;
234 im->bpl = im->xim->bytes_per_line;
235 im->rows = im->xim->height;
236 if (im->xim->bits_per_pixel <= 8) im->bpp = 1;
237 else if (im->xim->bits_per_pixel <= 16) im->bpp = 2;
238 else if (im->xim->bits_per_pixel <= 24) im->bpp = 3;
243 _ecore_x_image_shm_create(Ecore_X_Image *im)
245 im->xim = XShmCreateImage(_ecore_x_disp, im->vis, im->depth,
246 ZPixmap, NULL, &(im->shminfo),
251 im->shminfo.shmid = shmget(IPC_PRIVATE,
252 im->xim->bytes_per_line * im->xim->height,
254 if (im->shminfo.shmid == -1)
256 ERR("shmget failed: %s", strerror(errno));
257 XDestroyImage(im->xim);
262 im->shminfo.readOnly = False;
263 im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0);
264 im->xim->data = im->shminfo.shmaddr;
265 if ((im->xim->data == (char *)-1) ||
268 ERR("shmat failed: %s", strerror(errno));
269 shmdt(im->shminfo.shmaddr);
270 shmctl(im->shminfo.shmid, IPC_RMID, 0);
271 XDestroyImage(im->xim);
276 XShmAttach(_ecore_x_disp, &im->shminfo);
277 _ecore_x_image_finalize(im);
281 _ecore_x_image_create(Ecore_X_Image *im)
283 im->xim = XCreateImage(_ecore_x_disp, im->vis, im->depth,
284 ZPixmap, 0, NULL, im->w, im->h, 32, 0);
285 if (!im->xim) return;
286 im->xim->data = malloc(im->xim->bytes_per_line * im->h);
289 XDestroyImage(im->xim);
293 _ecore_x_image_finalize(im);
297 ecore_x_image_get(Ecore_X_Image *im,
298 Ecore_X_Drawable draw,
306 Eina_Bool ret = EINA_TRUE;
309 LOGFN(__FILE__, __LINE__, __FUNCTION__);
312 if (!im->xim) _ecore_x_image_shm_create(im);
317 _ecore_x_image_err = 0;
321 ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
322 if ((sx == 0) && (w == im->w))
324 im->xim->data = (char *)
325 im->data + (im->xim->bytes_per_line * sy) + (sx * im->bpp);
326 im->xim->width = MIN(w, im->w);
327 im->xim->height = MIN(h, im->h);
328 XGrabServer(_ecore_x_disp);
329 if (!XShmGetImage(_ecore_x_disp, draw, im->xim, x, y, 0xffffffff))
331 XUngrabServer(_ecore_x_disp);
334 // unavoidable thanks to mit-shm get api - tmp shm buf + copy into it
338 unsigned char *spixels, *sp, *pixels, *p;
339 int bpp, bpl, rows, sbpp, sbpl, srows;
342 tim = ecore_x_image_new(w, h, im->vis, im->depth);
345 ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h);
348 spixels = ecore_x_image_data_get(tim,
352 pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp);
353 if ((pixels) && (spixels))
355 p = pixels + (sy * bpl) + (sx * bpp);
357 for (r = srows; r > 0; r--)
366 ecore_x_image_free(tim);
370 XSetErrorHandler((XErrorHandler)ph);
371 if (_ecore_x_image_err)
377 _ecore_x_image_create(im);
382 if (XGetSubImage(_ecore_x_disp, draw, sx, sy, w, h,
383 0xffffffff, ZPixmap, im->xim, x, y) != im->xim)
391 ecore_x_image_put(Ecore_X_Image *im,
392 Ecore_X_Drawable draw,
403 LOGFN(__FILE__, __LINE__, __FUNCTION__);
407 memset(&gcv, 0, sizeof(gcv));
408 gcv.subwindow_mode = IncludeInferiors;
409 tgc = XCreateGC(_ecore_x_disp, draw, GCSubwindowMode, &gcv);
410 if (_ecore_xlib_sync) ecore_x_sync();
415 if (im->shm) _ecore_x_image_shm_create(im);
416 else _ecore_x_image_create(im);
421 XShmPutImage(_ecore_x_disp, draw, gc, im->xim,
422 sx, sy, x, y, w, h, False);
424 XPutImage(_ecore_x_disp, draw, gc, im->xim,
426 if (_ecore_xlib_sync) ecore_x_sync();
428 if (tgc) ecore_x_gc_free(tgc);
432 ecore_x_image_data_get(Ecore_X_Image *im,
437 LOGFN(__FILE__, __LINE__, __FUNCTION__);
440 if (im->shm) _ecore_x_image_shm_create(im);
441 else _ecore_x_image_create(im);
442 if (!im->xim) return NULL;
444 if (bpl) *bpl = im->bpl;
445 if (rows) *rows = im->rows;
446 if (bpp) *bpp = im->bpp;
451 ecore_x_image_is_argb32_get(Ecore_X_Image *im)
453 Visual *vis = im->vis;
454 if (((vis->class == TrueColor) ||
455 (vis->class == DirectColor)) &&
457 (vis->red_mask == 0xff0000) &&
458 (vis->green_mask == 0x00ff00) &&
459 (vis->blue_mask == 0x0000ff))
461 #ifdef WORDS_BIGENDIAN
462 if (BitmapBitOrder(_ecore_x_disp) == MSBFirst) return EINA_TRUE;
464 if (BitmapBitOrder(_ecore_x_disp) == LSBFirst) return EINA_TRUE;
471 ecore_x_image_to_argb_convert(void *src,
487 int n = 0, nret = 0, i, row;
488 unsigned int pal[256], r, g, b;
507 n = vis->map_entries;
509 ((vis->class == PseudoColor) ||
510 (vis->class == StaticColor) ||
511 (vis->class == GrayScale) ||
512 (vis->class == StaticGray)))
515 c = DefaultColormap(_ecore_x_disp,
516 DefaultScreen(_ecore_x_disp));
517 cols = alloca(n * sizeof(XColor));
518 for (i = 0; i < n; i++)
521 cols[i].flags = DoRed | DoGreen | DoBlue;
526 XQueryColors(_ecore_x_disp, c, cols, n);
527 for (i = 0; i < n; i++)
529 pal[i] = 0xff000000 |
530 ((cols[i].red >> 8) << 16) |
531 ((cols[i].green >> 8) << 8) |
532 ((cols[i].blue >> 8));
536 else if ((vis->class == TrueColor) ||
537 (vis->class == DirectColor))
541 if ((vis->red_mask == 0x00ff0000) &&
542 (vis->green_mask == 0x0000ff00) &&
543 (vis->blue_mask == 0x000000ff))
545 else if ((vis->red_mask == 0x000000ff) &&
546 (vis->green_mask == 0x0000ff00) &&
547 (vis->blue_mask == 0x00ff0000))
554 if ((vis->red_mask == 0x00ff0000) &&
555 (vis->green_mask == 0x0000ff00) &&
556 (vis->blue_mask == 0x000000ff))
558 else if ((vis->red_mask == 0x000000ff) &&
559 (vis->green_mask == 0x0000ff00) &&
560 (vis->blue_mask == 0x00ff0000))
562 else if ((vis->red_mask == 0xff000000) &&
563 (vis->green_mask == 0x00ff0000) &&
564 (vis->blue_mask == 0x0000ff00))
566 else if ((vis->red_mask == 0x0000ff00) &&
567 (vis->green_mask == 0x00ff0000) &&
568 (vis->blue_mask == 0xff000000))
570 else if ((vis->red_mask == 0x0003f000) &&
571 (vis->green_mask == 0x00000fc0) &&
572 (vis->blue_mask == 0x0000003f))
574 else if ((vis->red_mask == 0x0000f800) &&
575 (vis->green_mask == 0x000007e0) &&
576 (vis->blue_mask == 0x0000001f))
578 else if ((vis->red_mask == 0x0000001f) &&
579 (vis->green_mask == 0x000007e0) &&
580 (vis->blue_mask == 0x0000f800))
582 else if ((vis->red_mask == 0x00007c00) &&
583 (vis->green_mask == 0x000003e0) &&
584 (vis->blue_mask == 0x0000001f))
590 for (row = 0; row < h; row++)
595 unsigned int *dp, *de;
597 dp = ((unsigned int *)(((unsigned char *)dst) +
598 ((dy + row) * dbpl))) + dx;
603 s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
617 s16 = ((unsigned short *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
623 r = (*s16 & 0xf800) << 8;
624 g = (*s16 & 0x07e0) << 5;
625 b = (*s16 & 0x001f) << 3;
626 r |= (r >> 5) & 0xff0000;
627 g |= (g >> 6) & 0x00ff00;
629 *dp = 0xff000000 | r | g | b;
637 r = (*s16 & 0x001f) << 19;
638 g = (*s16 & 0x07e0) << 5;
639 b = (*s16 & 0xf800) >> 8;
640 r |= (r >> 5) & 0xff0000;
641 g |= (g >> 6) & 0x00ff00;
643 *dp = 0xff000000 | r | g | b;
651 r = (*s16 & 0x7c00) << 9;
652 g = (*s16 & 0x03e0) << 6;
653 b = (*s16 & 0x001f) << 3;
654 r |= (r >> 5) & 0xff0000;
655 g |= (g >> 5) & 0x00ff00;
657 *dp = 0xff000000 | r | g | b;
669 s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + (x * (sbpp / 8));
675 *dp = 0xff000000 | (s8[2] << 16) | (s8[1] << 8) | s8[0];
682 *dp = 0xff000000 | (s8[0] << 16) | (s8[1] << 8) | s8[2];
693 s32 = ((unsigned int *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
699 *dp = 0xff000000 | *s32;
707 r = *s32 & 0x000000ff;
708 g = *s32 & 0x0000ff00;
709 b = *s32 & 0x00ff0000;
710 *dp = 0xff000000 | (r << 16) | (g) | (b >> 16);
718 *dp = 0xff000000 | (*s32 >> 8);
726 r = *s32 & 0x0000ff00;
727 g = *s32 & 0x00ff0000;
728 b = *s32 & 0xff000000;
729 *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24);
737 r = (*s32 & 0x3f000) << 6;
738 g = (*s32 & 0x00fc0) << 4;
739 b = (*s32 & 0x0003f) << 2;
740 r |= (r >> 6) & 0xff0000;
741 g |= (g >> 6) & 0x00ff00;
743 *dp = 0xff000000 | r | g | b;