move around - flatter.
[profile/ivi/evas.git] / src / modules / engines / software_xcb / evas_outbuf.c
1 #include "evas_common.h"
2 #include "evas_engine.h"
3 #include "evas_macros.h"
4 #include <xcb/shm.h>
5 #include <xcb/xcb_image.h>
6 #include <pixman.h>
7 #include <sys/time.h>
8 #include <sys/utsname.h>
9
10
11 static Evas_List *shmpool = NULL;
12 static int shmsize = 0;
13 static int shmmemlimit = 10 * 1024 * 1024;
14 static int shmcountlimit = 32;
15
16 static Xcb_Output_Buffer *
17 _find_xcbob(xcb_connection_t *conn, int depth, int w, int h, int shm, void *data)
18 {
19    Evas_List         *l;
20    Evas_List         *xl;
21    Xcb_Output_Buffer *xcbob = NULL;
22    int                fitness = 0x7fffffff;
23    int                sz;
24    int                lbytes;
25    int                bpp;
26
27 //   return evas_software_xcb_x_output_buffer_new(d, v, depth, w, h, shm, data);
28    if (!shm)
29      return evas_software_xcb_x_output_buffer_new(conn, depth, w, h, shm, data);
30    if (depth > 1)
31      {
32         bpp = depth / 8;
33         if (bpp == 3) bpp = 4;
34         lbytes = (((w * bpp) + 3) / 4) * 4;
35      }
36    else
37      lbytes = ((w + 31) / 32) * 4;
38    sz = lbytes * h;
39    for (l = shmpool; l; l = l->next)
40      {
41         Xcb_Output_Buffer *xcbob2;
42         int                szdif;
43
44         xcbob2 = l->data;
45         if ((xcbob2->image->depth != depth) ||
46             (xcbob2->connection != conn))
47           continue;
48         szdif = xcbob2->psize - sz;
49         if (szdif < 0) continue;
50         if (szdif == 0)
51           {
52              xcbob = xcbob2;
53              xl = l;
54              goto have_xcbob;
55           }
56         if (szdif < fitness)
57           {
58              fitness = szdif;
59              xcbob = xcbob2;
60              xl = l;
61           }
62      }
63    if ((fitness > (100 * 100)) || (!xcbob))
64      return evas_software_xcb_x_output_buffer_new(conn, depth, w, h, shm, data);
65
66    have_xcbob:
67    shmpool = evas_list_remove_list(shmpool, xl);
68    xcbob->w = w;
69    xcbob->h = h;
70    xcbob->bpl = lbytes;
71    xcbob->image->width = xcbob->w;
72    xcbob->image->height = xcbob->h;
73    xcbob->image->stride = xcbob->bpl;
74    shmsize -= xcbob->psize * (xcbob->image->depth / 8);
75    return xcbob;
76 }
77
78 static void
79 _unfind_xcbob(Xcb_Output_Buffer *xcbob, int sync)
80 {
81 //   evas_software_xcb_x_output_buffer_free(xcbob, sync); return;
82    if (xcbob->shm_info)
83      {
84         shmpool = evas_list_prepend(shmpool, xcbob);
85         shmsize += xcbob->psize * xcbob->image->depth / 8;
86         while ((shmsize > (shmmemlimit)) ||
87                (evas_list_count(shmpool) > shmcountlimit))
88           {
89              Evas_List *xl;
90
91              xl = evas_list_last(shmpool);
92              if (!xl)
93                {
94                   shmsize = 0;
95                   break;
96                }
97              xcbob = xl->data;
98              shmpool = evas_list_remove_list(shmpool, xl);
99              evas_software_xcb_x_output_buffer_free(xcbob, sync);
100           }
101      }
102    else
103      evas_software_xcb_x_output_buffer_free(xcbob, sync);
104 }
105
106 static void
107 _clear_xcbob(int sync)
108 {
109    while (shmpool)
110      {
111         Xcb_Output_Buffer *xcbob;
112
113         xcbob = shmpool->data;
114         shmpool = evas_list_remove_list(shmpool, shmpool);
115         evas_software_xcb_x_output_buffer_free(xcbob, sync);
116      }
117    shmsize = 0;
118 }
119
120 void
121 evas_software_xcb_outbuf_init(void)
122 {
123 }
124
125 void
126 evas_software_xcb_outbuf_free(Outbuf * buf)
127 {
128    while (buf->priv.pending_writes)
129      {
130         RGBA_Image *im;
131         Outbuf_Region *obr;
132
133         im = buf->priv.pending_writes->data;
134         buf->priv.pending_writes = evas_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
135         obr = im->extended_info;
136         evas_cache_image_drop(&im->cache_entry);
137         if (obr->xcbob) _unfind_xcbob(obr->xcbob, 0);
138         if (obr->mxcbob) _unfind_xcbob(obr->mxcbob, 0);
139         free(obr);
140      }
141    evas_software_xcb_outbuf_idle_flush(buf);
142    evas_software_xcb_outbuf_flush(buf);
143    if (buf->priv.x.gc)
144       xcb_free_gc(buf->priv.x.conn, buf->priv.x.gc);
145    if (buf->priv.x.gcm)
146       xcb_free_gc(buf->priv.x.conn, buf->priv.x.gcm);
147    if (buf->priv.pal)
148      evas_software_xcb_x_color_deallocate(buf->priv.x.conn,
149                                           buf->priv.x.cmap,
150                                           buf->priv.x.vis,
151                                           buf->priv.pal);
152    free(buf);
153    _clear_xcbob(0);
154 }
155
156 void
157 evas_software_xcb_outbuf_rotation_set(Outbuf *buf, int rot)
158 {
159    buf->rot = rot;
160 }
161
162 Outbuf *
163 evas_software_xcb_outbuf_setup_x(int               w,
164                                  int               h,
165                                  int               rot,
166                                  Outbuf_Depth      depth,
167                                  xcb_connection_t *conn,
168                                  xcb_screen_t     *screen,
169                                  xcb_drawable_t    draw,
170                                  xcb_visualtype_t *vis,
171                                  xcb_colormap_t    cmap,
172                                  int               x_depth,
173                                  int               grayscale,
174                                  int               max_colors,
175                                  xcb_drawable_t    mask,
176                                  int               shape_dither,
177                                  int               destination_alpha)
178 {
179    Outbuf *buf;
180
181    buf = calloc(1, sizeof(Outbuf));
182    if (!buf)
183       return NULL;
184
185    buf->w = w;
186    buf->h = h;
187    buf->depth = depth;
188    buf->rot = rot;
189
190    buf->priv.x.conn = conn;
191    buf->priv.x.screen = screen;
192    buf->priv.x.vis = vis;
193    buf->priv.x.cmap = cmap;
194    buf->priv.x.depth = x_depth;
195
196    buf->priv.mask_dither = shape_dither;
197    buf->priv.destination_alpha = destination_alpha;
198
199    {
200       Gfx_Func_Convert    conv_func;
201       Xcb_Output_Buffer  *xcbob;
202
203       buf->priv.x.shm = evas_software_xcb_x_can_do_shm(buf->priv.x.conn, buf->priv.x.screen);
204       xcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn,
205                                                     buf->priv.x.depth,
206                                                     1, 1,
207                                                     buf->priv.x.shm, NULL);
208
209       conv_func = NULL;
210       if (xcbob)
211         {
212 #ifdef WORDS_BIGENDIAN
213            if (evas_software_xcb_x_output_buffer_byte_order(xcbob) == XCB_IMAGE_ORDER_LSB_FIRST)
214              buf->priv.x.swap = 1;
215            if (evas_software_xcb_x_output_buffer_bit_order(xcbob) == XCB_IMAGE_ORDER_MSB_FIRST)
216              buf->priv.x.bit_swap = 1;
217 #else
218            if (evas_software_xcb_x_output_buffer_byte_order(xcbob) == XCB_IMAGE_ORDER_MSB_FIRST)
219              buf->priv.x.swap = 1;
220            if (evas_software_xcb_x_output_buffer_bit_order(xcbob) == XCB_IMAGE_ORDER_MSB_FIRST)
221              buf->priv.x.bit_swap = 1;
222 #endif
223            if (((vis->_class == XCB_VISUAL_CLASS_TRUE_COLOR) ||
224                 (vis->_class == XCB_VISUAL_CLASS_DIRECT_COLOR)) &&
225                (x_depth > 8))
226
227              {
228                 buf->priv.mask.r = (DATA32) vis->red_mask;
229                 buf->priv.mask.g = (DATA32) vis->green_mask;
230                 buf->priv.mask.b = (DATA32) vis->blue_mask;
231                 if (buf->priv.x.swap)
232                   {
233                      SWAP32(buf->priv.mask.r);
234                      SWAP32(buf->priv.mask.g);
235                      SWAP32(buf->priv.mask.b);
236                   }
237              }
238            else if ((vis->_class == XCB_VISUAL_CLASS_STATIC_GRAY)  ||
239                     (vis->_class == XCB_VISUAL_CLASS_GRAY_SCALE)   ||
240                     (vis->_class == XCB_VISUAL_CLASS_STATIC_COLOR) ||
241                     (vis->_class == XCB_VISUAL_CLASS_PSEUDO_COLOR) ||
242                     (x_depth <= 8))
243              {
244                 Convert_Pal_Mode pm = PAL_MODE_RGB332;
245
246                 if ((vis->_class == XCB_VISUAL_CLASS_GRAY_SCALE) ||
247                     (vis->_class == XCB_VISUAL_CLASS_STATIC_GRAY))
248                    grayscale = 1;
249                 if (grayscale)
250                   {
251                      if (max_colors >= 256)
252                         pm = PAL_MODE_GRAY256;
253                      else if (max_colors >= 64)
254                         pm = PAL_MODE_GRAY64;
255                      else if (max_colors >= 16)
256                         pm = PAL_MODE_GRAY16;
257                      else if (max_colors >= 4)
258                         pm = PAL_MODE_GRAY4;
259                      else
260                         pm = PAL_MODE_MONO;
261                   }
262                 else
263                   {
264                      if (max_colors >= 256)
265                         pm = PAL_MODE_RGB332;
266                      else if (max_colors >= 216)
267                         pm = PAL_MODE_RGB666;
268                      else if (max_colors >= 128)
269                         pm = PAL_MODE_RGB232;
270                      else if (max_colors >= 64)
271                         pm = PAL_MODE_RGB222;
272                      else if (max_colors >= 32)
273                         pm = PAL_MODE_RGB221;
274                      else if (max_colors >= 16)
275                         pm = PAL_MODE_RGB121;
276                      else if (max_colors >= 8)
277                         pm = PAL_MODE_RGB111;
278                      else if (max_colors >= 4)
279                         pm = PAL_MODE_GRAY4;
280                      else
281                         pm = PAL_MODE_MONO;
282                   }
283                 /* FIXME: only alloc once per display+cmap */
284                 buf->priv.pal =
285                    evas_software_xcb_x_color_allocate(conn,
286                                                       cmap,
287                                                       vis,
288                                                       PAL_MODE_RGB666);
289                 if (!buf->priv.pal)
290                   {
291                      free(buf);
292                      return NULL;
293                   }
294              }
295            if (buf->priv.pal)
296              {
297                 if (buf->rot == 0 || buf->rot == 180)
298                    conv_func = evas_common_convert_func_get(0,
299                                                             buf->w,
300                                                             buf->h,
301                                                             evas_software_xcb_x_output_buffer_depth (xcbob),
302                                                             buf->priv.mask.r,
303                                                             buf->priv.mask.g,
304                                                             buf->priv.mask.b,
305                                                             buf->priv.pal->colors,
306                                                             buf->rot);
307                 else if (buf->rot == 90 || buf->rot == 270)
308                    conv_func = evas_common_convert_func_get(0,
309                                                             buf->h,
310                                                             buf->w,
311                                                             evas_software_xcb_x_output_buffer_depth (xcbob),
312                                                             buf->priv.mask.r,
313                                                             buf->priv.mask.g,
314                                                             buf->priv.mask.b,
315                                                             buf->priv.pal->colors,
316                                                             buf->rot);
317              }
318            else
319              {
320                 if (buf->rot == 0 || buf->rot == 180)
321                    conv_func = evas_common_convert_func_get(0,
322                                                             buf->w,
323                                                             buf->h,
324                                                             evas_software_xcb_x_output_buffer_depth(xcbob),
325                                                             buf->priv.mask.r,
326                                                             buf->priv.mask.g,
327                                                             buf->priv.mask.b,
328                                                             PAL_MODE_NONE,
329                                                             buf->rot);
330                 else if (buf->rot == 90 || buf->rot == 270)
331                    conv_func = evas_common_convert_func_get(0,
332                                                             buf->h,
333                                                             buf->w,
334                                                             evas_software_xcb_x_output_buffer_depth(xcbob),
335                                                             buf->priv.mask.r,
336                                                             buf->priv.mask.g,
337                                                             buf->priv.mask.b,
338                                                             PAL_MODE_NONE,
339                                                             buf->rot);
340              }
341            evas_software_xcb_x_output_buffer_free(xcbob, 1);
342            if (!conv_func)
343              {
344                 printf(".[ Evas Error ].\n"
345                        " {\n"
346                        "  At depth         %i:\n"
347                        "  RGB format mask: %08x, %08x, %08x\n"
348                        "  Palette mode:    %i\n"
349                        "  Not supported by and compiled in converters!\n"
350                        " }\n",
351                        buf->priv.x.depth,
352                        buf->priv.mask.r,
353                        buf->priv.mask.g,
354                        buf->priv.mask.b,
355                        buf->priv.pal->colors);
356              }
357         }
358       evas_software_xcb_outbuf_drawable_set(buf, draw);
359       evas_software_xcb_outbuf_mask_set(buf, mask);
360    }
361
362    return buf;
363 }
364
365 RGBA_Image *
366 evas_software_xcb_outbuf_new_region_for_update(Outbuf *buf,
367                                                int     x,
368                                                int     y,
369                                                int     w,
370                                                int     h,
371                                                int    *cx,
372                                                int    *cy,
373                                                int    *cw,
374                                                int    *ch)
375 {
376    RGBA_Image    *im;
377    Outbuf_Region *obr;
378    int            bpl = 0;
379    int            use_shm = 1;
380    int                 alpha;
381
382    if ((buf->onebuf) && (buf->priv.x.shm))
383      {
384         Evas_Rectangle *rect;
385
386         rect = malloc(sizeof(Evas_Rectangle));
387         RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, buf->w, buf->h);
388         rect->x = x;
389         rect->y = y;
390         rect->w = w;
391         rect->h = h;
392         buf->priv.onebuf_regions = evas_list_append(buf->priv.onebuf_regions, rect);
393         if (buf->priv.onebuf)
394           {
395              *cx = x;
396              *cy = y;
397              *cw = w;
398              *ch = h;
399              if (!buf->priv.synced)
400                {
401                   /* we sync */
402                   free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
403                   buf->priv.synced = 1;
404                }
405              if ((buf->priv.x.mask) || (buf->priv.destination_alpha))
406                {
407                   int yy;
408
409                   im = buf->priv.onebuf;
410                   for (yy = y; yy < (y + h); yy++)
411                     {
412                        memset(im->image.data + (im->cache_entry.w * yy) + x,
413                               0, w * sizeof(DATA32));
414                     }
415                }
416              return buf->priv.onebuf;
417           }
418         obr = calloc(1, sizeof(Outbuf_Region));
419         obr->x = 0;
420         obr->y = 0;
421         obr->w = buf->w;
422         obr->h = buf->h;
423         *cx = x;
424         *cy = y;
425         *cw = w;
426         *ch = h;
427
428         alpha = ((buf->priv.x.mask) || (buf->priv.destination_alpha));
429
430         use_shm = buf->priv.x.shm;
431         if ((buf->rot == 0) &&
432             (buf->priv.mask.r == 0xff0000) &&
433             (buf->priv.mask.g == 0x00ff00) &&
434             (buf->priv.mask.b == 0x0000ff))
435           {
436              obr->xcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn,
437                                                                 buf->priv.x.depth,
438                                                                 buf->w, buf->h,
439                                                                 use_shm,
440                                                                 NULL);
441              im = (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
442                                                        buf->w, buf->h,
443                                                        (DATA32 *) evas_software_xcb_x_output_buffer_data(obr->xcbob, &bpl),
444                                                        alpha, EVAS_COLORSPACE_ARGB8888);
445              im->extended_info = obr;
446              if (buf->priv.x.mask)
447                obr->mxcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn,
448                                                                    1,
449                                                                    buf->w, buf->h,
450                                                                    use_shm,
451                                                                    NULL);
452           }
453         else
454           {
455              im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
456              im->cache_entry.flags.alpha |= alpha ? 1 : 0;
457              evas_cache_image_surface_alloc(&im->cache_entry, buf->w, buf->h);
458              im->extended_info = obr;
459              if ((buf->rot == 0) || (buf->rot == 180))
460                obr->xcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn,
461                                                                   buf->priv.x.depth,
462                                                                   buf->w, buf->h,
463                                                                   use_shm,
464                                                                   NULL);
465              else if ((buf->rot == 90) || (buf->rot == 270))
466                obr->xcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn,
467                                                                   buf->priv.x.depth,
468                                                                   buf->h, buf->w,
469                                                                   use_shm,
470                                                                   NULL);
471              if (buf->priv.x.mask)
472                obr->mxcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn,
473                                                                    1, buf->w, buf->h,
474                                                                    use_shm,
475                                                                    NULL);
476           }
477         if (alpha)
478           /* FIXME: faster memset! */
479           memset(im->image.data, 0, w * h * sizeof(DATA32));
480
481         buf->priv.onebuf = im;
482         return im;
483      }
484
485
486    obr = calloc(1, sizeof(Outbuf_Region));
487    obr->x = x;
488    obr->y = y;
489    obr->w = w;
490    obr->h = h;
491    *cx = 0;
492    *cy = 0;
493    *cw = w;
494    *ch = h;
495
496    use_shm = buf->priv.x.shm;
497    /* FIXME: magic - i found if shm regions are smaller than 200x200 its
498     * faster to use ximages over unix sockets - trial and error
499     */
500 //   use_shm = 0; /* 630 -> 1006 fps */
501 //   if ((w * h) < (200 * 200)) use_shm = 0; /* 630 -> 962 fps */
502
503    alpha = ((buf->priv.x.mask) || (buf->priv.destination_alpha));
504
505    if ((buf->rot == 0) &&
506        (buf->priv.mask.r == 0xff0000) &&
507        (buf->priv.mask.g == 0x00ff00) &&
508        (buf->priv.mask.b == 0x0000ff))
509      {
510         obr->xcbob = _find_xcbob(buf->priv.x.conn,
511                                  buf->priv.x.depth,
512                                  w, h,
513                                  use_shm,
514                                  NULL);
515         im = (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
516                                                   w, h,
517                                                   (DATA32 *) evas_software_xcb_x_output_buffer_data(obr->xcbob, &bpl),
518                                                   alpha, EVAS_COLORSPACE_ARGB8888);
519         im->extended_info = obr;
520         if (buf->priv.x.mask)
521           obr->mxcbob = _find_xcbob(buf->priv.x.conn,
522                                     1, w, h,
523                                     use_shm,
524                                     NULL);
525 /*        obr->mxcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn, */
526 /*                                                            1, */
527 /*                                                            w, */
528 /*                                                            h, */
529 /*                                                            use_shm, */
530 /*                                                            NULL); */
531      }
532    else
533      {
534         im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
535         im->cache_entry.flags.alpha |= alpha ? 1 : 0;
536         evas_cache_image_surface_alloc(&im->cache_entry, w, h);
537         im->extended_info = obr;
538         if ((buf->rot == 0) || (buf->rot == 180))
539           obr->xcbob = _find_xcbob(buf->priv.x.conn,
540                                    buf->priv.x.depth,
541                                    w, h,
542                                    use_shm,
543                                    NULL);
544 /*         obr->xcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn, */
545 /*                                                            buf->priv.x.depth, */
546 /*                                                            w, */
547 /*                                                            h, */
548 /*                                                            use_shm, */
549 /*                                                            NULL); */
550         else if ((buf->rot == 90) || (buf->rot == 270))
551           obr->xcbob = _find_xcbob(buf->priv.x.conn,
552                                    buf->priv.x.depth,
553                                    h, w,
554                                    use_shm,
555                                    NULL);
556 /*        obr->xcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn, */
557 /*                                                           buf->priv.x.depth, */
558 /*                                                           h, */
559 /*                                                           w, */
560 /*                                                           use_shm, */
561 /*                                                           NULL); */
562         if (buf->priv.x.mask)
563           obr->mxcbob = _find_xcbob(buf->priv.x.conn,
564                                     1, w, h,
565                                     use_shm,
566                                     NULL);
567 /*        obr->mxcbob = evas_software_xcb_x_output_buffer_new(buf->priv.x.conn, */
568 /*                                                            1, */
569 /*                                                            w, */
570 /*                                                            h, */
571 /*                                                            use_shm, */
572 /*                                                            NULL); */
573      }
574    if ((buf->priv.x.mask) || (buf->priv.destination_alpha))
575         /* FIXME: faster memset! */
576      memset(im->image.data, 0, w * h * sizeof(DATA32));
577
578    buf->priv.pending_writes = evas_list_append(buf->priv.pending_writes, im);
579    return im;
580 }
581
582 void
583 evas_software_xcb_outbuf_free_region_for_update(Outbuf     *buf,
584                                                 RGBA_Image *update)
585 {
586    /* no need to do anything - they are cleaned up on flush */
587 }
588
589 void
590 evas_software_xcb_outbuf_flush(Outbuf *buf)
591 {
592    Evas_List           *l;
593
594    if ((buf->priv.onebuf) && (buf->priv.onebuf_regions))
595      {
596         RGBA_Image *im;
597         Outbuf_Region *obr;
598         pixman_region16_t tmpr;
599
600         im = buf->priv.onebuf;
601         obr = im->extended_info;
602         pixman_region_init(&tmpr);
603         while (buf->priv.onebuf_regions)
604           {
605              Evas_Rectangle *rect;
606
607              rect = buf->priv.onebuf_regions->data;
608              buf->priv.onebuf_regions = evas_list_remove_list(buf->priv.onebuf_regions, buf->priv.onebuf_regions);
609              pixman_region_union_rect(&tmpr, &tmpr,
610                                       rect->x, rect->y,
611                                       rect->w, rect->h);
612              if (buf->priv.debug)
613                evas_software_xcb_outbuf_debug_show(buf, buf->priv.x.win,
614                                                    rect->x, rect->y, rect->w, rect->h);
615              free(rect);
616           }
617         xcb_set_clip_rectangles(buf->priv.x.conn, XCB_CLIP_ORDERING_YX_BANDED,
618                                 buf->priv.x.gc,
619                                 0, 0, pixman_region_n_rects(&tmpr),
620                                 (const xcb_rectangle_t *)pixman_region_rectangles(&tmpr, NULL));
621         evas_software_xcb_x_output_buffer_paste(obr->xcbob, buf->priv.x.win,
622                                                 buf->priv.x.gc,
623                                                 0, 0, 0);
624         if (obr->mxcbob)
625           {
626              xcb_set_clip_rectangles(buf->priv.x.conn, XCB_CLIP_ORDERING_YX_BANDED,
627                                      buf->priv.x.gcm,
628                                      0, 0, pixman_region_n_rects(&tmpr),
629                                      (const xcb_rectangle_t *)pixman_region_rectangles(&tmpr, NULL));
630              evas_software_xcb_x_output_buffer_paste(obr->mxcbob,
631                                                      buf->priv.x.mask,
632                                                      buf->priv.x.gcm,
633                                                      0, 0, 0);
634           }
635         buf->priv.synced = 0;
636      }
637    else
638      {
639 #if 1
640         /* we sync */
641         free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
642         for (l = buf->priv.pending_writes; l; l = l->next)
643           {
644              RGBA_Image *im;
645              Outbuf_Region      *obr;
646
647              im = l->data;
648              obr = im->extended_info;
649              if (buf->priv.debug)
650                evas_software_xcb_outbuf_debug_show(buf,
651                                                    buf->priv.x.win,
652                                                    obr->x,
653                                                    obr->y,
654                                                    obr->w,
655                                                    obr->h);
656              evas_software_xcb_x_output_buffer_paste(obr->xcbob,
657                                                      buf->priv.x.win,
658                                                      buf->priv.x.gc,
659                                                      obr->x,
660                                                      obr->y, 0);
661              if (obr->mxcbob)
662                evas_software_xcb_x_output_buffer_paste(obr->mxcbob,
663                                                        buf->priv.x.mask,
664                                                        buf->priv.x.gcm,
665                                                        obr->x,
666                                                        obr->y, 0);
667           }
668         while (buf->priv.pending_writes)
669           {
670              RGBA_Image    *im;
671              Outbuf_Region *obr;
672
673              im = buf->priv.pending_writes->data;
674              buf->priv.pending_writes = evas_list_remove_list(buf->priv.pending_writes,
675                                                               buf->priv.pending_writes);
676              obr = im->extended_info;
677              evas_cache_image_drop(&im->cache_entry);
678              if (obr->xcbob) _unfind_xcbob(obr->xcbob, 0);
679              if (obr->mxcbob) _unfind_xcbob(obr->mxcbob, 0);
680 /*              if (obr->xcbob) evas_software_xcb_x_output_buffer_free(obr->xcbob, 0); */
681 /*              if (obr->mxcbob) evas_software_xcb_x_output_buffer_free(obr->mxcbob, 0); */
682              free(obr);
683           }
684         buf->priv.prev_pending_writes = buf->priv.pending_writes;
685         buf->priv.pending_writes = NULL;
686         xcb_flush(buf->priv.x.conn);
687 #else
688         /* XX async push - disable */
689         /*
690         for (l = buf->priv.pending_writes; l; l = l->next)
691           {
692              RGBA_Image *im;
693              Outbuf_Region *obr;
694
695              im = l->data;
696              obr = im->extended_info;
697              if (buf->priv.debug)
698                evas_software_x11_outbuf_debug_show(buf, buf->priv.x.win,
699                                                    obr->x, obr->y, obr->w, obr->h);
700              evas_software_x11_x_output_buffer_paste(obr->xcbob, buf->priv.x.win,
701                                                      buf->priv.x.gc,
702                                                      obr->x, obr->y, 0);
703              if (obr->mxcbob)
704                evas_software_x11_x_output_buffer_paste(obr->mxcbob,
705                                                        buf->priv.x.mask,
706                                                        buf->priv.x.gcm,
707                                                        obr->x, obr->y, 0);
708           }
709          */
710         /* we sync */
711         free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
712
713         while (buf->priv.pending_writes)
714           {
715              RGBA_Image *im;
716              Outbuf_Region *obr;
717
718              im = evas_list_data(buf->priv.pending_writes);
719              buf->priv.pending_writes = evas_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
720              obr = im->extended_info;
721              evas_cache_image_drop(&im->cache_entry);
722              if (obr->xcbob) _unfind_xcbob(obr->xcbob, 0);
723              if (obr->mxcbob) _unfind_xcbob(obr->mxcbob, 0);
724 /*
725              if (obr->xcbob) evas_software_x11_x_output_buffer_free(obr->xcbob, 0);
726              if (obr->mxcbob) evas_software_x11_x_output_buffer_free(obr->mxcbob, 0);
727  */
728              free(obr);
729              evas_cache_image_drop(&im->cache_entry);
730           }
731 #endif
732      }
733    evas_common_cpu_end_opt();
734 }
735
736 void
737 evas_software_xcb_outbuf_idle_flush(Outbuf *buf)
738 {
739    if (buf->priv.onebuf)
740      {
741         RGBA_Image *im;
742         Outbuf_Region *obr;
743
744         im = buf->priv.onebuf;
745         buf->priv.onebuf = NULL;
746         obr = im->extended_info;
747         if (obr->xcbob) evas_software_xcb_x_output_buffer_free(obr->xcbob, 0);
748         if (obr->mxcbob) evas_software_xcb_x_output_buffer_free(obr->mxcbob, 0);
749         free(obr);
750         evas_cache_image_drop(&im->cache_entry);
751      }
752    else
753      {
754         if (buf->priv.prev_pending_writes)
755           free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
756         while (buf->priv.prev_pending_writes)
757           {
758              RGBA_Image *im;
759              Outbuf_Region *obr;
760
761              im = buf->priv.prev_pending_writes->data;
762              buf->priv.prev_pending_writes =
763                evas_list_remove_list(buf->priv.prev_pending_writes,
764                                      buf->priv.prev_pending_writes);
765              obr = im->extended_info;
766              evas_cache_image_drop(&im->cache_entry);
767              if (obr->xcbob) _unfind_xcbob(obr->xcbob, 0);
768              if (obr->mxcbob) _unfind_xcbob(obr->mxcbob, 0);
769              free(obr);
770           }
771         _clear_xcbob(0);
772      }
773 }
774
775 void
776 evas_software_xcb_outbuf_push_updated_region(Outbuf     *buf,
777                                              RGBA_Image *update,
778                                              int         x,
779                                              int         y,
780                                              int         w,
781                                              int         h)
782 {
783    Gfx_Func_Convert conv_func = NULL;
784    Outbuf_Region   *obr;
785    DATA32          *src_data;
786    void            *data;
787    int              bpl = 0;
788    int              yy;
789
790    obr = update->extended_info;
791    if (buf->priv.pal)
792      {
793         if ((buf->rot == 0) || (buf->rot == 180))
794           conv_func = evas_common_convert_func_get(0, w, h,
795                                                    evas_software_xcb_x_output_buffer_depth
796                                                    (obr->xcbob), buf->priv.mask.r,
797                                                    buf->priv.mask.g, buf->priv.mask.b,
798                                                    buf->priv.pal->colors, buf->rot);
799         else if ((buf->rot == 90) || (buf->rot == 270))
800           conv_func = evas_common_convert_func_get(0, h, w,
801                                                    evas_software_xcb_x_output_buffer_depth
802                                                    (obr->xcbob), buf->priv.mask.r,
803                                                    buf->priv.mask.g, buf->priv.mask.b,
804                                                    buf->priv.pal->colors, buf->rot);
805      }
806    else
807      {
808         if ((buf->rot == 0) || (buf->rot == 180))
809           conv_func = evas_common_convert_func_get(0, w, h,
810                                                    evas_software_xcb_x_output_buffer_depth
811                                                    (obr->xcbob), buf->priv.mask.r,
812                                                    buf->priv.mask.g, buf->priv.mask.b,
813                                                    PAL_MODE_NONE, buf->rot);
814         else if ((buf->rot == 90) || (buf->rot == 270))
815           conv_func = evas_common_convert_func_get(0, h, w,
816                                                    evas_software_xcb_x_output_buffer_depth
817                                                    (obr->xcbob), buf->priv.mask.r,
818                                                    buf->priv.mask.g, buf->priv.mask.b,
819                                                    PAL_MODE_NONE, buf->rot);
820      }
821    if (!conv_func) return;
822
823    data = evas_software_xcb_x_output_buffer_data(obr->xcbob, &bpl);
824    src_data = update->image.data;
825    if (buf->rot == 0)
826      {
827         obr->x = x;
828         obr->y = y;
829      }
830    else if (buf->rot == 90)
831      {
832         obr->x = y;
833         obr->y = buf->w - x - w;
834      }
835    else if (buf->rot == 180)
836      {
837         obr->x = buf->w - x - w;
838         obr->y = buf->h - y - h;
839      }
840    else if (buf->rot == 270)
841      {
842         obr->x = buf->h - y - h;
843         obr->y = x;
844      }
845    if ((buf->rot == 0) || (buf->rot == 180))
846      {
847         obr->w = w;
848         obr->h = h;
849      }
850    else if ((buf->rot == 90) || (buf->rot == 270))
851      {
852         obr->w = h;
853         obr->h = w;
854      }
855    if (buf->priv.pal)
856      {
857         if (data != src_data)
858           conv_func(src_data, data,
859                     0,
860                     bpl /
861                     ((evas_software_xcb_x_output_buffer_depth(obr->xcbob) / 8)) - obr->w,
862                     obr->w, obr->h, x, y,
863                     buf->priv.pal->lookup);
864      }
865    else
866      {
867         if (data != src_data)
868           conv_func(src_data, data,
869                     0,
870                     bpl /
871                     ((evas_software_xcb_x_output_buffer_depth(obr->xcbob) / 8)) - obr->w,
872                     obr->w, obr->h, x, y, NULL);
873      }
874 #if 1
875 #else
876    /* XX async push */
877    if (!((buf->priv.onebuf) && (buf->priv.onebuf_regions)))
878      {
879         if (buf->priv.debug)
880           evas_software_xcb_outbuf_debug_show(buf, buf->priv.x.win,
881                                               obr->x, obr->y, obr->w, obr->h);
882         evas_software_xcb_x_output_buffer_paste(obr->xcbob, buf->priv.x.win,
883                                                 buf->priv.x.gc,
884                                                 obr->x, obr->y, 0);
885      }
886 #endif
887    if (obr->mxcbob)
888      {
889         for (yy = 0; yy < obr->h; yy++)
890           evas_software_xcb_x_write_mask_line(buf, obr->mxcbob,
891                                               src_data + (yy * obr->w),
892                                               obr->w,
893                                               yy);
894 #if 1
895 #else
896         /* XX async push */
897         if (!((buf->priv.onebuf) && (buf->priv.onebuf_regions)))
898           evas_software_xcb_x_output_buffer_paste(obr->mxcbob,
899                                                   buf->priv.x.mask,
900                                                   buf->priv.x.gcm,
901                                                   obr->x, obr->y, 0);
902 #endif
903      }
904 #if 1
905 #else
906    xcb_flush(buf->priv.x.conn);
907 #endif
908 }
909
910 void
911 evas_software_xcb_outbuf_reconfigure(Outbuf      *buf,
912                                      int          w,
913                                      int          h,
914                                      int          rot,
915                                      Outbuf_Depth depth)
916 {
917    if ((w == buf->w) &&
918        (h == buf->h) &&
919        (rot == buf->rot) &&
920        (depth == buf->depth)) return;
921    buf->w = w;
922    buf->h = h;
923    buf->rot = rot;
924    evas_software_xcb_outbuf_idle_flush(buf);
925 }
926
927 int
928 evas_software_xcb_outbuf_get_width(Outbuf * buf)
929 {
930    return buf->w;
931 }
932
933 int
934 evas_software_xcb_outbuf_get_height(Outbuf * buf)
935 {
936    return buf->h;
937 }
938
939 Outbuf_Depth
940 evas_software_xcb_outbuf_get_depth(Outbuf * buf)
941 {
942    return buf->depth;
943 }
944
945 int
946 evas_software_xcb_outbuf_get_rot(Outbuf * buf)
947 {
948    return buf->rot;
949 }
950
951 void
952 evas_software_xcb_outbuf_drawable_set(Outbuf        *buf,
953                                       xcb_drawable_t draw)
954 {
955    if (buf->priv.x.win == draw) return;
956    if (buf->priv.x.gc)
957      {
958         xcb_free_gc(buf->priv.x.conn, buf->priv.x.gc);
959         buf->priv.x.gc = 0;
960      }
961    buf->priv.x.win = draw;
962    buf->priv.x.gc = xcb_generate_id(buf->priv.x.conn);
963    xcb_create_gc(buf->priv.x.conn, buf->priv.x.gc, buf->priv.x.win, 0, NULL);
964 }
965
966 void
967 evas_software_xcb_outbuf_mask_set(Outbuf        *buf,
968                                   xcb_drawable_t mask)
969 {
970    if (buf->priv.x.mask == mask) return;
971    if (buf->priv.x.gcm)
972      {
973         xcb_free_gc(buf->priv.x.conn, buf->priv.x.gcm);
974         buf->priv.x.gcm = 0;
975      }
976    buf->priv.x.mask = mask;
977    if (buf->priv.x.mask)
978       {
979          buf->priv.x.gcm = xcb_generate_id(buf->priv.x.conn);
980          xcb_create_gc(buf->priv.x.conn, buf->priv.x.gcm, buf->priv.x.win, 0, NULL);
981       }
982 }
983
984 void
985 evas_software_xcb_outbuf_debug_set(Outbuf *buf,
986                                    int     debug)
987 {
988    buf->priv.debug = debug;
989 }
990 void
991 evas_software_xcb_outbuf_debug_show(Outbuf        *buf,
992                                     xcb_drawable_t draw,
993                                     int            x,
994                                     int            y,
995                                     int            w,
996                                     int            h)
997 {
998    int                          i;
999    xcb_screen_t                *screen = NULL;
1000
1001    {
1002       xcb_get_geometry_reply_t *geom;
1003       xcb_drawable_t            root;
1004       xcb_screen_iterator_t     i;
1005
1006       geom = xcb_get_geometry_reply (buf->priv.x.conn, xcb_get_geometry_unchecked(buf->priv.x.conn, draw), 0);
1007       root = geom->root;
1008       free (geom);
1009       geom = xcb_get_geometry_reply (buf->priv.x.conn, xcb_get_geometry_unchecked(buf->priv.x.conn, root), 0);
1010
1011       i = xcb_setup_roots_iterator((xcb_setup_t *)xcb_get_setup(buf->priv.x.conn));
1012       for (; i.rem; xcb_screen_next(&i))
1013          if (i.data->root == geom->root)
1014             {
1015                screen = i.data;
1016                break;
1017             }
1018       free (geom);
1019    }
1020    for (i = 0; i < 20; i++)
1021      {
1022 /*      xcb_image_t    *image; */
1023         xcb_rectangle_t rect = { x, y, w, h};
1024         uint32_t        mask;
1025         uint32_t        value[2];
1026
1027         mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
1028         value[0] = screen->black_pixel;
1029         value[1] = XCB_EXPOSURES_NOT_ALLOWED; /* no graphics exposures allowed */
1030         xcb_change_gc(buf->priv.x.conn, buf->priv.x.gc, mask, value);
1031         xcb_poly_fill_rectangle (buf->priv.x.conn, draw, buf->priv.x.gc, 1, &rect);
1032         /* we sync */
1033         free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
1034 //      image = xcb_image_get(buf->priv.x.conn, draw, x, y, w, h, XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP);
1035 //      if (image)
1036 //         xcb_image_destroy(image);
1037         /* we sync */
1038         free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
1039         mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
1040         value[0] = screen->white_pixel;
1041         value[1] = XCB_EXPOSURES_NOT_ALLOWED; /* no graphics exposures allowed */
1042         xcb_change_gc(buf->priv.x.conn, buf->priv.x.gc, mask, value);
1043         xcb_poly_fill_rectangle (buf->priv.x.conn, draw, buf->priv.x.gc, 1, &rect);
1044         /* we sync */
1045         free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
1046 //      image = xcb_image_get(buf->priv.x.conn, draw, x, y, w, h, XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP);
1047 //      if (image)
1048 //         xcb_image_destroy(image);
1049         /* we sync */
1050         free(xcb_get_input_focus_reply(buf->priv.x.conn, xcb_get_input_focus_unchecked(buf->priv.x.conn), NULL));
1051      }
1052 }