1 #include "evas_common_private.h"
2 #include "evas_private.h"
4 #include "evas_cs2_private.h"
7 #include "Evas_Engine_Software_X11.h"
8 #include "evas_engine.h"
10 #include "evas_xlib_outbuf.h"
11 #include "evas_xlib_buffer.h"
12 #include "evas_xlib_swapbuf.h"
13 #include "evas_xlib_color.h"
14 #include "evas_xlib_image.h"
15 #include "evas_xlib_dri_image.h"
16 #include "evas_x_egl.h"
18 #include "../software_generic/evas_native_common.h"
27 Evas_Native_Tbm_Surface_Image_Set_Call glsym__evas_native_tbm_surface_image_set = NULL;
28 Evas_Native_Tbm_Surface_Stride_Get_Call glsym__evas_native_tbm_surface_stride_get = NULL;
29 int _evas_engine_soft_x11_log_dom = -1;
31 /* function tables - filled in later (func and parent func) */
32 static Evas_Func func, pfunc;
34 /* engine struct data */
35 typedef struct _Render_Engine Render_Engine;
39 Render_Engine_Software_Generic generic;
40 Eina_Bool (*outbuf_alpha_get)(Outbuf *ob);
49 typedef struct _Region_Push_Hook_Ctx {
50 X_Output_Buffer *changed_pixels;
54 void (*cb)(Evas *evas, int x, int y, int w, int h, const void *pixels);
59 } Region_Push_Hook_Ctx;
61 /* prototypes we will use here */
62 static void *_best_visual_get(int backend, void *connection, int screen);
63 static unsigned int _best_colormap_get(int backend, void *connection, int screen);
64 static int _best_depth_get(int backend, void *connection, int screen);
66 static void *eng_info(Evas *eo_e);
67 static void eng_info_free(Evas *eo_e, void *info);
68 static int eng_setup(Evas *eo_e, void *info);
69 static void eng_output_free(void *data);
71 static Eina_List *_outbufs = NULL;
73 /* internal engine routines */
77 _evas_software_x11_region_push_hook_call(void *data)
79 Region_Push_Hook_Ctx *ctx = data;
81 if (eina_list_data_find(_outbufs, ctx->buf))
83 ctx->region_push_hook.cb(ctx->region_push_hook.evas, ctx->x, ctx->y,
84 ctx->changed_pixels->xim->width,
85 ctx->changed_pixels->xim->height,
86 evas_software_xlib_x_output_buffer_data(ctx->changed_pixels, NULL));
87 eina_spinlock_take(ctx->lock);
88 evas_software_xlib_x_output_buffer_unref(ctx->changed_pixels, 0);
89 eina_spinlock_release(ctx->lock);
95 evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, void *out_buf,
98 Region_Push_Hook_Ctx *ctx;
100 if (!buf->region_push_hook.cb)
103 ctx = malloc(sizeof(Region_Push_Hook_Ctx));
104 EINA_SAFETY_ON_NULL_RETURN(ctx);
107 ctx->region_push_hook.cb = buf->region_push_hook.cb;
108 ctx->region_push_hook.evas = buf->region_push_hook.evas;
109 ctx->changed_pixels = evas_software_xlib_x_output_buffer_ref(out_buf);
112 ecore_main_loop_thread_safe_call_async(_evas_software_x11_region_push_hook_call,
117 _output_egl_shutdown(Render_Engine *re)
119 if (!re->egl.disp) return;
120 _egl_x_win_surf_free(re->egl.disp, re->egl.surface);
121 _egl_x_disp_terminate(re->egl.disp);
125 _output_xlib_setup(int w, int h, int rot, Display *disp, Drawable draw,
126 Visual *vis, Colormap cmap, int depth, int debug,
127 int grayscale, int max_colors, Pixmap mask,
128 int shape_dither, int destination_alpha)
132 Render_Engine_Merge_Mode merge_mode = MERGE_SMART;
135 if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
137 evas_software_xlib_x_init();
138 evas_software_xlib_x_color_init();
139 evas_software_xlib_outbuf_init();
142 evas_software_xlib_outbuf_setup_x(w, h, rot, OUTBUF_DEPTH_INHERIT, disp,
143 draw, vis, cmap, depth, grayscale,
144 max_colors, mask, shape_dither,
146 if (!ob) goto on_error;
148 /* for updates return 1 big buffer, but only use portions of it, also cache
149 * it and keepit around until an idle_flush */
151 /* disable for now - i am hunting down why some expedite tests are slower,
152 * as well as shaped stuff is broken and probable non-32bpp is broken as
153 * convert funcs dont do the right thing
156 // re->ob->onebuf = 1;
158 evas_software_xlib_outbuf_debug_set(ob, debug);
159 if (!evas_render_engine_software_generic_init(&re->generic, ob, NULL,
160 evas_software_xlib_outbuf_get_rot,
161 evas_software_xlib_outbuf_reconfigure,
164 evas_software_xlib_outbuf_new_region_for_update,
165 evas_software_xlib_outbuf_push_updated_region,
166 evas_software_xlib_outbuf_free_region_for_update,
167 evas_software_xlib_outbuf_idle_flush,
168 evas_software_xlib_outbuf_flush,
170 evas_software_xlib_outbuf_free,
174 if ((s = getenv("EVAS_SOFTWARE_PARTIAL_MERGE")))
176 if ((!strcmp(s, "bounding")) ||
178 merge_mode = MERGE_BOUNDING;
179 else if ((!strcmp(s, "full")) ||
181 merge_mode = MERGE_FULL;
182 else if ((!strcmp(s, "smart")) ||
184 merge_mode = MERGE_SMART;
187 evas_render_engine_software_generic_merge_mode_set(&re->generic, merge_mode);
192 if (ob) evas_software_xlib_outbuf_free(ob);
198 _output_swapbuf_setup(int w, int h, int rot, Display *disp, Drawable draw,
199 Visual *vis, Colormap cmap, int depth,
200 int debug EINA_UNUSED,
201 int grayscale, int max_colors, Pixmap mask,
202 int shape_dither, int destination_alpha)
207 if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
209 evas_software_xlib_x_init();
210 evas_software_xlib_x_color_init();
211 evas_software_xlib_swapbuf_init();
214 evas_software_xlib_swapbuf_setup_x(w, h, rot, OUTBUF_DEPTH_INHERIT, disp,
215 draw, vis, cmap, depth, grayscale,
216 max_colors, mask, shape_dither,
218 if (!ob) goto on_error;
220 if (!evas_render_engine_software_generic_init(&re->generic, ob,
221 evas_software_xlib_swapbuf_buffer_state_get,
222 evas_software_xlib_swapbuf_get_rot,
223 evas_software_xlib_swapbuf_reconfigure,
226 evas_software_xlib_swapbuf_new_region_for_update,
227 evas_software_xlib_swapbuf_push_updated_region,
228 evas_software_xlib_swapbuf_free_region_for_update,
229 evas_software_xlib_swapbuf_idle_flush,
230 evas_software_xlib_swapbuf_flush,
232 evas_software_xlib_swapbuf_free,
238 if (ob) evas_software_xlib_swapbuf_free(ob);
244 _best_visual_get(int backend, void *connection, int screen)
246 if (!connection) return NULL;
248 if (backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
249 return DefaultVisual((Display *)connection, screen);
255 _best_colormap_get(int backend, void *connection, int screen)
257 if (!connection) return 0;
259 if (backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
260 return DefaultColormap((Display *)connection, screen);
265 _best_depth_get(int backend, void *connection, int screen)
267 if (!connection) return 0;
269 if (backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
270 return DefaultDepth((Display *)connection, screen);
281 #define LINK2GENERIC(sym) \
282 glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
284 // Get function pointer to native_common that is now provided through the link of SW_Generic.
285 LINK2GENERIC(_evas_native_tbm_surface_image_set);
286 LINK2GENERIC(_evas_native_tbm_surface_stride_get);
291 /* engine api this module provides */
293 eng_info(Evas *eo_e EINA_UNUSED)
295 Evas_Engine_Info_Software_X11 *info;
297 if (!(info = calloc(1, sizeof(Evas_Engine_Info_Software_X11))))
300 info->magic.magic = rand();
301 info->info.debug = 0;
302 info->info.alloc_grayscale = 0;
303 info->info.alloc_colors_max = 216;
304 info->func.best_visual_get = _best_visual_get;
305 info->func.best_colormap_get = _best_colormap_get;
306 info->func.best_depth_get = _best_depth_get;
307 info->render_mode = EVAS_RENDER_MODE_BLOCKING;
312 eng_info_free(Evas *eo_e EINA_UNUSED, void *info)
314 Evas_Engine_Info_Software_X11 *in;
316 in = (Evas_Engine_Info_Software_X11 *)info;
321 eng_setup(Evas *eo_e, void *in)
323 Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
324 Evas_Engine_Info_Software_X11 *info;
325 Render_Engine *re = NULL;
327 info = (Evas_Engine_Info_Software_X11 *)in;
328 if (!e->engine.data.output)
330 /* if we haven't initialized - init (automatic abort if already done) */
333 if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
335 static int try_swapbuf = -1;
338 if (try_swapbuf == -1)
340 if ((s = getenv("EVAS_NO_DRI_SWAPBUF")) != NULL)
342 if (atoi(s) == 1) try_swapbuf = 0;
343 else try_swapbuf = 1;
345 else try_swapbuf = 1;
348 re = _output_swapbuf_setup(e->output.w, e->output.h,
349 info->info.rotation, info->info.connection,
350 info->info.drawable, info->info.visual,
352 info->info.depth, info->info.debug,
353 info->info.alloc_grayscale,
354 info->info.alloc_colors_max,
355 info->info.mask, info->info.shape_dither,
356 info->info.destination_alpha);
357 if (re) re->outbuf_alpha_get = evas_software_xlib_swapbuf_alpha_get;
360 re = _output_xlib_setup(e->output.w, e->output.h,
361 info->info.rotation, info->info.connection,
362 info->info.drawable, info->info.visual,
364 info->info.depth, info->info.debug,
365 info->info.alloc_grayscale,
366 info->info.alloc_colors_max,
367 info->info.mask, info->info.shape_dither,
368 info->info.destination_alpha);
369 re->outbuf_alpha_get = evas_software_xlib_outbuf_alpha_get;
371 re->generic.ob->region_push_hook.cb = info->func.region_push_hook;
372 re->generic.ob->region_push_hook.evas = eo_e;
374 e->engine.data.output = re;
379 /* int ponebuf = 0; */
381 re = e->engine.data.output;
382 /* if ((re) && (re->ob)) ponebuf = re->ob->onebuf; */
384 _outbufs = eina_list_remove(_outbufs, re->generic.ob);
386 if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
388 if (re->generic.outbuf_free == evas_software_xlib_swapbuf_free)
391 evas_software_xlib_swapbuf_setup_x(e->output.w, e->output.h,
393 OUTBUF_DEPTH_INHERIT,
394 info->info.connection,
399 info->info.alloc_grayscale,
400 info->info.alloc_colors_max,
402 info->info.shape_dither,
403 info->info.destination_alpha);
408 evas_software_xlib_outbuf_setup_x(e->output.w, e->output.h,
410 OUTBUF_DEPTH_INHERIT,
411 info->info.connection,
416 info->info.alloc_grayscale,
417 info->info.alloc_colors_max,
419 info->info.shape_dither,
420 info->info.destination_alpha);
421 evas_software_xlib_outbuf_debug_set(ob, info->info.debug);
426 evas_render_engine_software_generic_update(&re->generic, ob, e->output.w, e->output.h);
427 ob->region_push_hook.cb = info->func.region_push_hook;
428 ob->region_push_hook.evas = eo_e;
431 /* if ((re) && (re->ob)) re->ob->onebuf = ponebuf; */
433 if (!e->engine.data.output) return 0;
434 if (!e->engine.data.context)
436 e->engine.data.context =
437 e->engine.func->context_new(e->engine.data.output);
440 re = e->engine.data.output;
441 _outbufs = eina_list_append(_outbufs, re->generic.ob);
447 eng_output_free(void *data)
451 if ((re = (Render_Engine *)data))
453 _outbufs = eina_list_remove(_outbufs, re->generic.ob);
454 evas_render_engine_software_generic_clean(&re->generic);
455 _output_egl_shutdown(re);
459 evas_common_shutdown();
463 eng_canvas_alpha_get(void *data, void *context EINA_UNUSED)
467 re = (Render_Engine *)data;
468 return (re->generic.ob->priv.destination_alpha) ||
469 (re->outbuf_alpha_get(re->generic.ob));
473 _native_evasgl_free(void *image)
475 RGBA_Image *im = image;
476 Native *n = im->native.data;
478 im->native.data = NULL;
479 im->native.func.bind = NULL;
480 im->native.func.unbind = NULL;
481 im->native.func.free = NULL;
482 //im->image.data = NULL;
487 eng_image_native_init(void *data EINA_UNUSED, Evas_Native_Surface_Type type)
492 case EVAS_NATIVE_SURFACE_TBM:
493 return _evas_native_tbm_init();
495 case EVAS_NATIVE_SURFACE_X11:
496 case EVAS_NATIVE_SURFACE_EVASGL:
499 ERR("Native surface type %d not supported!", type);
505 eng_image_native_shutdown(void *data EINA_UNUSED, Evas_Native_Surface_Type type)
510 case EVAS_NATIVE_SURFACE_TBM:
511 _evas_native_tbm_shutdown();
514 case EVAS_NATIVE_SURFACE_X11:
515 case EVAS_NATIVE_SURFACE_OPENGL:
518 ERR("Native surface type %d not supported!", type);
524 eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
526 Render_Engine *re = (Render_Engine *)data;
527 Evas_Native_Surface *ns = native;
528 Image_Entry *ie = image, *ie2 = NULL;
529 RGBA_Image *im = image;
532 if (!im) return NULL;
535 if (im->native.data && im->native.func.free)
536 im->native.func.free(im);
540 if (ns->type == EVAS_NATIVE_SURFACE_X11)
544 //image have native surface already
545 Evas_Native_Surface *ens = im->native.data;
547 if ((ens->type == ns->type) &&
548 (ens->data.x11.visual == ns->data.x11.visual) &&
549 (ens->data.x11.pixmap == ns->data.x11.pixmap))
553 else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
557 //image have native surface already
558 Evas_Native_Surface *ens = im->native.data;
560 if ((ens->type == ns->type) &&
561 (ens->data.tbm.buffer == ns->data.tbm.buffer))
566 // Code from software_generic
567 if ((ns->type == EVAS_NATIVE_SURFACE_EVASGL) &&
568 (ns->version == EVAS_NATIVE_SURFACE_VERSION))
569 ie2 = evas_cache_image_data(evas_common_image_cache_get(),
570 ie->w, ie->h, ns->data.evasgl.surface, 1,
571 EVAS_COLORSPACE_ARGB8888);
572 else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
574 stride = glsym__evas_native_tbm_surface_stride_get(re->generic.ob, ns);
575 ie2 = evas_cache_image_copied_data(evas_common_image_cache_get(),
576 stride, ie->h, NULL, ie->flags.alpha,
577 EVAS_COLORSPACE_ARGB8888);
580 ie2 = evas_cache_image_data(evas_common_image_cache_get(),
581 ie->w, ie->h, NULL, ie->flags.alpha,
582 EVAS_COLORSPACE_ARGB8888);
586 if (im->native.func.free)
587 im->native.func.free(im);
591 if (evas_cserve2_use_get() && evas_cache2_image_cached(ie))
592 evas_cache2_image_close(ie);
595 evas_cache_image_drop(ie);
598 if (ns->type == EVAS_NATIVE_SURFACE_X11)
600 RGBA_Image *ret_im = NULL;
601 ret_im = evas_xlib_image_dri_native_set(re->generic.ob, ie, ns);
603 ret_im = evas_xlib_image_native_set(re->generic.ob, ie, ns);
606 else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
608 return glsym__evas_native_tbm_surface_image_set(re->generic.ob, ie, ns);
610 else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
612 /* Native contains Evas_Native_Surface. What a mess. */
613 Native *n = calloc(1, sizeof(Native));
616 n->ns_data.evasgl.surface = ns->data.evasgl.surface;
617 im = (RGBA_Image *) ie;
618 n->ns.type = EVAS_NATIVE_SURFACE_EVASGL;
619 n->ns.version = EVAS_NATIVE_SURFACE_VERSION;
620 n->ns.data.evasgl.surface = ns->data.evasgl.surface;
622 im->native.func.free = _native_evasgl_free;
623 im->native.func.bind = NULL;
624 im->native.func.unbind = NULL;
632 eng_image_native_get(void *data EINA_UNUSED, void *image)
634 RGBA_Image *im = image;
636 if (!im) return NULL;
643 /* module advertising code */
645 module_open(Evas_Module *em)
649 /* get whatever engine module we inherit from */
650 if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
652 _evas_engine_soft_x11_log_dom =
653 eina_log_domain_register("evas-software_x11", EVAS_DEFAULT_LOG_COLOR);
655 if (_evas_engine_soft_x11_log_dom < 0)
657 EINA_LOG_ERR("Can not create a module log domain.");
661 /* store it for later use */
664 /* now to override methods */
665 #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
669 ORD(canvas_alpha_get);
671 ORD(image_native_init);
672 ORD(image_native_shutdown);
673 ORD(image_native_set);
674 ORD(image_native_get);
677 /* now advertise out own api */
678 em->functions = (void *)(&func);
683 module_close(Evas_Module *em EINA_UNUSED)
685 eina_log_domain_unregister(_evas_engine_soft_x11_log_dom);
688 static Evas_Module_Api evas_modapi =
690 EVAS_MODULE_API_VERSION, "software_x11", "none",
697 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_x11);
699 #ifndef EVAS_STATIC_BUILD_SOFTWARE_X11
700 EVAS_EINA_MODULE_DEFINE(engine, software_x11);