diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_image.c | 740 |
1 files changed, 740 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_image.c b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_image.c new file mode 100644 index 0000000..6789b94 --- /dev/null +++ b/libraries/ecore/src/lib/ecore_x/xcb/ecore_xcb_image.c | |||
@@ -0,0 +1,740 @@ | |||
1 | #include "ecore_xcb_private.h" | ||
2 | #include <sys/ipc.h> | ||
3 | #include <sys/shm.h> | ||
4 | #include <xcb/xcb_event.h> | ||
5 | #include <xcb/shm.h> | ||
6 | |||
7 | struct _Ecore_X_Image | ||
8 | { | ||
9 | xcb_shm_segment_info_t shminfo; | ||
10 | xcb_image_t *xim; | ||
11 | Ecore_X_Visual vis; | ||
12 | int depth, w, h; | ||
13 | int bpl, bpp, rows; | ||
14 | unsigned char *data; | ||
15 | Eina_Bool shm : 1; | ||
16 | }; | ||
17 | |||
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, | ||
22 | uint8_t depth); | ||
23 | |||
24 | /* local variables */ | ||
25 | static int _ecore_xcb_image_shm_can = -1; | ||
26 | |||
27 | EAPI Ecore_X_Image * | ||
28 | ecore_x_image_new(int w, | ||
29 | int h, | ||
30 | Ecore_X_Visual vis, | ||
31 | int depth) | ||
32 | { | ||
33 | Ecore_X_Image *im; | ||
34 | |||
35 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
36 | |||
37 | if (!(im = calloc(1, sizeof(Ecore_X_Image)))) return NULL; | ||
38 | im->w = w; | ||
39 | im->h = h; | ||
40 | im->vis = vis; | ||
41 | im->depth = depth; | ||
42 | _ecore_xcb_image_shm_check(); | ||
43 | im->shm = _ecore_xcb_image_shm_can; | ||
44 | return im; | ||
45 | } | ||
46 | |||
47 | EAPI void | ||
48 | ecore_x_image_free(Ecore_X_Image *im) | ||
49 | { | ||
50 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
51 | CHECK_XCB_CONN; | ||
52 | |||
53 | if (!im) return; | ||
54 | if (im->shm) | ||
55 | { | ||
56 | if (im->xim) | ||
57 | { | ||
58 | xcb_shm_detach(_ecore_xcb_conn, im->shminfo.shmseg); | ||
59 | xcb_image_destroy(im->xim); | ||
60 | shmdt(im->shminfo.shmaddr); | ||
61 | shmctl(im->shminfo.shmid, IPC_RMID, 0); | ||
62 | } | ||
63 | } | ||
64 | else if (im->xim) | ||
65 | { | ||
66 | if (im->xim->data) free(im->xim->data); | ||
67 | im->xim->data = NULL; | ||
68 | xcb_image_destroy(im->xim); | ||
69 | } | ||
70 | |||
71 | free(im); | ||
72 | // ecore_x_flush(); | ||
73 | } | ||
74 | |||
75 | EAPI Eina_Bool | ||
76 | ecore_x_image_get(Ecore_X_Image *im, | ||
77 | Ecore_X_Drawable draw, | ||
78 | int x, | ||
79 | int y, | ||
80 | int sx, | ||
81 | int sy, | ||
82 | int w, | ||
83 | int h) | ||
84 | { | ||
85 | Eina_Bool ret = EINA_TRUE; | ||
86 | |||
87 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
88 | CHECK_XCB_CONN; | ||
89 | |||
90 | if (im->shm) | ||
91 | { | ||
92 | if (!im->xim) _ecore_xcb_image_shm_create(im); | ||
93 | if (!im->xim) return EINA_FALSE; | ||
94 | |||
95 | if ((sx == 0) && (w == im->w)) | ||
96 | { | ||
97 | im->xim->data = (uint8_t *)im->data + (im->xim->stride * sy) + | ||
98 | (sx * im->bpp); | ||
99 | im->xim->width = w; | ||
100 | im->xim->height = h; | ||
101 | |||
102 | ecore_x_grab(); | ||
103 | if (!xcb_image_shm_get(_ecore_xcb_conn, draw, im->xim, | ||
104 | im->shminfo, x, y, 0xffffffff)) | ||
105 | { | ||
106 | DBG("\tImage Shm Get Failed"); | ||
107 | ret = EINA_FALSE; | ||
108 | } | ||
109 | ecore_x_ungrab(); | ||
110 | ecore_x_sync(); // needed | ||
111 | } | ||
112 | else | ||
113 | { | ||
114 | Ecore_X_Image *tim; | ||
115 | |||
116 | tim = ecore_x_image_new(w, h, im->vis, im->depth); | ||
117 | if (tim) | ||
118 | { | ||
119 | ret = ecore_x_image_get(tim, draw, x, y, 0, 0, w, h); | ||
120 | if (ret) | ||
121 | { | ||
122 | unsigned char *spixels, *pixels; | ||
123 | int sbpp = 0, sbpl = 0, srows = 0; | ||
124 | int bpp = 0, bpl = 0, rows = 0; | ||
125 | |||
126 | spixels = | ||
127 | ecore_x_image_data_get(tim, &sbpl, &srows, &sbpp); | ||
128 | pixels = ecore_x_image_data_get(im, &bpl, &rows, &bpp); | ||
129 | if ((spixels) && (pixels)) | ||
130 | { | ||
131 | unsigned char *p, *sp; | ||
132 | int r = 0; | ||
133 | |||
134 | p = (pixels + (sy * bpl) + (sx * bpp)); | ||
135 | sp = spixels; | ||
136 | for (r = srows; r > 0; r--) | ||
137 | { | ||
138 | memcpy(p, sp, sbpl); | ||
139 | p += bpl; | ||
140 | sp += sbpl; | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | ecore_x_image_free(tim); | ||
145 | } | ||
146 | } | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | ret = EINA_FALSE; | ||
151 | ecore_x_grab(); | ||
152 | im->xim = | ||
153 | xcb_image_get(_ecore_xcb_conn, draw, x, y, w, h, | ||
154 | 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP); | ||
155 | if (!im->xim) ret = EINA_FALSE; | ||
156 | ecore_x_ungrab(); | ||
157 | ecore_x_sync(); // needed | ||
158 | |||
159 | if (im->xim) | ||
160 | { | ||
161 | im->data = (unsigned char *)im->xim->data; | ||
162 | im->bpl = im->xim->stride; | ||
163 | im->rows = im->xim->height; | ||
164 | if (im->xim->bpp <= 8) | ||
165 | im->bpp = 1; | ||
166 | else if (im->xim->bpp <= 16) | ||
167 | im->bpp = 2; | ||
168 | else | ||
169 | im->bpp = 4; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | EAPI void * | ||
177 | ecore_x_image_data_get(Ecore_X_Image *im, | ||
178 | int *bpl, | ||
179 | int *rows, | ||
180 | int *bpp) | ||
181 | { | ||
182 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
183 | |||
184 | if (!im) return NULL; | ||
185 | if (!im->xim) _ecore_xcb_image_shm_create(im); | ||
186 | if (!im->xim) return NULL; | ||
187 | |||
188 | if (bpl) *bpl = im->bpl; | ||
189 | if (rows) *rows = im->rows; | ||
190 | if (bpp) *bpp = im->bpp; | ||
191 | |||
192 | return im->data; | ||
193 | } | ||
194 | |||
195 | EAPI void | ||
196 | ecore_x_image_put(Ecore_X_Image *im, | ||
197 | Ecore_X_Drawable draw, | ||
198 | Ecore_X_GC gc, | ||
199 | int x, | ||
200 | int y, | ||
201 | int sx, | ||
202 | int sy, | ||
203 | int w, | ||
204 | int h) | ||
205 | { | ||
206 | Ecore_X_GC tgc = 0; | ||
207 | |||
208 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
209 | CHECK_XCB_CONN; | ||
210 | |||
211 | if (!gc) | ||
212 | { | ||
213 | uint32_t mask, values[1]; | ||
214 | |||
215 | tgc = xcb_generate_id(_ecore_xcb_conn); | ||
216 | mask = XCB_GC_SUBWINDOW_MODE; | ||
217 | values[0] = XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS; | ||
218 | xcb_create_gc(_ecore_xcb_conn, tgc, draw, mask, values); | ||
219 | gc = tgc; | ||
220 | } | ||
221 | if (!im->xim) _ecore_xcb_image_shm_create(im); | ||
222 | if (im->xim) | ||
223 | { | ||
224 | if (im->shm) | ||
225 | xcb_shm_put_image(_ecore_xcb_conn, draw, gc, im->xim->width, | ||
226 | im->xim->height, sx, sy, w, h, x, y, | ||
227 | im->xim->depth, im->xim->format, 0, | ||
228 | im->shminfo.shmseg, | ||
229 | im->xim->data - im->shminfo.shmaddr); | ||
230 | // xcb_image_shm_put(_ecore_xcb_conn, draw, gc, im->xim, | ||
231 | // im->shminfo, sx, sy, x, y, w, h, 0); | ||
232 | else | ||
233 | xcb_image_put(_ecore_xcb_conn, draw, gc, im->xim, sx, sy, 0); | ||
234 | } | ||
235 | if (tgc) ecore_x_gc_free(tgc); | ||
236 | ecore_x_sync(); | ||
237 | } | ||
238 | |||
239 | EAPI Eina_Bool | ||
240 | ecore_x_image_is_argb32_get(Ecore_X_Image *im) | ||
241 | { | ||
242 | xcb_visualtype_t *vis; | ||
243 | |||
244 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
245 | CHECK_XCB_CONN; | ||
246 | |||
247 | vis = (xcb_visualtype_t *)im->vis; | ||
248 | if (!im->xim) _ecore_xcb_image_shm_create(im); | ||
249 | |||
250 | if (((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) || | ||
251 | (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) && | ||
252 | (im->depth >= 24) && (vis->red_mask == 0xff0000) && | ||
253 | (vis->green_mask == 0x00ff00) && (vis->blue_mask == 0x0000ff)) | ||
254 | { | ||
255 | #ifdef WORDS_BIGENDIAN | ||
256 | if (im->xim->byte_order == XCB_IMAGE_ORDER_LSB_FIRST) | ||
257 | return EINA_TRUE; | ||
258 | #else | ||
259 | if (im->xim->byte_order == XCB_IMAGE_ORDER_MSB_FIRST) | ||
260 | return EINA_TRUE; | ||
261 | #endif | ||
262 | } | ||
263 | |||
264 | return EINA_FALSE; | ||
265 | } | ||
266 | |||
267 | EAPI Eina_Bool | ||
268 | ecore_x_image_to_argb_convert(void *src, | ||
269 | int sbpp, | ||
270 | int sbpl, | ||
271 | Ecore_X_Colormap c, | ||
272 | Ecore_X_Visual v, | ||
273 | int x, | ||
274 | int y, | ||
275 | int w, | ||
276 | int h, | ||
277 | unsigned int *dst, | ||
278 | int dbpl, | ||
279 | int dx, | ||
280 | int dy) | ||
281 | { | ||
282 | xcb_visualtype_t *vis; | ||
283 | uint32_t *cols; | ||
284 | int n = 0, nret = 0, i, row, mode = 0; | ||
285 | unsigned int pal[256], r, g, b; | ||
286 | enum | ||
287 | { | ||
288 | rgbnone = 0, | ||
289 | rgb565, | ||
290 | bgr565, | ||
291 | rgbx555, | ||
292 | argbx888, | ||
293 | abgrx888, | ||
294 | rgba888x, | ||
295 | bgra888x, | ||
296 | argbx666 | ||
297 | }; | ||
298 | |||
299 | LOGFN(__FILE__, __LINE__, __FUNCTION__); | ||
300 | CHECK_XCB_CONN; | ||
301 | |||
302 | sbpp *= 8; | ||
303 | |||
304 | vis = (xcb_visualtype_t *)v; | ||
305 | n = vis->colormap_entries; | ||
306 | if ((n <= 256) && | ||
307 | ((vis->_class == XCB_VISUAL_CLASS_PSEUDO_COLOR) || | ||
308 | (vis->_class == XCB_VISUAL_CLASS_STATIC_COLOR) || | ||
309 | (vis->_class == XCB_VISUAL_CLASS_GRAY_SCALE) || | ||
310 | (vis->_class == XCB_VISUAL_CLASS_STATIC_GRAY))) | ||
311 | { | ||
312 | xcb_query_colors_cookie_t cookie; | ||
313 | xcb_query_colors_reply_t *reply; | ||
314 | |||
315 | if (!c) | ||
316 | { | ||
317 | c = (xcb_colormap_t)((xcb_screen_t *) | ||
318 | _ecore_xcb_screen)->default_colormap; | ||
319 | } | ||
320 | |||
321 | cols = alloca(n * sizeof(uint32_t)); | ||
322 | for (i = 0; i < n; i++) | ||
323 | cols[i] = i; | ||
324 | |||
325 | cookie = xcb_query_colors_unchecked(_ecore_xcb_conn, c, n, cols); | ||
326 | reply = xcb_query_colors_reply(_ecore_xcb_conn, cookie, NULL); | ||
327 | if (reply) | ||
328 | { | ||
329 | xcb_rgb_iterator_t iter; | ||
330 | xcb_rgb_t *ret; | ||
331 | |||
332 | iter = xcb_query_colors_colors_iterator(reply); | ||
333 | ret = xcb_query_colors_colors(reply); | ||
334 | if (ret) | ||
335 | { | ||
336 | for (i = 0; iter.rem; xcb_rgb_next(&iter), i++) | ||
337 | { | ||
338 | pal[i] = 0xff000000 | | ||
339 | ((iter.data->red >> 8) << 16) | | ||
340 | ((iter.data->green >> 8) << 8) | | ||
341 | ((iter.data->blue >> 8)); | ||
342 | } | ||
343 | nret = n; | ||
344 | } | ||
345 | free(reply); | ||
346 | } | ||
347 | } | ||
348 | else if ((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) || | ||
349 | (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) | ||
350 | { | ||
351 | if ((vis->red_mask == 0x00ff0000) && | ||
352 | (vis->green_mask == 0x0000ff00) && | ||
353 | (vis->blue_mask == 0x000000ff)) | ||
354 | mode = argbx888; | ||
355 | else if ((vis->red_mask == 0x000000ff) && | ||
356 | (vis->green_mask == 0x0000ff00) && | ||
357 | (vis->blue_mask == 0x00ff0000)) | ||
358 | mode = abgrx888; | ||
359 | else if ((vis->red_mask == 0xff000000) && | ||
360 | (vis->green_mask == 0x00ff0000) && | ||
361 | (vis->blue_mask == 0x0000ff00)) | ||
362 | mode = rgba888x; | ||
363 | else if ((vis->red_mask == 0x0000ff00) && | ||
364 | (vis->green_mask == 0x00ff0000) && | ||
365 | (vis->blue_mask == 0xff000000)) | ||
366 | mode = bgra888x; | ||
367 | else if ((vis->red_mask == 0x0003f000) && | ||
368 | (vis->green_mask == 0x00000fc0) && | ||
369 | (vis->blue_mask == 0x0000003f)) | ||
370 | mode = argbx666; | ||
371 | else if ((vis->red_mask == 0x0000f800) && | ||
372 | (vis->green_mask == 0x000007e0) && | ||
373 | (vis->blue_mask == 0x0000001f)) | ||
374 | mode = rgb565; | ||
375 | else if ((vis->red_mask == 0x0000001f) && | ||
376 | (vis->green_mask == 0x000007e0) && | ||
377 | (vis->blue_mask == 0x0000f800)) | ||
378 | mode = bgr565; | ||
379 | else if ((vis->red_mask == 0x00007c00) && | ||
380 | (vis->green_mask == 0x000003e0) && | ||
381 | (vis->blue_mask == 0x0000001f)) | ||
382 | mode = rgbx555; | ||
383 | else | ||
384 | return EINA_FALSE; | ||
385 | } | ||
386 | for (row = 0; row < h; row++) | ||
387 | { | ||
388 | unsigned char *s8; | ||
389 | unsigned short *s16; | ||
390 | unsigned int *s32, *dp, *de; | ||
391 | |||
392 | dp = ((unsigned int *)(((unsigned char *)dst) + | ||
393 | ((dy + row) * dbpl))) + dx; | ||
394 | de = dp + w; | ||
395 | switch (sbpp) | ||
396 | { | ||
397 | case 8: | ||
398 | s8 = ((unsigned char *)(((unsigned char *)src) + | ||
399 | ((y + row) * sbpl))) + x; | ||
400 | if (nret > 0) | ||
401 | { | ||
402 | while (dp < de) | ||
403 | { | ||
404 | *dp = pal[*s8]; | ||
405 | s8++; dp++; | ||
406 | } | ||
407 | } | ||
408 | else | ||
409 | return EINA_FALSE; | ||
410 | break; | ||
411 | |||
412 | case 16: | ||
413 | s16 = ((unsigned short *)(((unsigned char *)src) + | ||
414 | ((y + row) * sbpl))) + x; | ||
415 | switch (mode) | ||
416 | { | ||
417 | case rgb565: | ||
418 | while (dp < de) | ||
419 | { | ||
420 | r = (*s16 & 0xf800) << 8; | ||
421 | g = (*s16 & 0x07e0) << 5; | ||
422 | b = (*s16 & 0x001f) << 3; | ||
423 | r |= (r >> 5) & 0xff0000; | ||
424 | g |= (g >> 6) & 0x00ff00; | ||
425 | b |= (b >> 5); | ||
426 | *dp = 0xff000000 | r | g | b; | ||
427 | s16++; dp++; | ||
428 | } | ||
429 | break; | ||
430 | |||
431 | case bgr565: | ||
432 | while (dp < de) | ||
433 | { | ||
434 | r = (*s16 & 0x001f) << 19; | ||
435 | g = (*s16 & 0x07e0) << 5; | ||
436 | b = (*s16 & 0xf800) >> 8; | ||
437 | r |= (r >> 5) & 0xff0000; | ||
438 | g |= (g >> 6) & 0x00ff00; | ||
439 | b |= (b >> 5); | ||
440 | *dp = 0xff000000 | r | g | b; | ||
441 | s16++; dp++; | ||
442 | } | ||
443 | break; | ||
444 | |||
445 | case rgbx555: | ||
446 | while (dp < de) | ||
447 | { | ||
448 | r = (*s16 & 0x7c00) << 9; | ||
449 | g = (*s16 & 0x03e0) << 6; | ||
450 | b = (*s16 & 0x001f) << 3; | ||
451 | r |= (r >> 5) & 0xff0000; | ||
452 | g |= (g >> 5) & 0x00ff00; | ||
453 | b |= (b >> 5); | ||
454 | *dp = 0xff000000 | r | g | b; | ||
455 | s16++; dp++; | ||
456 | } | ||
457 | break; | ||
458 | |||
459 | default: | ||
460 | return EINA_FALSE; | ||
461 | break; | ||
462 | } | ||
463 | break; | ||
464 | |||
465 | case 24: | ||
466 | case 32: | ||
467 | s32 = ((unsigned int *)(((unsigned char *)src) + | ||
468 | ((y + row) * sbpl))) + x; | ||
469 | switch (mode) | ||
470 | { | ||
471 | case argbx888: | ||
472 | while (dp < de) | ||
473 | { | ||
474 | *dp = 0xff000000 | *s32; | ||
475 | s32++; dp++; | ||
476 | } | ||
477 | break; | ||
478 | |||
479 | case abgrx888: | ||
480 | while (dp < de) | ||
481 | { | ||
482 | r = *s32 & 0x000000ff; | ||
483 | g = *s32 & 0x0000ff00; | ||
484 | b = *s32 & 0x00ff0000; | ||
485 | *dp = 0xff000000 | (r << 16) | (g) | (b >> 16); | ||
486 | s32++; dp++; | ||
487 | } | ||
488 | break; | ||
489 | |||
490 | case rgba888x: | ||
491 | while (dp < de) | ||
492 | { | ||
493 | *dp = 0xff000000 | (*s32 >> 8); | ||
494 | s32++; dp++; | ||
495 | } | ||
496 | break; | ||
497 | |||
498 | case bgra888x: | ||
499 | while (dp < de) | ||
500 | { | ||
501 | r = *s32 & 0x0000ff00; | ||
502 | g = *s32 & 0x00ff0000; | ||
503 | b = *s32 & 0xff000000; | ||
504 | *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24); | ||
505 | s32++; dp++; | ||
506 | } | ||
507 | break; | ||
508 | |||
509 | case argbx666: | ||
510 | while (dp < de) | ||
511 | { | ||
512 | r = (*s32 & 0x3f000) << 6; | ||
513 | g = (*s32 & 0x00fc0) << 4; | ||
514 | b = (*s32 & 0x0003f) << 2; | ||
515 | r |= (r >> 6) & 0xff0000; | ||
516 | g |= (g >> 6) & 0x00ff00; | ||
517 | b |= (b >> 6); | ||
518 | *dp = 0xff000000 | r | g | b; | ||
519 | s32++; dp++; | ||
520 | } | ||
521 | break; | ||
522 | |||
523 | default: | ||
524 | return EINA_FALSE; | ||
525 | break; | ||
526 | } | ||
527 | break; | ||
528 | break; | ||
529 | |||
530 | default: | ||
531 | return EINA_FALSE; | ||
532 | break; | ||
533 | } | ||
534 | } | ||
535 | return EINA_TRUE; | ||
536 | } | ||
537 | |||
538 | /* local functions */ | ||
539 | static void | ||
540 | _ecore_xcb_image_shm_check(void) | ||
541 | { | ||
542 | // xcb_shm_query_version_reply_t *reply; | ||
543 | xcb_shm_segment_info_t shminfo; | ||
544 | xcb_shm_get_image_cookie_t cookie; | ||
545 | xcb_shm_get_image_reply_t *ireply; | ||
546 | xcb_image_t *img = 0; | ||
547 | uint8_t depth = 0; | ||
548 | |||
549 | if (_ecore_xcb_image_shm_can != -1) return; | ||
550 | CHECK_XCB_CONN; | ||
551 | |||
552 | /* reply = */ | ||
553 | /* xcb_shm_query_version_reply(_ecore_xcb_conn, */ | ||
554 | /* xcb_shm_query_version(_ecore_xcb_conn), NULL); */ | ||
555 | /* if (!reply) */ | ||
556 | /* { */ | ||
557 | /* _ecore_xcb_image_shm_can = 0; */ | ||
558 | /* return; */ | ||
559 | /* } */ | ||
560 | |||
561 | /* if ((reply->major_version < 1) || */ | ||
562 | /* ((reply->major_version == 1) && (reply->minor_version == 0))) */ | ||
563 | /* { */ | ||
564 | /* _ecore_xcb_image_shm_can = 0; */ | ||
565 | /* free(reply); */ | ||
566 | /* return; */ | ||
567 | /* } */ | ||
568 | |||
569 | /* free(reply); */ | ||
570 | |||
571 | depth = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth; | ||
572 | |||
573 | ecore_x_sync(); // needed | ||
574 | |||
575 | img = _ecore_xcb_image_create_native(1, 1, XCB_IMAGE_FORMAT_Z_PIXMAP, | ||
576 | depth, NULL, ~0, NULL); | ||
577 | if (!img) | ||
578 | { | ||
579 | _ecore_xcb_image_shm_can = 0; | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | shminfo.shmid = | ||
584 | shmget(IPC_PRIVATE, img->stride * img->height, (IPC_CREAT | 0666)); | ||
585 | if (shminfo.shmid == (uint32_t)-1) | ||
586 | { | ||
587 | xcb_image_destroy(img); | ||
588 | _ecore_xcb_image_shm_can = 0; | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | shminfo.shmaddr = shmat(shminfo.shmid, 0, 0); | ||
593 | img->data = shminfo.shmaddr; | ||
594 | if (img->data == (uint8_t *)-1) | ||
595 | { | ||
596 | xcb_image_destroy(img); | ||
597 | _ecore_xcb_image_shm_can = 0; | ||
598 | return; | ||
599 | } | ||
600 | |||
601 | shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn); | ||
602 | xcb_shm_attach(_ecore_xcb_conn, shminfo.shmseg, shminfo.shmid, 0); | ||
603 | |||
604 | cookie = | ||
605 | xcb_shm_get_image(_ecore_xcb_conn, | ||
606 | ((xcb_screen_t *)_ecore_xcb_screen)->root, | ||
607 | 0, 0, img->width, img->height, | ||
608 | 0xffffffff, img->format, | ||
609 | shminfo.shmseg, img->data - shminfo.shmaddr); | ||
610 | |||
611 | ecore_x_sync(); // needed | ||
612 | |||
613 | ireply = xcb_shm_get_image_reply(_ecore_xcb_conn, cookie, NULL); | ||
614 | if (ireply) | ||
615 | { | ||
616 | _ecore_xcb_image_shm_can = 1; | ||
617 | free(ireply); | ||
618 | } | ||
619 | else | ||
620 | _ecore_xcb_image_shm_can = 0; | ||
621 | |||
622 | xcb_shm_detach(_ecore_xcb_conn, shminfo.shmseg); | ||
623 | xcb_image_destroy(img); | ||
624 | shmdt(shminfo.shmaddr); | ||
625 | shmctl(shminfo.shmid, IPC_RMID, 0); | ||
626 | } | ||
627 | |||
628 | static void | ||
629 | _ecore_xcb_image_shm_create(Ecore_X_Image *im) | ||
630 | { | ||
631 | CHECK_XCB_CONN; | ||
632 | |||
633 | im->xim = | ||
634 | _ecore_xcb_image_create_native(im->w, im->h, XCB_IMAGE_FORMAT_Z_PIXMAP, | ||
635 | im->depth, NULL, ~0, NULL); | ||
636 | if (!im->xim) return; | ||
637 | |||
638 | im->shminfo.shmid = shmget(IPC_PRIVATE, im->xim->size, (IPC_CREAT | 0666)); | ||
639 | if (im->shminfo.shmid == (uint32_t)-1) | ||
640 | { | ||
641 | xcb_image_destroy(im->xim); | ||
642 | return; | ||
643 | } | ||
644 | |||
645 | im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0); | ||
646 | im->xim->data = im->shminfo.shmaddr; | ||
647 | if ((!im->xim->data) || (im->xim->data == (uint8_t *)-1)) | ||
648 | { | ||
649 | DBG("Shm Create No Image Data"); | ||
650 | xcb_image_destroy(im->xim); | ||
651 | shmdt(im->shminfo.shmaddr); | ||
652 | shmctl(im->shminfo.shmid, IPC_RMID, 0); | ||
653 | return; | ||
654 | } | ||
655 | |||
656 | im->shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn); | ||
657 | xcb_shm_attach(_ecore_xcb_conn, im->shminfo.shmseg, im->shminfo.shmid, 0); | ||
658 | |||
659 | im->data = (unsigned char *)im->xim->data; | ||
660 | im->bpl = im->xim->stride; | ||
661 | im->rows = im->xim->height; | ||
662 | if (im->xim->bpp <= 8) | ||
663 | im->bpp = 1; | ||
664 | else if (im->xim->bpp <= 16) | ||
665 | im->bpp = 2; | ||
666 | else | ||
667 | im->bpp = 4; | ||
668 | } | ||
669 | |||
670 | xcb_image_t * | ||
671 | _ecore_xcb_image_create_native(int w, | ||
672 | int h, | ||
673 | xcb_image_format_t format, | ||
674 | uint8_t depth, | ||
675 | void *base, | ||
676 | uint32_t bytes, | ||
677 | uint8_t *data) | ||
678 | { | ||
679 | static uint8_t dpth = 0; | ||
680 | static xcb_format_t *fmt = NULL; | ||
681 | const xcb_setup_t *setup; | ||
682 | xcb_image_format_t xif; | ||
683 | |||
684 | CHECK_XCB_CONN; | ||
685 | |||
686 | /* NB: We cannot use xcb_image_create_native as it only creates images | ||
687 | * using MSB_FIRST, so this routine recreates that function and uses | ||
688 | * the endian-ness of the server setup */ | ||
689 | setup = xcb_get_setup(_ecore_xcb_conn); | ||
690 | xif = format; | ||
691 | |||
692 | if ((xif == XCB_IMAGE_FORMAT_Z_PIXMAP) && (depth == 1)) | ||
693 | xif = XCB_IMAGE_FORMAT_XY_PIXMAP; | ||
694 | |||
695 | if (dpth != depth) | ||
696 | { | ||
697 | dpth = depth; | ||
698 | fmt = _ecore_xcb_image_find_format(setup, depth); | ||
699 | if (!fmt) return 0; | ||
700 | } | ||
701 | |||
702 | switch (xif) | ||
703 | { | ||
704 | case XCB_IMAGE_FORMAT_XY_BITMAP: | ||
705 | if (depth != 1) return 0; | ||
706 | |||
707 | case XCB_IMAGE_FORMAT_XY_PIXMAP: | ||
708 | case XCB_IMAGE_FORMAT_Z_PIXMAP: | ||
709 | return xcb_image_create(w, h, xif, | ||
710 | fmt->scanline_pad, | ||
711 | fmt->depth, fmt->bits_per_pixel, | ||
712 | setup->bitmap_format_scanline_unit, | ||
713 | setup->image_byte_order, | ||
714 | setup->bitmap_format_bit_order, | ||
715 | base, bytes, data); | ||
716 | |||
717 | default: | ||
718 | break; | ||
719 | } | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | |||
724 | static xcb_format_t * | ||
725 | _ecore_xcb_image_find_format(const xcb_setup_t *setup, | ||
726 | uint8_t depth) | ||
727 | { | ||
728 | xcb_format_t *fmt, *fmtend; | ||
729 | |||
730 | CHECK_XCB_CONN; | ||
731 | |||
732 | fmt = xcb_setup_pixmap_formats(setup); | ||
733 | fmtend = fmt + xcb_setup_pixmap_formats_length(setup); | ||
734 | for (; fmt != fmtend; ++fmt) | ||
735 | if (fmt->depth == depth) | ||
736 | return fmt; | ||
737 | |||
738 | return 0; | ||
739 | } | ||
740 | |||