Add:Build:Cmake-Options for OpenGLES and OpenGLES2
[profile/ivi/navit.git] / navit / navit / graphics / opengl / graphics_opengl.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2010 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #define USE_FLOAT 0
21 #define REQUIRES_POWER_OF_2 0
22
23 #include <glib.h>
24 #include <unistd.h>
25 #include <math.h>
26 #include <stdio.h>
27
28 #include <time.h>
29
30 #include "item.h"
31 #include "attr.h"
32 #include "config.h"
33 #include "point.h"
34 #include "graphics.h"
35 #include "color.h"
36 #include "plugin.h"
37 #include "event.h"
38 #include "debug.h"
39 #include "callback.h"
40 #include "keys.h"
41 #include "window.h"
42 #include "navit/font/freetype/font_freetype.h"
43
44 #if defined(WINDOWS) || defined(WIN32)
45 #define PIXEL_FORMAT GL_RGBA
46 #include <windows.h>
47 # define sleep(i) Sleep(i * 1000)
48 #else
49 #define PIXEL_FORMAT GL_BGRA
50 #endif
51
52 #if HAVE_FREEIMAGE
53 #include <FreeImage.h>
54 #endif
55
56 #ifdef USE_OPENGLES
57 #ifdef USE_OPENGLES2
58 #include <GLES2/gl2.h>
59 #include <EGL/egl.h>
60 #undef USE_FLOAT
61 #define USE_FLOAT 1
62 #else
63 #include <GLES/gl.h>
64 #include <GLES/egl.h>
65 #endif
66 extern EGLSurface eglwindow;
67 extern EGLDisplay egldisplay;
68 #else
69 #define glOrthof        glOrtho
70 #undef USE_FLOAT
71 #define USE_FLOAT 1
72 #ifdef __APPLE__
73 #include <GLUT/glut.h>
74 #else
75 #include <GL/glut.h>            /* glut.h includes gl.h and glu.h */
76 #endif
77 #endif
78
79 #if USE_FLOAT
80 #define glF(x)  x
81 #define glD(x)  x
82 #define GL_F    GL_FLOAT
83 typedef GLfloat GLf;
84 #else
85 #define glF(x)  ((GLfixed)((x)*(1<<16)))
86 #define glD(x)  glF(x)
87 #define GL_F    GL_FIXED
88 typedef GLfixed GLf;
89
90 #define glClearColor    glClearColorx
91 #define glTranslatef    glTranslatex
92 #define glRotatef       glRotatex
93 #define glMaterialfv    glMaterialxv
94 #define glMaterialf     glMaterialx
95 #define glOrthof        glOrthox
96 #define glScalef        glScalex
97 #define glColor4f       glColor4x
98 #endif
99 #define glTexParameteri       glTexParameterx
100
101 #define SCREEN_WIDTH 700
102 #define SCREEN_HEIGHT 700
103
104 //#define MIRRORED_VIEW 1
105
106 struct graphics_gc_priv {
107         struct graphics_priv *gr;
108         float fr, fg, fb, fa;
109         float br, bg, bb, ba;
110         int linewidth;
111         unsigned char *dash_list;
112         int dash_count;
113         int dash_mask;
114 } graphics_gc_priv;
115
116 struct graphics_priv {
117         int button_timeout;
118         struct point p;
119         int width;
120         int height;
121         int library_init;
122         int visible;
123         int overlay_enabled;
124         int overlay_autodisabled;
125         int wraparound;
126         struct graphics_priv *parent;
127         struct graphics_priv *overlays;
128         struct graphics_priv *next;
129         struct graphics_gc_priv *background_gc;
130         enum draw_mode_num mode;
131         void (*resize_callback) (void *data, int w, int h);
132         void *resize_callback_data;
133         void (*motion_callback) (void *data, struct point * p);
134         void *motion_callback_data;
135         void (*button_callback) (void *data, int press, int button,
136                                  struct point * p);
137         void *button_callback_data;
138 #ifdef USE_OPENGLES
139         GLuint program;
140         GLint mvp_location, position_location, color_location, texture_position_location, use_texture_location, texture_location;
141 #else
142         GLuint DLid;
143 #endif
144         struct callback_list *cbl;
145         struct font_freetype_methods freetype_methods;
146         struct navit *nav;
147         int timeout;
148         int delay;
149         struct window window;
150         int dirty;              //display needs to be redrawn (draw on root graphics or overlay is done)
151         int force_redraw;       //display needs to be redrawn (draw on root graphics or overlay is done)
152         time_t last_refresh_time;       //last display refresh time
153 };
154
155 static struct graphics_priv *graphics_priv_root;
156 struct graphics_image_priv {
157         int w;
158         int h;
159         int hot_x;
160         int hot_y;
161         unsigned char *data;
162         char *path;
163 } graphics_image_priv;
164
165 struct mouse_event_queue_element {
166         int button;
167         int state;
168         int x;
169         int y;
170 };
171
172 static const int mouse_event_queue_size = 100;
173 static int mouse_event_queue_begin_idx = 0;
174 static int mouse_event_queue_end_idx = 0;
175 static struct mouse_event_queue_element mouse_queue[100];
176
177 //hastable for uncompressed image data
178 static GHashTable *hImageData;
179
180 #ifdef USE_OPENGLES
181 #else
182 /*  prototypes */
183 void APIENTRY tessBeginCB(GLenum which);
184 void APIENTRY tessEndCB();
185 void APIENTRY tessErrorCB(GLenum errorCode);
186 void APIENTRY tessVertexCB(const GLvoid * data);
187 void APIENTRY tessVertexCB2(const GLvoid * data);
188 void APIENTRY tessCombineCB(GLdouble c[3], void *d[4], GLfloat w[4], void **out);
189 const char *getPrimitiveType(GLenum type);
190 #endif
191
192 static struct graphics_priv *graphics_opengl_new_helper(struct
193                                                         graphics_methods
194                                                         *meth);
195 static void display(void);
196 static void resize_callback(int w, int h);
197 static void glut_close();
198
199 #ifdef USE_OPENGLES2
200 const char vertex_src [] =
201 "                                        \
202    attribute vec2        position;       \
203    attribute vec2        texture_position;       \
204    uniform mat4        mvp;             \
205    varying vec2 v_texture_position; \
206                                          \
207    void main()                           \
208    {                                     \
209       v_texture_position=texture_position; \
210       gl_Position = mvp*vec4(position, 0.0, 1.0);   \
211    }                                     \
212 ";
213
214 const char fragment_src [] =
215 "                                                      \
216    uniform lowp vec4   avcolor;                        \
217    uniform sampler2D texture; \
218    uniform bool use_texture; \
219    varying vec2 v_texture_position; \
220    void  main()                                        \
221    {                                                   \
222       if (use_texture) { \
223          gl_FragColor = texture2D(texture, v_texture_position);     \
224       } else { \
225          gl_FragColor = avcolor; \
226       } \
227    }                                                   \
228 ";
229 #endif
230
231 static void
232 graphics_destroy(struct graphics_priv *gr)
233 {
234         /*FIXME graphics_destroy is never called */
235         /*TODO add destroy code for image cache(delete entries in hImageData) */
236         g_free(gr);
237         gr = NULL;
238 }
239
240 static void
241 gc_destroy(struct graphics_gc_priv *gc)
242 {
243         g_free(gc);
244         gc = NULL;
245 }
246
247 static void
248 gc_set_linewidth(struct graphics_gc_priv *gc, int w)
249 {
250         gc->linewidth = w;
251 }
252
253 static void
254 gc_set_dashes(struct graphics_gc_priv *gc, int width, int offset,
255               unsigned char *dash_list, int n)
256 {
257         int i;
258         const int cOpenglMaskBits = 16;
259         gc->dash_count = n;
260         if (1 == n) {
261                 gc->dash_mask = 0;
262                 for (i = 0; i < cOpenglMaskBits; ++i) {
263                         gc->dash_mask <<= 1;
264                         gc->dash_mask |= (i / n) % 2;
265                 }
266         } else if (1 < n) {
267                 unsigned char *curr = dash_list;
268                 int cnt = 0;    //dot counter
269                 int dcnt = 0;   //dash element counter
270                 int sum_dash = 0;
271                 gc->dash_mask = 0;
272
273                 for (i = 0; i < n; ++i) {
274                         sum_dash += dash_list[i];
275                 }
276
277                 //scale dashlist elements to max size
278                 if (sum_dash > cOpenglMaskBits) {
279                         int num_error[2] = { 0, 0 };    //count elements rounded to 0 for odd(drawn) and even(masked) for compensation
280                         double factor = (1.0 * cOpenglMaskBits) / sum_dash;
281                         for (i = 0; i < n; ++i) {       //calculate dashlist max and largest common denomiator for scaling
282                                 dash_list[i] *= factor;
283                                 if (dash_list[i] == 0) {
284                                         ++dash_list[i];
285                                         ++num_error[i % 2];
286                                 } else if (0 < num_error[i % 2]
287                                            && 2 < dash_list[i]) {
288                                         ++dash_list[i];
289                                         --num_error[i % 2];
290                                 }
291                         }
292                 }
293                 //calculate mask
294                 for (i = 0; i < cOpenglMaskBits; ++i) {
295                         gc->dash_mask <<= 1;
296                         gc->dash_mask |= 1 - dcnt % 2;
297                         ++cnt;
298                         if (cnt == *curr) {
299                                 cnt = 0;
300                                 ++curr;
301                                 ++dcnt;
302                                 if (dcnt == n) {
303                                         curr = dash_list;
304                                 }
305                         }
306                 }
307         }
308 }
309
310
311 static void
312 gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
313 {
314         gc->fr = c->r / 65535.0;
315         gc->fg = c->g / 65535.0;
316         gc->fb = c->b / 65535.0;
317         gc->fa = c->a / 65535.0;
318 }
319
320 static void
321 gc_set_background(struct graphics_gc_priv *gc, struct color *c)
322 {
323         gc->br = c->r / 65535.0;
324         gc->bg = c->g / 65535.0;
325         gc->bb = c->b / 65535.0;
326         gc->ba = c->a / 65535.0;
327 }
328
329 static struct graphics_gc_methods gc_methods = {
330         gc_destroy,
331         gc_set_linewidth,
332         gc_set_dashes,
333         gc_set_foreground,
334         gc_set_background
335 };
336
337 static struct graphics_gc_priv *
338 gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
339 {
340         struct graphics_gc_priv *gc = g_new0(struct graphics_gc_priv, 1);
341
342         *meth = gc_methods;
343         gc->gr = gr;
344         gc->linewidth = 1;
345         return gc;
346 }
347
348 static struct graphics_image_priv image_error;
349
350 static struct graphics_image_priv *
351 image_new(struct graphics_priv *gr, struct graphics_image_methods *meth,
352           char *path, int *w, int *h, struct point *hot, int rotation)
353 {
354 #if HAVE_FREEIMAGE
355         FIBITMAP *image;
356         RGBQUAD aPixel;
357         unsigned char *data;
358         int width, height, i, j;
359         struct graphics_image_priv *gi;
360         //check if image already exists in hashmap
361         struct graphics_image_priv *curr_elem =
362             g_hash_table_lookup(hImageData, path);
363         if (curr_elem == &image_error) {
364                 //found but couldn't be loaded
365                 return NULL;
366         } else if (curr_elem) {
367                 //found and OK -> use hastable entry
368                 *w = curr_elem->w;
369                 *h = curr_elem->h;
370                 hot->x = curr_elem->w / 2 - 1;
371                 hot->y = curr_elem->h / 2 - 1;
372                 return curr_elem;
373         } else {
374                 if (strlen(path) < 4) {
375                         g_hash_table_insert(hImageData, g_strdup(path),
376                                             &image_error);
377                         return NULL;
378                 }
379                 char *ext_str = path + strlen(path) - 3;
380                 if (strstr(ext_str, "png") || strstr(path, "PNG")) {
381                         if ((image =
382                              FreeImage_Load(FIF_PNG, path, 0)) == NULL) {
383                                 g_hash_table_insert(hImageData,
384                                                     g_strdup(path),
385                                                     &image_error);
386                                 return NULL;
387                         }
388                 } else if (strstr(ext_str, "xpm") || strstr(path, "XPM")) {
389                         if ((image =
390                              FreeImage_Load(FIF_XPM, path, 0)) == NULL) {
391                                 g_hash_table_insert(hImageData,
392                                                     g_strdup(path),
393                                                     &image_error);
394                                 return NULL;
395                         }
396                 } else if (strstr(ext_str, "svg") || strstr(path, "SVG")) {
397                         char path_new[256];
398                         snprintf(path_new, strlen(path) - 3, "%s", path);
399                         strcat(path_new, "_48_48.png");
400
401                         if ((image =
402                              FreeImage_Load(FIF_PNG, path_new,
403                                             0)) == NULL) {
404                                 g_hash_table_insert(hImageData,
405                                                     g_strdup(path),
406                                                     &image_error);
407                                 return NULL;
408                         }
409                 } else {
410                         g_hash_table_insert(hImageData, g_strdup(path),
411                                             &image_error);
412                         return NULL;
413                 }
414
415                 if (FreeImage_GetBPP(image) == 64) {
416                         FIBITMAP *image2;
417                         image2 = FreeImage_ConvertTo32Bits(image);
418                         FreeImage_Unload(image);
419                         image = image2;
420                 }
421 #if FREEIMAGE_MAJOR_VERSION*100+FREEIMAGE_MINOR_VERSION  >= 313
422                 if (rotation) {
423                         FIBITMAP *image2;
424                         image2 = FreeImage_Rotate(image, rotation, NULL);
425                         image = image2;
426                 }
427 #endif
428
429                 gi = g_new0(struct graphics_image_priv, 1);
430
431                 width = FreeImage_GetWidth(image);
432                 height = FreeImage_GetHeight(image);
433
434                 if ((*w != width || *h != height) && 0 < *w && 0 < *h) {
435                         FIBITMAP *image2;
436                         image2 = FreeImage_Rescale(image, *w, *h, NULL);
437                         FreeImage_Unload(image);
438                         image = image2;
439                         width = *w;
440                         height = *h;
441                 }
442
443                 data = (unsigned char *) malloc(width * height * 4);
444
445                 RGBQUAD *palette = NULL;
446                 if (FreeImage_GetBPP(image) == 8) {
447                         palette = FreeImage_GetPalette(image);
448                 }
449
450                 for (i = 0; i < height; i++) {
451                         for (j = 0; j < width; j++) {
452                                 unsigned char idx;
453                                 if (FreeImage_GetBPP(image) == 8) {
454                                         FreeImage_GetPixelIndex(image, j,
455                                                                 height -
456                                                                 i - 1,
457                                                                 &idx);
458                                         data[4 * width * i + 4 * j + 0] =
459                                             palette[idx].rgbRed;
460                                         data[4 * width * i + 4 * j + 1] =
461                                             palette[idx].rgbGreen;
462                                         data[4 * width * i + 4 * j + 2] =
463                                             palette[idx].rgbBlue;
464                                         data[4 * width * i + 4 * j + 3] =
465                                             255;
466                                 } else if (FreeImage_GetBPP(image) == 16
467                                            || FreeImage_GetBPP(image) == 24
468                                            || FreeImage_GetBPP(image) ==
469                                            32) {
470                                         FreeImage_GetPixelColor(image, j,
471                                                                 height -
472                                                                 i - 1,
473                                                                 &aPixel);
474                                         int transparent =
475                                             (aPixel.rgbRed == 0
476                                              && aPixel.rgbBlue == 0
477                                              && aPixel.rgbGreen == 0);
478                                         data[4 * width * i + 4 * j + 0] =
479                                             transparent ? 0 : (aPixel.
480                                                                rgbRed);
481                                         data[4 * width * i + 4 * j + 1] =
482                                             (aPixel.rgbGreen);
483                                         data[4 * width * i + 4 * j + 2] =
484                                             transparent ? 0 : (aPixel.
485                                                                rgbBlue);
486                                         data[4 * width * i + 4 * j + 3] =
487                                             transparent ? 0 : 255;
488
489                                 }
490                         }
491                 }
492
493                 FreeImage_Unload(image);
494
495                 *w = width;
496                 *h = height;
497                 gi->w = width;
498                 gi->h = height;
499                 gi->hot_x = width / 2 - 1;
500                 gi->hot_y = height / 2 - 1;
501                 hot->x = width / 2 - 1;
502                 hot->y = height / 2 - 1;
503                 gi->data = data;
504                 gi->path = path;
505                 //add to hashtable
506                 g_hash_table_insert(hImageData, g_strdup(path), gi);
507                 return gi;
508         }
509 #else
510         return NULL;
511 #endif
512 }
513
514 #ifdef USE_OPENGLES
515
516 static void
517 set_color(struct graphics_priv *gr, struct graphics_gc_priv *gc)
518 {
519 #ifdef USE_OPENGLES2
520         GLfloat col[4];
521         col[0]=gc->fr;
522         col[1]=gc->fg;
523         col[2]=gc->fb;
524         col[3]=1.0;
525         glUniform4fv(gr->color_location, 1, col);
526 #else
527         glColor4f(glF(gc->fr), glF(gc->fg), glF(gc->fb), glF(gc->fa));
528 #endif
529 }
530
531 static void
532 draw_array(struct graphics_priv *gr, struct point *p, int count, GLenum mode)
533 {
534         GLf x[count*2];
535         int i;
536
537         for (i = 0 ; i < count ; i++) {
538                 x[i*2]=glF(p[i].x);
539                 x[i*2+1]=glF(p[i].y);
540         }
541 #ifdef USE_OPENGLES2
542         glVertexAttribPointer (gr->position_location, 2, GL_FLOAT, 0, 0, x );
543 #else
544         glVertexPointer(2, GL_F, 0, x);
545 #endif
546         glDrawArrays(mode, 0, count);
547 }
548
549 static void
550 draw_rectangle_es(struct graphics_priv *gr, struct point *p, int w, int h)
551 {
552         struct point pa[4];
553         pa[0]=pa[1]=pa[2]=pa[3]=*p;
554         pa[0].x+=w;
555         pa[1].x+=w;
556         pa[1].y+=h;
557         pa[3].y+=h;
558         draw_array(gr, pa, 4, GL_TRIANGLE_STRIP);
559 }
560
561 static int next_power2(int x)
562 {
563         int r=1;
564         while (r < x) 
565                 r*=2;
566         return r;
567 }
568
569 static void
570 draw_image_es(struct graphics_priv *gr, struct point *p, int w, int h, unsigned char *data)
571 {
572         GLf x[8];
573
574         memset(x, 0, sizeof(x));
575 #if REQUIRES_POWER_OF_2
576         int w2=next_power2(w);
577         int h2=next_power2(h);
578         int y;
579         if (w2 != w || h2 != h) {
580                 char *newpix=g_malloc0(w2*h2*4);
581                 for (y=0 ; y < h ; y++) 
582                         memcpy(newpix+y*w2*4, data+y*w*4, w*4);
583                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w2, h2, 0, GL_RGBA, GL_UNSIGNED_BYTE, newpix);
584                 g_free(newpix);
585                 w=w2;
586                 h=h2;
587         } else 
588                 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
589 #else
590         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
591 #endif
592         x[0]+=glF(1);
593         x[2]+=glF(1);
594         x[3]+=glF(1);
595         x[7]+=glF(1);
596 #ifdef USE_OPENGLES2
597         glUniform1i(gr->use_texture_location, 1);
598         glEnableVertexAttribArray(gr->texture_position_location);
599         glVertexAttribPointer (gr->texture_position_location, 2, GL_FLOAT, 0, 0, x );
600 #else
601         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
602         glEnable(GL_TEXTURE_2D);
603         glTexCoordPointer(2, GL_F, 0, x);
604 #endif
605         glEnable(GL_BLEND);
606         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
607         draw_rectangle_es(gr, p, w, h);
608 #ifdef USE_OPENGLES2
609         glUniform1i(gr->use_texture_location, 0);
610         glDisableVertexAttribArray(gr->texture_position_location);
611 #else
612         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
613         glDisable(GL_TEXTURE_2D);
614 #endif
615         glDisable(GL_BLEND);
616 }
617
618
619 #else
620 const char *
621 getPrimitiveType(GLenum type)
622 {
623         char *ret = "";
624
625         switch (type) {
626         case 0x0000:
627                 ret = "GL_POINTS";
628                 break;
629         case 0x0001:
630                 ret = "GL_LINES";
631                 break;
632         case 0x0002:
633                 ret = "GL_LINE_LOOP";
634                 break;
635         case 0x0003:
636                 ret = "GL_LINE_STRIP";
637                 break;
638         case 0x0004:
639                 ret = "GL_TRIANGLES";
640                 break;
641         case 0x0005:
642                 ret = "GL_TRIANGLE_STRIP";
643                 break;
644         case 0x0006:
645                 ret = "GL_TRIANGLE_FAN";
646                 break;
647         case 0x0007:
648                 ret = "GL_QUADS";
649                 break;
650         case 0x0008:
651                 ret = "GL_QUAD_STRIP";
652                 break;
653         case 0x0009:
654                 ret = "GL_POLYGON";
655                 break;
656         }
657         return ret;
658 }
659
660 void APIENTRY
661 tessBeginCB(GLenum which)
662 {
663         glBegin(which);
664
665         dbg(1, "glBegin( %s );\n", getPrimitiveType(which));
666 }
667
668
669
670 void APIENTRY
671 tessEndCB()
672 {
673         glEnd();
674
675         dbg(1, "glEnd();\n");
676 }
677
678
679
680 void APIENTRY
681 tessVertexCB(const GLvoid * data)
682 {
683         // cast back to double type
684         const GLdouble *ptr = (const GLdouble *) data;
685
686         glVertex3dv(ptr);
687
688         dbg(1, "  glVertex3d();\n");
689 }
690 #endif
691
692 static void
693 get_overlay_pos(struct graphics_priv *gr, struct point *point_out)
694 {
695         if (gr->parent == NULL) {
696                 point_out->x = 0;
697                 point_out->y = 0;
698                 return;
699         }
700         point_out->x = gr->p.x;
701         if (point_out->x < 0) {
702                 point_out->x += gr->parent->width;
703         }
704
705         point_out->y = gr->p.y;
706         if (point_out->y < 0) {
707                 point_out->y += gr->parent->height;
708         }
709 }
710
711 static void
712 draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc,
713            struct point *p, int count)
714 {
715         if ((gr->parent && !gr->parent->overlay_enabled)
716             || (gr->parent && gr->parent->overlay_enabled
717                 && !gr->overlay_enabled)) {
718                 return;
719         }
720 #if !defined(USE_OPENGLES) || defined(USE_OPENGLES2)
721         glLineWidth(gc->linewidth);
722 #endif
723 #ifdef USE_OPENGLES
724         set_color(gr, gc);
725         draw_array(gr, p, count, GL_LINE_STRIP);
726 #else
727
728         graphics_priv_root->dirty = 1;
729
730         glColor4f(gc->fr, gc->fg, gc->fb, gc->fa);
731         if (!gr->parent && 0 < gc->dash_count) {
732                 glLineStipple(1, gc->dash_mask);
733                 glEnable(GL_LINE_STIPPLE);
734         }
735         glBegin(GL_LINE_STRIP);
736         int i;
737         for (i = 0; i < count; i++) {
738                 struct point p_eff;
739                 p_eff.x = p[i].x;
740                 p_eff.y = p[i].y;
741                 glVertex2f(p_eff.x, p_eff.y);
742         }
743         glEnd();
744         if (!gr->parent && 0 < gc->dash_count) {
745                 glDisable(GL_LINE_STIPPLE);
746         }
747 #endif
748 }
749
750 #ifdef USE_OPENGLES
751 #else
752 void APIENTRY
753 tessCombineCB(GLdouble c[3], void *d[4], GLfloat w[4], void **out)
754 {
755         GLdouble *nv = (GLdouble *) malloc(sizeof(GLdouble) * 3);
756         nv[0] = c[0];
757         nv[1] = c[1];
758         nv[2] = c[2];
759         *out = nv;
760 }
761 #endif
762
763
764 static void
765 draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc,
766              struct point *p, int count)
767 {
768         if ((gr->parent && !gr->parent->overlay_enabled)
769             || (gr->parent && gr->parent->overlay_enabled
770                 && !gr->overlay_enabled)) {
771                 return;
772         }
773 #ifdef USE_OPENGLES
774         set_color(gr, gc);
775         draw_array(gr, p, count, GL_LINE_STRIP);
776 #else
777         graphics_priv_root->dirty = 1;
778
779         GLUtesselator *tess = gluNewTess();     // create a tessellator
780         if (!tess)
781                 return;         // failed to create tessellation object, return 0
782
783         GLdouble quad1[count][3];
784         int i;
785         for (i = 0; i < count; i++) {
786                 quad1[i][0] = (GLdouble) (p[i].x);
787                 quad1[i][1] = (GLdouble) (p[i].y);
788                 quad1[i][2] = 0;
789         }
790
791
792         // register callback functions
793         gluTessCallback(tess, GLU_TESS_BEGIN,   (void (APIENTRY *)(void)) tessBeginCB);
794         gluTessCallback(tess, GLU_TESS_END,             (void (APIENTRY *)(void)) tessEndCB);
795         //     gluTessCallback(tess, GLU_TESS_ERROR, (void (*)(void))tessErrorCB);
796         gluTessCallback(tess, GLU_TESS_VERTEX,  (void (APIENTRY *)(void)) tessVertexCB);
797         gluTessCallback(tess, GLU_TESS_COMBINE, (void (APIENTRY *)(void)) tessCombineCB);
798
799         // tessellate and compile a concave quad into display list
800         // gluTessVertex() takes 3 params: tess object, pointer to vertex coords,
801         // and pointer to vertex data to be passed to vertex callback.
802         // The second param is used only to perform tessellation, and the third
803         // param is the actual vertex data to draw. It is usually same as the second
804         // param, but It can be more than vertex coord, for example, color, normal
805         // and UV coords which are needed for actual drawing.
806         // Here, we are looking at only vertex coods, so the 2nd and 3rd params are
807         // pointing same address.
808         glColor4f(gc->fr, gc->fg, gc->fb, gc->fa);
809         gluTessBeginPolygon(tess, 0);   // with NULL data
810         gluTessBeginContour(tess);
811         for (i = 0; i < count; i++) {
812                 gluTessVertex(tess, quad1[i], quad1[i]);
813         }
814         gluTessEndContour(tess);
815         gluTessEndPolygon(tess);
816
817         gluDeleteTess(tess);    // delete after tessellation
818 #endif
819 }
820
821 static void
822 draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc,
823                struct point *p, int w, int h)
824 {
825         if ((gr->parent && !gr->parent->overlay_enabled)
826             || (gr->parent && gr->parent->overlay_enabled
827                 && !gr->overlay_enabled)) {
828                 return;
829         }
830 #ifdef USE_OPENGLES
831         set_color(gr, gc);
832         draw_rectangle_es(gr, p, w, h);
833 #else
834
835         graphics_priv_root->dirty = 1;
836
837         struct point p_eff;
838         p_eff.x = p->x;
839         p_eff.y = p->y;
840
841         glColor4f(gc->fr, gc->fg, gc->fb, gc->fa);
842         glBegin(GL_POLYGON);
843         glVertex2f(p_eff.x, p_eff.y);
844         glVertex2f(p_eff.x + w, p_eff.y);
845         glVertex2f(p_eff.x + w, p_eff.y + h);
846         glVertex2f(p_eff.x, p_eff.y + h);
847         glEnd();
848 #endif
849 }
850
851 static void
852 draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc,
853             struct point *p, int r)
854 {
855 #ifdef USE_OPENGLES
856 #else
857         if ((gr->parent && !gr->parent->overlay_enabled)
858             || (gr->parent && gr->parent->overlay_enabled
859                 && !gr->overlay_enabled)) {
860                 return;
861         }
862
863         graphics_priv_root->dirty = 1;
864
865         /* FIXME: does not quite match gtk */
866         /* hack for osd compass.. why is this needed!? */
867         if (gr->parent) {
868                 r = r / 2;
869         }
870
871         struct point p_eff;
872         p_eff.x = p->x;
873         p_eff.y = p->y;
874
875         GLUquadricObj *quadratic;
876         quadratic = gluNewQuadric();
877         glPushMatrix();
878         glTranslatef(p_eff.x, p_eff.y, 0);
879         glColor4f(gc->fr, gc->fg, gc->fb, gc->fa);
880         gluDisk(quadratic, r - (gc->linewidth / 2) - 2,
881                 r + (gc->linewidth / 2), 10 + r / 5, 10 + r / 5);
882         glPopMatrix();
883         gluDeleteQuadric(quadratic);
884 #endif
885 }
886
887 static void
888 display_text_draw(struct font_freetype_text *text,
889                   struct graphics_priv *gr, struct graphics_gc_priv *fg,
890                   struct graphics_gc_priv *bg, int color, struct point *p)
891 {
892         int i, x, y, stride;
893         struct font_freetype_glyph *g, **gp;
894         unsigned char *shadow, *glyph;
895         struct color transparent = { 0x0000, 0x0000, 0x0000, 0x0000 };
896         struct color black =
897             { fg->fr * 65535, fg->fg * 65535, fg->fb * 65535,
898    fg->fa * 65535 };
899         struct color white = { 0xffff, 0xffff, 0xffff, 0xffff };
900
901         if (bg) {
902                 if (COLOR_IS_WHITE(black) && COLOR_IS_BLACK(white)) {
903                         black.r = 65535;
904                         black.g = 65535;
905                         black.b = 65535;
906                         black.a = 65535;
907
908                         white.r = 0;
909                         white.g = 0;
910                         white.b = 0;
911                         white.a = 65535;
912                 } else if (COLOR_IS_BLACK(black) && COLOR_IS_WHITE(white)) {
913                         white.r = 65535;
914                         white.g = 65535;
915                         white.b = 65535;
916                         white.a = 65535;
917
918                         black.r = 0;
919                         black.g = 0;
920                         black.b = 0;
921                         black.a = 65535;
922                 } else {
923                         white.r = bg->fr;
924                         white.g = bg->fg;
925                         white.b = bg->fb;
926                         white.a = bg->fa;
927                 }
928         } else {
929                 white.r = 0;
930                 white.g = 0;
931                 white.b = 0;
932                 white.a = 0;
933         }
934
935         gp = text->glyph;
936         i = text->glyph_count;
937         x = p->x << 6;
938         y = p->y << 6;
939         while (i-- > 0) {
940                 g = *gp++;
941                 if (g->w && g->h && bg) {
942                         stride = (g->w + 2) * 4;
943                         if (color) {
944                                 shadow = g_malloc(stride * (g->h + 2));
945                                 gr->freetype_methods.get_shadow(g, shadow,
946                                                                 32, stride,
947                                                                 &white,
948                                                                 &transparent);
949 #ifdef USE_OPENGLES
950                                 struct point p;
951                                 p.x=((x + g->x) >> 6)-1;
952                                 p.y=((y + g->y) >> 6)-1;
953                                 draw_image_es(gr, &p, g->w+2, g->h+2, shadow);
954 #else
955 #ifdef MIRRORED_VIEW
956                                 glPixelZoom(-1.0, -1.0);        //mirrored mode
957 #else
958                                 glPixelZoom(1.0, -1.0);
959 #endif
960                                 glRasterPos2d((x + g->x) >> 6,
961                                               (y + g->y) >> 6);
962                                 glDrawPixels(g->w + 2, g->h + 2, PIXEL_FORMAT,
963                                              GL_UNSIGNED_BYTE, shadow);
964 #endif
965                                 g_free(shadow);
966                         }
967                 }
968                 x += g->dx;
969                 y += g->dy;
970         }
971
972         x = p->x << 6;
973         y = p->y << 6;
974         gp = text->glyph;
975         i = text->glyph_count;
976         while (i-- > 0) {
977                 g = *gp++;
978                 if (g->w && g->h) {
979                         if (color) {
980                                 stride = g->w;
981                                 if (bg) {
982                                         glyph =
983                                             g_malloc(stride * g->h * 4);
984                                         gr->freetype_methods.get_glyph(g,
985                                                                        glyph,
986                                                                        32,
987                                                                        stride
988                                                                        * 4,
989                                                                        &black,
990                                                                        &white,
991                                                                        &transparent);
992 #ifdef USE_OPENGLES
993                                         struct point p;
994                                         p.x=(x + g->x) >> 6;
995                                         p.y=(y + g->y) >> 6;
996                                         draw_image_es(gr, &p, g->w, g->h, glyph);
997 #else
998 #ifdef MIRRORED_VIEW
999                                         glPixelZoom(-1.0, -1.0);        //mirrored mode
1000 #else
1001                                         glPixelZoom(1.0, -1.0);
1002 #endif
1003                                         glRasterPos2d((x + g->x) >> 6,
1004                                                       (y + g->y) >> 6);
1005                                         glDrawPixels(g->w, g->h, PIXEL_FORMAT,
1006                                                      GL_UNSIGNED_BYTE,
1007                                                      glyph);
1008 #endif
1009                                         g_free(glyph);
1010                                 }
1011                                 stride *= 4;
1012                                 glyph = g_malloc(stride * g->h);
1013                                 gr->freetype_methods.get_glyph(g, glyph,
1014                                                                32, stride,
1015                                                                &black,
1016                                                                &white,
1017                                                                &transparent);
1018 #ifdef USE_OPENGLES
1019                                 struct point p;
1020                                 p.x=(x + g->x) >> 6;
1021                                 p.y=(y + g->y) >> 6;
1022                                 draw_image_es(gr, &p, g->w, g->h, glyph);
1023 #else
1024 #ifdef MIRRORED_VIEW
1025                                 glPixelZoom(-1.0, -1.0);        //mirrored mode
1026 #else
1027                                 glPixelZoom(1.0, -1.0);
1028 #endif
1029                                 glRasterPos2d((x + g->x) >> 6,
1030                                               (y + g->y) >> 6);
1031                                 glDrawPixels(g->w, g->h, PIXEL_FORMAT,
1032                                              GL_UNSIGNED_BYTE, glyph);
1033 #endif
1034                                 g_free(glyph);
1035                         }
1036                 }
1037                 x += g->dx;
1038                 y += g->dy;
1039         }
1040 }
1041
1042 static void
1043 draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg,
1044           struct graphics_gc_priv *bg, struct graphics_font_priv *font,
1045           char *text, struct point *p, int dx, int dy)
1046 {
1047         if ((gr->parent && !gr->parent->overlay_enabled)
1048             || (gr->parent && gr->parent->overlay_enabled
1049                 && !gr->overlay_enabled)) {
1050                 return;
1051         }
1052
1053         struct font_freetype_text *t;
1054         int color = 1;
1055
1056         if (!font) {
1057                 dbg(0, "no font, returning\n");
1058                 return;
1059         }
1060
1061         graphics_priv_root->dirty = 1;
1062
1063         t = gr->freetype_methods.text_new(text,
1064                                           (struct font_freetype_font *)
1065                                           font, dx, dy);
1066
1067         struct point p_eff;
1068         p_eff.x = p->x;
1069         p_eff.y = p->y;
1070
1071         display_text_draw(t, gr, fg, bg, color, &p_eff);
1072         gr->freetype_methods.text_destroy(t);
1073 }
1074
1075
1076 static void
1077 draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg,
1078            struct point *p, struct graphics_image_priv *img)
1079 {
1080 #ifdef USE_OPENGLES
1081         draw_image_es(gr, p, img->w, img->h, img->data);
1082 #else
1083         if ((gr->parent && !gr->parent->overlay_enabled)
1084             || (gr->parent && gr->parent->overlay_enabled
1085                 && !gr->overlay_enabled)) {
1086                 return;
1087         }
1088
1089         if (!img || !img->data) {
1090                 return;
1091         }
1092
1093         graphics_priv_root->dirty = 1;
1094
1095         struct point p_eff;
1096         p_eff.x = p->x + img->hot_x;
1097         p_eff.y = p->y + img->hot_y;
1098
1099         glEnable(GL_BLEND);
1100         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1101
1102         glRasterPos2d(p_eff.x - img->hot_x, p_eff.y - img->hot_y);
1103         glDrawPixels(img->w, img->h, GL_RGBA, GL_UNSIGNED_BYTE, img->data);
1104 #endif
1105
1106 }
1107
1108 static void
1109 draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg,
1110                 struct point *p, int count, char *data)
1111 {
1112 }
1113
1114 static void
1115 draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
1116 {
1117 }
1118
1119 static void
1120 draw_drag(struct graphics_priv *gr, struct point *p)
1121 {
1122
1123         if (p) {
1124                 gr->p.x = p->x;
1125                 gr->p.y = p->y;
1126         }
1127 }
1128
1129 static void
1130 background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
1131 {
1132         gr->background_gc = gc;
1133 }
1134
1135 static void
1136 handle_mouse_queue()
1137 {
1138 #ifdef USE_OPENGLES
1139 #else
1140         static locked = 0;
1141         if (!locked) {
1142                 locked = 1;
1143         } else {
1144                 return;
1145         }
1146
1147         if (mouse_event_queue_begin_idx < mouse_event_queue_end_idx) {
1148                 if (mouse_queue[mouse_event_queue_begin_idx].button ==
1149                     GLUT_LEFT_BUTTON
1150                     && mouse_queue[mouse_event_queue_begin_idx].state ==
1151                     GLUT_UP) {
1152                         struct point p;
1153                         p.x =
1154                             mouse_queue[mouse_event_queue_begin_idx %
1155                                         mouse_event_queue_size].x;
1156                         p.y =
1157                             mouse_queue[mouse_event_queue_begin_idx %
1158                                         mouse_event_queue_size].y;
1159                         graphics_priv_root->force_redraw = 1;
1160                         callback_list_call_attr_3(graphics_priv_root->cbl,
1161                                                   attr_button, (void *) 0,
1162                                                   1, (void *) &p);
1163                 } else if (mouse_queue[mouse_event_queue_begin_idx].
1164                            button == GLUT_LEFT_BUTTON
1165                            && mouse_queue[mouse_event_queue_begin_idx].
1166                            state == GLUT_DOWN) {
1167                         struct point p;
1168                         p.x =
1169                             mouse_queue[mouse_event_queue_begin_idx %
1170                                         mouse_event_queue_size].x;
1171                         p.y =
1172                             mouse_queue[mouse_event_queue_begin_idx %
1173                                         mouse_event_queue_size].y;
1174                         graphics_priv_root->force_redraw = 1;
1175                         callback_list_call_attr_3(graphics_priv_root->cbl,
1176                                                   attr_button, (void *) 1,
1177                                                   1, (void *) &p);
1178                 }
1179                 ++mouse_event_queue_begin_idx;
1180         }
1181         locked = 0;
1182 #endif
1183 }
1184
1185
1186 /*draws root graphics and its overlays*/
1187 static int
1188 redraw_screen(struct graphics_priv *gr)
1189 {
1190 #ifdef USE_OPENGLES
1191 #else
1192         time_t curr_time = time(0);
1193         graphics_priv_root->dirty = 0;
1194
1195         glCallList(gr->DLid);
1196         //display overlays display list
1197         struct graphics_priv *overlay;
1198         overlay = gr->overlays;
1199         while (gr->overlay_enabled && overlay) {
1200                 if (overlay->overlay_enabled) {
1201                         glPushMatrix();
1202                         struct point p_eff;
1203                         get_overlay_pos(overlay, &p_eff);
1204                         glTranslatef(p_eff.x, p_eff.y, 1);
1205                         glCallList(overlay->DLid);
1206                         glPopMatrix();
1207                 }
1208                 overlay = overlay->next;
1209         }
1210         glutSwapBuffers();
1211 #endif
1212
1213         return TRUE;
1214 }
1215
1216
1217 #ifndef USE_OPENGLES
1218 /*filters call to redraw in overlay enabled(map) mode*/
1219 static void
1220 redraw_filter(struct graphics_priv *gr)
1221 {
1222         if (gr->overlay_enabled && gr->dirty) {
1223                 redraw_screen(gr);
1224         }
1225 }
1226 #endif
1227
1228
1229
1230 static void
1231 draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
1232 {
1233         if (gr->parent) {       //overlay
1234 #ifdef USE_OPENGLES
1235 #else
1236                 if (mode == draw_mode_begin) {
1237                         glNewList(gr->DLid, GL_COMPILE);
1238                 }
1239
1240                 if (mode == draw_mode_end || mode == draw_mode_end_lazy) {
1241                         glEndList();
1242                 }
1243 #endif
1244         } else {                //root graphics
1245                 if (mode == draw_mode_begin) {
1246 #ifdef USE_OPENGLES
1247 #else
1248                         glNewList(gr->DLid, GL_COMPILE);
1249 #endif
1250                 }
1251
1252                 if (mode == draw_mode_end) {
1253 #ifdef USE_OPENGLES
1254                         eglSwapBuffers(egldisplay, eglwindow);
1255 #else
1256                         glEndList();
1257                         gr->force_redraw = 1;
1258                         if (!gr->overlay_enabled || gr->force_redraw) {
1259                                 redraw_screen(gr);
1260                         }
1261 #endif
1262                 }
1263         }
1264         gr->mode = mode;
1265 }
1266
1267 static struct graphics_priv *overlay_new(struct graphics_priv *gr,
1268                                          struct graphics_methods *meth,
1269                                          struct point *p, int w, int h,
1270                                          int alpha, int wraparound);
1271
1272 static int
1273 graphics_opengl_fullscreen(struct window *w, int on)
1274 {
1275         return 1;
1276 }
1277
1278 static void
1279 graphics_opengl_disable_suspend(struct window *w)
1280 {
1281 }
1282
1283 #ifdef USE_OPENGLES2
1284 static GLuint
1285 load_shader(const char *shader_source, GLenum type)
1286 {
1287         GLuint shader = glCreateShader(type);
1288
1289         glShaderSource(shader, 1, &shader_source, NULL);
1290         glCompileShader(shader);
1291
1292         return shader;
1293 }
1294 #endif
1295
1296 static void *
1297 get_data(struct graphics_priv *this, char *type)
1298 {
1299         /*TODO initialize gtkglext context when type=="gtk_widget" */
1300         if (!strcmp(type, "gtk_widget")) {
1301                 fprintf(stderr,
1302                         "Currently GTK gui is not yet supported with opengl graphics driver\n");
1303                 return NULL;
1304         }
1305         if (strcmp(type, "window") == 0) {
1306                 struct window *win;
1307 #ifdef USE_OPENGLES
1308                 GLuint vertexShader;
1309                 GLuint fragmentShader;
1310                 GLuint textures;
1311                 GLfloat matrix[16];
1312                 int i;
1313
1314                 createEGLWindow(this->width,this->height,"Navit");
1315                 resize_callback(this->width,this->height);
1316 #if 0
1317                 glClearColor ( 0.4 , 0.4 , 0.4 , 1);
1318 #endif
1319                 glClear ( GL_COLOR_BUFFER_BIT );
1320 #ifdef USE_OPENGLES2
1321                 this->program=glCreateProgram();
1322                 vertexShader = load_shader(vertex_src, GL_VERTEX_SHADER);
1323                 fragmentShader = load_shader(fragment_src, GL_FRAGMENT_SHADER);
1324                 glAttachShader(this->program, vertexShader);
1325                 glAttachShader(this->program, fragmentShader);
1326                 glLinkProgram(this->program);
1327                 glUseProgram(this->program);
1328                 this->mvp_location=glGetUniformLocation(this->program, "mvp");
1329                 this->position_location=glGetAttribLocation(this->program, "position");
1330                 glEnableVertexAttribArray(this->position_location);
1331                 this->texture_position_location=glGetAttribLocation(this->program, "texture_position");
1332                 this->color_location=glGetUniformLocation(this->program, "avcolor");
1333                 this->texture_location=glGetUniformLocation(this->program, "texture");
1334                 this->use_texture_location=glGetUniformLocation(this->program, "use_texture");
1335                 glUniform1i(this->use_texture_location, 0);
1336                 glUniform1i(this->texture_location, 0);
1337
1338                 for (i = 0 ; i < 16 ; i++)
1339                         matrix[i]=0.0;
1340                 matrix[0]=2.0/this->width;
1341                 matrix[5]=-2.0/this->height;
1342                 matrix[10]=1;
1343                 matrix[12]=-1;
1344                 matrix[13]=1;
1345                 matrix[15]=1;
1346                 glUniformMatrix4fv(this->mvp_location, 1, GL_FALSE, matrix);
1347 #else
1348                 glEnableClientState(GL_VERTEX_ARRAY);
1349 #endif
1350                 glGenTextures(1, &textures);
1351                 glActiveTexture(GL_TEXTURE0);
1352                 glBindTexture(GL_TEXTURE_2D, textures);
1353 #ifndef USE_OPENGLES2
1354                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1355                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1356                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1357                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1358
1359                 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1360 #endif
1361 #endif
1362                 win = g_new0(struct window, 1);
1363                 win->priv = this;
1364                 win->fullscreen = graphics_opengl_fullscreen;
1365                 win->disable_suspend = graphics_opengl_disable_suspend;
1366                 return win;
1367         } else {
1368 #ifdef USE_OPENGLES
1369                 return NULL;
1370 #else
1371                 return &this->DLid;
1372 #endif
1373         }
1374
1375
1376 }
1377
1378 static void
1379 image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
1380 {
1381 //TODO free image data in hashtable when graphics is destroyed
1382 //currently graphics destroy is not called !!!
1383 /*
1384   g_free(priv->data);
1385   priv->data = NULL;
1386   g_free(priv); 
1387   priv = NULL;
1388 */
1389 }
1390
1391 static void
1392 overlay_disable(struct graphics_priv *gr, int disable)
1393 {
1394         gr->overlay_enabled = !disable;
1395         gr->force_redraw = 1;
1396         draw_mode(gr, draw_mode_end);
1397 }
1398
1399 static void
1400 overlay_resize(struct graphics_priv *gr, struct point *p, int w, int h,
1401                int alpha, int wraparound)
1402 {
1403         int changed = 0;
1404         int w2, h2;
1405
1406         if (w == 0) {
1407                 w2 = 1;
1408         } else {
1409                 w2 = w;
1410         }
1411
1412         if (h == 0) {
1413                 h2 = 1;
1414         } else {
1415                 h2 = h;
1416         }
1417
1418         gr->p = *p;
1419         if (gr->width != w2) {
1420                 gr->width = w2;
1421                 changed = 1;
1422         }
1423
1424         if (gr->height != h2) {
1425                 gr->height = h2;
1426                 changed = 1;
1427         }
1428
1429         gr->wraparound = wraparound;
1430
1431         if (changed) {
1432                 if ((w == 0) || (h == 0)) {
1433                         gr->overlay_autodisabled = 1;
1434                 } else {
1435                         gr->overlay_autodisabled = 0;
1436                 }
1437
1438                 callback_list_call_attr_2(gr->cbl, attr_resize,
1439                                           GINT_TO_POINTER(gr->width),
1440                                           GINT_TO_POINTER(gr->height));
1441         }
1442 }
1443
1444 static struct graphics_methods graphics_methods = {
1445         graphics_destroy,
1446         draw_mode,
1447         draw_lines,
1448         draw_polygon,
1449         draw_rectangle,
1450 #ifdef USE_OPENGLES
1451         NULL,
1452 #else
1453         draw_circle,
1454 #endif
1455         draw_text,
1456         draw_image,
1457         draw_image_warp,
1458         draw_restore,
1459         draw_drag,
1460         NULL,
1461         gc_new,
1462         background_gc,
1463         overlay_new,
1464         image_new,
1465         get_data,
1466         image_free,
1467         NULL,
1468         overlay_disable,
1469         overlay_resize,
1470 };
1471
1472 static struct graphics_priv *
1473 graphics_opengl_new_helper(struct graphics_methods *meth)
1474 {
1475         struct font_priv *(*font_freetype_new) (void *meth);
1476         font_freetype_new = plugin_get_font_type("freetype");
1477
1478         if (!font_freetype_new) {
1479                 return NULL;
1480         }
1481
1482         struct graphics_priv *this = g_new0(struct graphics_priv, 1);
1483
1484         font_freetype_new(&this->freetype_methods);
1485         *meth = graphics_methods;
1486
1487         meth->font_new =
1488             (struct graphics_font_priv *
1489              (*)(struct graphics_priv *, struct graphics_font_methods *,
1490                  char *, int, int)) this->freetype_methods.font_new;
1491         meth->get_text_bbox = this->freetype_methods.get_text_bbox;
1492
1493         return this;
1494 }
1495
1496 static struct graphics_priv *
1497 overlay_new(struct graphics_priv *gr, struct graphics_methods *meth,
1498             struct point *p, int w, int h, int alpha, int wraparound)
1499 {
1500         int w2, h2;
1501         struct graphics_priv *this = graphics_opengl_new_helper(meth);
1502         this->p = *p;
1503         this->width = w;
1504         this->height = h;
1505         this->parent = gr;
1506
1507         /* If either height or width is 0, we set it to 1 to avoid warnings, and
1508          * disable the overlay. */
1509         if (h == 0) {
1510                 h2 = 1;
1511         } else {
1512                 h2 = h;
1513         }
1514
1515         if (w == 0) {
1516                 w2 = 1;
1517         } else {
1518                 w2 = w;
1519         }
1520
1521         if ((w == 0) || (h == 0)) {
1522                 this->overlay_autodisabled = 1;
1523         } else {
1524                 this->overlay_autodisabled = 0;
1525         }
1526         this->overlay_enabled = 1;
1527         this->overlay_autodisabled = 0;
1528
1529         this->next = gr->overlays;
1530         gr->overlays = this;
1531 #ifdef USE_OPENGLES
1532 #else
1533         this->DLid = glGenLists(1);
1534 #endif
1535         return this;
1536 }
1537
1538
1539 static void
1540 click_notify(int button, int state, int x, int y)
1541 {
1542         mouse_queue[mouse_event_queue_end_idx %
1543                     mouse_event_queue_size].button = button;
1544         mouse_queue[mouse_event_queue_end_idx %
1545                     mouse_event_queue_size].state = state;
1546 #ifdef MIRRORED_VIEW
1547         mouse_queue[mouse_event_queue_end_idx % mouse_event_queue_size].x =
1548             graphics_priv_root->width - x;
1549 #else
1550         mouse_queue[mouse_event_queue_end_idx % mouse_event_queue_size].x =
1551             x;
1552 #endif
1553         mouse_queue[mouse_event_queue_end_idx % mouse_event_queue_size].y =
1554             y;
1555         ++mouse_event_queue_end_idx;
1556 }
1557
1558 static void
1559 motion_notify(int x, int y)
1560 {
1561         struct point p;
1562 #ifdef MIRRORED_VIEW
1563         p.x = graphics_priv_root->width - x;
1564 #else
1565         p.x = x;
1566 #endif
1567         p.y = y;
1568         callback_list_call_attr_1(graphics_priv_root->cbl, attr_motion,
1569                                   (void *) &p);
1570         return;
1571 }
1572
1573 #ifndef USE_OPENGLES
1574 static gboolean
1575 graphics_opengl_idle(void *data)
1576 {
1577         static int opengl_init_ok = 0;
1578         if (!opengl_init_ok) {
1579                 callback_list_call_attr_2(graphics_priv_root->cbl,
1580                                           attr_resize,
1581                                           GINT_TO_POINTER
1582                                           (graphics_priv_root->width),
1583                                           GINT_TO_POINTER
1584                                           (graphics_priv_root->height));
1585                 opengl_init_ok = 1;
1586         } else {
1587                 
1588 #ifdef FREEGLUT
1589                 glutMainLoopEvent();
1590 #endif
1591                 handle_mouse_queue();
1592         }
1593         return TRUE;
1594 }
1595 #endif
1596
1597 static void
1598 ProcessNormalKeys(unsigned char key_in, int x, int y)
1599 {
1600         int key = 0;
1601         char keybuf[2];
1602
1603         switch (key_in) {
1604         case 13:
1605                 key = NAVIT_KEY_RETURN;
1606                 break;
1607         default:
1608                 key = key_in;
1609                 break;
1610         }
1611         keybuf[0] = key;
1612         keybuf[1] = '\0';
1613         graphics_priv_root->force_redraw = 1;
1614         callback_list_call_attr_1(graphics_priv_root->cbl, attr_keypress,
1615                                   (void *) keybuf);
1616 }
1617
1618 static void
1619 ProcessSpecialKeys(int key_in, int x, int y)
1620 {
1621         int key = 0;
1622         char keybuf[2];
1623
1624         switch (key_in) {
1625         case 102:
1626                 key = NAVIT_KEY_RIGHT;
1627                 break;
1628         case 100:
1629                 key = NAVIT_KEY_LEFT;
1630                 break;
1631         case 103:
1632                 key = NAVIT_KEY_DOWN;
1633                 break;
1634         case 101:
1635                 key = NAVIT_KEY_UP;
1636                 break;
1637         case 104:
1638                 key = NAVIT_KEY_ZOOM_OUT;
1639                 break;
1640         case 105:
1641                 key = NAVIT_KEY_ZOOM_IN;
1642                 break;
1643         default:
1644                 break;
1645         }                       //switch
1646
1647         graphics_priv_root->force_redraw = 1;
1648         keybuf[0] = key;
1649         keybuf[1] = '\0';
1650         callback_list_call_attr_1(graphics_priv_root->cbl, attr_keypress,
1651                                   (void *) keybuf);
1652 }
1653
1654 static void
1655 resize_callback(int w, int h)
1656 {
1657         glViewport(0, 0, w, h);
1658 #ifndef USE_OPENGLES2
1659         glMatrixMode(GL_PROJECTION);
1660         glLoadIdentity();
1661 #ifdef MIRRORED_VIEW
1662         glOrthof(glF(w), glF(0), glF(h), glF(0), glF(1), glF(-1));
1663 #else
1664         glOrthof(glF(0), glF(w), glF(h), glF(0), glF(1), glF(-1));
1665 #endif
1666 #endif
1667         graphics_priv_root->width = w;
1668         graphics_priv_root->height = h;
1669
1670         callback_list_call_attr_2(graphics_priv_root->cbl, attr_resize,
1671                                   GINT_TO_POINTER(w), GINT_TO_POINTER(h));
1672 }
1673
1674 static void
1675 display(void)
1676 {
1677         graphics_priv_root->force_redraw = 1;
1678         redraw_screen(graphics_priv_root);
1679         resize_callback(graphics_priv_root->width,
1680                         graphics_priv_root->height);
1681 }
1682
1683 static void
1684 glut_close(void)
1685 {
1686         callback_list_call_attr_0(graphics_priv_root->cbl,
1687                                   attr_window_closed);
1688 }
1689
1690
1691 static struct graphics_priv *
1692 graphics_opengl_new(struct navit *nav, struct graphics_methods *meth,
1693                     struct attr **attrs, struct callback_list *cbl)
1694 {
1695         struct attr *attr;
1696
1697         if (!event_request_system("glib", "graphics_opengl_new"))
1698                 return NULL;
1699
1700         struct graphics_priv *this = graphics_opengl_new_helper(meth);
1701         graphics_priv_root = this;
1702
1703         this->nav = nav;
1704         this->parent = NULL;
1705         this->overlay_enabled = 1;
1706
1707         this->width = SCREEN_WIDTH;
1708         if ((attr = attr_search(attrs, NULL, attr_w)))
1709                 this->width = attr->u.num;
1710         this->height = SCREEN_HEIGHT;
1711         if ((attr = attr_search(attrs, NULL, attr_h)))
1712                 this->height = attr->u.num;
1713         this->timeout = 100;
1714         if ((attr = attr_search(attrs, NULL, attr_timeout)))
1715                 this->timeout = attr->u.num;
1716         this->delay = 0;
1717         if ((attr = attr_search(attrs, NULL, attr_delay)))
1718                 this->delay = attr->u.num;
1719         this->cbl = cbl;
1720
1721         char *cmdline = "";
1722         int argc = 0;
1723 #ifndef USE_OPENGLES
1724         glutInit(&argc, &cmdline);
1725         glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
1726
1727         glutInitWindowSize(this->width, this->height);
1728         glutInitWindowPosition(0, 0);
1729         glutCreateWindow("Navit opengl window");
1730
1731         glutDisplayFunc(display);
1732         glutReshapeFunc(resize_callback);
1733         resize_callback(this->width, this->height);
1734 #endif
1735
1736         graphics_priv_root->cbl = cbl;
1737         graphics_priv_root->width = this->width;
1738         graphics_priv_root->height = this->height;
1739
1740 #ifndef USE_OPENGLES
1741         glutMotionFunc(motion_notify);
1742         glutPassiveMotionFunc(motion_notify);
1743         glutMouseFunc(click_notify);
1744         glutKeyboardFunc(ProcessNormalKeys);
1745         glutSpecialFunc(ProcessSpecialKeys);
1746 #ifdef FREEGLUT
1747         glutCloseFunc(glut_close);
1748 #endif
1749         this->DLid = glGenLists(1);
1750
1751         g_timeout_add(G_PRIORITY_DEFAULT + 10, graphics_opengl_idle, NULL);
1752
1753         /*this will only refresh screen in map(overlay enabled) mode */
1754         g_timeout_add(G_PRIORITY_DEFAULT + 1000, redraw_filter, this);
1755 #endif
1756
1757         //create hash table for uncompressed image data
1758         hImageData = g_hash_table_new(g_str_hash, g_str_equal);
1759         return this;
1760 }
1761
1762
1763 static void
1764 event_opengl_main_loop_run(void)
1765 {
1766         dbg(0, "enter\n");
1767 }
1768
1769 static void
1770 event_opengl_main_loop_quit(void)
1771 {
1772         dbg(0, "enter\n");
1773 }
1774
1775 static struct event_watch *
1776 event_opengl_add_watch(void *h, enum event_watch_cond cond,
1777                        struct callback *cb)
1778 {
1779         dbg(0, "enter\n");
1780         return NULL;
1781 }
1782
1783 static void
1784 event_opengl_remove_watch(struct event_watch *ev)
1785 {
1786         dbg(0, "enter\n");
1787 }
1788
1789
1790 static struct event_timeout *
1791 event_opengl_add_timeout(int timeout, int multi, struct callback *cb)
1792 {
1793         dbg(0, "enter\n");
1794         return NULL;
1795 }
1796
1797 static void
1798 event_opengl_remove_timeout(struct event_timeout *to)
1799 {
1800         dbg(0, "enter\n");
1801 }
1802
1803
1804 static struct event_idle *
1805 event_opengl_add_idle(int priority, struct callback *cb)
1806 {
1807         dbg(0, "enter\n");
1808         return NULL;
1809 }
1810
1811 static void
1812 event_opengl_remove_idle(struct event_idle *ev)
1813 {
1814         dbg(0, "enter\n");
1815 }
1816
1817 static void
1818 event_opengl_call_callback(struct callback_list *cb)
1819 {
1820         dbg(0, "enter\n");
1821 }
1822
1823 static struct event_methods event_opengl_methods = {
1824         event_opengl_main_loop_run,
1825         event_opengl_main_loop_quit,
1826         event_opengl_add_watch,
1827         event_opengl_remove_watch,
1828         event_opengl_add_timeout,
1829         event_opengl_remove_timeout,
1830         event_opengl_add_idle,
1831         event_opengl_remove_idle,
1832         event_opengl_call_callback,
1833 };
1834
1835 static struct event_priv *
1836 event_opengl_new(struct event_methods *meth)
1837 {
1838         *meth = event_opengl_methods;
1839         return NULL;
1840 }
1841
1842 void
1843 plugin_init(void)
1844 {
1845         plugin_register_graphics_type("opengl", graphics_opengl_new);
1846         plugin_register_event_type("opengl", event_opengl_new);
1847 }