remove xcb support in ecore_x and evas engines as per mailing list
[platform/upstream/efl.git] / src / modules / evas / engines / software_x11 / evas_engine.c
1 #include "evas_common_private.h"
2 #include "evas_private.h"
3 #ifdef EVAS_CSERVE2
4 #include "evas_cs2_private.h"
5 #endif
6
7 #include "Evas_Engine_Software_X11.h"
8 #include "evas_engine.h"
9
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"
17
18 #include "../software_generic/evas_native_common.h"
19
20 #ifdef HAVE_DLSYM
21 # include <dlfcn.h>
22 #endif
23
24 #include <Ecore.h>
25 #include <Eina.h>
26
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;
30
31 /* function tables - filled in later (func and parent func) */
32 static Evas_Func func, pfunc;
33
34 /* engine struct data */
35 typedef struct _Render_Engine Render_Engine;
36
37 struct _Render_Engine
38 {
39    Render_Engine_Software_Generic generic;
40    Eina_Bool (*outbuf_alpha_get)(Outbuf *ob);
41
42    struct {
43       void *disp;
44       void *config;
45       void *surface;
46    } egl;
47 };
48
49 typedef struct _Region_Push_Hook_Ctx {
50    X_Output_Buffer *changed_pixels;
51    Outbuf *buf;
52    Eina_Spinlock *lock;
53    struct {
54       void (*cb)(Evas *evas, int x, int y, int w, int h, const void *pixels);
55       Evas *evas;
56    } region_push_hook;
57    int x;
58    int y;
59 } Region_Push_Hook_Ctx;
60
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);
65
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);
70
71 static Eina_List *_outbufs = NULL;
72
73 /* internal engine routines */
74
75
76 static void
77 _evas_software_x11_region_push_hook_call(void *data)
78 {
79    Region_Push_Hook_Ctx *ctx = data;
80
81    if (eina_list_data_find(_outbufs, ctx->buf))
82      {
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);
90      }
91    free(ctx);
92 }
93
94 void
95 evas_software_x11_region_push_hook_call(Outbuf *buf, int x, int y, void *out_buf,
96                                         Eina_Spinlock *lock)
97 {
98    Region_Push_Hook_Ctx *ctx;
99
100    if (!buf->region_push_hook.cb)
101      return;
102
103    ctx = malloc(sizeof(Region_Push_Hook_Ctx));
104    EINA_SAFETY_ON_NULL_RETURN(ctx);
105    ctx->x = x;
106    ctx->y = y;
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);
110    ctx->buf = buf;
111    ctx->lock = lock;
112    ecore_main_loop_thread_safe_call_async(_evas_software_x11_region_push_hook_call,
113                                           ctx);
114 }
115
116 static void
117 _output_egl_shutdown(Render_Engine *re)
118 {
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);
122 }
123
124 static void *
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)
129 {
130    Render_Engine *re;
131    Outbuf *ob;
132    Render_Engine_Merge_Mode merge_mode = MERGE_SMART;
133    const char *s;
134
135    if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
136
137    evas_software_xlib_x_init();
138    evas_software_xlib_x_color_init();
139    evas_software_xlib_outbuf_init();
140
141    ob =
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,
145                                        destination_alpha);
146    if (!ob) goto on_error;
147
148    /* for updates return 1 big buffer, but only use portions of it, also cache
149     * it and keepit around until an idle_flush */
150
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
154     *
155     */
156 //   re->ob->onebuf = 1;
157
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,
162                                                  NULL,
163                                                  NULL,
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,
169                                                  NULL,
170                                                  evas_software_xlib_outbuf_free,
171                                                  w, h))
172      goto on_error;
173
174    if ((s = getenv("EVAS_SOFTWARE_PARTIAL_MERGE")))
175      {
176         if ((!strcmp(s, "bounding")) ||
177             (!strcmp(s, "b")))
178           merge_mode = MERGE_BOUNDING;
179         else if ((!strcmp(s, "full")) ||
180                  (!strcmp(s, "f")))
181           merge_mode = MERGE_FULL;
182         else if ((!strcmp(s, "smart")) ||
183                  (!strcmp(s, "s")))
184           merge_mode = MERGE_SMART;
185      }
186
187    evas_render_engine_software_generic_merge_mode_set(&re->generic, merge_mode);
188
189    return re;
190
191  on_error:
192    if (ob) evas_software_xlib_outbuf_free(ob);
193    free(re);
194    return NULL;
195 }
196
197 static void *
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)
203 {
204    Render_Engine *re;
205    Outbuf *ob;
206
207    if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL;
208
209    evas_software_xlib_x_init();
210    evas_software_xlib_x_color_init();
211    evas_software_xlib_swapbuf_init();
212
213    ob =
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,
217                                         destination_alpha);
218    if (!ob) goto on_error;
219
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,
224                                                  NULL,
225                                                  NULL,
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,
231                                                  NULL,
232                                                  evas_software_xlib_swapbuf_free,
233                                                  w, h))
234      goto on_error;
235    return re;
236
237  on_error:
238    if (ob) evas_software_xlib_swapbuf_free(ob);
239    free(re);
240    return NULL;
241 }
242
243 static void *
244 _best_visual_get(int backend, void *connection, int screen)
245 {
246    if (!connection) return NULL;
247
248    if (backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
249      return DefaultVisual((Display *)connection, screen);
250
251    return NULL;
252 }
253
254 static unsigned int
255 _best_colormap_get(int backend, void *connection, int screen)
256 {
257    if (!connection) return 0;
258
259    if (backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
260      return DefaultColormap((Display *)connection, screen);
261    return 0;
262 }
263
264 static int
265 _best_depth_get(int backend, void *connection, int screen)
266 {
267    if (!connection) return 0;
268
269    if (backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
270      return DefaultDepth((Display *)connection, screen);
271    return 0;
272 }
273
274 static void
275 _symbols(void)
276 {
277    static int done = 0;
278
279    if (done) return;
280
281 #define LINK2GENERIC(sym) \
282    glsym_##sym = dlsym(RTLD_DEFAULT, #sym);
283
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);
287
288    done = 1;
289 }
290
291 /* engine api this module provides */
292 static void *
293 eng_info(Evas *eo_e EINA_UNUSED)
294 {
295    Evas_Engine_Info_Software_X11 *info;
296
297    if (!(info = calloc(1, sizeof(Evas_Engine_Info_Software_X11))))
298      return NULL;
299
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;
308    return info;
309 }
310
311 static void
312 eng_info_free(Evas *eo_e EINA_UNUSED, void *info)
313 {
314    Evas_Engine_Info_Software_X11 *in;
315
316    in = (Evas_Engine_Info_Software_X11 *)info;
317    free(in);
318 }
319
320 static int
321 eng_setup(Evas *eo_e, void *in)
322 {
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;
326
327    info = (Evas_Engine_Info_Software_X11 *)in;
328    if (!e->engine.data.output)
329      {
330         /* if we haven't initialized - init (automatic abort if already done) */
331         evas_common_init();
332
333         if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
334           {
335              static int try_swapbuf = -1;
336              char* s;
337
338              if (try_swapbuf == -1)
339                {
340                   if ((s = getenv("EVAS_NO_DRI_SWAPBUF")) != NULL)
341                     {
342                        if (atoi(s) == 1) try_swapbuf = 0;
343                        else try_swapbuf = 1;
344                     }
345                   else try_swapbuf = 1;
346                }
347              if (try_swapbuf)
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,
351                                           info->info.colormap,
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;
358              else
359                {
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,
363                                           info->info.colormap,
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;
370                }
371              re->generic.ob->region_push_hook.cb = info->func.region_push_hook;
372              re->generic.ob->region_push_hook.evas = eo_e;
373           }
374         e->engine.data.output = re;
375      }
376    else
377      {
378         Outbuf *ob = NULL;
379         /* int ponebuf = 0; */
380
381         re = e->engine.data.output;
382         /* if ((re) && (re->ob)) ponebuf = re->ob->onebuf; */
383
384         _outbufs = eina_list_remove(_outbufs, re->generic.ob);
385
386         if (info->info.backend == EVAS_ENGINE_INFO_SOFTWARE_X11_BACKEND_XLIB)
387           {
388              if (re->generic.outbuf_free == evas_software_xlib_swapbuf_free)
389                {
390                   ob =
391                     evas_software_xlib_swapbuf_setup_x(e->output.w, e->output.h,
392                                                        info->info.rotation,
393                                                        OUTBUF_DEPTH_INHERIT,
394                                                        info->info.connection,
395                                                        info->info.drawable,
396                                                        info->info.visual,
397                                                        info->info.colormap,
398                                                        info->info.depth,
399                                                        info->info.alloc_grayscale,
400                                                        info->info.alloc_colors_max,
401                                                        info->info.mask,
402                                                        info->info.shape_dither,
403                                                        info->info.destination_alpha);
404                }
405              else
406                {
407                   ob =
408                     evas_software_xlib_outbuf_setup_x(e->output.w, e->output.h,
409                                                       info->info.rotation,
410                                                       OUTBUF_DEPTH_INHERIT,
411                                                       info->info.connection,
412                                                       info->info.drawable,
413                                                       info->info.visual,
414                                                       info->info.colormap,
415                                                       info->info.depth,
416                                                       info->info.alloc_grayscale,
417                                                       info->info.alloc_colors_max,
418                                                       info->info.mask,
419                                                       info->info.shape_dither,
420                                                       info->info.destination_alpha);
421                   evas_software_xlib_outbuf_debug_set(ob, info->info.debug);
422                }
423           }
424         if (ob)
425           {
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;
429           }
430
431         /* if ((re) && (re->ob)) re->ob->onebuf = ponebuf; */
432      }
433    if (!e->engine.data.output) return 0;
434    if (!e->engine.data.context)
435      {
436         e->engine.data.context =
437           e->engine.func->context_new(e->engine.data.output);
438      }
439
440    re = e->engine.data.output;
441    _outbufs =  eina_list_append(_outbufs, re->generic.ob);
442
443    return 1;
444 }
445
446 static void
447 eng_output_free(void *data)
448 {
449    Render_Engine *re;
450
451    if ((re = (Render_Engine *)data))
452      {
453         _outbufs = eina_list_remove(_outbufs, re->generic.ob);
454         evas_render_engine_software_generic_clean(&re->generic);
455         _output_egl_shutdown(re);
456         free(re);
457      }
458
459    evas_common_shutdown();
460 }
461
462 static Eina_Bool
463 eng_canvas_alpha_get(void *data, void *context EINA_UNUSED)
464 {
465    Render_Engine *re;
466
467    re = (Render_Engine *)data;
468    return (re->generic.ob->priv.destination_alpha) ||
469      (re->outbuf_alpha_get(re->generic.ob));
470 }
471
472 static void
473 _native_evasgl_free(void *image)
474 {
475    RGBA_Image *im = image;
476    Native *n = im->native.data;
477
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;
483    free(n);
484 }
485
486 static int
487 eng_image_native_init(void *data EINA_UNUSED, Evas_Native_Surface_Type type)
488 {
489    switch (type)
490      {
491 #ifdef GL_GLES
492       case EVAS_NATIVE_SURFACE_TBM:
493         return _evas_native_tbm_init();
494 #endif
495       case EVAS_NATIVE_SURFACE_X11:
496       case EVAS_NATIVE_SURFACE_EVASGL:
497         return 1;
498       default:
499         ERR("Native surface type %d not supported!", type);
500         return 0;
501      }
502 }
503
504 static void
505 eng_image_native_shutdown(void *data EINA_UNUSED, Evas_Native_Surface_Type type)
506 {
507    switch (type)
508      {
509 #ifdef GL_GLES
510       case EVAS_NATIVE_SURFACE_TBM:
511         _evas_native_tbm_shutdown();
512         return;
513 #endif
514       case EVAS_NATIVE_SURFACE_X11:
515       case EVAS_NATIVE_SURFACE_OPENGL:
516         return;
517       default:
518         ERR("Native surface type %d not supported!", type);
519         return;
520      }
521 }
522
523 static void *
524 eng_image_native_set(void *data EINA_UNUSED, void *image, void *native)
525 {
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;
530    int stride;
531
532    if (!im) return NULL;
533    if (!ns)
534      {
535         if (im->native.data && im->native.func.free)
536           im->native.func.free(im);
537         return NULL;
538      }
539
540    if (ns->type == EVAS_NATIVE_SURFACE_X11)
541      {
542         if (im->native.data)
543           {
544              //image have native surface already
545              Evas_Native_Surface *ens = im->native.data;
546
547              if ((ens->type == ns->type) &&
548                  (ens->data.x11.visual == ns->data.x11.visual) &&
549                  (ens->data.x11.pixmap == ns->data.x11.pixmap))
550                return im;
551           }
552      }
553    else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
554      {
555         if (im->native.data)
556           {
557              //image have native surface already
558              Evas_Native_Surface *ens = im->native.data;
559
560              if ((ens->type == ns->type) &&
561                  (ens->data.tbm.buffer == ns->data.tbm.buffer))
562                return im;
563           }
564      }
565
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)
573      {
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);
578      }
579    else
580      ie2 = evas_cache_image_data(evas_common_image_cache_get(),
581                                  ie->w, ie->h, NULL, ie->flags.alpha,
582                                  EVAS_COLORSPACE_ARGB8888);
583
584    if (im->native.data)
585      {
586         if (im->native.func.free)
587           im->native.func.free(im);
588      }
589
590 #ifdef EVAS_CSERVE2
591    if (evas_cserve2_use_get() && evas_cache2_image_cached(ie))
592      evas_cache2_image_close(ie);
593    else
594 #endif
595      evas_cache_image_drop(ie);
596    ie = ie2;
597
598    if (ns->type == EVAS_NATIVE_SURFACE_X11)
599      {
600         RGBA_Image *ret_im = NULL;
601         ret_im = evas_xlib_image_dri_native_set(re->generic.ob, ie, ns);
602         if (!ret_im) 
603            ret_im = evas_xlib_image_native_set(re->generic.ob, ie, ns);
604         return ret_im;
605      }
606    else if (ns->type == EVAS_NATIVE_SURFACE_TBM)
607      {
608         return glsym__evas_native_tbm_surface_image_set(re->generic.ob, ie, ns);
609      }
610    else if (ns->type == EVAS_NATIVE_SURFACE_EVASGL)
611      {
612         /* Native contains Evas_Native_Surface. What a mess. */
613         Native *n = calloc(1, sizeof(Native));
614         if (n)
615           {
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;
621              im->native.data = n;
622              im->native.func.free = _native_evasgl_free;
623              im->native.func.bind = NULL;
624              im->native.func.unbind = NULL;
625           }
626      }
627
628    return ie;
629 }
630
631 static void *
632 eng_image_native_get(void *data EINA_UNUSED, void *image)
633 {
634    RGBA_Image *im = image;
635    Native *n;
636    if (!im) return NULL;
637    n = im->native.data;
638    if (!n) return NULL;
639    return &(n->ns);
640 }
641
642
643 /* module advertising code */
644 static int
645 module_open(Evas_Module *em)
646 {
647    if (!em) return 0;
648
649    /* get whatever engine module we inherit from */
650    if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
651
652    _evas_engine_soft_x11_log_dom = 
653      eina_log_domain_register("evas-software_x11", EVAS_DEFAULT_LOG_COLOR);
654
655    if (_evas_engine_soft_x11_log_dom < 0)
656      {
657         EINA_LOG_ERR("Can not create a module log domain.");
658         return 0;
659      }
660
661    /* store it for later use */
662    func = pfunc;
663
664    /* now to override methods */
665 #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
666    ORD(info);
667    ORD(info_free);
668    ORD(setup);
669    ORD(canvas_alpha_get);
670    ORD(output_free);
671    ORD(image_native_init);
672    ORD(image_native_shutdown);
673    ORD(image_native_set);
674    ORD(image_native_get);
675
676    _symbols();
677    /* now advertise out own api */
678    em->functions = (void *)(&func);
679    return 1;
680 }
681
682 static void
683 module_close(Evas_Module *em EINA_UNUSED)
684 {
685   eina_log_domain_unregister(_evas_engine_soft_x11_log_dom);
686 }
687
688 static Evas_Module_Api evas_modapi =
689 {
690    EVAS_MODULE_API_VERSION, "software_x11", "none",
691    {
692      module_open,
693      module_close
694    }
695 };
696
697 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, software_x11);
698
699 #ifndef EVAS_STATIC_BUILD_SOFTWARE_X11
700 EVAS_EINA_MODULE_DEFINE(engine, software_x11);
701 #endif