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