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