merged evas image masking code from brett
[framework/uifw/evas.git] / src / modules / engines / gl_x11 / evas_engine.c
1 #include "evas_common.h" /* Also includes international specific stuff */
2 #include "evas_engine.h"
3
4 #include <dlfcn.h>      /* dlopen,dlclose,etc */
5
6 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
7 // EGL / GLES
8 # if defined(GLES_VARIETY_S3C6410)
9 # elif defined(GLES_VARIETY_SGX)
10 # endif
11 #else
12 // GLX
13 #endif
14
15 typedef struct _Render_Engine Render_Engine;
16
17 struct _Render_Engine
18 {
19    Evas_GL_X11_Window      *win;
20    Evas_Engine_Info_GL_X11 *info;
21    Evas                    *evas;
22    int                      end;
23    
24    XrmDatabase   xrdb; // xres - dpi
25    struct { // xres - dpi
26       int        dpi; // xres - dpi
27    } xr; // xres - dpi
28    
29    int w, h;
30    int vsync;
31 };
32
33 static int initted = 0;
34 static int gl_wins = 0;
35
36 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
37
38 #ifndef EGL_NATIVE_PIXMAP_KHR
39 # define EGL_NATIVE_PIXMAP_KHR 0x30b0
40 #endif
41 typedef void (*_eng_fn) (void);
42
43 typedef _eng_fn (*glsym_func_eng_fn) ();
44 typedef void    (*glsym_func_void) ();
45 typedef void   *(*glsym_func_void_ptr) ();
46
47 _eng_fn  (*glsym_eglGetProcAddress)            (const char *a) = NULL;
48 void     (*glsym_eglBindTexImage)              (EGLDisplay a, EGLSurface b, int c) = NULL;
49 void     (*glsym_eglReleaseTexImage)           (EGLDisplay a, EGLSurface b, int c) = NULL;
50 void    *(*glsym_eglCreateImage)               (EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL;
51 void     (*glsym_eglDestroyImage)              (EGLDisplay a, void *b) = NULL;
52 void     (*glsym_glEGLImageTargetTexture2DOES) (int a, void *b)  = NULL;
53 #else
54 typedef void (*_eng_fn) (void);
55
56 typedef _eng_fn (*glsym_func_eng_fn) ();
57 typedef void    (*glsym_func_void) ();
58 typedef int     (*glsym_func_int) ();
59 typedef XID     (*glsym_func_xid) ();
60
61 _eng_fn  (*glsym_glXGetProcAddress)  (const char *a) = NULL;
62 void     (*glsym_glXBindTexImage)    (Display *a, GLXDrawable b, int c, int *d) = NULL;
63 void     (*glsym_glXReleaseTexImage) (Display *a, GLXDrawable b, int c) = NULL;
64 int      (*glsym_glXGetVideoSync)    (unsigned int *a) = NULL;
65 int      (*glsym_glXWaitVideoSync)   (int a, int b, unsigned int *c) = NULL;
66 XID      (*glsym_glXCreatePixmap)    (Display *a, void *b, Pixmap c, const int *d) = NULL;
67 void     (*glsym_glXDestroyPixmap)   (Display *a, XID b) = NULL;
68 void     (*glsym_glXQueryDrawable)   (Display *a, XID b, int c, unsigned int *d) = NULL;
69 #endif
70
71 static void
72 _sym_init(void)
73 {
74    static int done = 0;
75    
76    if (done) return;
77    
78 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
79 #define FINDSYM(dst, sym, typ) \
80    if ((!dst) && (glsym_eglGetProcAddress)) dst = (typ)glsym_eglGetProcAddress(sym); \
81    if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
82    
83    FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddress", glsym_func_eng_fn);
84    FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressEXT", glsym_func_eng_fn);
85    FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressARB", glsym_func_eng_fn);
86    FINDSYM(glsym_eglGetProcAddress, "eglGetProcAddressKHR", glsym_func_eng_fn);
87    
88    FINDSYM(glsym_eglBindTexImage, "eglBindTexImage", glsym_func_void);
89    FINDSYM(glsym_eglBindTexImage, "eglBindTexImageEXT", glsym_func_void);
90    FINDSYM(glsym_eglBindTexImage, "eglBindTexImageARB", glsym_func_void);
91    FINDSYM(glsym_eglBindTexImage, "eglBindTexImageKHR", glsym_func_void);
92    
93    FINDSYM(glsym_eglReleaseTexImage, "eglReleaseTexImage", glsym_func_void);
94    FINDSYM(glsym_eglReleaseTexImage, "eglReleaseTexImageEXT", glsym_func_void);
95    FINDSYM(glsym_eglReleaseTexImage, "eglReleaseTexImageARB", glsym_func_void);
96    FINDSYM(glsym_eglReleaseTexImage, "eglReleaseTexImageKHR", glsym_func_void);
97    
98    FINDSYM(glsym_eglCreateImage, "eglCreateImage", glsym_func_void_ptr);
99    FINDSYM(glsym_eglCreateImage, "eglCreateImageEXT", glsym_func_void_ptr);
100    FINDSYM(glsym_eglCreateImage, "eglCreateImageARB", glsym_func_void_ptr);
101    FINDSYM(glsym_eglCreateImage, "eglCreateImageKHR", glsym_func_void_ptr);
102
103    FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void);
104    FINDSYM(glsym_eglDestroyImage, "eglDestroyImageEXT", glsym_func_void);
105    FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void);
106    FINDSYM(glsym_eglDestroyImage, "eglDestroyImageKHR", glsym_func_void);
107
108    FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES", glsym_func_void);
109 #else
110 #define FINDSYM(dst, sym, typ) \
111    if ((!dst) && (glsym_glXGetProcAddress)) dst = (typ)glsym_glXGetProcAddress(sym); \
112    if (!dst) dst = (typ)dlsym(RTLD_DEFAULT, sym)
113
114    FINDSYM(glsym_glXGetProcAddress, "glXGetProcAddress", glsym_func_eng_fn);
115    FINDSYM(glsym_glXGetProcAddress, "glXGetProcAddressEXT", glsym_func_eng_fn);
116    FINDSYM(glsym_glXGetProcAddress, "glXGetProcAddressARB", glsym_func_eng_fn);
117    
118    FINDSYM(glsym_glXBindTexImage, "glXBindTexImage", glsym_func_void);
119    FINDSYM(glsym_glXBindTexImage, "glXBindTexImageEXT", glsym_func_void);
120    FINDSYM(glsym_glXBindTexImage, "glXBindTexImageARB", glsym_func_void);
121
122    FINDSYM(glsym_glXReleaseTexImage, "glXReleaseTexImage", glsym_func_void);
123    FINDSYM(glsym_glXReleaseTexImage, "glXReleaseTexImageEXT", glsym_func_void);
124    FINDSYM(glsym_glXReleaseTexImage, "glXReleaseTexImageARB", glsym_func_void);
125
126    FINDSYM(glsym_glXGetVideoSync, "glXGetVideoSyncSGI", glsym_func_int);
127    
128    FINDSYM(glsym_glXWaitVideoSync, "glXWaitVideoSyncSGI", glsym_func_int);
129
130    FINDSYM(glsym_glXCreatePixmap, "glXCreatePixmap", glsym_func_xid);
131    FINDSYM(glsym_glXCreatePixmap, "glXCreatePixmapEXT", glsym_func_xid);
132    FINDSYM(glsym_glXCreatePixmap, "glXCreatePixmapARB", glsym_func_xid);
133    
134    FINDSYM(glsym_glXDestroyPixmap, "glXDestroyPixmap", glsym_func_void);
135    FINDSYM(glsym_glXDestroyPixmap, "glXDestroyPixmapEXT", glsym_func_void);
136    FINDSYM(glsym_glXDestroyPixmap, "glXDestroyPixmapARB", glsym_func_void);
137    
138    FINDSYM(glsym_glXQueryDrawable, "glXQueryDrawable", glsym_func_void);
139    FINDSYM(glsym_glXQueryDrawable, "glXQueryDrawableEXT", glsym_func_void);
140    FINDSYM(glsym_glXQueryDrawable, "glXQueryDrawableARB", glsym_func_void);
141 #endif
142 }
143
144 int _evas_engine_GL_X11_log_dom = -1;
145 /* function tables - filled in later (func and parent func) */
146 static Evas_Func func, pfunc;
147
148 struct xrdb_user
149 {
150    time_t last_stat;
151    time_t last_mtime;
152    XrmDatabase db;
153 };
154 static struct xrdb_user xrdb_user = {0, 0, NULL};
155
156 static Eina_Bool
157 xrdb_user_query(const char *name, const char *cls, char **type, XrmValue *val)
158 {
159    time_t last = xrdb_user.last_stat, now = time(NULL);
160
161    xrdb_user.last_stat = now;
162    if (last != now) /* don't stat() more than once every second */
163      {
164         struct stat st;
165         const char *home = getenv("HOME");
166         char tmp[PATH_MAX];
167
168         if (!home) goto failed;
169         snprintf(tmp, sizeof(tmp), "%s/.Xdefaults", home);
170         if (stat(tmp, &st) != 0) goto failed;
171         if (xrdb_user.last_mtime != st.st_mtime)
172           {
173              if (xrdb_user.db) XrmDestroyDatabase(xrdb_user.db);
174              xrdb_user.db = XrmGetFileDatabase(tmp);
175              if (!xrdb_user.db) goto failed;
176              xrdb_user.last_mtime = st.st_mtime;
177           }
178      }
179
180    if (!xrdb_user.db) return EINA_FALSE;
181    return XrmGetResource(xrdb_user.db, name, cls, type, val);
182
183  failed:
184    if (xrdb_user.db)
185      {
186         XrmDestroyDatabase(xrdb_user.db);
187         xrdb_user.db = NULL;
188      }
189    xrdb_user.last_mtime = 0;
190    return EINA_FALSE;
191 }
192
193 static void *
194 eng_info(Evas *e)
195 {
196    Evas_Engine_Info_GL_X11 *info;
197
198    info = calloc(1, sizeof(Evas_Engine_Info_GL_X11));
199    info->magic.magic = rand();
200    info->func.best_visual_get = eng_best_visual_get;
201    info->func.best_colormap_get = eng_best_colormap_get;
202    info->func.best_depth_get = eng_best_depth_get;
203    info->render_mode = EVAS_RENDER_MODE_BLOCKING;
204    return info;
205    e = NULL;
206 }
207
208 static void
209 eng_info_free(Evas *e __UNUSED__, void *info)
210 {
211    Evas_Engine_Info_GL_X11 *in;
212 // dont free! why bother? its not worth it   
213 //   eina_log_domain_unregister(_evas_engine_GL_X11_log_dom);
214    in = (Evas_Engine_Info_GL_X11 *)info;
215    free(in);
216 }
217
218 static int
219 _re_wincheck(Render_Engine *re)
220 {
221    if (re->win->surf) return 1;
222    eng_window_resurf(re->win);
223    if (!re->win->surf)
224      {
225         ERR("GL engine can't re-create window surface!");
226      }
227    return 0;
228 }
229
230 static void
231 _re_winfree(Render_Engine *re)
232 {
233    if (!re->win->surf) return;
234    eng_window_unsurf(re->win);
235 }
236
237 static int
238 eng_setup(Evas *e, void *in)
239 {
240    Render_Engine *re;
241    Evas_Engine_Info_GL_X11 *info;
242
243    info = (Evas_Engine_Info_GL_X11 *)in;
244    if (!e->engine.data.output)
245      {
246 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
247 #else        
248         int eb, evb;
249         
250         if (!glXQueryExtension(info->info.display, &eb, &evb)) return 0;
251 #endif
252         re = calloc(1, sizeof(Render_Engine));
253         if (!re) return 0;
254         re->info = info;
255         re->evas = e;
256         e->engine.data.output = re;
257         re->w = e->output.w;
258         re->h = e->output.h;
259         re->win = eng_window_new(re->info->info.display,
260                                  re->info->info.drawable,
261                                  re->info->info.screen,
262                                  re->info->info.visual,
263                                  re->info->info.colormap,
264                                  re->info->info.depth,
265                                  re->w,
266                                  re->h,
267                                  re->info->indirect,
268                                  re->info->info.destination_alpha,
269                                  re->info->info.rotation);
270         if (!re->win)
271           {
272              free(re);
273              e->engine.data.output = NULL;
274              return 0;
275           }
276         gl_wins++;
277         
278           {
279              int status;
280              char *type = NULL;
281              XrmValue val;
282              
283              re->xr.dpi = 75000; // dpy * 1000
284
285              status = xrdb_user_query("Xft.dpi", "Xft.Dpi", &type, &val);
286              if ((!status) || (!type))
287                {
288                   if (!re->xrdb) re->xrdb = XrmGetDatabase(re->info->info.display);
289                   if (re->xrdb)
290                     status = XrmGetResource(re->xrdb,
291                                             "Xft.dpi", "Xft.Dpi", &type, &val);
292                }
293
294              if ((status) && (type))
295                {
296                   if (!strcmp(type, "String"))
297                     {
298                        const char *str, *dp;
299                        
300                        str = val.addr;
301                        dp = strchr(str, '.');
302                        if (!dp) dp = strchr(str, ',');
303                        
304                        if (dp)
305                          {
306                             int subdpi, len, i;
307                             char *buf;
308                             
309                             buf = alloca(dp - str + 1);
310                             strncpy(buf, str, dp - str);
311                             buf[dp - str] = 0;
312                             len = strlen(dp + 1);
313                             subdpi = atoi(dp + 1);
314                             
315                             if (len < 3)
316                               {
317                                  for (i = len; i < 3; i++) subdpi *= 10;
318                               }
319                             else if (len > 3)
320                               {
321                                  for (i = len; i > 3; i--) subdpi /= 10;
322                               }
323                             re->xr.dpi = atoi(buf) * 1000;
324                          }
325                        else
326                          re->xr.dpi = atoi(str) * 1000;
327                        evas_common_font_dpi_set(re->xr.dpi / 1000);
328                     }
329                }
330           }
331
332         if (!initted)
333           {
334              evas_common_cpu_init();
335              
336              evas_common_blend_init();
337              evas_common_image_init();
338              evas_common_convert_init();
339              evas_common_scale_init();
340              evas_common_rectangle_init();
341              evas_common_polygon_init();
342              evas_common_line_init();
343              evas_common_font_init();
344              evas_common_draw_init();
345              evas_common_tilebuf_init();
346              initted = 1;
347           }
348      }
349    else
350      {
351         re = e->engine.data.output;
352         if (_re_wincheck(re))
353           {
354              if ((re->info->info.display != re->win->disp) ||
355                  (re->info->info.drawable != re->win->win) ||
356                  (re->info->info.screen != re->win->screen) ||
357                  (re->info->info.visual != re->win->visual) ||
358                  (re->info->info.colormap != re->win->colormap) ||
359                  (re->info->info.depth != re->win->depth) ||
360                  (re->info->info.destination_alpha != re->win->alpha) ||
361                  (re->info->info.rotation != re->win->rot))
362                {
363                   int inc = 0;
364                   
365                   if (re->win)
366                     {
367                        re->win->gl_context->references++;
368                        eng_window_free(re->win);
369                        inc = 1;
370                        gl_wins--;
371                     }
372                   re->w = e->output.w;
373                   re->h = e->output.h;
374                   re->win = eng_window_new(re->info->info.display,
375                                            re->info->info.drawable,
376                                            re->info->info.screen,
377                                            re->info->info.visual,
378                                            re->info->info.colormap,
379                                            re->info->info.depth,
380                                            re->w,
381                                            re->h,
382                                            re->info->indirect,
383                                            re->info->info.destination_alpha,
384                                            re->info->info.rotation);
385                   if (re->win) gl_wins++;
386                   if ((re->win) && (inc))
387                      re->win->gl_context->references--;
388                }
389              else if ((re->win->w != e->output.w) ||
390                       (re->win->h != e->output.h))
391                {
392                   re->w = e->output.w;
393                   re->h = e->output.h;
394                   re->win->w = e->output.w;
395                   re->win->h = e->output.h;
396                   eng_window_use(re->win);
397                   evas_gl_common_context_resize(re->win->gl_context, re->win->w, re->win->h, re->win->rot);
398                }
399           }
400      }
401    if (!re->win)
402      {
403         free(re);
404         return 0;
405      }
406    
407    if (!e->engine.data.output)
408      {
409         if (re->win)
410           {
411              eng_window_free(re->win);
412              gl_wins--;
413           }
414         free(re);
415         return 0;
416      }
417    if (!e->engine.data.context)
418      e->engine.data.context =
419      e->engine.func->context_new(e->engine.data.output);
420    eng_window_use(re->win);
421    
422    re->vsync = 0;
423    if (re->win->alpha)
424      {
425         glClearColor(0.0, 0.0, 0.0, 0.0);
426         glClear(GL_COLOR_BUFFER_BIT);
427      }
428    
429    _sym_init();
430    
431    return 1;
432 }
433
434 static void
435 eng_output_free(void *data)
436 {
437    Render_Engine *re;
438
439    re = (Render_Engine *)data;
440    
441    if (re)
442      {
443 // NOTE: XrmGetDatabase() result is shared per connection, do not free it.
444 //   if (re->xrdb) XrmDestroyDatabase(re->xrdb);
445
446         if (re->win)
447           {
448              eng_window_free(re->win);
449              gl_wins--;
450           }
451         free(re);
452      }
453    if ((initted == 1) && (gl_wins == 0))
454      {
455         evas_common_image_shutdown();
456         evas_common_font_shutdown();
457         initted = 0;
458      }
459 }
460
461 static void
462 eng_output_resize(void *data, int w, int h)
463 {
464    Render_Engine *re;
465
466    re = (Render_Engine *)data;
467    re->win->w = w;
468    re->win->h = h;
469    eng_window_use(re->win);
470    evas_gl_common_context_resize(re->win->gl_context, w, h, re->win->rot);
471 }
472
473 static void
474 eng_output_tile_size_set(void *data __UNUSED__, int w __UNUSED__, int h __UNUSED__)
475 {
476 }
477
478 static void
479 eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
480 {
481    Render_Engine *re;
482
483    re = (Render_Engine *)data;
484    evas_gl_common_context_resize(re->win->gl_context, re->win->w, re->win->h, re->win->rot);
485    /* smple bounding box */
486    RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, re->win->w, re->win->h);
487    if ((w <= 0) || (h <= 0)) return;
488    if (!re->win->draw.redraw)
489      {
490 #if 0
491         re->win->draw.x1 = x;
492         re->win->draw.y1 = y;
493         re->win->draw.x2 = x + w - 1;
494         re->win->draw.y2 = y + h - 1;
495 #else
496         re->win->draw.x1 = 0;
497         re->win->draw.y1 = 0;
498         re->win->draw.x2 = re->win->w - 1;
499         re->win->draw.y2 = re->win->h - 1;
500 #endif
501      }
502    else
503      {
504         if (x < re->win->draw.x1) re->win->draw.x1 = x;
505         if (y < re->win->draw.y1) re->win->draw.y1 = y;
506         if ((x + w - 1) > re->win->draw.x2) re->win->draw.x2 = x + w - 1;
507         if ((y + h - 1) > re->win->draw.y2) re->win->draw.y2 = y + h - 1;
508      }
509    re->win->draw.redraw = 1;
510 }
511
512 static void
513 eng_output_redraws_rect_del(void *data __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
514 {
515 }
516
517 static void
518 eng_output_redraws_clear(void *data)
519 {
520    Render_Engine *re;
521
522    re = (Render_Engine *)data;
523    re->win->draw.redraw = 0;
524 //   INF("GL: finish update cycle!");
525 }
526
527 /* vsync games - not for now though */
528 #define VSYNC_TO_SCREEN 1
529
530 static void *
531 eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
532 {
533    Render_Engine *re;
534
535    re = (Render_Engine *)data;
536    /* get the upate rect surface - return engine data as dummy */
537    if (!re->win->draw.redraw) return NULL;
538    if (!_re_wincheck(re)) return NULL;
539    evas_gl_common_context_flush(re->win->gl_context);
540    eng_window_use(re->win);
541    evas_gl_common_context_newframe(re->win->gl_context);
542    if (x) *x = re->win->draw.x1;
543    if (y) *y = re->win->draw.y1;
544    if (w) *w = re->win->draw.x2 - re->win->draw.x1 + 1;
545    if (h) *h = re->win->draw.y2 - re->win->draw.y1 + 1;
546    if (cx) *cx = re->win->draw.x1;
547    if (cy) *cy = re->win->draw.y1;
548    if (cw) *cw = re->win->draw.x2 - re->win->draw.x1 + 1;
549    if (ch) *ch = re->win->draw.y2 - re->win->draw.y1 + 1;
550    return re->win->gl_context->def_surface;
551 }
552
553 //#define FRAMECOUNT 1
554
555 #ifdef FRAMECOUNT
556 double
557 get_time(void)
558 {
559    struct timeval      timev;
560    
561    gettimeofday(&timev, NULL);
562    return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
563 }
564 #endif
565
566 static int safe_native = -1;
567
568 static void
569 eng_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__)
570 {
571    Render_Engine *re;
572 #ifdef FRAMECOUNT
573    static double pt = 0.0;
574    double ta, tb;
575 #endif
576    
577    re = (Render_Engine *)data;
578    /* put back update surface.. in this case just unflag redraw */
579    if (!_re_wincheck(re)) return;
580    re->win->draw.redraw = 0;
581    re->win->draw.drew = 1;
582    evas_gl_common_context_flush(re->win->gl_context);
583    if (safe_native == -1)
584      {
585         const char *s = getenv("EVAS_GL_SAFE_NATIVE");
586         safe_native = 0;
587         if (s) safe_native = atoi(s);
588         else
589           {
590              s = (const char *)glGetString(GL_RENDERER);
591              if (s)
592                {
593                   if (strstr(s, "PowerVR SGX 540"))
594                      safe_native = 1;
595                }
596           }
597      }
598 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
599    // this is needed to make sure all previous rendering is flushed to
600    // buffers/surfaces
601 #ifdef FRAMECOUNT
602    double t0 = get_time();
603    ta = t0 - pt;
604    pt = t0;
605 #endif
606    // previous rendering should be done and swapped
607    if (!safe_native) eglWaitNative(EGL_CORE_NATIVE_ENGINE);
608 #ifdef FRAMECOUNT
609    double t1 = get_time();
610    tb = t1 - t0;
611    printf("... %1.5f -> %1.5f | ", ta, tb);
612 #endif   
613 //   if (eglGetError() != EGL_SUCCESS)
614 //     {
615 //        printf("Error:  eglWaitNative(EGL_CORE_NATIVE_ENGINE) fail.\n");
616 //     }
617 #else
618    // previous rendering should be done and swapped
619    if (!safe_native) glXWaitX();
620 #endif
621 //x//   printf("frame -> push\n");
622 }
623
624 static void
625 eng_output_flush(void *data)
626 {
627    Render_Engine *re;
628
629    re = (Render_Engine *)data;
630    if (!_re_wincheck(re)) return;
631    if (!re->win->draw.drew) return;
632 //x//   printf("frame -> flush\n");
633    re->win->draw.drew = 0;
634    eng_window_use(re->win);
635
636 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
637 #ifdef FRAMECOUNT
638    double t0 = get_time();
639 #endif
640    if (!re->vsync)
641      {
642         if (re->info->vsync) eglSwapInterval(re->win->egl_disp, 1);
643         else eglSwapInterval(re->win->egl_disp, 0);
644         re->vsync = 1;
645      }
646    eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]);
647    if (!safe_native) eglWaitGL();
648 #ifdef FRAMECOUNT
649    double t1 = get_time();
650    printf("%1.5f\n", t1 - t0);
651 #endif   
652 //   if (eglGetError() != EGL_SUCCESS)
653 //     {
654 //        printf("Error:  eglSwapBuffers() fail.\n");
655 //     }
656 #else
657 #ifdef VSYNC_TO_SCREEN   
658    if ((re->info->vsync)/* || (1)*/)
659      {
660         if ((glsym_glXGetVideoSync) && (glsym_glXWaitVideoSync))
661           {
662              unsigned int rc;
663              
664              glsym_glXGetVideoSync(&rc);
665              glsym_glXWaitVideoSync(1, 0, &rc);
666           }
667      }
668 # endif
669    if (re->info->callback.pre_swap)
670      {
671         re->info->callback.pre_swap(re->info->callback.data, re->evas);
672      }
673 /*   
674    if ((1)
675 //       (re->win->draw.x1 == 0) && 
676 //       (re->win->draw.y1 == 0) &&
677 //       (re->win->draw.x2 == (re->win->w - 1)) &&
678 //       (re->win->draw.y2 == (re->win->h - 1))
679        )
680  */
681      {
682         glXSwapBuffers(re->win->disp, re->win->win);
683         if (!safe_native) glXWaitGL();
684      }
685 /*   
686    else
687      {
688 // FIXME: this doesn't work.. why oh why?        
689         int sx, sy, sw, sh;
690         
691         // fimxe - reset when done
692 //        glEnable(GL_SCISSOR_TEST);
693         glDrawBuffer(GL_FRONT);
694         
695         sx = re->win->draw.x1;
696         sy = re->win->draw.y1;
697         sw = (re->win->draw.x2 - re->win->draw.x1) + 1;
698         sh = (re->win->draw.y2 - re->win->draw.y1) + 1;
699         sy = re->win->h - sy - sh;
700
701 //        glScissor(sx, sy, sw, sh);
702         glRasterPos2i(sx, re->win->h - sy);
703         glCopyPixels(sx, sy, sw, sh, GL_COLOR);
704         glRasterPos2i(0, 0);
705         
706 //        glDisable(GL_SCISSOR_TEST);
707         glDrawBuffer(GL_BACK);
708         glFlush();
709      }
710  */
711    if (re->info->callback.post_swap)
712      {
713         re->info->callback.post_swap(re->info->callback.data, re->evas);
714      }
715 #endif
716    
717    if (re->win->alpha)
718      {
719         glClearColor(0.0, 0.0, 0.0, 0.0);
720         glClear(GL_COLOR_BUFFER_BIT);
721      }
722 }
723
724 static void
725 eng_output_idle_flush(void *data)
726 {
727    Render_Engine *re;
728
729    re = (Render_Engine *)data;
730 }
731
732 static void
733 eng_output_dump(void *data)
734 {
735    Render_Engine *re;
736
737    re = (Render_Engine *)data;
738    evas_common_image_image_all_unload();
739    evas_common_font_font_all_unload();
740    evas_gl_common_image_all_unload(re->win->gl_context);
741    _re_winfree(re);
742 }
743
744 static void
745 eng_context_cutout_add(void *data __UNUSED__, void *context, int x, int y, int w, int h)
746 {
747 //   Render_Engine *re;
748 //
749 //   re = (Render_Engine *)data;
750 //   re->win->gl_context->dc = context;
751    evas_common_draw_context_add_cutout(context, x, y, w, h);
752 }
753
754 static void
755 eng_context_cutout_clear(void *data __UNUSED__, void *context)
756 {
757 //   Render_Engine *re;
758 //
759 //   re = (Render_Engine *)data;
760 //   re->win->gl_context->dc = context;
761    evas_common_draw_context_clear_cutouts(context);
762 }
763
764 static void
765 eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h)
766 {
767    Render_Engine *re;
768
769    re = (Render_Engine *)data;
770    eng_window_use(re->win);
771    evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
772    re->win->gl_context->dc = context;
773    evas_gl_common_rect_draw(re->win->gl_context, x, y, w, h);
774 }
775
776 static void
777 eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2)
778 {
779    Render_Engine *re;
780
781    re = (Render_Engine *)data;
782    eng_window_use(re->win);
783    evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
784    re->win->gl_context->dc = context;
785    evas_gl_common_line_draw(re->win->gl_context, x1, y1, x2, y2);
786 }
787
788 static void *
789 eng_polygon_point_add(void *data, void *context __UNUSED__, void *polygon, int x, int y)
790 {
791    Render_Engine *re;
792
793    re = (Render_Engine *)data;
794    return evas_gl_common_poly_point_add(polygon, x, y);
795 }
796
797 static void *
798 eng_polygon_points_clear(void *data, void *context __UNUSED__, void *polygon)
799 {
800    Render_Engine *re;
801
802    re = (Render_Engine *)data;
803    return evas_gl_common_poly_points_clear(polygon);
804 }
805
806 static void
807 eng_polygon_draw(void *data, void *context, void *surface __UNUSED__, void *polygon, int x, int y)
808 {
809    Render_Engine *re;
810
811    re = (Render_Engine *)data;
812    eng_window_use(re->win);
813    evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
814    re->win->gl_context->dc = context;
815    evas_gl_common_poly_draw(re->win->gl_context, polygon, x, y);
816 }
817
818 static int
819 eng_image_alpha_get(void *data __UNUSED__, void *image)
820 {
821 //   Render_Engine *re;
822    Evas_GL_Image *im;
823
824 //   re = (Render_Engine *)data;
825    if (!image) return 1;
826    im = image;
827    return im->alpha;
828 }
829
830 static int
831 eng_image_colorspace_get(void *data __UNUSED__, void *image)
832 {
833 //   Render_Engine *re;
834    Evas_GL_Image *im;
835
836 //   re = (Render_Engine *)data;
837    if (!image) return EVAS_COLORSPACE_ARGB8888;
838    im = image;
839    return im->cs.space;
840 }
841
842 static void
843 eng_image_mask_create(void *data __UNUSED__, void *image)
844 {
845    Evas_GL_Image *im;
846
847    if (!image) return;
848    im = image;
849    if (!im->im->image.data)
850       evas_cache_image_load_data(&im->im->cache_entry);
851    if (!im->tex)
852       im->tex = evas_gl_common_texture_new(im->gc, im->im);
853 }
854
855
856 static void *
857 eng_image_alpha_set(void *data, void *image, int has_alpha)
858 {
859    Render_Engine *re;
860    Evas_GL_Image *im;
861
862    re = (Render_Engine *)data;
863    if (!image) return NULL;
864    im = image;
865    if (im->alpha == has_alpha) return image;
866    if (im->native.data)
867      {
868         im->alpha = has_alpha;
869         return image;
870      }
871    eng_window_use(re->win);
872    if ((im->tex) && (im->tex->pt->dyn.img))
873      {
874         im->alpha = has_alpha;
875         im->tex->alpha = im->alpha;
876         return image;
877      }
878    /* FIXME: can move to gl_common */
879    if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return im;
880    if ((has_alpha) && (im->im->cache_entry.flags.alpha)) return image;
881    else if ((!has_alpha) && (!im->im->cache_entry.flags.alpha)) return image;
882    if (im->references > 1)
883      {
884         Evas_GL_Image *im_new;
885         
886         im_new = evas_gl_common_image_new_from_copied_data
887            (im->gc, im->im->cache_entry.w, im->im->cache_entry.h, 
888                im->im->image.data,
889                eng_image_alpha_get(data, image),
890                eng_image_colorspace_get(data, image));
891         if (!im_new) return im;
892         evas_gl_common_image_free(im);
893         im = im_new;
894      }
895    else
896      evas_gl_common_image_dirty(im, 0, 0, 0, 0);
897    return evas_gl_common_image_alpha_set(im, has_alpha ? 1 : 0);
898 //   im->im->cache_entry.flags.alpha = has_alpha ? 1 : 0;
899 //   return image;
900 }
901
902 static void *
903 eng_image_border_set(void *data __UNUSED__, void *image, int l __UNUSED__, int r __UNUSED__, int t __UNUSED__, int b __UNUSED__)
904 {
905 //   Render_Engine *re;
906 //
907 //   re = (Render_Engine *)data;
908    return image;
909 }
910
911 static void
912 eng_image_border_get(void *data __UNUSED__, void *image __UNUSED__, int *l __UNUSED__, int *r __UNUSED__, int *t __UNUSED__, int *b __UNUSED__)
913 {
914 //   Render_Engine *re;
915 //
916 //   re = (Render_Engine *)data;
917 }
918
919 static char *
920 eng_image_comment_get(void *data __UNUSED__, void *image, char *key __UNUSED__)
921 {
922 //   Render_Engine *re;
923    Evas_GL_Image *im;
924
925 //   re = (Render_Engine *)data;
926    if (!image) return NULL;
927    im = image;
928    if (!im->im) return NULL;
929    return im->im->info.comment;
930 }
931
932 static char *
933 eng_image_format_get(void *data __UNUSED__, void *image)
934 {
935 //   Render_Engine *re;
936    Evas_GL_Image *im;
937
938 //   re = (Render_Engine *)data;
939    im = image;
940    return NULL;
941 }
942
943 static void
944 eng_image_colorspace_set(void *data, void *image, int cspace)
945 {
946    Render_Engine *re;
947    Evas_GL_Image *im;
948
949    re = (Render_Engine *)data;
950    if (!image) return;
951    im = image;
952    if (im->native.data) return;
953    /* FIXME: can move to gl_common */
954    if (im->cs.space == cspace) return;
955    eng_window_use(re->win);
956    evas_cache_image_colorspace(&im->im->cache_entry, cspace);
957    switch (cspace)
958      {
959       case EVAS_COLORSPACE_ARGB8888:
960         if (im->cs.data)
961           {
962              if (!im->cs.no_free) free(im->cs.data);
963              im->cs.data = NULL;
964              im->cs.no_free = 0;
965           }
966         break;
967       case EVAS_COLORSPACE_YCBCR422P601_PL:
968       case EVAS_COLORSPACE_YCBCR422P709_PL:
969         if (im->tex) evas_gl_common_texture_free(im->tex);
970         im->tex = NULL;
971         if (im->cs.data)
972           {
973              if (!im->cs.no_free) free(im->cs.data);
974           }
975         if (im->im->cache_entry.h > 0)
976           im->cs.data = 
977           calloc(1, im->im->cache_entry.h * sizeof(unsigned char *) * 2);
978         else
979           im->cs.data = NULL;
980         im->cs.no_free = 0;
981         break;
982       default:
983         abort();
984         break;
985      }
986    im->cs.space = cspace;
987 }
988
989 /////////////////////////////////////////////////////////////////////////
990 //
991 //
992 typedef struct _Native Native;
993
994 struct _Native
995 {
996    Evas_Native_Surface ns;
997    Pixmap     pixmap;
998    Visual    *visual;
999    
1000 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
1001    void      *egl_surface;
1002 #else
1003    void  *fbc;
1004    XID    glx_pixmap;
1005 #endif
1006 };
1007
1008 // FIXME: this is enabled so updates happen - but its SLOOOOOOOOOOOOOOOW
1009 // (i am sure this is the reason)  not to mention seemingly superfluous. but
1010 // i need to enable it for it to work on fglrx at least. havent tried nvidia.
1011 // 
1012 // why is this the case? does anyone know? has anyone tried it on other gfx
1013 // drivers?
1014 // 
1015 //#define GLX_TEX_PIXMAP_RECREATE 1
1016
1017 static void
1018 _native_bind_cb(void *data, void *image)
1019 {
1020    Evas_GL_Image *im = image;
1021    Native *n = im->native.data;
1022    
1023 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
1024    if (n->egl_surface)
1025      {
1026         if (glsym_glEGLImageTargetTexture2DOES)
1027           {
1028              glsym_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, n->egl_surface);
1029              if (eglGetError() != EGL_SUCCESS)
1030                ERR("glEGLImageTargetTexture2DOES() failed.");
1031           }
1032         else
1033           ERR("Try glEGLImageTargetTexture2DOES on EGL with no support");
1034      }
1035 #else
1036 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
1037    Render_Engine *re = data;
1038    
1039    if (glsym_glXBindTexImage)
1040      {
1041         glsym_glXBindTexImage(re->win->disp, n->glx_pixmap, 
1042                               GLX_FRONT_LEFT_EXT, NULL);
1043         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
1044      }
1045    else
1046      ERR("Try glXBindTexImage on GLX with no support");
1047 # endif
1048 #endif
1049 }
1050
1051 static void
1052 _native_unbind_cb(void *data, void *image)
1053 {
1054    Evas_GL_Image *im = image;
1055
1056 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
1057    // nothing
1058 #else
1059 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
1060    Render_Engine *re = data;
1061    Native *n = im->native.data;
1062    
1063    if (glsym_glXReleaseTexImage)
1064      {
1065         glsym_glXReleaseTexImage(re->win->disp, n->glx_pixmap, 
1066                                  GLX_FRONT_LEFT_EXT);
1067         GLERR(__FUNCTION__, __FILE__, __LINE__, "");
1068      }
1069    else
1070      ERR("Try glXReleaseTexImage on GLX with no support");
1071 # endif
1072 #endif
1073 }
1074
1075 static void
1076 _native_free_cb(void *data, void *image)
1077 {
1078    Render_Engine *re = data;
1079    Evas_GL_Image *im = image;
1080    Native *n = im->native.data;
1081    uint32_t pmid;
1082
1083    pmid = n->pixmap;
1084    eina_hash_del(re->win->gl_context->shared->native_hash, &pmid, im);
1085 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
1086    if (n->egl_surface)
1087      {
1088         if (glsym_eglDestroyImage)
1089           {
1090              glsym_eglDestroyImage(re->win->egl_disp,
1091                                    n->egl_surface);
1092              if (eglGetError() != EGL_SUCCESS)
1093                ERR("eglDestroyImage() failed.");
1094           }
1095         else
1096           ERR("Try eglDestroyImage on EGL with no support");
1097      }
1098 #else
1099 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
1100    if (n->glx_pixmap)
1101      {
1102         if (im->native.loose)
1103           {
1104              if (glsym_glXReleaseTexImage)
1105                {
1106                   glsym_glXReleaseTexImage(re->win->disp, n->glx_pixmap,
1107                                            GLX_FRONT_LEFT_EXT);
1108                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
1109                }
1110              else
1111                ERR("Try glXReleaseTexImage on GLX with no support");
1112           }
1113         if (glsym_glXDestroyPixmap)
1114           {
1115              glsym_glXDestroyPixmap(re->win->disp, n->glx_pixmap);
1116              GLERR(__FUNCTION__, __FILE__, __LINE__, "");
1117           }
1118         else
1119            ERR("Try glXDestroyPixmap on GLX with no support");
1120         n->glx_pixmap = 0;
1121      }
1122 # endif
1123 #endif
1124    im->native.data        = NULL;
1125    im->native.func.data   = NULL;
1126    im->native.func.bind   = NULL;
1127    im->native.func.unbind = NULL;
1128    im->native.func.free   = NULL;
1129    free(n);
1130 }
1131
1132 static void *
1133 eng_image_native_set(void *data, void *image, void *native)
1134 {
1135    Render_Engine *re = (Render_Engine *)data;
1136    Evas_Native_Surface *ns = native;
1137    Evas_GL_Image *im = image, *im2 = NULL;
1138    Visual *vis = NULL;
1139    Pixmap pm = 0;
1140    Native *n = NULL;
1141    uint32_t pmid;
1142    
1143    if (!im) return NULL;
1144    
1145    if (ns)
1146      {
1147         vis = ns->data.x11.visual;
1148         pm = ns->data.x11.pixmap;
1149         if (im->native.data)
1150           {
1151              Evas_Native_Surface *ens = im->native.data;
1152              if ((ens->data.x11.visual == vis) && (ens->data.x11.pixmap == pm))
1153                 return im;
1154           }
1155      }
1156    if ((!ns) && (!im->native.data)) return im;
1157    
1158    eng_window_use(re->win);
1159    
1160    if (im->native.data)
1161      {
1162         if (im->native.func.free)
1163            im->native.func.free(im->native.func.data, im);
1164         evas_gl_common_image_native_disable(im);
1165      }
1166    
1167    pmid = pm;
1168    im2 = eina_hash_find(re->win->gl_context->shared->native_hash, &pmid);
1169    if (im2 == im) return im;
1170    if (im2)
1171      {
1172         n = im2->native.data;
1173         if (n)
1174           {
1175              im2->references++;
1176              evas_gl_common_image_free(im);
1177              return im2;
1178           }
1179      }
1180    im2 = evas_gl_common_image_new_from_data(re->win->gl_context, 
1181                                             im->w, im->h, NULL, im->alpha,
1182                                             EVAS_COLORSPACE_ARGB8888);
1183    evas_gl_common_image_free(im);
1184    im = im2;
1185 #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX)
1186    if (native) 
1187      {
1188         n = calloc(1, sizeof(Native));
1189         if (n)
1190           {
1191              EGLConfig egl_config;
1192              int config_attrs[20];
1193              int num_config, i = 0;
1194              
1195              eina_hash_add(re->win->gl_context->shared->native_hash, &pmid, im);
1196                   
1197              config_attrs[i++] = EGL_RED_SIZE;
1198              config_attrs[i++] = 8;
1199              config_attrs[i++] = EGL_GREEN_SIZE;
1200              config_attrs[i++] = 8;
1201              config_attrs[i++] = EGL_BLUE_SIZE;
1202              config_attrs[i++] = 8;
1203              config_attrs[i++] = EGL_ALPHA_SIZE;
1204              config_attrs[i++] = 8;
1205              config_attrs[i++] = EGL_DEPTH_SIZE;
1206              config_attrs[i++] = 0;
1207              config_attrs[i++] = EGL_STENCIL_SIZE;
1208              config_attrs[i++] = 0;
1209              config_attrs[i++] = EGL_RENDERABLE_TYPE;
1210              config_attrs[i++] = EGL_OPENGL_ES2_BIT;
1211              config_attrs[i++] = EGL_SURFACE_TYPE;
1212              config_attrs[i++] = EGL_PIXMAP_BIT;
1213              config_attrs[i++] = EGL_NONE;
1214              
1215              if (!eglChooseConfig(re->win->egl_disp, config_attrs, 
1216                                   &egl_config, 1, &num_config))
1217                ERR("eglChooseConfig() failed for pixmap 0x%x, num_config = %i", (unsigned int)pm, num_config);
1218              n->pixmap = pm;
1219              n->visual = vis;
1220              if (glsym_eglCreateImage)
1221                 n->egl_surface = glsym_eglCreateImage(re->win->egl_disp,
1222                                                       EGL_NO_CONTEXT,
1223                                                       EGL_NATIVE_PIXMAP_KHR,
1224                                                       (void *)pm,
1225                                                       NULL);
1226              else
1227                ERR("Try eglCreateImage on EGL with no support");
1228              if (!n->egl_surface)
1229                ERR("eglCreatePixmapSurface() for 0x%x failed", (unsigned int)pm);
1230              im->native.yinvert     = 1;
1231              im->native.loose       = 0;
1232              im->native.data        = n;
1233              im->native.func.data   = re;
1234              im->native.func.bind   = _native_bind_cb;
1235              im->native.func.unbind = _native_unbind_cb;
1236              im->native.func.free   = _native_free_cb;
1237              im->native.target      = GL_TEXTURE_2D;
1238              im->native.mipmap      = 0;
1239              evas_gl_common_image_native_enable(im);
1240           }
1241      }
1242 #else
1243 # ifdef GLX_BIND_TO_TEXTURE_TARGETS_EXT
1244    if (native)
1245      {
1246         int dummy;
1247         unsigned int w, h, depth = 32, border;
1248         Window wdummy;
1249
1250         // fixme: round trip :(
1251         XGetGeometry(re->win->disp, pm, &wdummy, &dummy, &dummy, 
1252                      &w, &h, &border, &depth);
1253         n = calloc(1, sizeof(Native));
1254         if (n)
1255           {
1256              int pixmap_att[20];
1257              unsigned int target = 0;
1258              unsigned int i = 0;
1259
1260              eina_hash_add(re->win->gl_context->shared->native_hash, &pmid, im);
1261              if ((re->win->depth_cfg[depth].tex_target &
1262                   GLX_TEXTURE_2D_BIT_EXT) 
1263 //                 && (1) // we assume npo2 for now
1264                  // size is pow2 || mnpo2 supported
1265                 )
1266                 target = GLX_TEXTURE_2D_EXT;
1267              else if ((re->win->depth_cfg[depth].tex_target &
1268                        GLX_TEXTURE_RECTANGLE_BIT_EXT))
1269                {
1270                   ERR("rect!!! (not handled)");
1271                   target = GLX_TEXTURE_RECTANGLE_EXT;
1272                }
1273              if (!target)
1274                {
1275                   ERR("broken text-from-pixmap");
1276                   if (!(re->win->depth_cfg[depth].tex_target &
1277                         GLX_TEXTURE_2D_BIT_EXT))
1278                      target = GLX_TEXTURE_RECTANGLE_EXT;
1279                   else if (!(re->win->depth_cfg[depth].tex_target &
1280                              GLX_TEXTURE_RECTANGLE_BIT_EXT))
1281                      target = GLX_TEXTURE_2D_EXT;
1282                }
1283              
1284              
1285              pixmap_att[i++] = GLX_TEXTURE_FORMAT_EXT;
1286              pixmap_att[i++] = re->win->depth_cfg[depth].tex_format;
1287              pixmap_att[i++] = GLX_MIPMAP_TEXTURE_EXT;
1288              pixmap_att[i++] = re->win->depth_cfg[depth].mipmap;
1289              
1290              if (target)
1291                {
1292                   pixmap_att[i++] = GLX_TEXTURE_TARGET_EXT;
1293                   pixmap_att[i++] = target;
1294                }
1295              
1296              pixmap_att[i++] = 0;
1297              
1298              memcpy(&(n->ns), ns, sizeof(Evas_Native_Surface));
1299              n->pixmap = pm;
1300              n->visual = vis;
1301              n->fbc = re->win->depth_cfg[depth].fbc;
1302              if (glsym_glXCreatePixmap)
1303                 n->glx_pixmap = glsym_glXCreatePixmap(re->win->disp, 
1304                                                       n->fbc, 
1305                                                       n->pixmap, 
1306                                                       pixmap_att);
1307              else
1308                ERR("Try glXCreatePixmap on GLX with no support");
1309              if (n->glx_pixmap)
1310                {
1311 //                  printf("%p: new native texture for %x | %4i x %4i @ %2i = %p\n",
1312 //                         n, pm, w, h, depth, n->glx_pixmap);
1313                   if (!target)
1314                     {
1315                        ERR("no target :(");
1316                        if (glsym_glXQueryDrawable)
1317                           glsym_glXQueryDrawable(re->win->disp,
1318                                                  n->pixmap, 
1319                                                  GLX_TEXTURE_TARGET_EXT, 
1320                                                  &target);
1321                     }
1322                   if (target == GLX_TEXTURE_2D_EXT)
1323                     {
1324                        im->native.target = GL_TEXTURE_2D;
1325                        im->native.mipmap = re->win->depth_cfg[depth].mipmap;
1326                     }
1327 #  ifdef GL_TEXTURE_RECTANGLE_ARB             
1328                   else if (target == GLX_TEXTURE_RECTANGLE_EXT)
1329                     {
1330                        im->native.target = GL_TEXTURE_RECTANGLE_ARB;
1331                        im->native.mipmap = 0;
1332                     }
1333 #  endif             
1334                   else
1335                     {
1336                        im->native.target = GL_TEXTURE_2D;
1337                        im->native.mipmap = 0;
1338                        ERR("still unknown target");
1339                     }
1340                }
1341              else
1342                ERR("GLX Pixmap create fail");
1343              im->native.yinvert     = re->win->depth_cfg[depth].yinvert;
1344              im->native.loose       = re->win->detected.loose_binding;
1345              im->native.data        = n;
1346              im->native.func.data   = re;
1347              im->native.func.bind   = _native_bind_cb;
1348              im->native.func.unbind = _native_unbind_cb;
1349              im->native.func.free   = _native_free_cb;
1350
1351              evas_gl_common_image_native_enable(im);
1352           }
1353      }
1354 # endif   
1355 #endif
1356    return im;
1357 }
1358
1359 static void *
1360 eng_image_native_get(void *data __UNUSED__, void *image)
1361 {
1362    Evas_GL_Image *im = image;
1363    Native *n;
1364    if (!im) return NULL;
1365    n = im->native.data;
1366    if (!n) return NULL;
1367    return &(n->ns);
1368 }
1369
1370 //
1371 //
1372 /////////////////////////////////////////////////////////////////////////
1373
1374 static void *
1375 eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
1376 {
1377    Render_Engine *re;
1378
1379    re = (Render_Engine *)data;
1380    *error = EVAS_LOAD_ERROR_NONE;
1381    eng_window_use(re->win);
1382    return evas_gl_common_image_load(re->win->gl_context, file, key, lo, error);
1383 }
1384
1385 static void *
1386 eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
1387 {
1388    Render_Engine *re;
1389
1390    re = (Render_Engine *)data;
1391    eng_window_use(re->win);
1392    return evas_gl_common_image_new_from_data(re->win->gl_context, w, h, image_data, alpha, cspace);
1393 }
1394
1395 static void *
1396 eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace)
1397 {
1398    Render_Engine *re;
1399
1400    re = (Render_Engine *)data;
1401    eng_window_use(re->win);
1402    return evas_gl_common_image_new_from_copied_data(re->win->gl_context, w, h, image_data, alpha, cspace);
1403 }
1404
1405 static void
1406 eng_image_free(void *data, void *image)
1407 {
1408    Render_Engine *re;
1409
1410    re = (Render_Engine *)data;
1411    if (!image) return;
1412    eng_window_use(re->win);
1413    evas_gl_common_image_free(image);
1414 }
1415
1416 static void
1417 eng_image_size_get(void *data __UNUSED__, void *image, int *w, int *h)
1418 {
1419    if (!image)
1420      {
1421         *w = 0;
1422         *h = 0;
1423         return;
1424      }
1425    if (w) *w = ((Evas_GL_Image *)image)->w;
1426    if (h) *h = ((Evas_GL_Image *)image)->h;
1427 }
1428
1429 static void *
1430 eng_image_size_set(void *data, void *image, int w, int h)
1431 {
1432    Render_Engine *re;
1433    Evas_GL_Image *im = image;
1434    Evas_GL_Image *im_old;
1435    
1436    re = (Render_Engine *)data;
1437    if (!im) return NULL;
1438    if (im->native.data)
1439      {
1440         im->w = w;
1441         im->h = h;
1442         return image;
1443      }
1444    eng_window_use(re->win);
1445    if ((im->tex) && (im->tex->pt->dyn.img))
1446      {
1447         evas_gl_common_texture_free(im->tex);
1448         im->tex = NULL;
1449         im->w = w;
1450         im->h = h;
1451         im->tex = evas_gl_common_texture_dynamic_new(im->gc, im);
1452         return image;
1453      }
1454    im_old = image;
1455    if ((eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P601_PL) ||
1456        (eng_image_colorspace_get(data, image) == EVAS_COLORSPACE_YCBCR422P709_PL))
1457      w &= ~0x1;
1458    if ((im_old) &&
1459        ((int)im_old->im->cache_entry.w == w) &&
1460        ((int)im_old->im->cache_entry.h == h))
1461      return image;
1462    if (im_old)
1463      {
1464         im = evas_gl_common_image_new(re->win->gl_context, w, h,
1465                                       eng_image_alpha_get(data, image),
1466                                       eng_image_colorspace_get(data, image));
1467 /*
1468         evas_common_load_image_data_from_file(im_old->im);
1469         if (im_old->im->image->data)
1470           {
1471              evas_common_blit_rectangle(im_old->im, im->im, 0, 0, w, h, 0, 0);
1472              evas_common_cpu_end_opt();
1473           }
1474  */
1475         evas_gl_common_image_free(im_old);
1476      }
1477    else
1478      im = evas_gl_common_image_new(re->win->gl_context, w, h, 1, EVAS_COLORSPACE_ARGB8888);
1479    return im;
1480 }
1481
1482 static void *
1483 eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h)
1484 {
1485    Render_Engine *re;
1486    Evas_GL_Image *im = image;
1487
1488    re = (Render_Engine *)data;
1489    if (!image) return NULL;
1490    if (im->native.data) return image;
1491    eng_window_use(re->win);
1492    evas_gl_common_image_dirty(image, x, y, w, h);
1493    return image;
1494 }
1495
1496 static void *
1497 eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data)
1498 {
1499    Render_Engine *re;
1500    Evas_GL_Image *im;
1501
1502    re = (Render_Engine *)data;
1503    if (!image)
1504      {
1505         *image_data = NULL;
1506         return NULL;
1507      }
1508    im = image;
1509    if (im->native.data)
1510      {
1511         *image_data = NULL;
1512         return im;
1513      }
1514    if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data))
1515      {
1516         *image_data = im->tex->pt->dyn.data;
1517         return im;
1518      }
1519    eng_window_use(re->win);
1520    evas_cache_image_load_data(&im->im->cache_entry);
1521    switch (im->cs.space)
1522      {
1523       case EVAS_COLORSPACE_ARGB8888:
1524         if (to_write)
1525           {
1526              if (im->references > 1)
1527                {
1528                   Evas_GL_Image *im_new;
1529
1530                   im_new = evas_gl_common_image_new_from_copied_data
1531                      (im->gc, im->im->cache_entry.w, im->im->cache_entry.h,
1532                          im->im->image.data,
1533                          eng_image_alpha_get(data, image),
1534                          eng_image_colorspace_get(data, image));
1535                   if (!im_new)
1536                     {
1537                        *image_data = NULL;
1538                        return im;
1539                     }
1540                   evas_gl_common_image_free(im);
1541                   im = im_new;
1542                }
1543              else
1544                evas_gl_common_image_dirty(im, 0, 0, 0, 0);
1545           }
1546         *image_data = im->im->image.data;
1547         break;
1548       case EVAS_COLORSPACE_YCBCR422P601_PL:
1549       case EVAS_COLORSPACE_YCBCR422P709_PL:
1550         *image_data = im->cs.data;
1551         break;
1552       default:
1553         abort();
1554         break;
1555      }
1556    return im;
1557 }
1558
1559 static void *
1560 eng_image_data_put(void *data, void *image, DATA32 *image_data)
1561 {
1562    Render_Engine *re;
1563    Evas_GL_Image *im, *im2;
1564
1565    re = (Render_Engine *)data;
1566    if (!image) return NULL;
1567    im = image;
1568    if (im->native.data) return image;
1569    eng_window_use(re->win);
1570    if ((im->tex) && (im->tex->pt) && (im->tex->pt->dyn.data))
1571      {
1572         if (im->tex->pt->dyn.data == image_data)
1573           {
1574              return image;
1575           }
1576         else
1577           {
1578              int w, h;
1579
1580              w = im->im->cache_entry.w;
1581              h = im->im->cache_entry.h;
1582              im2 = eng_image_new_from_data(data, w, h, image_data,
1583                                            eng_image_alpha_get(data, image),
1584                                            eng_image_colorspace_get(data, image));
1585              if (!im2) return im;
1586              evas_gl_common_image_free(im);
1587              im = im2;
1588              evas_gl_common_image_dirty(im, 0, 0, 0, 0);
1589              return im;
1590           }
1591      }
1592    switch (im->cs.space)
1593      {
1594       case EVAS_COLORSPACE_ARGB8888:
1595         if (image_data != im->im->image.data)
1596           {
1597              int w, h;
1598
1599              w = im->im->cache_entry.w;
1600              h = im->im->cache_entry.h;
1601              im2 = eng_image_new_from_data(data, w, h, image_data,
1602                                            eng_image_alpha_get(data, image),
1603                                            eng_image_colorspace_get(data, image));
1604              if (!im2) return im;
1605              evas_gl_common_image_free(im);
1606              im = im2;
1607           }
1608         break;
1609       case EVAS_COLORSPACE_YCBCR422P601_PL:
1610       case EVAS_COLORSPACE_YCBCR422P709_PL:
1611         if (image_data != im->cs.data)
1612           {
1613              if (im->cs.data)
1614                {
1615                   if (!im->cs.no_free) free(im->cs.data);
1616                }
1617              im->cs.data = image_data;
1618           }
1619         break;
1620       default:
1621         abort();
1622         break;
1623      }
1624    /* hmmm - but if we wrote... why bother? */
1625    evas_gl_common_image_dirty(im, 0, 0, 0, 0);
1626    return im;
1627 }
1628
1629 static void
1630 eng_image_data_preload_request(void *data __UNUSED__, void *image, const void *target)
1631 {
1632    Evas_GL_Image *gim = image;
1633    RGBA_Image *im;
1634
1635    if (!gim) return;
1636    if (gim->native.data) return;
1637    im = (RGBA_Image *)gim->im;
1638    if (!im) return;
1639    evas_cache_image_preload_data(&im->cache_entry, target);
1640 }
1641
1642 static void
1643 eng_image_data_preload_cancel(void *data __UNUSED__, void *image, const void *target)
1644 {
1645    Evas_GL_Image *gim = image;
1646    RGBA_Image *im;
1647
1648    if (!gim) return;
1649    if (gim->native.data) return;
1650    im = (RGBA_Image *)gim->im;
1651    if (!im) return;
1652    evas_cache_image_preload_cancel(&im->cache_entry, target);
1653 }
1654
1655 static void
1656 eng_image_draw(void *data, void *context, void *surface, void *image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
1657 {
1658    Render_Engine *re;
1659
1660    re = (Render_Engine *)data;
1661    if (!image) return;
1662    eng_window_use(re->win);
1663    evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
1664    re->win->gl_context->dc = context;
1665    evas_gl_common_image_draw(re->win->gl_context, image,
1666                              src_x, src_y, src_w, src_h,
1667                              dst_x, dst_y, dst_w, dst_h,
1668                              smooth);
1669 }
1670
1671 static void
1672 eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint)
1673 {
1674    if (image) evas_gl_common_image_scale_hint_set(image, hint);
1675 }
1676
1677 static int
1678 eng_image_scale_hint_get(void *data __UNUSED__, void *image)
1679 {
1680    Evas_GL_Image *gim = image;
1681    if (!gim) return EVAS_IMAGE_SCALE_HINT_NONE;
1682    return gim->scale_hint;
1683 }
1684
1685 static void
1686 eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level)
1687 {
1688    Evas_GL_Image *gim = image;
1689    Render_Engine *re;
1690    
1691    re = (Render_Engine *)data;
1692    if (!image) return;
1693    eng_window_use(re->win);
1694    evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
1695    re->win->gl_context->dc = context;
1696    if ((p[0].x == p[3].x) &&
1697        (p[1].x == p[2].x) &&
1698        (p[0].y == p[1].y) &&
1699        (p[3].y == p[2].y) &&
1700        (p[0].x <= p[1].x) &&
1701        (p[0].y <= p[2].y) &&
1702        (p[0].u == 0) &&
1703        (p[0].v == 0) &&
1704        (p[1].u == (gim->w << FP)) &&
1705        (p[1].v == 0) &&
1706        (p[2].u == (gim->w << FP)) &&
1707        (p[2].v == (gim->h << FP)) &&
1708        (p[3].u == 0) &&
1709        (p[3].v == (gim->h << FP)) &&
1710        (p[0].col == 0xffffffff) &&
1711        (p[1].col == 0xffffffff) &&
1712        (p[2].col == 0xffffffff) &&
1713        (p[3].col == 0xffffffff))
1714      {
1715         int dx, dy, dw, dh;
1716         
1717         dx = p[0].x >> FP;
1718         dy = p[0].y >> FP;
1719         dw = (p[2].x >> FP) - dx;
1720         dh = (p[2].y >> FP) - dy;
1721         eng_image_draw
1722            (data, context, surface, image,
1723                0, 0, gim->w, gim->h,
1724                dx, dy, dw, dh, smooth);
1725      }
1726    else
1727      {
1728         evas_gl_common_image_map4_draw(re->win->gl_context, image, p,
1729                                        smooth, level);
1730      }
1731 }
1732
1733 static void *
1734 eng_image_map_surface_new(void *data __UNUSED__, int w, int h, int alpha)
1735 {
1736    Render_Engine *re;
1737    
1738    re = (Render_Engine *)data;
1739    return evas_gl_common_image_surface_new(re->win->gl_context, w, h, alpha);
1740 }
1741
1742 static void
1743 eng_image_map_surface_free(void *data __UNUSED__, void *surface)
1744 {
1745    evas_gl_common_image_free(surface);
1746 }
1747
1748 static void
1749 eng_image_content_hint_set(void *data __UNUSED__, void *image, int hint)
1750 {
1751    if (image) evas_gl_common_image_content_hint_set(image, hint);
1752 }
1753
1754 static int
1755 eng_image_content_hint_get(void *data __UNUSED__, void *image)
1756 {
1757    Evas_GL_Image *gim = image;
1758    if (!gim) return EVAS_IMAGE_CONTENT_HINT_NONE;
1759    return gim->content_hint;
1760 }
1761
1762 static void
1763 eng_image_stride_get(void *data __UNUSED__, void *image, int *stride)
1764 {
1765    Evas_GL_Image *im = image;
1766    *stride = im->w * 4;
1767    if ((im->tex) && (im->tex->pt->dyn.img))
1768      {
1769         *stride = im->tex->pt->dyn.w * 4;
1770         // FIXME: for other image formats (yuv etc.) different stride needed
1771      }
1772 }
1773
1774 static void
1775 eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Eina_Unicode *text, const Evas_BiDi_Props *intl_props)
1776 {
1777    Render_Engine *re;
1778
1779    re = (Render_Engine *)data;
1780    eng_window_use(re->win);
1781    evas_gl_common_context_target_surface_set(re->win->gl_context, surface);
1782    re->win->gl_context->dc = context;
1783      {
1784         // FIXME: put im into context so we can free it
1785         static RGBA_Image *im = NULL;
1786         
1787         if (!im)
1788           im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get());
1789         im->cache_entry.w = re->win->w;
1790         im->cache_entry.h = re->win->h;
1791         evas_common_draw_context_font_ext_set(context,
1792                                               re->win->gl_context,
1793                                               evas_gl_font_texture_new,
1794                                               evas_gl_font_texture_free,
1795                                               evas_gl_font_texture_draw);
1796         evas_common_font_draw(im, context, font, x, y, text, intl_props);
1797         evas_common_draw_context_font_ext_set(context,
1798                                               NULL,
1799                                               NULL,
1800                                               NULL,
1801                                               NULL);
1802      }
1803 }
1804
1805 static Eina_Bool
1806 eng_canvas_alpha_get(void *data __UNUSED__, void *info __UNUSED__)
1807 {
1808    // FIXME: support ARGB gl targets!!!
1809    return EINA_FALSE;
1810 }
1811
1812 static int
1813 module_open(Evas_Module *em)
1814 {
1815    static Eina_Bool xrm_inited = EINA_FALSE;
1816    if (!xrm_inited)
1817      {
1818         xrm_inited = EINA_TRUE;
1819         XrmInitialize();
1820      }
1821
1822    if (!em) return 0;
1823    if (!evas_gl_common_module_open()) return 0;
1824    /* get whatever engine module we inherit from */
1825    if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
1826    if (_evas_engine_GL_X11_log_dom < 0)
1827      _evas_engine_GL_X11_log_dom = eina_log_domain_register
1828        ("evas-gl_x11", EVAS_DEFAULT_LOG_COLOR);
1829    if (_evas_engine_GL_X11_log_dom < 0)
1830      {
1831         EINA_LOG_ERR("Can not create a module log domain.");
1832         return 0;
1833      }
1834    /* store it for later use */
1835    func = pfunc;
1836    /* now to override methods */
1837    #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
1838    ORD(info);
1839    ORD(info_free);
1840    ORD(setup);
1841    ORD(canvas_alpha_get);
1842    ORD(output_free);
1843    ORD(output_resize);
1844    ORD(output_tile_size_set);
1845    ORD(output_redraws_rect_add);
1846    ORD(output_redraws_rect_del);
1847    ORD(output_redraws_clear);
1848    ORD(output_redraws_next_update_get);
1849    ORD(output_redraws_next_update_push);
1850    ORD(context_cutout_add);
1851    ORD(context_cutout_clear);
1852    ORD(output_flush);
1853    ORD(output_idle_flush);
1854    ORD(output_dump);
1855    ORD(rectangle_draw);
1856    ORD(line_draw);
1857    ORD(polygon_point_add);
1858    ORD(polygon_points_clear);
1859    ORD(polygon_draw);
1860
1861    ORD(image_load);
1862    ORD(image_new_from_data);
1863    ORD(image_new_from_copied_data);
1864    ORD(image_free);
1865    ORD(image_size_get);
1866    ORD(image_size_set);
1867    ORD(image_dirty_region);
1868    ORD(image_data_get);
1869    ORD(image_data_put);
1870    ORD(image_data_preload_request);
1871    ORD(image_data_preload_cancel);
1872    ORD(image_alpha_set);
1873    ORD(image_alpha_get);
1874    ORD(image_border_set);
1875    ORD(image_border_get);
1876    ORD(image_draw);
1877    ORD(image_comment_get);
1878    ORD(image_format_get);
1879    ORD(image_colorspace_set);
1880    ORD(image_colorspace_get);
1881    ORD(image_mask_create);
1882    ORD(image_native_set);
1883    ORD(image_native_get);
1884    
1885    ORD(font_draw);
1886    
1887    ORD(image_scale_hint_set);
1888    ORD(image_scale_hint_get);
1889    ORD(image_stride_get);
1890    
1891    ORD(image_map_draw);
1892    ORD(image_map_surface_new);
1893    ORD(image_map_surface_free);
1894    
1895    ORD(image_content_hint_set);
1896    ORD(image_content_hint_get);
1897    
1898    /* now advertise out own api */
1899    em->functions = (void *)(&func);
1900    return 1;
1901 }
1902
1903 static void
1904 module_close(Evas_Module *em __UNUSED__)
1905 {
1906     eina_log_domain_unregister(_evas_engine_GL_X11_log_dom);
1907     if (xrdb_user.db)
1908       {
1909          XrmDestroyDatabase(xrdb_user.db);
1910          xrdb_user.last_stat = 0;
1911          xrdb_user.last_mtime = 0;
1912          xrdb_user.db = NULL;
1913       }
1914     evas_gl_common_module_close();
1915 }
1916
1917 static Evas_Module_Api evas_modapi =
1918 {
1919    EVAS_MODULE_API_VERSION,
1920    "gl_x11",
1921    "none",
1922    {
1923      module_open,
1924      module_close
1925    }
1926 };
1927
1928 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, gl_x11);
1929
1930 #ifndef EVAS_STATIC_BUILD_GL_X11
1931 EVAS_EINA_MODULE_DEFINE(engine, gl_x11);
1932 #endif