2 // "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $"
4 // GLUT emulation routines for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
28 // Emulation of Glut using fltk.
30 // GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996.
31 // "This program is freely distributable without licensing fees and is
32 // provided without guarantee or warrantee expressed or implied. This
33 // program is -not- in the public domain."
35 // Although I have copied the GLUT API, none of my code is based on
36 // any Glut implementation details and is therefore covered by the LGPL.
42 # ifdef HAVE_GLXGETPROCADDRESSARB
43 # define GLX_GLXEXT_LEGACY
45 # endif // HAVE_GLXGETPROCADDRESSARB
48 # endif // HAVE_DLFCN_H
49 # define MAXWINDOWS 32
50 static Fl_Glut_Window
*windows
[MAXWINDOWS
+1];
52 static void (*glut_idle_func
)() = 0; // global glut idle function
54 Fl_Glut_Window
*glut_window
;
56 void (*glut_menustate_function
)(int);
57 void (*glut_menustatus_function
)(int,int,int);
59 static void default_reshape(int w
, int h
) {glViewport(0,0,w
,h
);}
60 static void default_display() {}
62 void Fl_Glut_Window::make_current() {
64 if (shown()) Fl_Gl_Window::make_current();
68 void Fl_Glut_Window::draw() {
71 if (!valid()) {reshape(w(),h()); valid(1);}
76 void glutSwapBuffers() {
77 if (!indraw
) glut_window
->swap_buffers();
80 void Fl_Glut_Window::draw_overlay() {
82 if (!valid()) {reshape(w(),h()); valid(1);}
86 static void domenu(int, int, int);
88 int Fl_Glut_Window::handle(int event
) {
90 int ex
= Fl::event_x();
91 int ey
= Fl::event_y();
96 if (keyboard
|| special
) Fl::focus(this);
97 button
= Fl::event_button()-1;
98 if (button
<0) button
= 0;
99 if (button
>2) button
= 2;
100 if (menu
[button
]) {domenu(menu
[button
],ex
,ey
); return 1;}
101 mouse_down
|= 1<<button
;
102 if (mouse
) {mouse(button
,GLUT_DOWN
,ex
,ey
); return 1;}
103 if (motion
) return 1;
107 button
= Fl::event_dy();
108 while (button
< 0) {if (mouse
) mouse(3,GLUT_DOWN
,ex
,ey
); ++button
;}
109 while (button
> 0) {if (mouse
) mouse(4,GLUT_DOWN
,ex
,ey
); --button
;}
113 for (button
= 0; button
< 3; button
++) if (mouse_down
& (1<<button
)) {
114 if (mouse
) mouse(button
,GLUT_UP
,ex
,ey
);
120 if (entry
) {entry(GLUT_ENTERED
); return 1;}
121 if (passivemotion
) return 1;
125 if (entry
) {entry(GLUT_LEFT
); return 1;}
126 if (passivemotion
) return 1;
130 if (motion
) {motion(ex
, ey
); return 1;}
134 if (passivemotion
) {passivemotion(ex
, ey
); return 1;}
138 if (keyboard
|| special
) return 1;
142 if (!keyboard
&& !special
) break;
145 if (Fl::event_text()[0]) {
146 if (keyboard
) {keyboard(Fl::event_text()[0],ex
,ey
); return 1;}
150 int k
= Fl::event_key();
151 if (k
> FL_F
&& k
<= FL_F_Last
) k
-= FL_F
;
159 if (visibility
) visibility(GLUT_NOT_VISIBLE
);
163 if (visibility
) visibility(GLUT_VISIBLE
);
167 return Fl_Gl_Window::handle(event
);
170 static int glut_mode
= GLUT_RGB
| GLUT_SINGLE
| GLUT_DEPTH
;
172 void Fl_Glut_Window::_init() {
173 for (number
=1; number
<MAXWINDOWS
; number
++) if (!windows
[number
]) break;
174 windows
[number
] = this;
175 menu
[0] = menu
[1] = menu
[2] = 0;
176 reshape
= default_reshape
;
177 display
= default_display
;
178 overlaydisplay
= default_display
;
190 /** Creates a glut window, registers to the glut windows list.*/
191 Fl_Glut_Window::Fl_Glut_Window(int W
, int H
, const char *t
) :
192 Fl_Gl_Window(W
,H
,t
) {_init();}
194 /** Creates a glut window, registers to the glut windows list.*/
195 Fl_Glut_Window::Fl_Glut_Window(int X
,int Y
,int W
,int H
, const char *t
) :
196 Fl_Gl_Window(X
,Y
,W
,H
,t
) {_init();}
199 static char **initargv
;
201 void glutInit(int *argc
, char **argv
) {
203 initargv
= new char*[*argc
+1];
205 for (i
=0; i
<=*argc
; i
++) initargv
[i
] = argv
[i
];
206 for (i
=j
=1; i
<*argc
; ) {
207 if (Fl::arg(*argc
,argv
,i
));
208 else argv
[j
++] = argv
[i
++];
214 void glutInitDisplayMode(unsigned int mode
) {
218 void glutMainLoop() {Fl::run();}
220 ////////////////////////////////////////////////////////////////
222 static int initx
=0, inity
=0, initw
=300, inith
=300, initpos
=0;
224 void glutInitWindowPosition(int x
, int y
) {
225 initx
= x
; inity
= y
; initpos
= 1;
228 void glutInitWindowSize(int w
, int h
) {
229 initw
= w
; inith
= h
;
232 int glutCreateWindow(char *title
) {
233 return glutCreateWindow((const char*)title
);
236 int glutCreateWindow(const char *title
) {
239 W
= new Fl_Glut_Window(initx
,inity
,initw
,inith
,title
);
242 W
= new Fl_Glut_Window(initw
,inith
,title
);
246 W
->show(initargc
,initargv
);
257 int glutCreateSubWindow(int win
, int x
, int y
, int w
, int h
) {
258 Fl_Glut_Window
*W
= new Fl_Glut_Window(x
,y
,w
,h
,0);
259 windows
[win
]->add(W
);
260 if (windows
[win
]->shown()) W
->show();
264 /** Destroys the glut window, first unregister it from the glut windows list */
265 Fl_Glut_Window::~Fl_Glut_Window() {
266 if (glut_window
== this) glut_window
= 0;
270 void glutDestroyWindow(int win
) {
271 // should destroy children!!!
275 void glutPostWindowRedisplay(int win
) {
276 windows
[win
]->redraw();
279 void glutSetWindow(int win
) {
280 windows
[win
]->make_current();
283 ////////////////////////////////////////////////////////////////
284 #include <FL/Fl_Menu_Item.H>
294 static menu menus
[MAXMENUS
+1];
296 static void domenu(int n
, int ex
, int ey
) {
299 if (glut_menustate_function
) glut_menustate_function(1);
300 if (glut_menustatus_function
) glut_menustatus_function(1,ex
,ey
);
301 const Fl_Menu_Item
* g
= m
->m
->popup(Fl::event_x(), Fl::event_y(), 0);
302 if (g
&& g
->callback_
) ((void (*)(int))(g
->callback_
))(int(g
->argument()));
303 if (glut_menustatus_function
) glut_menustatus_function(0,ex
,ey
);
304 if (glut_menustate_function
) glut_menustate_function(0);
307 int glutCreateMenu(void (*cb
)(int)) {
309 for (i
=1; i
<MAXMENUS
; i
++) if (!menus
[i
].cb
) break;
312 return glut_menu
= i
;
315 void glutDestroyMenu(int n
) {
320 m
->size
= m
->alloc
= 0;
323 static Fl_Menu_Item
* additem(menu
*m
) {
324 if (m
->size
+1 >= m
->alloc
) {
325 m
->alloc
= m
->size
*2+10;
326 Fl_Menu_Item
* nm
= new Fl_Menu_Item
[m
->alloc
];
327 for (int i
=0; i
<m
->size
; i
++) nm
[i
] = m
->m
[i
];
333 Fl_Menu_Item
* i
= &(m
->m
[n
]);
336 i
->labeltype_
= i
->labelfont_
= i
->labelsize_
= i
->labelcolor_
= 0;
340 void glutAddMenuEntry(char *label
, int value
) {
341 menu
*m
= &menus
[glut_menu
];
342 Fl_Menu_Item
* i
= additem(m
);
344 i
->callback_
= (Fl_Callback
*)(m
->cb
);
345 i
->user_data_
= (void *)value
;
348 void glutAddSubMenu(char *label
, int submenu
) {
349 menu
*m
= &menus
[glut_menu
];
350 Fl_Menu_Item
* i
= additem(m
);
353 i
->user_data_
= (void *)(menus
[submenu
].m
);
354 i
->flags
= FL_PUP_SUBMENU
;
357 void glutChangeToMenuEntry(int item
, char *label
, int value
) {
358 menu
*m
= &menus
[glut_menu
];
359 Fl_Menu_Item
* i
= &m
->m
[item
-1];
361 i
->callback_
= (Fl_Callback
*)(m
->cb
);
362 i
->user_data_
= (void *)value
;
366 void glutChangeToSubMenu(int item
, char *label
, int submenu
) {
367 menu
*m
= &menus
[glut_menu
];
368 Fl_Menu_Item
* i
= &m
->m
[item
-1];
371 i
->user_data_
= (void *)(menus
[submenu
].m
);
372 i
->flags
= FL_PUP_SUBMENU
;
375 void glutRemoveMenuItem(int item
) {
376 menu
*m
= &menus
[glut_menu
];
377 if (item
> m
->size
|| item
< 1) return;
378 for (int i
= item
-1; i
<= m
->size
; i
++) m
->m
[i
] = m
->m
[i
+1];
382 ////////////////////////////////////////////////////////////////
384 int glutGet(GLenum type
) {
386 case GLUT_RETURN_ZERO
: return 0;
387 case GLUT_WINDOW_X
: return glut_window
->x();
388 case GLUT_WINDOW_Y
: return glut_window
->y();
389 case GLUT_WINDOW_WIDTH
: return glut_window
->w();
390 case GLUT_WINDOW_HEIGHT
: return glut_window
->h();
391 case GLUT_WINDOW_PARENT
:
392 if (glut_window
->parent())
393 return ((Fl_Glut_Window
*)(glut_window
->parent()))->number
;
396 //case GLUT_WINDOW_NUM_CHILDREN:
397 //case GLUT_WINDOW_CURSOR: return
398 case GLUT_SCREEN_WIDTH
: return Fl::w();
399 case GLUT_SCREEN_HEIGHT
: return Fl::h();
400 //case GLUT_SCREEN_WIDTH_MM:
401 //case GLUT_SCREEN_HEIGHT_MM:
402 case GLUT_MENU_NUM_ITEMS
: return menus
[glut_menu
].size
;
403 case GLUT_DISPLAY_MODE_POSSIBLE
: return Fl_Gl_Window::can_do(glut_mode
);
404 case GLUT_INIT_WINDOW_X
: return initx
;
405 case GLUT_INIT_WINDOW_Y
: return inity
;
406 case GLUT_INIT_WINDOW_WIDTH
: return initw
;
407 case GLUT_INIT_WINDOW_HEIGHT
: return inith
;
408 case GLUT_INIT_DISPLAY_MODE
: return glut_mode
;
409 //case GLUT_ELAPSED_TIME:
410 case GLUT_WINDOW_BUFFER_SIZE
:
411 if (glutGet(GLUT_WINDOW_RGBA
))
412 return glutGet(GLUT_WINDOW_RED_SIZE
)+
413 glutGet(GLUT_WINDOW_GREEN_SIZE
)+
414 glutGet(GLUT_WINDOW_BLUE_SIZE
)+
415 glutGet(GLUT_WINDOW_ALPHA_SIZE
);
417 return glutGet(GLUT_WINDOW_COLORMAP_SIZE
);
418 case GLUT_VERSION
: return 20400;
419 default: {GLint p
; glGetIntegerv(type
, &p
); return p
;}
423 int glutLayerGet(GLenum type
) {
425 case GLUT_OVERLAY_POSSIBLE
: return glut_window
->can_do_overlay();
426 //case GLUT_LAYER_IN_USE:
427 //case GLUT_HAS_OVERLAY:
428 case GLUT_TRANSPARENT_INDEX
: return 0; // true for SGI
429 case GLUT_NORMAL_DAMAGED
: return glut_window
->damage();
430 case GLUT_OVERLAY_DAMAGED
: return 1; // kind of works...
435 int glutDeviceGet(GLenum type
) {
437 case GLUT_HAS_KEYBOARD
: return 1;
438 case GLUT_HAS_MOUSE
: return 1;
439 case GLUT_NUM_MOUSE_BUTTONS
: return 3;
444 // Get extension function address...
445 GLUTproc
glutGetProcAddress(const char *procName
) {
447 return (GLUTproc
)wglGetProcAddress((LPCSTR
)procName
);
449 # elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H)
452 snprintf(symbol
, sizeof(symbol
), "_%s", procName
);
455 return (GLUTproc
)dlsym(RTLD_DEFAULT
, symbol
);
457 # else // No RTLD_DEFAULT support, so open the current a.out symbols...
458 static void *rtld_default
= 0;
460 if (!rtld_default
) rtld_default
= dlopen(0, RTLD_LAZY
);
462 if (rtld_default
) return (GLUTproc
)dlsym(rtld_default
, symbol
);
465 # endif // RTLD_DEFAULT
467 # elif defined(HAVE_GLXGETPROCADDRESSARB)
468 return (GLUTproc
)glXGetProcAddressARB((const GLubyte
*)procName
);
475 // Parse the GL_EXTENSIONS string to see if the named extension is
478 // This code was copied from FreeGLUT 2.4.0 which carries the
481 // Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
482 int glutExtensionSupported( const char* extension
)
484 if (!extension
|| strchr(extension
, ' ')) return 0;
486 const char *extensions
, *start
;
487 const int len
= strlen( extension
);
489 start
= extensions
= (const char *) glGetString(GL_EXTENSIONS
);
491 if (!extensions
) return 0;
494 const char *p
= strstr(extensions
, extension
);
495 if (!p
) return 0; /* not found */
496 /* check that the match isn't a super string */
497 if ((p
== start
|| p
[-1] == ' ') &&
498 (p
[len
] == ' ' || p
[len
] == 0)) return 1;
499 /* skip the false match and continue */
500 extensions
= p
+ len
;
504 // Add a mechanism to handle adding/removing the glut idle function
505 // without depending on the (deprecated) set_idle method.
506 void glutIdleFunc(void (*f
)())
509 if(glut_idle_func
== f
) return;
510 // remove current idle
511 if(glut_idle_func
) Fl::remove_idle((void (*)(void *))glut_idle_func
);
512 // install new idle func - if one was passed
513 if(f
) Fl::add_idle((void (*)(void *))f
);
514 // record new idle func - even if it is NULL
521 // End of "$Id: glut_compatability.cxx 7818 2010-11-11 18:22:43Z engelsman $".