7c21781cf8477ce01a67214d678e5d0052c26d21
[platform/upstream/efl.git] / src / lib / ecore_x / xcb / ecore_xcb_image.c
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 = MIN(w, im->w);
100              im->xim->height = MIN(h, im->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
249    if (((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) ||
250         (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) &&
251        (im->bpp == 4) &&
252        (vis->red_mask == 0xff0000) &&
253        (vis->green_mask == 0x00ff00) && 
254        (vis->blue_mask == 0x0000ff))
255      {
256         const xcb_setup_t *setup = xcb_get_setup(_ecore_xcb_conn);
257
258         if (!setup) return EINA_FALSE;
259 #ifdef WORDS_BIGENDIAN
260         if (setup->image_byte_order == XCB_IMAGE_ORDER_MSB_FIRST) return EINA_TRUE;
261 #else
262         if (setup->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST) return EINA_TRUE;
263 #endif
264      }
265
266    return EINA_FALSE;
267 }
268
269 EAPI Eina_Bool
270 ecore_x_image_to_argb_convert(void            *src,
271                               int              sbpp,
272                               int              sbpl,
273                               Ecore_X_Colormap c,
274                               Ecore_X_Visual   v,
275                               int              x,
276                               int              y,
277                               int              w,
278                               int              h,
279                               unsigned int    *dst,
280                               int              dbpl,
281                               int              dx,
282                               int              dy)
283 {
284    xcb_visualtype_t *vis;
285    uint32_t *cols;
286    int n = 0, nret = 0, i, row, mode = 0;
287    unsigned int pal[256], r, g, b;
288    enum
289    {
290       rgbnone = 0,
291       rgb565,
292       bgr565,
293       rgbx555,
294       rgb888,
295       bgr888,
296       argbx888,
297       abgrx888,
298       rgba888x,
299       bgra888x,
300       argbx666
301    };
302
303    LOGFN(__FILE__, __LINE__, __FUNCTION__);
304    CHECK_XCB_CONN;
305
306    sbpp *= 8;
307
308    vis = (xcb_visualtype_t *)v;
309    n = vis->colormap_entries;
310    if ((n <= 256) &&
311        ((vis->_class == XCB_VISUAL_CLASS_PSEUDO_COLOR) ||
312         (vis->_class == XCB_VISUAL_CLASS_STATIC_COLOR) ||
313         (vis->_class == XCB_VISUAL_CLASS_GRAY_SCALE) ||
314         (vis->_class == XCB_VISUAL_CLASS_STATIC_GRAY)))
315      {
316         xcb_query_colors_cookie_t cookie;
317         xcb_query_colors_reply_t *reply;
318
319         if (!c)
320           {
321              c = (xcb_colormap_t)((xcb_screen_t *)
322                                   _ecore_xcb_screen)->default_colormap;
323           }
324
325         cols = alloca(n * sizeof(uint32_t));
326         for (i = 0; i < n; i++)
327           cols[i] = i;
328
329         cookie = xcb_query_colors_unchecked(_ecore_xcb_conn, c, n, cols);
330         reply = xcb_query_colors_reply(_ecore_xcb_conn, cookie, NULL);
331         if (reply)
332           {
333              xcb_rgb_iterator_t iter;
334              xcb_rgb_t *ret;
335
336              iter = xcb_query_colors_colors_iterator(reply);
337              ret = xcb_query_colors_colors(reply);
338              if (ret)
339                {
340                   for (i = 0; iter.rem; xcb_rgb_next(&iter), i++)
341                     {
342                        pal[i] = 0xff000000 |
343                          ((iter.data->red >> 8) << 16) |
344                          ((iter.data->green >> 8) << 8) |
345                          ((iter.data->blue >> 8));
346                     }
347                   nret = n;
348                }
349              free(reply);
350           }
351      }
352    else if ((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) ||
353             (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR))
354      {
355         if (sbpp == 24)
356           {
357              if ((vis->red_mask == 0x00ff0000) &&
358                  (vis->green_mask == 0x0000ff00) &&
359                  (vis->blue_mask == 0x000000ff))
360                mode = rgb888;
361              else if ((vis->red_mask == 0x000000ff) &&
362                       (vis->green_mask == 0x0000ff00) &&
363                       (vis->blue_mask == 0x00ff0000))
364                mode = bgr888;
365              else
366                return EINA_FALSE;
367           }
368         else
369           {
370              if ((vis->red_mask == 0x00ff0000) &&
371                  (vis->green_mask == 0x0000ff00) &&
372                  (vis->blue_mask == 0x000000ff))
373                mode = argbx888;
374              else if ((vis->red_mask == 0x000000ff) &&
375                       (vis->green_mask == 0x0000ff00) &&
376                       (vis->blue_mask == 0x00ff0000))
377                mode = abgrx888;
378              else if ((vis->red_mask == 0xff000000) &&
379                       (vis->green_mask == 0x00ff0000) &&
380                       (vis->blue_mask == 0x0000ff00))
381                mode = rgba888x;
382              else if ((vis->red_mask == 0x0000ff00) &&
383                       (vis->green_mask == 0x00ff0000) &&
384                       (vis->blue_mask == 0xff000000))
385                mode = bgra888x;
386              else if ((vis->red_mask == 0x0003f000) &&
387                       (vis->green_mask == 0x00000fc0) &&
388                       (vis->blue_mask == 0x0000003f))
389                mode = argbx666;
390              else if ((vis->red_mask == 0x0000f800) &&
391                       (vis->green_mask == 0x000007e0) &&
392                       (vis->blue_mask == 0x0000001f))
393                mode = rgb565;
394              else if ((vis->red_mask == 0x0000001f) &&
395                       (vis->green_mask == 0x000007e0) &&
396                       (vis->blue_mask == 0x0000f800))
397                mode = bgr565;
398              else if ((vis->red_mask == 0x00007c00) &&
399                       (vis->green_mask == 0x000003e0) &&
400                       (vis->blue_mask == 0x0000001f))
401                mode = rgbx555;
402              else
403                return EINA_FALSE;
404           }
405      }
406    for (row = 0; row < h; row++)
407      {
408         unsigned char *s8;
409         unsigned short *s16;
410         unsigned int *s32, *dp, *de;
411
412         dp = ((unsigned int *)(((unsigned char *)dst) +
413                                ((dy + row) * dbpl))) + dx;
414         de = dp + w;
415         switch (sbpp)
416           {
417            case 8:
418              s8 = ((unsigned char *)(((unsigned char *)src) +
419                                      ((y + row) * sbpl))) + x;
420              if (nret > 0)
421                {
422                   while (dp < de)
423                     {
424                        *dp = pal[*s8];
425                        s8++; dp++;
426                     }
427                }
428              else
429                return EINA_FALSE;
430              break;
431
432            case 16:
433              s16 = ((unsigned short *)(((unsigned char *)src) +
434                                        ((y + row) * sbpl))) + x;
435              switch (mode)
436                {
437                 case rgb565:
438                   while (dp < de)
439                     {
440                        r = (*s16 & 0xf800) << 8;
441                        g = (*s16 & 0x07e0) << 5;
442                        b = (*s16 & 0x001f) << 3;
443                        r |= (r >> 5) & 0xff0000;
444                        g |= (g >> 6) & 0x00ff00;
445                        b |= (b >> 5);
446                        *dp = 0xff000000 | r | g | b;
447                        s16++; dp++;
448                     }
449                   break;
450
451                 case bgr565:
452                   while (dp < de)
453                     {
454                        r = (*s16 & 0x001f) << 19;
455                        g = (*s16 & 0x07e0) << 5;
456                        b = (*s16 & 0xf800) >> 8;
457                        r |= (r >> 5) & 0xff0000;
458                        g |= (g >> 6) & 0x00ff00;
459                        b |= (b >> 5);
460                        *dp = 0xff000000 | r | g | b;
461                        s16++; dp++;
462                     }
463                   break;
464
465                 case rgbx555:
466                   while (dp < de)
467                     {
468                        r = (*s16 & 0x7c00) << 9;
469                        g = (*s16 & 0x03e0) << 6;
470                        b = (*s16 & 0x001f) << 3;
471                        r |= (r >> 5) & 0xff0000;
472                        g |= (g >> 5) & 0x00ff00;
473                        b |= (b >> 5);
474                        *dp = 0xff000000 | r | g | b;
475                        s16++; dp++;
476                     }
477                   break;
478
479                 default:
480                   return EINA_FALSE;
481                   break;
482                }
483              break;
484
485            case 24:
486             s8 = ((unsigned char *)(((unsigned char *)src) + ((y + row) * sbpl))) + (x * (sbpp / 8));
487              switch (mode)
488                {
489                 case rgb888:
490                   while (dp < de)
491                     {
492                        *dp = 0xff000000 | (s8[2] << 16) | (s8[1] << 8) | s8[0];
493                        s8 += 3; dp++;
494                     }
495                   break;
496                 case bgr888:
497                   while (dp < de)
498                     {
499                        *dp = 0xff000000 | (s8[0] << 16) | (s8[1] << 8) | s8[2];
500                        s8 += 3; dp++;
501                     }
502                   break;
503                 default:
504                   return EINA_FALSE;
505                   break;
506                }
507              break;
508              
509            case 32:
510              s32 = ((unsigned int *)(((unsigned char *)src) +
511                                      ((y + row) * sbpl))) + x;
512              switch (mode)
513                {
514                 case argbx888:
515                   while (dp < de)
516                     {
517                        *dp = 0xff000000 | *s32;
518                        s32++; dp++;
519                     }
520                   break;
521
522                 case abgrx888:
523                   while (dp < de)
524                     {
525                        r = *s32 & 0x000000ff;
526                        g = *s32 & 0x0000ff00;
527                        b = *s32 & 0x00ff0000;
528                        *dp = 0xff000000 | (r << 16) | (g) | (b >> 16);
529                        s32++; dp++;
530                     }
531                   break;
532
533                 case rgba888x:
534                   while (dp < de)
535                     {
536                        *dp = 0xff000000 | (*s32 >> 8);
537                        s32++; dp++;
538                     }
539                   break;
540
541                 case bgra888x:
542                   while (dp < de)
543                     {
544                        r = *s32 & 0x0000ff00;
545                        g = *s32 & 0x00ff0000;
546                        b = *s32 & 0xff000000;
547                        *dp = 0xff000000 | (r << 8) | (g >> 8) | (b >> 24);
548                        s32++; dp++;
549                     }
550                   break;
551
552                 case argbx666:
553                   while (dp < de)
554                     {
555                        r = (*s32 & 0x3f000) << 6;
556                        g = (*s32 & 0x00fc0) << 4;
557                        b = (*s32 & 0x0003f) << 2;
558                        r |= (r >> 6) & 0xff0000;
559                        g |= (g >> 6) & 0x00ff00;
560                        b |= (b >> 6);
561                        *dp = 0xff000000 | r | g | b;
562                        s32++; dp++;
563                     }
564                   break;
565
566                 default:
567                   return EINA_FALSE;
568                   break;
569                }
570              break;
571
572            default:
573              return EINA_FALSE;
574              break;
575           }
576      }
577    return EINA_TRUE;
578 }
579
580 /* local functions */
581 static void
582 _ecore_xcb_image_shm_check(void)
583 {
584 //   xcb_shm_query_version_reply_t *reply;
585      xcb_shm_segment_info_t shminfo;
586      xcb_shm_get_image_cookie_t cookie;
587      xcb_shm_get_image_reply_t *ireply;
588      xcb_image_t *img = 0;
589      uint8_t depth = 0;
590
591      if (_ecore_xcb_image_shm_can != -1) return;
592      CHECK_XCB_CONN;
593
594      /* reply =  */
595      /*   xcb_shm_query_version_reply(_ecore_xcb_conn,  */
596      /*                               xcb_shm_query_version(_ecore_xcb_conn), NULL); */
597      /* if (!reply)  */
598      /*   { */
599      /*      _ecore_xcb_image_shm_can = 0; */
600      /*      return; */
601      /*   } */
602
603      /* if ((reply->major_version < 1) ||  */
604      /*     ((reply->major_version == 1) && (reply->minor_version == 0)))  */
605      /*   { */
606      /*      _ecore_xcb_image_shm_can = 0; */
607      /*      free(reply); */
608      /*      return; */
609      /*   } */
610
611      /* free(reply); */
612
613      depth = ((xcb_screen_t *)_ecore_xcb_screen)->root_depth;
614
615      ecore_x_sync(); // needed
616
617      img = _ecore_xcb_image_create_native(1, 1, XCB_IMAGE_FORMAT_Z_PIXMAP,
618                                           depth, NULL, ~0, NULL);
619      if (!img)
620        {
621           _ecore_xcb_image_shm_can = 0;
622           return;
623        }
624
625      shminfo.shmid =
626        shmget(IPC_PRIVATE, img->stride * img->height, (IPC_CREAT | 0600));
627      if (shminfo.shmid == (uint32_t)-1)
628        {
629           xcb_image_destroy(img);
630           _ecore_xcb_image_shm_can = 0;
631           return;
632        }
633
634      shminfo.shmaddr = shmat(shminfo.shmid, 0, 0);
635      img->data = shminfo.shmaddr;
636      if (img->data == (uint8_t *)-1)
637        {
638           xcb_image_destroy(img);
639           _ecore_xcb_image_shm_can = 0;
640           return;
641        }
642
643      shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn);
644      xcb_shm_attach(_ecore_xcb_conn, shminfo.shmseg, shminfo.shmid, 0);
645
646      cookie =
647        xcb_shm_get_image(_ecore_xcb_conn,
648                          ((xcb_screen_t *)_ecore_xcb_screen)->root,
649                          0, 0, img->width, img->height,
650                          0xffffffff, img->format,
651                          shminfo.shmseg, img->data - shminfo.shmaddr);
652
653      ecore_x_sync(); // needed
654
655      ireply = xcb_shm_get_image_reply(_ecore_xcb_conn, cookie, NULL);
656      if (ireply)
657        {
658           _ecore_xcb_image_shm_can = 1;
659           free(ireply);
660        }
661      else
662        _ecore_xcb_image_shm_can = 0;
663
664      xcb_shm_detach(_ecore_xcb_conn, shminfo.shmseg);
665      xcb_image_destroy(img);
666      shmdt(shminfo.shmaddr);
667      shmctl(shminfo.shmid, IPC_RMID, 0);
668 }
669
670 static void
671 _ecore_xcb_image_shm_create(Ecore_X_Image *im)
672 {
673    CHECK_XCB_CONN;
674
675    im->xim =
676      _ecore_xcb_image_create_native(im->w, im->h, XCB_IMAGE_FORMAT_Z_PIXMAP,
677                                     im->depth, NULL, ~0, NULL);
678    if (!im->xim) return;
679
680    im->shminfo.shmid = shmget(IPC_PRIVATE, im->xim->size, (IPC_CREAT | 0600));
681    if (im->shminfo.shmid == (uint32_t)-1)
682      {
683         xcb_image_destroy(im->xim);
684         return;
685      }
686
687    im->shminfo.shmaddr = shmat(im->shminfo.shmid, 0, 0);
688    im->xim->data = im->shminfo.shmaddr;
689    if ((!im->xim->data) || (im->xim->data == (uint8_t *)-1))
690      {
691         DBG("Shm Create No Image Data");
692         xcb_image_destroy(im->xim);
693         shmdt(im->shminfo.shmaddr);
694         shmctl(im->shminfo.shmid, IPC_RMID, 0);
695         return;
696      }
697
698    im->shminfo.shmseg = xcb_generate_id(_ecore_xcb_conn);
699    xcb_shm_attach(_ecore_xcb_conn, im->shminfo.shmseg, im->shminfo.shmid, 0);
700
701    im->data = (unsigned char *)im->xim->data;
702    im->bpl = im->xim->stride;
703    im->rows = im->xim->height;
704    if (im->xim->bpp <= 8)
705      im->bpp = 1;
706    else if (im->xim->bpp <= 16)
707      im->bpp = 2;
708    else
709      im->bpp = 4;
710 }
711
712 xcb_image_t *
713 _ecore_xcb_image_create_native(int                w,
714                                int                h,
715                                xcb_image_format_t format,
716                                uint8_t            depth,
717                                void              *base,
718                                uint32_t           bytes,
719                                uint8_t           *data)
720 {
721    static uint8_t dpth = 0;
722    static xcb_format_t *fmt = NULL;
723    const xcb_setup_t *setup;
724    xcb_image_format_t xif;
725
726    CHECK_XCB_CONN;
727
728    /* NB: We cannot use xcb_image_create_native as it only creates images
729     * using MSB_FIRST, so this routine recreates that function and uses
730     * the endian-ness of the server setup */
731    setup = xcb_get_setup(_ecore_xcb_conn);
732    xif = format;
733
734    if ((xif == XCB_IMAGE_FORMAT_Z_PIXMAP) && (depth == 1))
735      xif = XCB_IMAGE_FORMAT_XY_PIXMAP;
736
737    if (dpth != depth)
738      {
739         dpth = depth;
740         fmt = _ecore_xcb_image_find_format(setup, depth);
741         if (!fmt) return 0;
742      }
743
744    switch (xif)
745      {
746       case XCB_IMAGE_FORMAT_XY_BITMAP:
747         if (depth != 1) return 0;
748
749       case XCB_IMAGE_FORMAT_XY_PIXMAP:
750       case XCB_IMAGE_FORMAT_Z_PIXMAP:
751         return xcb_image_create(w, h, xif,
752                                 fmt->scanline_pad,
753                                 fmt->depth, fmt->bits_per_pixel,
754                                 setup->bitmap_format_scanline_unit,
755                                 setup->image_byte_order,
756                                 setup->bitmap_format_bit_order,
757                                 base, bytes, data);
758
759       default:
760         break;
761      }
762
763    return 0;
764 }
765
766 static xcb_format_t *
767 _ecore_xcb_image_find_format(const xcb_setup_t *setup,
768                              uint8_t            depth)
769 {
770    xcb_format_t *fmt, *fmtend;
771
772    CHECK_XCB_CONN;
773
774    fmt = xcb_setup_pixmap_formats(setup);
775    fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
776    for (; fmt != fmtend; ++fmt)
777      if (fmt->depth == depth)
778        return fmt;
779
780    return 0;
781 }
782