// // "$Id: glut_compatability.cxx 5845 2007-05-20 00:01:06Z mike $" // // GLUT emulation routines for the Fast Light Tool Kit (FLTK). // // Copyright 1998-2007 by Bill Spitzak and others. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 // USA. // // Please report all bugs and problems on the following page: // // http://www.fltk.org/str.php // // Emulation of Glut using fltk. // GLUT is Copyright (c) Mark J. Kilgard, 1994, 1995, 1996. // "This program is freely distributable without licensing fees and is // provided without guarantee or warrantee expressed or implied. This // program is -not- in the public domain." // Although I have copied the GLUT API, none of my code is based on // any Glut implementation details and is therefore covered by the LGPL. #include "flstring.h" #if HAVE_GL # include # ifdef HAVE_GLXGETPROCADDRESSARB # define GLX_GLXEXT_LEGACY # include # endif // HAVE_GLXGETPROCADDRESSARB # ifdef HAVE_DLFCN_H # include # endif // HAVE_DLFCN_H # define MAXWINDOWS 32 static Fl_Glut_Window *windows[MAXWINDOWS+1]; Fl_Glut_Window *glut_window; int glut_menu; void (*glut_menustate_function)(int); void (*glut_menustatus_function)(int,int,int); static void default_reshape(int w, int h) {glViewport(0,0,w,h);} static void default_display() {} void Fl_Glut_Window::make_current() { glut_window = this; if (shown()) Fl_Gl_Window::make_current(); } static int indraw; void Fl_Glut_Window::draw() { glut_window = this; indraw = 1; if (!valid()) {reshape(w(),h()); valid(1);} display(); indraw = 0; } void glutSwapBuffers() { if (!indraw) glut_window->swap_buffers(); } void Fl_Glut_Window::draw_overlay() { glut_window = this; if (!valid()) {reshape(w(),h()); valid(1);} overlaydisplay(); } static void domenu(int, int, int); int Fl_Glut_Window::handle(int event) { make_current(); int ex = Fl::event_x(); int ey = Fl::event_y(); int button; switch (event) { case FL_PUSH: if (keyboard || special) Fl::focus(this); button = Fl::event_button()-1; if (button<0) button = 0; if (button>2) button = 2; if (menu[button]) {domenu(menu[button],ex,ey); return 1;} mouse_down |= 1< 0) {mouse(4,GLUT_DOWN,ex,ey); --button;} return 1; case FL_RELEASE: for (button = 0; button < 3; button++) if (mouse_down & (1< FL_F && k <= FL_F_Last) k -= FL_F; special(k,ex,ey); return 1; } break; } case FL_HIDE: if (visibility) visibility(GLUT_NOT_VISIBLE); break; case FL_SHOW: if (visibility) visibility(GLUT_VISIBLE); break; } return Fl_Gl_Window::handle(event); } static int glut_mode = GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH; void Fl_Glut_Window::_init() { for (number=1; numberresizable(W); if (initargc) { W->show(initargc,initargv); initargc = 0; } else { W->show(); } W->valid(0); W->context_valid(0); W->make_current(); return W->number; } int glutCreateSubWindow(int win, int x, int y, int w, int h) { Fl_Glut_Window *W = new Fl_Glut_Window(x,y,w,h,0); windows[win]->add(W); if (windows[win]->shown()) W->show(); W->make_current(); return W->number; } Fl_Glut_Window::~Fl_Glut_Window() { if (glut_window == this) glut_window = 0; windows[number] = 0; } void glutDestroyWindow(int win) { // should destroy children!!! delete windows[win]; } void glutPostWindowRedisplay(int win) { windows[win]->redraw(); } void glutSetWindow(int win) { windows[win]->make_current(); } //////////////////////////////////////////////////////////////// #include struct menu { void (*cb)(int); Fl_Menu_Item *m; int size; int alloc; }; #define MAXMENUS 32 static menu menus[MAXMENUS+1]; static void domenu(int n, int ex, int ey) { glut_menu = n; menu *m = &menus[n]; if (glut_menustate_function) glut_menustate_function(1); if (glut_menustatus_function) glut_menustatus_function(1,ex,ey); const Fl_Menu_Item* g = m->m->popup(Fl::event_x(), Fl::event_y(), 0); if (g && g->callback_) ((void (*)(int))(g->callback_))(int(g->argument())); if (glut_menustatus_function) glut_menustatus_function(0,ex,ey); if (glut_menustate_function) glut_menustate_function(0); } int glutCreateMenu(void (*cb)(int)) { int i; for (i=1; icb = cb; return glut_menu = i; } void glutDestroyMenu(int n) { menu *m = &menus[n]; delete[] m->m; m->m = 0; m->cb = 0; m->size = m->alloc = 0; } static Fl_Menu_Item* additem(menu *m) { if (m->size+1 >= m->alloc) { m->alloc = m->size*2+10; Fl_Menu_Item* nm = new Fl_Menu_Item[m->alloc]; for (int i=0; isize; i++) nm[i] = m->m[i]; delete[] m->m; m->m = nm; } int n = m->size++; m->m[n+1].text = 0; Fl_Menu_Item* i = &(m->m[n]); i->shortcut_ = 0; i->flags = 0; i->labeltype_ = i->labelfont_ = i->labelsize_ = i->labelcolor_ = 0; return i; } void glutAddMenuEntry(char *label, int value) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = additem(m); i->text = label; i->callback_ = (Fl_Callback*)(m->cb); i->user_data_ = (void *)value; } void glutAddSubMenu(char *label, int submenu) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = additem(m); i->text = label; i->callback_ = 0; i->user_data_ = (void *)(menus[submenu].m); i->flags = FL_PUP_SUBMENU; } void glutChangeToMenuEntry(int item, char *label, int value) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = &m->m[item-1]; i->text = label; i->callback_ = (Fl_Callback*)(m->cb); i->user_data_ = (void *)value; i->flags = 0; } void glutChangeToSubMenu(int item, char *label, int submenu) { menu *m = &menus[glut_menu]; Fl_Menu_Item* i = &m->m[item-1]; i->text = label; i->callback_ = 0; i->user_data_ = (void *)(menus[submenu].m); i->flags = FL_PUP_SUBMENU; } void glutRemoveMenuItem(int item) { menu *m = &menus[glut_menu]; if (item > m->size || item < 1) return; for (int i = item-1; i <= m->size; i++) m->m[i] = m->m[i+1]; m->size--; } //////////////////////////////////////////////////////////////// int glutGet(GLenum type) { switch (type) { case GLUT_RETURN_ZERO: return 0; case GLUT_WINDOW_X: return glut_window->x(); case GLUT_WINDOW_Y: return glut_window->y(); case GLUT_WINDOW_WIDTH: return glut_window->w(); case GLUT_WINDOW_HEIGHT: return glut_window->h(); case GLUT_WINDOW_PARENT: if (glut_window->parent()) return ((Fl_Glut_Window *)(glut_window->parent()))->number; else return 0; //case GLUT_WINDOW_NUM_CHILDREN: //case GLUT_WINDOW_CURSOR: return case GLUT_SCREEN_WIDTH: return Fl::w(); case GLUT_SCREEN_HEIGHT: return Fl::h(); //case GLUT_SCREEN_WIDTH_MM: //case GLUT_SCREEN_HEIGHT_MM: case GLUT_MENU_NUM_ITEMS: return menus[glut_menu].size; case GLUT_DISPLAY_MODE_POSSIBLE: return Fl_Gl_Window::can_do(glut_mode); case GLUT_INIT_WINDOW_X: return initx; case GLUT_INIT_WINDOW_Y: return inity; case GLUT_INIT_WINDOW_WIDTH: return initw; case GLUT_INIT_WINDOW_HEIGHT: return inith; case GLUT_INIT_DISPLAY_MODE: return glut_mode; //case GLUT_ELAPSED_TIME: case GLUT_WINDOW_BUFFER_SIZE: if (glutGet(GLUT_WINDOW_RGBA)) return glutGet(GLUT_WINDOW_RED_SIZE)+ glutGet(GLUT_WINDOW_GREEN_SIZE)+ glutGet(GLUT_WINDOW_BLUE_SIZE)+ glutGet(GLUT_WINDOW_ALPHA_SIZE); else return glutGet(GLUT_WINDOW_COLORMAP_SIZE); case GLUT_VERSION: return 20400; default: {GLint p; glGetIntegerv(type, &p); return p;} } } int glutLayerGet(GLenum type) { switch (type) { case GLUT_OVERLAY_POSSIBLE: return glut_window->can_do_overlay(); //case GLUT_LAYER_IN_USE: //case GLUT_HAS_OVERLAY: case GLUT_TRANSPARENT_INDEX: return 0; // true for SGI case GLUT_NORMAL_DAMAGED: return glut_window->damage(); case GLUT_OVERLAY_DAMAGED: return 1; // kind of works... default: return 0; } } int glutDeviceGet(GLenum type) { switch (type) { case GLUT_HAS_KEYBOARD : return 1; case GLUT_HAS_MOUSE : return 1; case GLUT_NUM_MOUSE_BUTTONS : return 3; default : return 0; } } // Get extension function address... GLUTproc glutGetProcAddress(const char *procName) { # ifdef WIN32 return (GLUTproc)wglGetProcAddress((LPCSTR)procName); # elif defined(HAVE_DLSYM) && defined(HAVE_DLFCN_H) char symbol[1024]; snprintf(symbol, sizeof(symbol), "_%s", procName); # ifdef RTLD_DEFAULT return (GLUTproc)dlsym(RTLD_DEFAULT, symbol); # else // No RTLD_DEFAULT support, so open the current a.out symbols... static void *rtld_default = 0; if (!rtld_default) rtld_default = dlopen(0, RTLD_LAZY); if (rtld_default) return (GLUTproc)dlsym(rtld_default, symbol); else return 0; # endif // RTLD_DEFAULT # elif defined(HAVE_GLXGETPROCADDRESSARB) return (GLUTproc)glXGetProcAddressARB((const GLubyte *)procName); # else return (GLUTproc)0; # endif // WIN32 } // Parse the GL_EXTENSIONS string to see if the named extension is // supported. // // This code was copied from FreeGLUT 2.4.0 which carries the // following notice: // // Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. int glutExtensionSupported( const char* extension ) { if (!extension || strchr(extension, ' ')) return 0; const char *extensions, *start; const int len = strlen( extension ); start = extensions = (const char *) glGetString(GL_EXTENSIONS); if (!extensions) return 0; for (;;) { const char *p = strstr(extensions, extension); if (!p) return 0; /* not found */ /* check that the match isn't a super string */ if ((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len] == 0)) return 1; /* skip the false match and continue */ extensions = p + len; } } #endif // HAVE_GL // // End of "$Id: glut_compatability.cxx 5845 2007-05-20 00:01:06Z mike $". //