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