aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore_x/xlib/ecore_x_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore_x/xlib/ecore_x_image.c')
-rw-r--r--libraries/ecore/src/lib/ecore_x/xlib/ecore_x_image.c598
1 files changed, 598 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_x/xlib/ecore_x_image.c b/libraries/ecore/src/lib/ecore_x/xlib/ecore_x_image.c
new file mode 100644
index 0000000..2de5319
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore_x/xlib/ecore_x_image.c
@@ -0,0 +1,598 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif /* ifdef HAVE_CONFIG_H */
4
5#include "ecore_x_private.h"
6#include "Ecore_X.h"
7
8#include <X11/extensions/XShm.h>
9#include <X11/Xutil.h>
10#include <sys/ipc.h>
11#include <sys/shm.h>
12#include <string.h>
13
14static int _ecore_x_image_shm_can = -1;
15static int _ecore_x_image_err = 0;
16
17static int
18_ecore_x_image_error_handler(Display *d __UNUSED__,
19 XErrorEvent *ev __UNUSED__)
20{
21 _ecore_x_image_err = 1;
22 return 0;
23} /* _ecore_x_image_error_handler */
24
25static void
26_ecore_x_image_shm_check(void)
27{
28 XErrorHandler ph;
29 XShmSegmentInfo shminfo;
30 XImage *xim;
31
32 if (_ecore_x_image_shm_can != -1)
33 return;
34
35 XSync(_ecore_x_disp, False);
36 _ecore_x_image_err = 0;
37
38 xim = XShmCreateImage(_ecore_x_disp,
39 DefaultVisual(_ecore_x_disp,
40 DefaultScreen(_ecore_x_disp)),
41 DefaultDepth(_ecore_x_disp,
42 DefaultScreen(_ecore_x_disp)),
43 ZPixmap, NULL,
44 &shminfo, 1, 1);
45 if (!xim)
46 {
47 _ecore_x_image_shm_can = 0;
48 return;
49 }
50
51 shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
52 IPC_CREAT | 0666);
53 if (shminfo.shmid == -1)
54 {
55 XDestroyImage(xim);
56 _ecore_x_image_shm_can = 0;
57 return;
58 }
59
60 shminfo.readOnly = False;
61 shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
62 xim->data = shminfo.shmaddr;
63
64 if (xim->data == (char *)-1)
65 {
66 XDestroyImage(xim);
67 _ecore_x_image_shm_can = 0;
68 return;
69 }
70
71 ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
72 XShmAttach(_ecore_x_disp, &shminfo);
73 XShmGetImage(_ecore_x_disp, DefaultRootWindow(_ecore_x_disp),
74 xim, 0, 0, 0xffffffff);
75 XSync(_ecore_x_disp, False);
76 XSetErrorHandler((XErrorHandler)ph);
77 if (_ecore_x_image_err)
78 {
79 XShmDetach(_ecore_x_disp, &shminfo);
80 XDestroyImage(xim);
81 shmdt(shminfo.shmaddr);
82 shmctl(shminfo.shmid, IPC_RMID, 0);
83 _ecore_x_image_shm_can = 0;
84 return;
85 }
86
87 XShmDetach(_ecore_x_disp, &shminfo);
88 XDestroyImage(xim);
89 shmdt(shminfo.shmaddr);
90 shmctl(shminfo.shmid, IPC_RMID, 0);
91
92 _ecore_x_image_shm_can = 1;
93} /* _ecore_x_image_shm_check */
94
95struct _Ecore_X_Image
96{
97 XShmSegmentInfo shminfo;
98 Ecore_X_Visual vis;
99 XImage *xim;
100 int depth;
101 int w, h;
102 int bpl, bpp, rows;
103 unsigned char *data;
104 Eina_Bool shm : 1;
105};
106
107EAPI Ecore_X_Image *
108ecore_x_image_new(int w,
109 int h,
110 Ecore_X_Visual vis,
111 int depth)
112{
113 Ecore_X_Image *im;
114
115 im = calloc(1, sizeof(Ecore_X_Image));
116 if (!im)
117 return NULL;
118
119 LOGFN(__FILE__, __LINE__, __FUNCTION__);
120 im->w = w;
121 im->h = h;
122 im->vis = vis;
123 im->depth = depth;
124 _ecore_x_image_shm_check();
125 im->shm = _ecore_x_image_shm_can;
126 return im;
127} /* ecore_x_image_new */
128
129EAPI void
130ecore_x_image_free(Ecore_X_Image *im)
131{
132 LOGFN(__FILE__, __LINE__, __FUNCTION__);
133 if (im->shm)
134 {
135 if (im->xim)
136 {
137 XShmDetach(_ecore_x_disp, &(im->shminfo));
138 XDestroyImage(im->xim);
139 shmdt(im->shminfo.shmaddr);
140 shmctl(im->shminfo.shmid, IPC_RMID, 0);
141 }
142 }
143 else if (im->xim)
144 {
145 free(im->xim->data);
146 im->xim->data = NULL;
147 XDestroyImage(im->xim);
148 }
149
150 free(im);
151} /* ecore_x_image_free */
152
153static void
154_ecore_x_image_shm_create(Ecore_X_Image *im)
155{
156 im->xim = XShmCreateImage(_ecore_x_disp, im->vis, im->depth,
157 ZPixmap, NULL, &(im->shminfo),
158 im->w, im->h);
159 if (!im->xim)
160 return;
161
162 im->shminfo.shmid = shmget(IPC_PRIVATE,
163 im->xim->bytes_per_line * im->xim->height,
164 IPC_CREAT | 0666);
165 if (im->shminfo.shmid == -1)
166 {
167 XDestroyImage(im->xim);
168 return;
169 }
170
171 im->shminfo.readOnly = False;
172 im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0);
173 im->xim->data = im->shminfo.shmaddr;
174 if ((im->xim->data == (char *)-1) ||
175 (!im->xim->data))
176 {
177 shmdt(im->shminfo.shmaddr);
178 shmctl(im->shminfo.shmid, IPC_RMID, 0);
179 XDestroyImage(im->xim);
180 return;
181 }
182
183 XShmAttach(_ecore_x_disp, &im->shminfo);
184
185 im->data = (unsigned char *)im->xim->data;
186
187 im->bpl = im->xim->bytes_per_line;
188 im->rows = im->xim->height;
189 if (im->xim->bits_per_pixel <= 8)
190 im->bpp = 1;
191 else if (im->xim->bits_per_pixel <= 16)
192 im->bpp = 2;
193 else
194 im->bpp = 4;
195} /* _ecore_x_image_shm_create */
196
197EAPI Eina_Bool
198ecore_x_image_get(Ecore_X_Image *im,
199 Ecore_X_Drawable draw,
200 int x,
201 int y,
202 int sx,
203 int sy,
204 int w,
205 int h)
206{
207 Eina_Bool ret = EINA_TRUE;
208 XErrorHandler ph;
209
210 LOGFN(__FILE__, __LINE__, __FUNCTION__);
211 if (im->shm)
212 {
213 if (!im->xim)
214 _ecore_x_image_shm_create(im);
215
216 if (!im->xim)
217 return 0;
218
219 _ecore_x_image_err = 0;
220 // optimised path
221 ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
222 if ((sx == 0) && (w == im->w))
223 {
224 im->xim->data = (char *)
225 im->data + (im->xim->bytes_per_line * sy) + (sx * im->bpp);
226 im->xim->width = w;
227 im->xim->height = h;
228 XGrabServer(_ecore_x_disp);
229 if (!XShmGetImage(_ecore_x_disp, draw, im->xim, x, y, 0xffffffff))
230 ret = EINA_FALSE;
231 XUngrabServer(_ecore_x_disp);
232 ecore_x_sync();
233 }
234 // unavoidable thanks to mit-shm get api - tmp shm buf + copy into it
235 else
236 {
237 Ecore_X_Image *tim;
238 unsigned char *spixels, *sp, *pixels, *p;
239 int bpp, bpl, rows, sbpp, sbpl, srows;
240 int r;
241
242 tim = ecore_x_image_new(w, h, im->vis, im->depth);
243 if (tim)
244 {
245 ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h);
246 if (ret)
247 {
248 spixels = ecore_x_image_data_get(tim,
249 &sbpl,
250 &srows,
251 &sbpp);
252 pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp);
253 if ((pixels) && (spixels))
254 {
255 p = pixels + (sy * bpl) + (sx * bpp);
256 sp = spixels;
257 for (r = srows; r > 0; r--)
258 {
259 memcpy(p, sp, sbpl);
260 p += bpl;
261 sp += sbpl;
262 }
263 }
264 }
265
266 ecore_x_image_free(tim);
267 }
268 }
269
270 XSetErrorHandler((XErrorHandler)ph);
271 if (_ecore_x_image_err)
272 ret = EINA_FALSE;
273 }
274 else
275 {
276 printf("currently unimplemented ecore_x_image_get without shm\n");
277 ret = EINA_FALSE;
278 }
279
280 return ret;
281} /* ecore_x_image_get */
282
283EAPI void
284ecore_x_image_put(Ecore_X_Image *im,
285 Ecore_X_Drawable draw,
286 Ecore_X_GC gc,
287 int x,
288 int y,
289 int sx,
290 int sy,
291 int w,
292 int h)
293{
294 Ecore_X_GC tgc = 0;
295
296 LOGFN(__FILE__, __LINE__, __FUNCTION__);
297 if (!gc)
298 {
299 XGCValues gcv;
300 memset(&gcv, 0, sizeof(gcv));
301 gcv.subwindow_mode = IncludeInferiors;
302 tgc = XCreateGC(_ecore_x_disp, draw, GCSubwindowMode, &gcv);
303 gc = tgc;
304 }
305 if (!im->xim) _ecore_x_image_shm_create(im);
306 if (im->xim)
307 XShmPutImage(_ecore_x_disp, draw, gc, im->xim, sx, sy, x, y, w, h, False);
308 if (tgc) ecore_x_gc_free(tgc);
309} /* ecore_x_image_put */
310
311EAPI void *
312ecore_x_image_data_get(Ecore_X_Image *im,
313 int *bpl,
314 int *rows,
315 int *bpp)
316{
317 LOGFN(__FILE__, __LINE__, __FUNCTION__);
318 if (!im->xim) _ecore_x_image_shm_create(im);
319 if (!im->xim) return NULL;
320 if (bpl) *bpl = im->bpl;
321 if (rows) *rows = im->rows;
322 if (bpp) *bpp = im->bpp;
323 return im->data;
324} /* ecore_x_image_data_get */
325
326EAPI Eina_Bool
327ecore_x_image_is_argb32_get(Ecore_X_Image *im)
328{
329 Visual *vis = im->vis;
330 if (!im->xim) _ecore_x_image_shm_create(im);
331 if (((vis->class == TrueColor) ||
332 (vis->class == DirectColor)) &&
333 (im->depth >= 24) &&
334 (vis->red_mask == 0xff0000) &&
335 (vis->green_mask == 0x00ff00) &&
336 (vis->blue_mask == 0x0000ff))
337 {
338#ifdef WORDS_BIGENDIAN
339 if (im->xim->bitmap_bit_order == LSBFirst) return EINA_TRUE;
340#else
341 if (im->xim->bitmap_bit_order == MSBFirst) return EINA_TRUE;
342#endif
343 }
344 return EINA_FALSE;
345}
346
347EAPI Eina_Bool
348ecore_x_image_to_argb_convert(void *src,
349 int sbpp,
350 int sbpl,
351 Ecore_X_Colormap c,
352 Ecore_X_Visual v,
353 int x,
354 int y,
355 int w,
356 int h,
357 unsigned int *dst,
358 int dbpl,
359 int dx,
360 int dy)
361{
362 Visual *vis = v;
363 XColor *cols = NULL;
364 int n = 0, nret = 0, i, row;
365 unsigned int pal[256], r, g, b;
366 enum
367 {
368 rgbnone = 0,
369 rgb565,
370 bgr565,
371 rgbx555,
372 argbx888,
373 abgrx888,
374 rgba888x,
375 bgra888x,
376 argbx666
377 };
378 int mode = 0;
379
380 sbpp *= 8;
381
382 n = vis->map_entries;
383 if ((n <= 256) &&
384 ((vis->class == PseudoColor) ||
385 (vis->class == StaticColor) ||
386 (vis->class == GrayScale) ||
387 (vis->class == StaticGray)))
388 {
389 if (!c)
390 c = DefaultColormap(_ecore_x_disp,
391 DefaultScreen(_ecore_x_disp));
392 cols = alloca(n * sizeof(XColor));
393 for (i = 0; i < n; i++)
394 {
395 cols[i].pixel = i;
396 cols[i].flags = DoRed | DoGreen | DoBlue;
397 cols[i].red = 0;
398 cols[i].green = 0;
399 cols[i].blue = 0;
400 }
401 XQueryColors(_ecore_x_disp, c, cols, n);
402 for (i = 0; i < n; i++)
403 {
404 pal[i] = 0xff000000 |
405 ((cols[i].red >> 8) << 16) |
406 ((cols[i].green >> 8) << 8) |
407 ((cols[i].blue >> 8));
408 }
409 nret = n;
410 }
411 else if ((vis->class == TrueColor) ||
412 (vis->class == DirectColor))
413 {
414 if ((vis->red_mask == 0x00ff0000) &&
415 (vis->green_mask == 0x0000ff00) &&
416 (vis->blue_mask == 0x000000ff))
417 mode = argbx888;
418 else if ((vis->red_mask == 0x000000ff) &&
419 (vis->green_mask == 0x0000ff00) &&
420 (vis->blue_mask == 0x00ff0000))
421 mode = abgrx888;
422 else if ((vis->red_mask == 0xff000000) &&
423 (vis->green_mask == 0x00ff0000) &&
424 (vis->blue_mask == 0x0000ff00))
425 mode = rgba888x;
426 else if ((vis->red_mask == 0x0000ff00) &&
427 (vis->green_mask == 0x00ff0000) &&
428 (vis->blue_mask == 0xff000000))
429 mode = bgra888x;
430 else if ((vis->red_mask == 0x0003f000) &&
431 (vis->green_mask == 0x00000fc0) &&
432 (vis->blue_mask == 0x0000003f))
433 mode = argbx666;
434 else if ((vis->red_mask == 0x0000f800) &&
435 (vis->green_mask == 0x000007e0) &&
436 (vis->blue_mask == 0x0000001f))
437 mode = rgb565;
438 else if ((vis->red_mask == 0x0000001f) &&
439 (vis->green_mask == 0x000007e0) &&
440 (vis->blue_mask == 0x0000f800))
441 mode = bgr565;
442 else if ((vis->red_mask == 0x00007c00) &&
443 (vis->green_mask == 0x000003e0) &&
444 (vis->blue_mask == 0x0000001f))
445 mode = rgbx555;
446 else
447 return EINA_FALSE;
448 }
449 for (row = 0; row < h; row++)
450 {
451 unsigned char *s8;
452 unsigned short *s16;
453 unsigned int *s32;
454 unsigned int *dp, *de;
455
456 dp = ((unsigned int *)(((unsigned char *)dst) +
457 ((dy + row) * dbpl))) + dx;
458 de = dp + w;
459 switch (sbpp)
460 {
461 case 8:
462 s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
463 if (nret > 0)
464 {
465 while (dp < de)
466 {
467 *dp = pal[*s8];
468 s8++; dp++;
469 }
470 }
471 else
472 return EINA_FALSE;
473 break;
474
475 case 16:
476 s16 = ((unsigned short *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
477 switch (mode)
478 {
479 case rgb565:
480 while (dp < de)
481 {
482 r = (*s16 & 0xf800) << 8;
483 g = (*s16 & 0x07e0) << 5;
484 b = (*s16 & 0x001f) << 3;
485 r |= (r >> 5) & 0xff0000;
486 g |= (g >> 6) & 0x00ff00;
487 b |= (b >> 5);
488 *dp = 0xff000000 | r | g | b;
489 s16++; dp++;
490 }
491 break;
492
493 case bgr565:
494 while (dp < de)
495 {
496 r = (*s16 & 0x001f) << 19;
497 g = (*s16 & 0x07e0) << 5;
498 b = (*s16 & 0xf800) >> 8;
499 r |= (r >> 5) & 0xff0000;
500 g |= (g >> 6) & 0x00ff00;
501 b |= (b >> 5);
502 *dp = 0xff000000 | r | g | b;
503 s16++; dp++;
504 }
505 break;
506
507 case rgbx555:
508 while (dp < de)
509 {
510 r = (*s16 & 0x7c00) << 9;
511 g = (*s16 & 0x03e0) << 6;
512 b = (*s16 & 0x001f) << 3;
513 r |= (r >> 5) & 0xff0000;
514 g |= (g >> 5) & 0x00ff00;
515 b |= (b >> 5);
516 *dp = 0xff000000 | r | g | b;
517 s16++; dp++;
518 }
519 break;
520
521 default:
522 return EINA_FALSE;
523 break;
524 }
525 break;
526
527 case 24:
528 case 32:
529 s32 = ((unsigned int *)(((unsigned char *)src) + ((y + row) * sbpl))) + x;
530 switch (mode)
531 {
532 case argbx888:
533 while (dp < de)
534 {
535 *dp = 0xff000000 | *s32;
536 s32++; dp++;
537 }
538 break;
539
540 case abgrx888:
541 while (dp < de)
542 {
543 r = *s32 & 0x000000ff;
544 g = *s32 & 0x0000ff00;
545 b = *s32 & 0x00ff0000;
546 *dp = 0xff000000 | (r << 16) | (g) | (b >> 16);
547 s32++; dp++;
548 }
549 break;
550
551 case rgba888x:
552 while (dp < de)
553 {
554 *dp = 0xff000000 | (*s32 >> 8);
555 s32++; dp++;
556 }
557 break;
558
559 case bgra888x:
560 while (dp < de)
561 {
562 r = *s32 & 0x0000ff00;
563 g = *s32 & 0x00ff0000;
564 b = *s32 & 0xff000000;
565 *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24);
566 s32++; dp++;
567 }
568 break;
569
570 case argbx666:
571 while (dp < de)
572 {
573 r = (*s32 & 0x3f000) << 6;
574 g = (*s32 & 0x00fc0) << 4;
575 b = (*s32 & 0x0003f) << 2;
576 r |= (r >> 6) & 0xff0000;
577 g |= (g >> 6) & 0x00ff00;
578 b |= (b >> 6);
579 *dp = 0xff000000 | r | g | b;
580 s32++; dp++;
581 }
582 break;
583
584 default:
585 return EINA_FALSE;
586 break;
587 }
588 break;
589 break;
590
591 default:
592 return EINA_FALSE;
593 break;
594 }
595 }
596 return EINA_TRUE;
597}
598