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