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