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 |
}
|