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