fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_Gl_Choice.cxx

Go to the documentation of this file.
00001 //
00002 // "$Id: Fl_Gl_Choice.cxx 8175 2011-01-03 20:51:17Z manolo $"
00003 //
00004 // OpenGL visual selection code for the Fast Light Tool Kit (FLTK).
00005 //
00006 // Copyright 1998-2010 by Bill Spitzak and others.
00007 //
00008 // This library is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Library General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 2 of the License, or (at your option) any later version.
00012 //
00013 // This library is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016 // Library General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU Library General Public
00019 // License along with this library; if not, write to the Free Software
00020 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00021 // USA.
00022 //
00023 // Please report all bugs and problems on the following page:
00024 //
00025 //     http://www.fltk.org/str.php
00026 //
00027 
00028 #include <config.h>
00029 #if HAVE_GL
00030 
00031 #  include <FL/Fl.H>
00032 #  include <FL/x.H>
00033 #  include <stdlib.h>
00034 #  include "Fl_Gl_Choice.H"
00035 #  include <FL/gl_draw.H>
00036 #  include "flstring.h"
00037 #  include <FL/fl_utf8.h>
00038 
00039 #  ifdef __APPLE__
00040 #    include <ApplicationServices/ApplicationServices.H>
00041 #    include <FL/Fl_Window.H>
00042 #  endif
00043 
00044 #  ifdef WIN32
00045 void fl_save_dc(HWND, HDC);
00046 #  endif
00047 
00048 static Fl_Gl_Choice *first;
00049 
00050 // this assumes one of the two arguments is zero:
00051 // We keep the list system in Win32 to stay compatible and interpret
00052 // the list later...
00053 Fl_Gl_Choice *Fl_Gl_Choice::find(int m, const int *alistp) {
00054   Fl_Gl_Choice *g;
00055   
00056   for (g = first; g; g = g->next)
00057     if (g->mode == m && g->alist == alistp) 
00058       return g;
00059 
00060 #if defined(USE_X11)    
00061   const int *blist;
00062   int list[32];
00063     
00064   if (alistp)
00065     blist = alistp;
00066   else {
00067     int n = 0;
00068     if (m & FL_INDEX) {
00069       list[n++] = GLX_BUFFER_SIZE;
00070       list[n++] = 8; // glut tries many sizes, but this should work...
00071     } else {
00072       list[n++] = GLX_RGBA;
00073       list[n++] = GLX_GREEN_SIZE;
00074       list[n++] = (m & FL_RGB8) ? 8 : 1;
00075       if (m & FL_ALPHA) {
00076         list[n++] = GLX_ALPHA_SIZE;
00077         list[n++] = (m & FL_RGB8) ? 8 : 1;
00078       }
00079       if (m & FL_ACCUM) {
00080         list[n++] = GLX_ACCUM_GREEN_SIZE;
00081         list[n++] = 1;
00082         if (m & FL_ALPHA) {
00083           list[n++] = GLX_ACCUM_ALPHA_SIZE;
00084           list[n++] = 1;
00085         }
00086       }
00087     }
00088     if (m & FL_DOUBLE) {
00089       list[n++] = GLX_DOUBLEBUFFER;
00090     }
00091     if (m & FL_DEPTH) {
00092       list[n++] = GLX_DEPTH_SIZE; list[n++] = 1;
00093     }
00094     if (m & FL_STENCIL) {
00095       list[n++] = GLX_STENCIL_SIZE; list[n++] = 1;
00096     }
00097     if (m & FL_STEREO) {
00098       list[n++] = GLX_STEREO;
00099     }
00100 #    if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
00101     if (m & FL_MULTISAMPLE) {
00102       list[n++] = GLX_SAMPLES_SGIS;
00103       list[n++] = 4; // value Glut uses
00104     }
00105 #    endif
00106     list[n] = 0;
00107     blist = list;
00108   }
00109     
00110   fl_open_display();
00111   XVisualInfo *visp = glXChooseVisual(fl_display, fl_screen, (int *)blist);
00112   if (!visp) {
00113 #    if defined(GLX_VERSION_1_1) && defined(GLX_SGIS_multisample)
00114     if (m&FL_MULTISAMPLE) return find(m&~FL_MULTISAMPLE,0);
00115 #    endif
00116     return 0;
00117   }
00118 
00119 #elif defined(__APPLE_QUARTZ__)
00120   // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
00121   const int *blist;
00122   int list[32];
00123    
00124   if (alistp)
00125     blist = alistp;
00126   else {
00127     int n = 0;
00128     if (m & FL_INDEX) {
00129       list[n++] = AGL_BUFFER_SIZE;
00130       list[n++] = 8; // glut tries many sizes, but this should work...
00131     } else {
00132       list[n++] = AGL_RGBA;
00133       list[n++] = AGL_GREEN_SIZE;
00134       list[n++] = (m & FL_RGB8) ? 8 : 1;
00135       if (m & FL_ALPHA) {
00136         list[n++] = AGL_ALPHA_SIZE;
00137         list[n++] = (m & FL_RGB8) ? 8 : 1;
00138       }
00139       if (m & FL_ACCUM) {
00140         list[n++] = AGL_ACCUM_GREEN_SIZE;
00141         list[n++] = 1;
00142         if (m & FL_ALPHA) {
00143           list[n++] = AGL_ACCUM_ALPHA_SIZE;
00144           list[n++] = 1;
00145         }
00146       }
00147     }
00148     if (m & FL_DOUBLE) {
00149       list[n++] = AGL_DOUBLEBUFFER;
00150     }
00151     if (m & FL_DEPTH) {
00152       list[n++] = AGL_DEPTH_SIZE; list[n++] = 24;
00153     }
00154     if (m & FL_STENCIL) {
00155       list[n++] = AGL_STENCIL_SIZE; list[n++] = 1;
00156     }
00157 #    ifdef AGL_STEREO
00158     if (m & FL_STEREO) {
00159       list[n++] = AGL_STEREO;
00160     }
00161 #    endif
00162     list[n] = AGL_NONE;
00163     blist = list;
00164   }
00165   fl_open_display();
00166   AGLPixelFormat fmt = aglChoosePixelFormat(NULL, 0, (GLint*)blist);
00167   if (!fmt) return 0;
00168   
00169 #elif defined(WIN32)
00170 
00171   // Replacement for ChoosePixelFormat() that finds one with an overlay
00172   // if possible:
00173   if (!fl_gc) fl_GetDC(0);
00174   int pixelformat = 0;
00175   PIXELFORMATDESCRIPTOR chosen_pfd;
00176   for (int i = 1; ; i++) {
00177     PIXELFORMATDESCRIPTOR pfd;
00178     if (!DescribePixelFormat(fl_gc, i, sizeof(pfd), &pfd)) break;
00179     // continue if it does not satisfy our requirements:
00180     if (~pfd.dwFlags & (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL)) continue;
00181     if (pfd.iPixelType != ((m&FL_INDEX)?PFD_TYPE_COLORINDEX:PFD_TYPE_RGBA)) continue;
00182     if ((m & FL_ALPHA) && !pfd.cAlphaBits) continue;
00183     if ((m & FL_ACCUM) && !pfd.cAccumBits) continue;
00184     if ((!(m & FL_DOUBLE)) != (!(pfd.dwFlags & PFD_DOUBLEBUFFER))) continue;
00185     if ((!(m & FL_STEREO)) != (!(pfd.dwFlags & PFD_STEREO))) continue;
00186     if ((m & FL_DEPTH) && !pfd.cDepthBits) continue;
00187     if ((m & FL_STENCIL) && !pfd.cStencilBits) continue;
00188     // see if better than the one we have already:
00189     if (pixelformat) {
00190       // offering non-generic rendering is better (read: hardware accelleration)
00191       if (!(chosen_pfd.dwFlags & PFD_GENERIC_FORMAT) &&
00192           (pfd.dwFlags & PFD_GENERIC_FORMAT)) continue;
00193       // offering overlay is better:
00194       else if (!(chosen_pfd.bReserved & 15) && (pfd.bReserved & 15)) {}
00195       // otherwise more bit planes is better:
00196       else if (chosen_pfd.cColorBits > pfd.cColorBits) continue;
00197       else if (chosen_pfd.cDepthBits > pfd.cDepthBits) continue;
00198     }
00199     pixelformat = i;
00200     chosen_pfd = pfd;
00201   }
00202   //printf("Chosen pixel format is %d\n", pixelformat);
00203   if (!pixelformat) return 0;
00204 #else
00205 # error platform unsupported
00206 #endif
00207 
00208   g = new Fl_Gl_Choice;
00209   g->mode = m;
00210   g->alist = alistp;
00211   g->next = first;
00212   first = g;
00213 
00214 #if defined(USE_X11)
00215   g->vis = visp;
00216 
00217   if (/*MaxCmapsOfScreen(ScreenOfDisplay(fl_display,fl_screen))==1 && */
00218       visp->visualid == fl_visual->visualid &&
00219       !fl_getenv("MESA_PRIVATE_CMAP"))
00220     g->colormap = fl_colormap;
00221   else
00222     g->colormap = XCreateColormap(fl_display, RootWindow(fl_display,fl_screen),
00223                                   visp->visual, AllocNone);
00224 #  elif defined(WIN32)
00225   g->pixelformat = pixelformat;
00226   g->pfd = chosen_pfd;
00227 #  elif defined(__APPLE_QUARTZ__)
00228   // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
00229   g->pixelformat = fmt;
00230 #  else
00231 #    error unsupported platform
00232 #  endif
00233 
00234   return g;
00235 }
00236 
00237 static GLContext *context_list = 0;
00238 static int nContext = 0, NContext = 0;
00239 
00240 static void add_context(GLContext ctx) {
00241   if (!ctx) return;
00242   if (nContext==NContext) {
00243     if (!NContext) NContext = 8;
00244     NContext *= 2;
00245     context_list = (GLContext*)realloc(
00246       context_list, NContext*sizeof(GLContext));
00247   }
00248   context_list[nContext++] = ctx;
00249 }
00250 
00251 static void del_context(GLContext ctx) {
00252   int i; 
00253   for (i=0; i<nContext; i++) {
00254     if (context_list[i]==ctx) {
00255       memmove(context_list+i, context_list+i+1,
00256         (nContext-i-1) * sizeof(GLContext));
00257       context_list[--nContext] = 0;
00258       break;
00259     }
00260   }
00261   if (!nContext) gl_remove_displaylist_fonts();
00262 }
00263 
00264 #if defined(USE_X11)
00265 
00266 GLContext fl_create_gl_context(XVisualInfo* vis) {
00267   GLContext shared_ctx = 0;
00268   if (context_list && nContext) shared_ctx = context_list[0];
00269   GLContext context = glXCreateContext(fl_display, vis, shared_ctx, 1);
00270   if (context)
00271     add_context(context);
00272   return context;
00273 }
00274 
00275 #elif defined(WIN32)
00276 
00277 GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
00278   Fl_X* i = Fl_X::i(window);
00279   HDC hdc = i->private_dc;
00280   if (!hdc) {
00281     hdc = i->private_dc = GetDCEx(i->xid, 0, DCX_CACHE);
00282     fl_save_dc(i->xid, hdc);
00283     SetPixelFormat(hdc, g->pixelformat, (PIXELFORMATDESCRIPTOR*)(&g->pfd));
00284 #    if USE_COLORMAP
00285     if (fl_palette) SelectPalette(hdc, fl_palette, FALSE);
00286 #    endif
00287   }
00288   GLContext context =
00289     layer ? wglCreateLayerContext(hdc, layer) : wglCreateContext(hdc);
00290   if (context) {
00291     if (context_list && nContext) 
00292       wglShareLists(context_list[0], context);
00293     add_context(context);
00294   }
00295   return context;
00296 }
00297 
00298 #  elif defined(__APPLE_QUARTZ__)
00299 #if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && __LP64__)
00300 static CGrafPtr fl_GetWindowPort(WindowRef window)
00301 {
00302   typedef CGrafPtr (*wf)(WindowRef);
00303   static wf f = NULL;
00304   if ( ! f) f = (wf)Fl_X::get_carbon_function("GetWindowPort");
00305   return (*f)(window);
00306 }
00307 #endif
00308 
00309 // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
00310 GLContext fl_create_gl_context(Fl_Window* window, const Fl_Gl_Choice* g, int layer) {
00311   GLContext context, shared_ctx = 0;
00312   if (context_list && nContext) shared_ctx = context_list[0];
00313   context = aglCreateContext( g->pixelformat, shared_ctx);
00314   if (!context) return 0;
00315   add_context((GLContext)context);
00316   if ( window->parent() ) {
00317     int H = window->window()->h();
00318     GLint rect[] = { window->x(), H-window->h()-window->y(), window->w(), window->h() };
00319     aglSetInteger( (GLContext)context, AGL_BUFFER_RECT, rect );
00320     aglEnable( (GLContext)context, AGL_BUFFER_RECT );
00321   }
00322 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
00323 #if __LP64__
00324   // 64 bit version
00325   aglSetWindowRef(context, Fl_X::i(window)->window_ref() );
00326 #else
00327   // 32 bit version >= 10.5
00328   if (aglSetWindowRef != NULL)
00329     aglSetWindowRef(context, Fl_X::i(window)->window_ref() );
00330   else
00331     aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) );
00332 #endif
00333 #else
00334   // 32 bit version < 10.5
00335   aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(window)->window_ref() ) );
00336 #endif
00337   return (context);
00338 }
00339 #  else
00340 #    error unsupported platform
00341 #  endif
00342 
00343 static GLContext cached_context;
00344 static Fl_Window* cached_window;
00345 
00346 void fl_set_gl_context(Fl_Window* w, GLContext context) {
00347   if (context != cached_context || w != cached_window) {
00348     cached_context = context;
00349     cached_window = w;
00350 #  if defined(USE_X11)
00351     glXMakeCurrent(fl_display, fl_xid(w), context);
00352 #  elif defined(WIN32)
00353     wglMakeCurrent(Fl_X::i(w)->private_dc, context);
00354 #  elif defined(__APPLE_QUARTZ__)
00355     // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
00356     if ( w->parent() ) { //: resize our GL buffer rectangle
00357       int H = w->window()->h();
00358       GLint rect[] = { w->x(), H-w->h()-w->y(), w->w(), w->h() };
00359       aglSetInteger( context, AGL_BUFFER_RECT, rect );
00360       aglEnable( context, AGL_BUFFER_RECT );
00361     }
00362 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
00363 #if __LP64__
00364     // 64 bit version
00365     aglSetWindowRef(context, Fl_X::i(w)->window_ref() );
00366 #else
00367     // 32 bit version >= 10.5
00368     if (aglSetWindowRef != NULL)
00369       aglSetWindowRef(context, Fl_X::i(w)->window_ref() );
00370     else
00371       aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) );
00372 #endif
00373 #else
00374     // 32 bit version < 10.5
00375     aglSetDrawable( context, fl_GetWindowPort( Fl_X::i(w)->window_ref() ) );
00376 #endif
00377     aglSetCurrentContext(context);
00378 #  else
00379 #   error unsupported platform
00380 #  endif
00381   }
00382 }
00383 
00384 void fl_no_gl_context() {
00385   cached_context = 0;
00386   cached_window = 0;
00387 #  if defined(USE_X11)
00388   glXMakeCurrent(fl_display, 0, 0);
00389 #  elif defined(WIN32)
00390   wglMakeCurrent(0, 0);
00391 #  elif defined(__APPLE_QUARTZ__)
00392   // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
00393   AGLContext ctx = aglGetCurrentContext();  
00394 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
00395   if (aglSetWindowRef != NULL)
00396     { if(ctx) aglSetWindowRef(ctx, NULL ); }
00397   else
00398 #endif
00399   if(ctx) aglSetDrawable( ctx, NULL );
00400   aglSetCurrentContext(0);
00401 #  else
00402 #    error unsupported platform
00403 #  endif
00404 }
00405 
00406 void fl_delete_gl_context(GLContext context) {
00407   if (cached_context == context) fl_no_gl_context();
00408 #  if defined(USE_X11)
00409   glXDestroyContext(fl_display, context);
00410 #  elif defined(WIN32)
00411   wglDeleteContext(context);
00412 #  elif defined(__APPLE_QUARTZ__)
00413   // warning: the Quartz version should probably use Core GL (CGL) instead of AGL
00414   aglDestroyContext( context );
00415 #  else
00416 #    error unsupported platform
00417 #  endif
00418   del_context(context);
00419 }
00420 
00421 #endif // HAVE_GL
00422 
00423 
00424 //
00425 // End of "$Id: Fl_Gl_Choice.cxx 8175 2011-01-03 20:51:17Z manolo $".
00426 //