move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / xrender_xcb / evas_engine_ximage.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3 #include "evas_engine.h"
4 #include "Evas_Engine_XRender_Xcb.h"
5
6 static Evas_List *_image_info_list = NULL;
7
8 static int _xcb_err = 0;
9
10 enum
11 {
12   xcb_render_pictforminfo_id            = 1 << 0,
13   xcb_render_pictforminfo_type_t        = 1 << 1,
14   xcb_render_pictforminfo_depth_t       = 1 << 2,
15   xcb_render_pictforminfo_red_shift_t   = 1 << 3,
16   xcb_render_pictforminfo_red_mask_t    = 1 << 4,
17   xcb_render_pictforminfo_green_shift_t = 1 << 5,
18   xcb_render_pictforminfo_green_mask_t  = 1 << 6,
19   xcb_render_pictforminfo_blue_shift_t  = 1 << 7,
20   xcb_render_pictforminfo_blue_mask_t   = 1 << 8,
21   xcb_render_pictforminfo_alpha_shift_t = 1 << 9,
22   xcb_render_pictforminfo_alpha_mask_t  = 1 << 10,
23   xcb_render_pictforminfo_colormap_t    = 1 << 11,
24 };
25
26 enum
27 {
28   xcb_render_standard_pictforminfoargb_32_t,
29   xcb_render_standard_pictforminforgb_24_t,
30   xcb_render_standard_pictforminfoa_8_t,
31   xcb_render_standard_pictforminfoa_4_t,
32   xcb_render_standard_pictforminfoa_1_t,
33   xcb_render_standard_pictforminfo_count_t
34 };
35
36 static xcb_render_pictforminfo_t *
37 xcb_render_find_pictforminfo (xcb_connection_t *conn, uint32_t mask, const xcb_render_pictforminfo_t *template, int count)
38 {
39   xcb_render_query_pict_formats_cookie_t cookie;
40   xcb_render_query_pict_formats_reply_t *rep;
41   xcb_render_pictforminfo_iterator_t     iter_forminfo;
42
43   cookie = xcb_render_query_pict_formats_unchecked (conn);
44   rep = xcb_render_query_pict_formats_reply (conn, cookie, NULL);
45   iter_forminfo = xcb_render_query_pict_formats_formats_iterator (rep);
46   for (; iter_forminfo.rem; xcb_render_pictforminfo_next (&iter_forminfo)) {
47     if (mask & xcb_render_pictforminfo_id)
48       if (template->id != iter_forminfo.data->id)
49         continue;
50     if (mask & xcb_render_pictforminfo_type_t)
51       if (template->type != iter_forminfo.data->type)
52         continue;
53     if (mask & xcb_render_pictforminfo_depth_t)
54       if (template->depth != iter_forminfo.data->depth)
55         continue;
56     if (mask & xcb_render_pictforminfo_red_shift_t)
57       if (template->direct.red_shift != iter_forminfo.data->direct.red_shift)
58         continue;
59     if (mask & xcb_render_pictforminfo_red_mask_t)
60       if (template->direct.red_mask != iter_forminfo.data->direct.red_mask)
61         continue;
62     if (mask & xcb_render_pictforminfo_green_shift_t)
63       if (template->direct.green_shift != iter_forminfo.data->direct.green_shift)
64         continue;
65     if (mask & xcb_render_pictforminfo_green_mask_t)
66       if (template->direct.green_mask != iter_forminfo.data->direct.green_mask)
67         continue;
68     if (mask & xcb_render_pictforminfo_blue_shift_t)
69       if (template->direct.blue_shift != iter_forminfo.data->direct.blue_shift)
70         continue;
71     if (mask & xcb_render_pictforminfo_blue_mask_t)
72       if (template->direct.blue_mask != iter_forminfo.data->direct.blue_mask)
73         continue;
74     if (mask & xcb_render_pictforminfo_alpha_shift_t)
75       if (template->direct.alpha_shift != iter_forminfo.data->direct.alpha_shift)
76         continue;
77     if (mask & xcb_render_pictforminfo_alpha_mask_t)
78       if (template->direct.alpha_mask != iter_forminfo.data->direct.alpha_mask)
79         continue;
80     if (mask & xcb_render_pictforminfo_colormap_t)
81       if (template->colormap != iter_forminfo.data->colormap)
82         continue;
83     if (count-- == 0) {
84       xcb_render_pictforminfo_t *forminfo;
85
86       forminfo = (xcb_render_pictforminfo_t *)malloc (sizeof (xcb_render_pictforminfo_t));
87       memcpy (forminfo, iter_forminfo.data, sizeof (xcb_render_pictforminfo_t));
88
89       free (rep);
90       return forminfo;
91     }
92   }
93   free (rep);
94   return NULL;
95 }
96
97 static xcb_render_pictforminfo_t *
98 xcb_render_find_standard_pictforminfo (xcb_connection_t *conn, int format)
99 {
100   xcb_render_pictforminfo_t *forminfo = NULL;
101   struct {
102     xcb_render_pictforminfo_t template;
103     uint32_t                mask;
104   } standardFormats[xcb_render_standard_pictforminfo_count_t] = {
105     /* StandardPICTFORMINFOARGB32 */
106     {
107       {
108         0,                                /* id */
109         XCB_RENDER_PICT_TYPE_DIRECT,          /* type */
110         32,                               /* depth */
111         { 0, 0 },                         /* pad */
112         {                                 /* direct */
113           16,                             /* direct.red_shift */
114           0xff,                           /* direct.red_mask */
115           8,                              /* direct.green_shift */
116           0xff,                           /* direct.green_mask */
117           0,                              /* direct.blue_shift */
118           0xff,                           /* direct.blue_mask */
119           24,                             /* direct.alpha_shift */
120           0xff                            /* direct.alpha_mask */
121         },
122         0                                 /* colormap */
123       },
124       xcb_render_pictforminfo_type_t        |
125       xcb_render_pictforminfo_depth_t       |
126       xcb_render_pictforminfo_red_shift_t   |
127       xcb_render_pictforminfo_red_mask_t    |
128       xcb_render_pictforminfo_green_shift_t |
129       xcb_render_pictforminfo_green_mask_t  |
130       xcb_render_pictforminfo_blue_shift_t  |
131       xcb_render_pictforminfo_blue_mask_t   |
132       xcb_render_pictforminfo_alpha_shift_t |
133       xcb_render_pictforminfo_alpha_mask_t
134     },
135     /* StandardPICTFORMINFORGB24 */
136     {
137       {
138         0,                                /* id */
139         XCB_RENDER_PICT_TYPE_DIRECT,          /* type */
140         24,                               /* depth */
141         { 0, 0 },                         /* pad */
142         {                                 /* direct */
143           16,                             /* direct.red_shift */
144           0xff,                           /* direct.red_mask */
145           8,                              /* direct.green_shift */
146           0xff,                           /* direct.green_mask */
147           0,                              /* direct.blue_shift */
148           0xff,                           /* direct.blue_mask */
149           0,                              /* direct.alpha_shift */
150           0x00                            /* direct.alpha_mask */
151         },
152         0                                 /* colormap */
153       },
154       xcb_render_pictforminfo_type_t        |
155       xcb_render_pictforminfo_depth_t       |
156       xcb_render_pictforminfo_red_shift_t   |
157       xcb_render_pictforminfo_red_mask_t    |
158       xcb_render_pictforminfo_green_shift_t |
159       xcb_render_pictforminfo_green_mask_t  |
160       xcb_render_pictforminfo_blue_shift_t  |
161       xcb_render_pictforminfo_blue_mask_t   |
162       xcb_render_pictforminfo_alpha_mask_t
163     },
164     /* StandardPICTFORMINFOA8 */
165     {
166       {
167         0,                                /* id */
168         XCB_RENDER_PICT_TYPE_DIRECT,          /* type */
169         8,                                /* depth */
170         { 0, 0 },                         /* pad */
171         {                                 /* direct */
172           0,                              /* direct.red_shift */
173           0x00,                           /* direct.red_mask */
174           0,                              /* direct.green_shift */
175           0x00,                           /* direct.green_mask */
176           0,                              /* direct.blue_shift */
177           0x00,                           /* direct.blue_mask */
178           0,                              /* direct.alpha_shift */
179           0xff                            /* direct.alpha_mask */
180         },
181         0                                 /* colormap */
182       },
183       xcb_render_pictforminfo_type_t        |
184       xcb_render_pictforminfo_depth_t       |
185       xcb_render_pictforminfo_red_mask_t    |
186       xcb_render_pictforminfo_green_mask_t  |
187       xcb_render_pictforminfo_blue_mask_t   |
188       xcb_render_pictforminfo_alpha_shift_t |
189       xcb_render_pictforminfo_alpha_mask_t
190     },
191     /* StandardPICTFORMINFOA4 */
192     {
193       {
194         0,                                /* id */
195         XCB_RENDER_PICT_TYPE_DIRECT,          /* type */
196         4,                                /* depth */
197         { 0, 0 },                         /* pad */
198         {                                 /* direct */
199           0,                              /* direct.red_shift */
200           0x00,                           /* direct.red_mask */
201           0,                              /* direct.green_shift */
202           0x00,                           /* direct.green_mask */
203           0,                              /* direct.blue_shift */
204           0x00,                           /* direct.blue_mask */
205           0,                              /* direct.alpha_shift */
206           0x0f                            /* direct.alpha_mask */
207         },
208         0                                 /* colormap */
209       },
210       xcb_render_pictforminfo_type_t        |
211       xcb_render_pictforminfo_depth_t       |
212       xcb_render_pictforminfo_red_mask_t    |
213       xcb_render_pictforminfo_green_mask_t  |
214       xcb_render_pictforminfo_blue_mask_t   |
215       xcb_render_pictforminfo_alpha_shift_t |
216       xcb_render_pictforminfo_alpha_mask_t
217     },
218     /* StandardPICTFORMINFOA1 */
219     {
220       {
221         0,                                /* id */
222         XCB_RENDER_PICT_TYPE_DIRECT,          /* type */
223         1,                                /* depth */
224         { 0, 0 },                         /* pad */
225         {                                 /* direct */
226           0,                              /* direct.red_shift */
227           0x00,                           /* direct.red_mask */
228           0,                              /* direct.green_shift */
229           0x00,                           /* direct.green_mask */
230           0,                              /* direct.blue_shift */
231           0x00,                           /* direct.blue_mask */
232           0,                              /* direct.alpha_shift */
233           0x01                            /* direct.alpha_mask */
234         },
235         0                                 /* colormap */
236       },
237       xcb_render_pictforminfo_type_t        |
238       xcb_render_pictforminfo_depth_t       |
239       xcb_render_pictforminfo_red_mask_t    |
240       xcb_render_pictforminfo_green_mask_t  |
241       xcb_render_pictforminfo_blue_mask_t   |
242       xcb_render_pictforminfo_alpha_shift_t |
243       xcb_render_pictforminfo_alpha_mask_t
244     },
245   };
246   if ((format >= 0) && (format < xcb_render_standard_pictforminfo_count_t))
247     forminfo = xcb_render_find_pictforminfo (conn,
248                                              standardFormats[format].mask,
249                                              &standardFormats[format].template,
250                                              0);
251   return forminfo;
252 }
253
254 static void
255 _tmp_xcb_err(xcb_connection_t *conn/* , XErrorEvent *ev */)
256 {
257    _xcb_err = 1;
258    return;
259 }
260
261 Xcb_Image_Info *
262 _xr_image_info_get(xcb_connection_t *conn, xcb_drawable_t draw, xcb_visualid_t vis)
263 {
264    xcb_get_geometry_cookie_t cookie;
265    xcb_get_geometry_reply_t *rep;
266    Xcb_Image_Info           *xcbinf;
267    Xcb_Image_Info           *xcbinf2;
268    Evas_List                *l;
269
270    xcbinf2 = NULL;
271    for (l = _image_info_list; l; l = l->next)
272      {
273         xcbinf = l->data;
274         if (xcbinf->conn == conn)
275           {
276              xcbinf2 = xcbinf;
277              break;
278           }
279      }
280    xcbinf = calloc(1, sizeof(Xcb_Image_Info));
281    if (!xcbinf) return NULL;
282
283    xcbinf->references = 1;
284    xcbinf->conn = conn;
285    xcbinf->draw = draw;
286    cookie = xcb_get_geometry_unchecked(xcbinf->conn, xcbinf->draw);
287    rep = xcb_get_geometry_reply(xcbinf->conn, cookie, NULL);
288    xcbinf->root = rep->root;
289    free(rep);
290    xcbinf->vis = vis;
291    xcbinf->fmt32 = xcb_render_find_standard_pictforminfo(xcbinf->conn, xcb_render_standard_pictforminfoargb_32_t);
292    xcbinf->fmt24 = xcb_render_find_standard_pictforminfo(xcbinf->conn, xcb_render_standard_pictforminforgb_24_t);
293    xcbinf->fmt8 = xcb_render_find_standard_pictforminfo(xcbinf->conn, xcb_render_standard_pictforminfoa_8_t);
294    xcbinf->fmt4 = xcb_render_find_standard_pictforminfo(xcbinf->conn, xcb_render_standard_pictforminfoa_4_t);
295    xcbinf->fmt1 = xcb_render_find_standard_pictforminfo(xcbinf->conn, xcb_render_standard_pictforminfoa_1_t);
296    xcbinf->mul = _xr_render_surface_new(xcbinf, 1, 1, xcbinf->fmt32, 1);
297    _xr_render_surface_repeat_set(xcbinf->mul, 1);
298    xcbinf->mul_r = xcbinf->mul_g = xcbinf->mul_b = xcbinf->mul_a = 0xff;
299    _xr_render_surface_solid_rectangle_set(xcbinf->mul, xcbinf->mul_r, xcbinf->mul_g, xcbinf->mul_b, xcbinf->mul_a, 0, 0, 1, 1);
300    if (xcbinf2)
301      {
302         xcbinf->can_do_shm = xcbinf2->can_do_shm;
303         xcbinf->depth = xcbinf2->depth;
304      }
305    else
306      {
307        xcb_shm_segment_info_t shm_info;
308        xcb_image_t           *xcbim;
309
310         xcbinf->depth = 32;
311         {
312           xcb_setup_t          *rep;
313           xcb_screen_iterator_t iter_screen;
314
315           rep = (xcb_setup_t *)xcb_get_setup(xcbinf->conn);
316           iter_screen = xcb_setup_roots_iterator(rep);
317           for (; iter_screen.rem ; xcb_screen_next (&iter_screen)) {
318             xcb_depth_iterator_t iter_depth;
319
320             iter_depth = xcb_screen_allowed_depths_iterator (iter_screen.data);
321             for (; iter_depth.rem ; xcb_depth_next (&iter_depth)) {
322               xcb_visualtype_iterator_t iter_visual;
323
324               iter_visual = xcb_depth_visuals_iterator (iter_depth.data);
325               for (; iter_visual.rem ; xcb_visualtype_next (&iter_visual)) {
326                 if (iter_visual.data->visual_id == vis)
327                   xcbinf->depth = iter_depth.data->depth;
328               }
329             }
330           }
331         }
332
333         xcbinf->can_do_shm = 0;
334
335
336         shm_info.shmseg = xcb_generate_id(xcbinf->conn);
337         xcbim = xcb_image_shm_create(xcbinf->conn, xcbinf->depth, XCB_IMAGE_FORMAT_Z_PIXMAP, NULL, 1, 1);
338         if (xcbim) {
339            shm_info.shmid = shmget(IPC_PRIVATE, xcbim->bytes_per_line * xcbim->height, IPC_CREAT | 0777);
340            if (shm_info.shmid >= 0) {
341               shm_info.shmaddr = xcbim->data = shmat(shm_info.shmid, 0, 0);
342               if ((shm_info.shmaddr != NULL) && (shm_info.shmaddr != (void *) -1)) {
343                  xcb_get_input_focus_reply_t *reply;
344                  /*
345                   * FIXME: no error mechanism
346                   */
347                  /* XErrorHandler ph; */
348
349                  /* we sync */
350                  reply = xcb_get_input_focus_reply(xcbinf->conn,
351                                                xcb_get_input_focus_unchecked(xcbinf->conn),
352                                                NULL);
353                  free(reply);
354                  _xcb_err = 0;
355                  /* ph = XSetErrorHandler((XErrorHandler)_tmp_xcb_err); */
356                  xcb_shm_attach(xcbinf->conn, shm_info.shmseg, shm_info.shmid, 0);
357                  /* we sync */
358                  reply = xcb_get_input_focus_reply(xcbinf->conn,
359                                                xcb_get_input_focus_unchecked(xcbinf->conn),
360                                                NULL);
361                  free(reply);
362                  /* XSetErrorHandler((XErrorHandler)ph); */
363                  if (!_xcb_err) xcbinf->can_do_shm = 1;
364                  shmdt(shm_info.shmaddr);
365               }
366               shmctl(shm_info.shmid, IPC_RMID, 0);
367            }
368            xcb_image_shm_destroy(xcbim);
369         }
370      }
371    _image_info_list = evas_list_prepend(_image_info_list, xcbinf);
372    return xcbinf;
373 }
374
375 void
376 _xr_image_info_free(Xcb_Image_Info *xcbinf)
377 {
378   if (!xcbinf) return;
379    if (xcbinf->pool)
380      {
381         xcb_get_input_focus_reply_t *reply;
382        
383         reply = xcb_get_input_focus_reply(xcbinf->conn,
384                                           xcb_get_input_focus_unchecked(xcbinf->conn),
385                                           NULL);
386         free(reply);
387      }
388    _xr_image_info_pool_flush(xcbinf, 0, 0);
389    xcbinf->references--;
390    if (xcbinf->references != 0) return;
391    _xr_render_surface_free(xcbinf->mul);
392    if (xcbinf->fmt1)
393      free(xcbinf->fmt1);
394    if (xcbinf->fmt4)
395      free(xcbinf->fmt4);
396    if (xcbinf->fmt8)
397      free(xcbinf->fmt8);
398    if (xcbinf->fmt24)
399      free(xcbinf->fmt24);
400    if (xcbinf->fmt32)
401      free(xcbinf->fmt32);
402    free(xcbinf);
403    _image_info_list = evas_list_remove(_image_info_list, xcbinf);
404 }
405
406 void
407 _xr_image_info_pool_flush(Xcb_Image_Info *xcbinf, int max_num, int max_mem)
408 {
409    if ((xcbinf->pool_mem <= max_mem) && (evas_list_count(xcbinf->pool) <= max_num)) return;
410    while ((xcbinf->pool_mem > max_mem) || (evas_list_count(xcbinf->pool) > max_num))
411      {
412         Xcb_Image_Image *xcbim;
413
414         if (!xcbinf->pool) break;
415         xcbim = xcbinf->pool->data;
416         _xr_image_free(xcbim);
417      }
418 }
419
420 Xcb_Image_Image *
421 _xr_image_new(Xcb_Image_Info *xcbinf, int w, int h, int depth)
422 {
423    Xcb_Image_Image *xcbim, *xcbim2;
424    Evas_List       *l;
425
426    xcbim2 = NULL;
427    for (l = xcbinf->pool; l; l = l->next)
428      {
429         xcbim = l->data;
430         if ((xcbim->w >= w) && (xcbim->h >= h) && (xcbim->depth == depth) && (xcbim->available))
431           {
432              if (!xcbim2) xcbim2 = xcbim;
433              else if ((xcbim->w * xcbim->h) < (xcbim2->w * xcbim2->h)) xcbim2 = xcbim;
434           }
435      }
436    if (xcbim2)
437      {
438         xcbim2->available = 0;
439         return xcbim2;
440      }
441    xcbim = calloc(1, sizeof(Xcb_Image_Image));
442    if (xcbim)
443      {
444         xcbim->xcbinf = xcbinf;
445         xcbim->w = w;
446         xcbim->h = h;
447         xcbim->depth = depth;
448         xcbim->available = 0;
449         if (xcbim->xcbinf->can_do_shm)
450           {
451              xcbim->shm_info = calloc(1, sizeof(xcb_shm_segment_info_t));
452              if (xcbim->shm_info)
453                {
454                   xcbim->shm_info->shmseg = xcb_generate_id(xcbinf->conn);
455                   xcbim->xcbim = xcb_image_shm_create(xcbim->xcbinf->conn, xcbim->depth, XCB_IMAGE_FORMAT_Z_PIXMAP, NULL, xcbim->w, xcbim->h);
456                   if (xcbim->xcbim)
457                     {
458                        xcbim->shm_info->shmid = shmget(IPC_PRIVATE, xcbim->xcbim->bytes_per_line * xcbim->xcbim->height, IPC_CREAT | 0777);
459                        if (xcbim->shm_info->shmid >= 0)
460                          {
461                             xcbim->shm_info->shmaddr = xcbim->xcbim->data = shmat(xcbim->shm_info->shmid, 0, 0);
462                             if ((xcbim->shm_info->shmaddr) && (xcbim->shm_info->shmaddr != (void *) -1))
463                               {
464                                  xcb_get_input_focus_reply_t *reply;
465                                  /*
466                                   * FIXME: no error mechanism
467                                   */
468                                  /*                              XErrorHandler ph; */
469
470                                  /* we sync */
471                                  reply = xcb_get_input_focus_reply(xcbim->xcbinf->conn,
472                                                                xcb_get_input_focus_unchecked(xcbim->xcbinf->conn),
473                                                                NULL);
474                                  free(reply);
475                                  _xcb_err = 0;
476 /*                               ph = XSetErrorHandler((XErrorHandler)_tmp_xcb_err); */
477                                  xcb_shm_attach(xcbim->xcbinf->conn, xcbim->shm_info->shmseg, xcbim->shm_info->shmid, 0);
478                                  /* we sync */
479                                  reply = xcb_get_input_focus_reply(xcbim->xcbinf->conn,
480                                                                xcb_get_input_focus_unchecked(xcbim->xcbinf->conn),
481                                                                NULL);
482                                  free(reply);
483 /*                               XSetErrorHandler((XErrorHandler)ph); */
484                                  if (!_xcb_err) goto xcbim_ok;
485                                  shmdt(xcbim->shm_info->shmaddr);
486                               }
487                             shmctl(xcbim->shm_info->shmid, IPC_RMID, 0);
488                          }
489                        xcb_image_shm_destroy(xcbim->xcbim);
490                     }
491                   free(xcbim->shm_info);
492                   xcbim->shm_info = NULL;
493                }
494           }
495         xcbim->xcbim = xcb_image_create(xcbim->xcbinf->conn, xcbim->depth, XCB_IMAGE_FORMAT_Z_PIXMAP, 0, NULL, xcbim->w, xcbim->h, 32, 0);
496         if (!xcbim->xcbim)
497           {
498              free(xcbim);
499              return NULL;
500           }
501         xcbim->xcbim->data = malloc(xcbim->xcbim->bytes_per_line * xcbim->xcbim->height);
502         if (!xcbim->xcbim->data)
503           {
504              xcb_image_destroy(xcbim->xcbim);
505              free(xcbim);
506              return NULL;
507           }
508      }
509
510    xcbim_ok:
511    _xr_image_info_pool_flush(xcbinf, 32, (1600 * 1200 * 32 * 2));
512
513    xcbim->line_bytes = xcbim->xcbim->bytes_per_line;
514    xcbim->data = (void *)(xcbim->xcbim->data);
515    xcbinf->pool_mem += (xcbim->w * xcbim->h * xcbim->depth);
516    xcbinf->pool = evas_list_append(xcbinf->pool, xcbim);
517    return xcbim;
518 }
519
520 void
521 _xr_image_free(Xcb_Image_Image *xcbim)
522 {
523    if (xcbim->shm_info)
524      {
525         if (!xcbim->available)
526           {
527             xcb_get_input_focus_reply_t *reply;
528             
529             reply = xcb_get_input_focus_reply(xcbim->xcbinf->conn,
530                                               xcb_get_input_focus_unchecked(xcbim->xcbinf->conn),
531                                               NULL);
532             free(reply);
533           }
534         xcb_shm_detach(xcbim->xcbinf->conn, xcbim->shm_info->shmseg);
535         xcb_image_shm_destroy(xcbim->xcbim);
536         shmdt(xcbim->shm_info->shmaddr);
537         shmctl(xcbim->shm_info->shmid, IPC_RMID, 0);
538         free(xcbim->shm_info);
539      }
540    else
541      {
542         free(xcbim->xcbim->data);
543         xcbim->xcbim->data = NULL;
544         xcb_image_destroy(xcbim->xcbim);
545      }
546    xcbim->xcbinf->pool_mem -= (xcbim->w * xcbim->h * xcbim->depth);
547    xcbim->xcbinf->pool = evas_list_remove(xcbim->xcbinf->pool, xcbim);
548    free(xcbim);
549 }
550
551 void
552 _xr_image_put(Xcb_Image_Image *xcbim, xcb_drawable_t draw, int x, int y, int w, int h)
553 {
554    xcb_get_input_focus_reply_t *reply;
555    xcb_gcontext_t               gc;
556
557    gc = xcb_generate_id(xcbim->xcbinf->conn);
558    xcb_create_gc(xcbim->xcbinf->conn, gc, draw, 0, NULL);
559    if (xcbim->shm_info)
560      {
561         xcb_shm_put_image(xcbim->xcbinf->conn, draw, gc,
562                        xcbim->xcbim->width, xcbim->xcbim->height,
563                        0, 0,
564                        w, h,
565                        x, y,
566                        xcbim->xcbim->depth, xcbim->xcbim->format,
567                        0,
568                        xcbim->shm_info->shmseg,
569                        xcbim->xcbim->data - xcbim->shm_info->shmaddr);
570         /* we sync */
571         reply = xcb_get_input_focus_reply(xcbim->xcbinf->conn,
572                                       xcb_get_input_focus_unchecked(xcbim->xcbinf->conn),
573                                       NULL);
574         free(reply);
575      }
576    else
577      xcb_image_put(xcbim->xcbinf->conn, draw, gc, xcbim->xcbim, 0, 0, x, y, w, h);
578    xcbim->available = 1;
579    xcb_free_gc(xcbim->xcbinf->conn, gc);
580 }