/[zanavi_public1]/navit/navit/graphics/opengl/graphics_opengl.c
ZANavi

Contents of /navit/navit/graphics/opengl/graphics_opengl.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki