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
11 #include "evas_xlib_swapbuf.h"
12 #include "evas_xlib_color.h"
13 #include "evas_xlib_swapper.h"
14
15 typedef struct _Outbuf_Region Outbuf_Region;
16
17 struct _Outbuf_Region
18 {
19 RGBA_Image *im;
20 int x;
21 int y;
22 int w;
23 int h;
24 };
25
26 void
evas_software_xlib_swapbuf_init(void)27 evas_software_xlib_swapbuf_init(void)
28 {
29 }
30
31 void
evas_software_xlib_swapbuf_free(Outbuf * buf)32 evas_software_xlib_swapbuf_free(Outbuf *buf)
33 {
34 evas_software_xlib_swapbuf_flush(buf, NULL, NULL, EVAS_RENDER_MODE_UNDEF);
35 evas_software_xlib_swapbuf_idle_flush(buf);
36 if (buf->priv.pal)
37 evas_software_xlib_x_color_deallocate
38 (buf->priv.x11.xlib.disp, buf->priv.x11.xlib.cmap,
39 buf->priv.x11.xlib.vis, buf->priv.pal);
40 evas_xlib_swapper_free(buf->priv.swapper);
41 eina_array_flush(&buf->priv.onebuf_regions);
42 free(buf);
43 }
44
45 Outbuf *
evas_software_xlib_swapbuf_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 EINA_UNUSED,int shape_dither,int destination_alpha)46 evas_software_xlib_swapbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
47 Display *disp, Drawable draw, Visual *vis,
48 Colormap cmap, int x_depth,
49 int grayscale, int max_colors,
50 Pixmap mask EINA_UNUSED,
51 int shape_dither, int destination_alpha)
52 {
53 Outbuf *buf;
54 Gfx_Func_Convert conv_func = NULL;
55 int d;
56
57 buf = calloc(1, sizeof(Outbuf));
58 if (!buf) return NULL;
59
60 if (x_depth < 15) rot = 0;
61
62 buf->onebuf = 1;
63 buf->w = w;
64 buf->h = h;
65 buf->depth = depth;
66 buf->rot = rot;
67 buf->priv.x11.xlib.disp = disp;
68 buf->priv.x11.xlib.win = draw;
69 buf->priv.x11.xlib.vis = vis;
70 buf->priv.x11.xlib.cmap = cmap;
71 buf->priv.x11.xlib.depth = x_depth;
72 buf->priv.mask_dither = shape_dither;
73 buf->priv.destination_alpha = destination_alpha;
74
75 if ((buf->rot == 0) || (buf->rot == 180))
76 buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
77 buf->priv.x11.xlib.win,
78 buf->priv.x11.xlib.vis,
79 buf->priv.x11.xlib.depth,
80 buf->w, buf->h);
81 else if ((buf->rot == 90) || (buf->rot == 270))
82 buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
83 buf->priv.x11.xlib.win,
84 buf->priv.x11.xlib.vis,
85 buf->priv.x11.xlib.depth,
86 buf->h, buf->w);
87 if (!buf->priv.swapper)
88 {
89 free(buf);
90 return NULL;
91 }
92
93 eina_array_step_set(&buf->priv.onebuf_regions, sizeof (Eina_Array), 8);
94
95 #ifdef WORDS_BIGENDIAN
96 if (evas_xlib_swapper_byte_order_get(buf->priv.swapper) == LSBFirst)
97 buf->priv.x11.xlib.swap = 1;
98 if (evas_xlib_swapper_bit_order_get(buf->priv.swapper) == MSBFirst)
99 buf->priv.x11.xlib.bit_swap = 1;
100 #else
101 if (evas_xlib_swapper_byte_order_get(buf->priv.swapper) == MSBFirst)
102 buf->priv.x11.xlib.swap = 1;
103 if (evas_xlib_swapper_bit_order_get(buf->priv.swapper) == MSBFirst)
104 buf->priv.x11.xlib.bit_swap = 1;
105 #endif
106 if (((vis->class == TrueColor) || (vis->class == DirectColor)) &&
107 (x_depth > 8))
108 {
109 buf->priv.mask.r = (DATA32)vis->red_mask;
110 buf->priv.mask.g = (DATA32)vis->green_mask;
111 buf->priv.mask.b = (DATA32)vis->blue_mask;
112 if (buf->priv.x11.xlib.swap)
113 {
114 SWAP32(buf->priv.mask.r);
115 SWAP32(buf->priv.mask.g);
116 SWAP32(buf->priv.mask.b);
117 }
118 }
119 else if ((vis->class == PseudoColor) || (vis->class == StaticColor) ||
120 (vis->class == GrayScale) || (vis->class == StaticGray) ||
121 (x_depth <= 8))
122 {
123 Convert_Pal_Mode pm = PAL_MODE_RGB332;
124
125 if ((vis->class == GrayScale) || (vis->class == StaticGray))
126 grayscale = 1;
127 if (grayscale)
128 {
129 if (max_colors >= 256) pm = PAL_MODE_GRAY256;
130 else if (max_colors >= 64)
131 pm = PAL_MODE_GRAY64;
132 else if (max_colors >= 16)
133 pm = PAL_MODE_GRAY16;
134 else if (max_colors >= 4)
135 pm = PAL_MODE_GRAY4;
136 else pm = PAL_MODE_MONO;
137 }
138 else
139 {
140 if (max_colors >= 256) pm = PAL_MODE_RGB332;
141 else if (max_colors >= 216)
142 pm = PAL_MODE_RGB666;
143 else if (max_colors >= 128)
144 pm = PAL_MODE_RGB232;
145 else if (max_colors >= 64)
146 pm = PAL_MODE_RGB222;
147 else if (max_colors >= 32)
148 pm = PAL_MODE_RGB221;
149 else if (max_colors >= 16)
150 pm = PAL_MODE_RGB121;
151 else if (max_colors >= 8)
152 pm = PAL_MODE_RGB111;
153 else if (max_colors >= 4)
154 pm = PAL_MODE_GRAY4;
155 else pm = PAL_MODE_MONO;
156 }
157 /* FIXME: only alloc once per display+cmap */
158 buf->priv.pal = evas_software_xlib_x_color_allocate
159 (disp, cmap, vis, pm);
160 if (!buf->priv.pal)
161 {
162 evas_xlib_swapper_free(buf->priv.swapper);
163 free(buf);
164 return NULL;
165 }
166 }
167 d = evas_xlib_swapper_depth_get(buf->priv.swapper);
168 if (buf->priv.pal)
169 {
170 if (buf->rot == 0 || buf->rot == 180)
171 conv_func = evas_common_convert_func_get(0, buf->w, buf->h, d,
172 buf->priv.mask.r,
173 buf->priv.mask.g,
174 buf->priv.mask.b,
175 buf->priv.pal->colors,
176 buf->rot);
177 else if (buf->rot == 90 || buf->rot == 270)
178 conv_func = evas_common_convert_func_get(0, buf->h, buf->w, d,
179 buf->priv.mask.r,
180 buf->priv.mask.g,
181 buf->priv.mask.b,
182 buf->priv.pal->colors,
183 buf->rot);
184 }
185 else
186 {
187 if (buf->rot == 0 || buf->rot == 180)
188 conv_func = evas_common_convert_func_get(0, buf->w, buf->h, d,
189 buf->priv.mask.r,
190 buf->priv.mask.g,
191 buf->priv.mask.b,
192 PAL_MODE_NONE,
193 buf->rot);
194 else if (buf->rot == 90 || buf->rot == 270)
195 conv_func = evas_common_convert_func_get(0, buf->h, buf->w, d,
196 buf->priv.mask.r,
197 buf->priv.mask.g,
198 buf->priv.mask.b,
199 PAL_MODE_NONE,
200 buf->rot);
201 }
202 if (!conv_func)
203 {
204 ERR("At depth: %i, RGB format mask: %08x %08x %08x, "
205 "Palette mode: %i. "
206 "Not supported by compiled in converters!",
207 buf->priv.x11.xlib.depth,
208 buf->priv.mask.r,
209 buf->priv.mask.g,
210 buf->priv.mask.b,
211 buf->priv.pal ? (int)buf->priv.pal->colors : -1);
212 }
213 return buf;
214 }
215
216 void *
evas_software_xlib_swapbuf_new_region_for_update(Outbuf * buf,int x,int y,int w,int h,int * cx,int * cy,int * cw,int * ch)217 evas_software_xlib_swapbuf_new_region_for_update(Outbuf *buf, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
218 {
219 RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, buf->w, buf->h);
220 if ((w <= 0) || (h <= 0)) return NULL;
221 // if rotation is 0, and 32bit argb, we can use the buffer directly
222 if ((buf->rot == 0) &&
223 (buf->priv.mask.r == 0xff0000) &&
224 (buf->priv.mask.g == 0x00ff00) &&
225 (buf->priv.mask.b == 0x0000ff))
226 {
227 RGBA_Image *im;
228 void *data;
229 int bpl = 0;
230 Eina_Rectangle *rect;
231
232 im = buf->priv.onebuf;
233 if (!im)
234 {
235 int ww = 0, hh = 0;
236 int d, bpp;
237
238 d = evas_xlib_swapper_depth_get(buf->priv.swapper);
239 bpp = d / 8;
240
241 data = evas_xlib_swapper_buffer_map(buf->priv.swapper, &bpl,
242 &(ww), &(hh));
243 // To take stride into account, we do use bpl as the real image width, but return the real useful one.
244 im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
245 bpl / bpp, hh, data,
246 buf->priv.destination_alpha,
247 EVAS_COLORSPACE_ARGB8888);
248 buf->priv.onebuf = im;
249 if (!im) return NULL;
250 }
251 rect = eina_rectangle_new(x, y, w, h);
252 if (!eina_array_push(&buf->priv.onebuf_regions, rect))
253 {
254 evas_cache_image_drop(&im->cache_entry);
255 eina_rectangle_free(rect);
256 return NULL;
257 }
258
259 // the clip region of the onebuf to render
260 *cx = x;
261 *cy = y;
262 *cw = w;
263 *ch = h;
264 return im;
265 }
266 else
267 {
268 RGBA_Image *im;
269 Eina_Rectangle *rect;
270
271 rect = eina_rectangle_new(x, y, w, h);
272 if (!rect) return NULL;
273 im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
274 if (!im)
275 {
276 eina_rectangle_free(rect);
277 return NULL;
278 }
279 im->cache_entry.flags.alpha |= buf->priv.destination_alpha ? 1 : 0;
280 evas_cache_image_surface_alloc(&im->cache_entry, w, h);
281 im->extended_info = rect;
282 buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
283
284 // the region is the update image
285 *cx = 0;
286 *cy = 0;
287 *cw = w;
288 *ch = h;
289 return im;
290 }
291 return NULL;
292 }
293
294 void
evas_software_xlib_swapbuf_flush(Outbuf * buf,Tilebuf_Rect * surface_damage EINA_UNUSED,Tilebuf_Rect * buffer_damage EINA_UNUSED,Evas_Render_Mode render_mode)295 evas_software_xlib_swapbuf_flush(Outbuf *buf, Tilebuf_Rect *surface_damage EINA_UNUSED, Tilebuf_Rect *buffer_damage EINA_UNUSED, Evas_Render_Mode render_mode)
296 {
297 if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
298
299 if (!buf->priv.pending_writes)
300 {
301 Eina_Rectangle *result, *rect;
302 Eina_Array_Iterator it;
303 unsigned int n, i;
304 RGBA_Image *im;
305
306 n = eina_array_count_get(&buf->priv.onebuf_regions);
307 if (n == 0) return;
308 result = alloca(n * sizeof(Eina_Rectangle));
309 EINA_ARRAY_ITER_NEXT(&buf->priv.onebuf_regions, i, rect, it)
310 {
311 result[i] = *rect;
312 eina_rectangle_free(rect);
313 }
314 evas_xlib_swapper_buffer_unmap(buf->priv.swapper);
315 evas_xlib_swapper_swap(buf->priv.swapper, result, n);
316 eina_array_clean(&buf->priv.onebuf_regions);
317 im = buf->priv.onebuf;
318 buf->priv.onebuf = NULL;
319 if (im)
320 evas_cache_image_drop(&im->cache_entry);
321 }
322 else
323 {
324 RGBA_Image *im;
325 Eina_Rectangle *result;
326 unsigned int n, i = 0;
327
328 n = eina_list_count(buf->priv.pending_writes);
329 if (n == 0) return;
330 result = alloca(n * sizeof(Eina_Rectangle));
331 EINA_LIST_FREE(buf->priv.pending_writes, im)
332 {
333 Eina_Rectangle *rect = im->extended_info;
334 int x, y, w, h;
335
336 x = rect->x; y = rect->y; w = rect->w; h = rect->h;
337 if (buf->rot == 0)
338 {
339 result[i].x = x;
340 result[i].y = y;
341 }
342 else if (buf->rot == 90)
343 {
344 result[i].x = y;
345 result[i].y = buf->w - x - w;
346 }
347 else if (buf->rot == 180)
348 {
349 result[i].x = buf->w - x - w;
350 result[i].y = buf->h - y - h;
351 }
352 else if (buf->rot == 270)
353 {
354 result[i].x = buf->h - y - h;
355 result[i].y = x;
356 }
357 if ((buf->rot == 0) || (buf->rot == 180))
358 {
359 result[i].w = w;
360 result[i].h = h;
361 }
362 else if ((buf->rot == 90) || (buf->rot == 270))
363 {
364 result[i].w = h;
365 result[i].h = w;
366 }
367 eina_rectangle_free(rect);
368 evas_cache_image_drop(&im->cache_entry);
369 i++;
370 }
371 evas_xlib_swapper_buffer_unmap(buf->priv.swapper);
372 evas_xlib_swapper_swap(buf->priv.swapper, result, n);
373 // evas_xlib_swapper_swap(buf->priv.swapper, NULL, 0);
374 }
375 }
376
377 void
evas_software_xlib_swapbuf_idle_flush(Outbuf * buf EINA_UNUSED)378 evas_software_xlib_swapbuf_idle_flush(Outbuf *buf EINA_UNUSED)
379 {
380 return;
381 }
382
383 void
evas_software_xlib_swapbuf_push_updated_region(Outbuf * buf,RGBA_Image * update,int x,int y,int w,int h)384 evas_software_xlib_swapbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, int x, int y, int w, int h)
385 {
386 Gfx_Func_Convert conv_func = NULL;
387 Eina_Rectangle r = { 0, 0, 0, 0 }, pr;
388 int d, bpl = 0, wid, bpp, rx = 0, ry = 0, ww = 0, hh = 0;
389 DATA32 *src_data;
390 DATA8 *dst_data;
391
392 if (!buf->priv.pending_writes) return;
393 d = evas_xlib_swapper_depth_get(buf->priv.swapper);
394 bpp = d / 8;
395 if (bpp <= 0) return;
396 if (buf->priv.pal)
397 {
398 if ((buf->rot == 0) || (buf->rot == 180))
399 conv_func = evas_common_convert_func_get(0, w, h, d,
400 buf->priv.mask.r,
401 buf->priv.mask.g,
402 buf->priv.mask.b,
403 buf->priv.pal->colors,
404 buf->rot);
405 else if ((buf->rot == 90) || (buf->rot == 270))
406 conv_func = evas_common_convert_func_get(0, h, w, d,
407 buf->priv.mask.r,
408 buf->priv.mask.g,
409 buf->priv.mask.b,
410 buf->priv.pal->colors,
411 buf->rot);
412 }
413 else
414 {
415 if ((buf->rot == 0) || (buf->rot == 180))
416 conv_func = evas_common_convert_func_get(0, w, h, d,
417 buf->priv.mask.r,
418 buf->priv.mask.g,
419 buf->priv.mask.b,
420 PAL_MODE_NONE,
421 buf->rot);
422 else if ((buf->rot == 90) || (buf->rot == 270))
423 conv_func = evas_common_convert_func_get(0, h, w, d,
424 buf->priv.mask.r,
425 buf->priv.mask.g,
426 buf->priv.mask.b,
427 PAL_MODE_NONE,
428 buf->rot);
429 }
430 if (!conv_func) return;
431 if (buf->rot == 0)
432 {
433 r.x = x;
434 r.y = y;
435 }
436 else if (buf->rot == 90)
437 {
438 r.x = y;
439 r.y = buf->w - x - w;
440 }
441 else if (buf->rot == 180)
442 {
443 r.x = buf->w - x - w;
444 r.y = buf->h - y - h;
445 }
446 else if (buf->rot == 270)
447 {
448 r.x = buf->h - y - h;
449 r.y = x;
450 }
451 if ((buf->rot == 0) || (buf->rot == 180))
452 {
453 r.w = w;
454 r.h = h;
455 }
456 else if ((buf->rot == 90) || (buf->rot == 270))
457 {
458 r.w = h;
459 r.h = w;
460 }
461 src_data = update->image.data;
462 if (!src_data) return;
463 if ((buf->rot == 0) || (buf->rot == 180))
464 {
465 dst_data = evas_xlib_swapper_buffer_map(buf->priv.swapper, &bpl,
466 &(ww), &(hh));
467 if (!dst_data) return;
468 if (buf->rot == 0)
469 {
470 RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h, 0, 0, ww, hh);
471 dst_data += (bpl * r.y) + (r.x * bpp);
472 w -= rx;
473 }
474 else if (buf->rot == 180)
475 {
476 pr = r;
477 RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h, 0, 0, ww, hh);
478 rx = pr.w - r.w; ry = pr.h - r.h;
479 src_data += (update->cache_entry.w * ry) + rx;
480 w -= rx;
481 }
482 }
483 else
484 {
485 dst_data = evas_xlib_swapper_buffer_map(buf->priv.swapper, &bpl,
486 &(ww), &(hh));
487 if (!dst_data) return;
488 if (buf->rot == 90)
489 {
490 pr = r;
491 RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h, 0, 0, ww, hh);
492 rx = pr.w - r.w; ry = pr.h - r.h;
493 src_data += ry;
494 w -= ry;
495 }
496 else if (buf->rot == 270)
497 {
498 pr = r;
499 RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h, 0, 0, ww, hh);
500 rx = pr.w - r.w; ry = pr.h - r.h;
501 src_data += (update->cache_entry.w * rx);
502 w -= ry;
503 }
504 }
505 if ((r.w <= 0) || (r.h <= 0)) return;
506 wid = bpl / bpp;
507 dst_data += (bpl * r.y) + (r.x * bpp);
508 if (buf->priv.pal)
509 conv_func(src_data, dst_data,
510 update->cache_entry.w - w,
511 wid - r.w,
512 r.w, r.h,
513 x + rx, y + ry,
514 buf->priv.pal->lookup);
515 else
516 conv_func(src_data, dst_data,
517 update->cache_entry.w - w,
518 wid - r.w,
519 r.w, r.h,
520 x + rx, y + ry,
521 NULL);
522 }
523
524 void
evas_software_xlib_swapbuf_reconfigure(Outbuf * buf,int w,int h,int rot,Outbuf_Depth depth)525 evas_software_xlib_swapbuf_reconfigure(Outbuf *buf, int w, int h, int rot,
526 Outbuf_Depth depth)
527 {
528 if ((w == buf->w) && (h == buf->h) && (rot == buf->rot) &&
529 (depth == buf->depth))
530 return;
531 buf->w = w;
532 buf->h = h;
533 buf->rot = rot;
534 evas_xlib_swapper_free(buf->priv.swapper);
535 if ((buf->rot == 0) || (buf->rot == 180))
536 buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
537 buf->priv.x11.xlib.win,
538 buf->priv.x11.xlib.vis,
539 buf->priv.x11.xlib.depth,
540 buf->w, buf->h);
541 else if ((buf->rot == 90) || (buf->rot == 270))
542 buf->priv.swapper = evas_xlib_swapper_new(buf->priv.x11.xlib.disp,
543 buf->priv.x11.xlib.win,
544 buf->priv.x11.xlib.vis,
545 buf->priv.x11.xlib.depth,
546 buf->h, buf->w);
547 }
548
549 int
evas_software_xlib_swapbuf_get_rot(Outbuf * buf)550 evas_software_xlib_swapbuf_get_rot(Outbuf *buf)
551 {
552 return buf->rot;
553 }
554
555 Eina_Bool
evas_software_xlib_swapbuf_alpha_get(Outbuf * buf)556 evas_software_xlib_swapbuf_alpha_get(Outbuf *buf)
557 {
558 return buf->priv.destination_alpha;
559 }
560
561 Render_Output_Swap_Mode
evas_software_xlib_swapbuf_buffer_state_get(Outbuf * buf)562 evas_software_xlib_swapbuf_buffer_state_get(Outbuf *buf)
563 {
564 if (!buf->priv.swapper) return MODE_FULL;
565 return evas_xlib_swapper_buffer_state_get(buf->priv.swapper);
566 }
567
568