OSDLOpenGL.cc

Go to the documentation of this file.
00001 #include "OSDLOpenGL.h"
00002 
00003 #include "OSDLVideo.h"    // for VideoModule
00004 #include "OSDLUtils.h"    // for getBackendLastError
00005 
00006 // for CEYLAN_DETECTED_LITTLE_ENDIAN, openGLContextsCanBeLost, etc. :
00007 #include "Ceylan.h"       
00008 
00009 
00010 #ifdef OSDL_USES_CONFIG_H
00011 #include <OSDLConfig.h>   // for OSDL_USES_OPENGL and al 
00012 #endif // OSDL_USES_CONFIG_H
00013 
00014 #ifdef OSDL_HAVE_OPENGL
00015 #include "SDL_opengl.h"   // for GL, GLU
00016 #endif // OSDL_HAVE_OPENGL
00017 
00018 
00019 
00020 using std::string ;
00021 
00022 #include <list>
00023 using std::list ;
00024 
00025 
00026 using namespace OSDL::Video::OpenGL ;
00027 using namespace OSDL::Video::OpenGL::GLU ;
00028 
00029 using namespace Ceylan::Log ;
00030 
00031 
00032 
00033 
00034 // OpenGL RGBA masks, since it always assumes RGBA order : 
00035     
00036 #if CEYLAN_DETECTED_LITTLE_ENDIAN
00037 
00038 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::RedMask   = 0x000000ff ;
00039 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::GreenMask = 0x0000ff00 ;
00040 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::BlueMask  = 0x00ff0000 ;
00041 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::AlphaMask = 0xff000000 ;
00042 
00043 
00044 #else // CEYLAN_DETECTED_LITTLE_ENDIAN
00045 
00046 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::RedMask   = 0xff000000 ;
00047 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::GreenMask = 0x00ff0000 ;
00048 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::BlueMask  = 0x0000ff00 ;
00049 OSDL::Video::Pixels::ColorMask OSDL::Video::OpenGL::AlphaMask = 0x000000ff ;
00050 
00051 #endif // CEYLAN_DETECTED_LITTLE_ENDIAN
00052 
00053 
00054 
00055 
00056 OpenGLException::OpenGLException( const std::string & reason ) throw() : 
00057     VideoException( reason )
00058 {   
00059 
00060 }
00061 
00062 
00063 OpenGLException::~OpenGLException() throw() 
00064 {
00065 
00066 }
00067 
00068 
00069 const bool OpenGLContext::ContextCanBeLost =
00070     Ceylan::System::openGLContextsCanBeLost() ;
00071     
00072 const bool OpenGLContext::ContextIsLostOnResize = 
00073     Ceylan::System::openGLContextsLostOnResize() ;
00074     
00075 const bool OpenGLContext::ContextIsLostOnApplicationSwitch =
00076     Ceylan::System::openGLContextsLostOnApplicationSwitch() ;
00077     
00078 const bool OpenGLContext::ContextIsLostOnColorDepthChange =
00079     Ceylan::System::openGLContextsLostOnColorDepthChange() ;
00080     
00081 
00082 
00083 const GLLength OpenGLContext::DefaultOrthographicWidth = 1000.0f ;
00084 
00085 const GLCoordinate OpenGLContext::DefaultNearClippingPlaneFor2D =     -1.0f ;
00086 const GLCoordinate OpenGLContext::DefaultFarClippingPlaneFor2D  =      1.0f ;
00087 const GLCoordinate OpenGLContext::DefaultNearClippingPlaneFor3D =      1.0f ;   
00088 const GLCoordinate OpenGLContext::DefaultFarClippingPlaneFor3D  = 100000.0f ;
00089 
00090 
00091                 
00092 OpenGLContext::OpenGLContext( OpenGL::Flavour flavour ) 
00093         throw( OpenGLException ) :
00094     _flavour( OpenGL::None ),
00095     _redSize( 0 ),
00096     _greenSize( 0 ),
00097     _blueSize( 0 ),
00098     _viewportWidth( 0 ),
00099     _viewportHeight( 0 ),
00100     _projectionMode( Orthographic ),
00101     _projectionWidth( DefaultOrthographicWidth ),
00102     _nearClippingPlane( DefaultNearClippingPlaneFor2D ),
00103     _farClippingPlane( DefaultFarClippingPlaneFor2D )
00104 {
00105 
00106     selectFlavour( flavour ) ;
00107     
00108 }
00109 
00110 
00111 
00112 OpenGLContext::~OpenGLContext() throw()
00113 {
00114 
00115 }
00116 
00117 
00118 
00119 
00120 void OpenGLContext::selectFlavour( Flavour flavour 
00121     /*, BitsPerPixel plannedBpp */) throw( OpenGLException )
00122 {
00123     
00124     _flavour = flavour ;
00125     
00126     if ( VideoModule::IsDisplayInitialized() )
00127         LogPlug::warning( 
00128             "OpenGLContext::selectFlavour : display is already initialized." ) ;
00129     
00130     switch( flavour )
00131     {
00132     
00133         case None:
00134             // Nothing to do.
00135             return ;
00136             break ;
00137         
00138         case OpenGLFor2D:
00139             set2DFlavour( /*plannedBpp*/ ) ;
00140             break ;
00141             
00142         case OpenGLFor3D:
00143             set3DFlavour( /*plannedBpp*/ ) ;
00144             break ;
00145         
00146         default:
00147             LogPlug::error( 
00148                 "OpenGLContext:selectFlavour : unknown flavour selected, "
00149                 "defaulting to None." ) ;
00150             return ;
00151             break ;     
00152     
00153     }
00154     
00155 }
00156 
00157 
00158 
00159 void OpenGLContext::set2DFlavour() throw( OpenGLException )
00160 {
00161 
00162     //glShadeModel(GL_FLAT);
00163     setFullScreenAntialiasingStatus( true ) ;
00164     //glDisable( GL_DEPTH_TEST ) ;
00165     
00166     // Defines camera :
00167     setOrthographicProjection( DefaultOrthographicWidth, 
00168         DefaultNearClippingPlaneFor2D, DefaultFarClippingPlaneFor2D ) ;
00169     
00170     setDoubleBufferStatus( true ) ;
00171     
00172 }
00173 
00174 
00175 
00176 void OpenGLContext::set3DFlavour() throw( OpenGLException )
00177 {
00178 
00179     setFullScreenAntialiasingStatus( true ) ;
00180 
00181     setDoubleBufferStatus( true ) ;
00182     
00183     
00184     /*
00185     setDepthBufferSize( 16 ) ;
00186     glEnable( GL_DEPTH_TEST ) ;
00187     glMatrixMode( GL_PROJECTION ) ;
00188     glLoadIdentity() ;
00189 
00190     gluPerspective( 45.0f, (GLfloat) ScreenWidth/ (GLfloat) ScreenHeight, 3.0f, ZDepth ) ;
00191     */
00192     
00193     LogPlug::warning( "OpenGLContext::set3DFlavour : not implemented yet." ) ;
00194     
00195 }
00196 
00197 
00198 
00199 void OpenGLContext::blank() throw( OpenGLException )
00200 {
00201 
00202     LogPlug::warning( "OpenGLContext::blank not implemented yet." ) ;
00203         
00204 }
00205 
00206 
00207 
00208 void OpenGLContext::reload() throw( OpenGLException ) 
00209 {
00210 
00211     LogPlug::warning( "OpenGLContext::blank not implemented yet." ) ;
00212     
00213 }
00214 
00215 
00216 
00217 Ceylan::Uint8 OpenGLContext::getColorDepth( 
00218         OSDL::Video::BitsPerPixel & redSize, 
00219         OSDL::Video::BitsPerPixel & greenSize, 
00220         OSDL::Video::BitsPerPixel & blueSize )
00221     const throw( OpenGLException )
00222 {
00223 
00224     // @fixme : Alpha currently not managed here.
00225     
00226     int value ;
00227     
00228     SDL_GL_GetAttribute( SDL_GL_RED_SIZE, & value ) ;       
00229     redSize = static_cast<OSDL::Video::BitsPerPixel>( value ) ;
00230     
00231     SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, & value ) ; 
00232     greenSize = static_cast<OSDL::Video::BitsPerPixel>( value ) ;
00233         
00234     SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, & value  ) ;     
00235     blueSize = static_cast<OSDL::Video::BitsPerPixel>( value ) ;
00236     
00237     return redSize + greenSize + blueSize ;
00238     
00239 }
00240 
00241     
00242 void OpenGLContext::setColorDepth( BitsPerPixel plannedBpp ) 
00243     throw( OpenGLException )
00244 {
00245 
00246     // Setting the relevant bits per color component for OpenGL framebuffer :
00247 
00248     int rgbSize[ 3 ] ;
00249 
00250     switch( plannedBpp ) 
00251     {
00252         
00253         case 8:
00254             rgbSize[0] = 3 ;
00255             rgbSize[1] = 3 ;
00256             rgbSize[2] = 2 ;
00257             break ;
00258             
00259         case 15:
00260         case 16:
00261             rgbSize[0] = 5 ;
00262             rgbSize[1] = 5 ;
00263             rgbSize[2] = 5 ;
00264             break ;
00265 
00266         default:
00267             rgbSize[0] = 8 ;
00268             rgbSize[1] = 8 ;
00269             rgbSize[2] = 8 ;
00270             break ;
00271     }
00272     
00273     SDL_GL_SetAttribute( SDL_GL_RED_SIZE,   rgbSize[0] ) ;
00274     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgbSize[1] ) ;
00275     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE,  rgbSize[2] ) ;
00276 
00277 }
00278 
00279 
00280 void OpenGLContext::setColorDepth( 
00281         OSDL::Video::BitsPerPixel redSize, 
00282         OSDL::Video::BitsPerPixel greenSize,
00283         OSDL::Video::BitsPerPixel blueSize ) 
00284     throw( OpenGLException )
00285 {
00286 
00287     SDL_GL_SetAttribute( SDL_GL_RED_SIZE,   redSize   ) ;
00288     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, greenSize ) ;
00289     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE,  blueSize  ) ;
00290 
00291 }
00292     
00293 
00294     
00295 bool OpenGLContext::getDoubleBufferStatus() throw( OpenGLException )
00296 {
00297 
00298     int value ;
00299     
00300     if ( SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, & value ) != 0 ) 
00301         throw OpenGLException( 
00302             "OpenGLContext::getDoubleBufferStatus : error occurred, "
00303             + Utils::getBackendLastError() ) ;
00304 
00305     return ( value != 0 ) ; 
00306 
00307 }
00308 
00309 
00310 bool OpenGLContext::setDoubleBufferStatus( bool newStatus ) 
00311     throw( OpenGLException )
00312 {
00313 
00314     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, newStatus ) ;
00315     
00316     return getDoubleBufferStatus() ;
00317     
00318 }
00319 
00320 
00321 void OpenGLContext::setShadingModel( ShadingModel newShadingModel ) 
00322     throw( OpenGLException )
00323 {
00324 
00325     switch( newShadingModel )
00326     {
00327     
00328         case Flat:
00329             glShadeModel( GL_FLAT ) ; 
00330             break ;
00331             
00332         case Smooth:
00333             glShadeModel( GL_SMOOTH ) ;
00334             break ;
00335             
00336         default:
00337             throw OpenGLException( "OpenGLContext::setShadingModel : "
00338                 "unknown shading model specified." ) ;
00339             break ;     
00340             
00341     }
00342     
00343     switch ( glGetError() )
00344     {
00345     
00346         case GL_NO_ERROR:
00347             break ;
00348         
00349         case GL_INVALID_ENUM:
00350             throw OpenGLException( "OpenGLContext::setShadingModel : "
00351                 "unexpected value for shading model." ) ;
00352             break ;
00353                 
00354         case GL_INVALID_OPERATION:
00355             throw OpenGLException( "OpenGLContext::setShadingModel : "
00356                 "incorrectly executed between the execution of glBegin and "
00357                 "the corresponding execution of glEnd." ) ;
00358             break ;
00359         
00360         default:
00361             throw OpenGLException( "OpenGLContext::setShadingModel : "
00362                 "unexpected error reported." ) ;
00363             break ; 
00364                 
00365     }
00366     
00367 }
00368 
00369 
00370 void OpenGLContext::setCullingStatus( bool newStatus ) throw()
00371 {
00372 
00373     if ( newStatus )
00374         glEnable( GL_CULL_FACE ) ;
00375     else
00376         glDisable( GL_CULL_FACE ) ;
00377         
00378 }
00379 
00380 
00381 void OpenGLContext::setCulling( CulledFacet culledFacet, 
00382         FrontOrientation frontOrientation, bool autoEnable ) 
00383     throw( OpenGLException ) 
00384 {
00385 
00386     switch( culledFacet )
00387     {
00388     
00389         case Front:
00390             glCullFace( GL_FRONT ) ;
00391             break ;
00392         
00393         case Back:  
00394             glCullFace( GL_BACK ) ;
00395             break ;
00396             
00397         case FrontAndBack:
00398             glCullFace( GL_FRONT_AND_BACK ) ;
00399             break ;
00400     }
00401 
00402 
00403     switch ( glGetError() )
00404     {
00405     
00406         case GL_NO_ERROR:
00407             break ;
00408         
00409         case GL_INVALID_ENUM:
00410             throw OpenGLException( "OpenGLContext::setCulling (facet) : "
00411                 "unexpected culled facet selection." ) ;
00412             break ;
00413                 
00414         case GL_INVALID_OPERATION:
00415             throw OpenGLException( "OpenGLContext::setCulling (facet) : "
00416                 "incorrectly executed between the execution of glBegin and "
00417                 "the corresponding execution of glEnd." ) ;
00418             break ;
00419         
00420         default:
00421             throw OpenGLException( "OpenGLContext::setCulling (facet) : "
00422                 "unexpected error reported." ) ;
00423             break ; 
00424                 
00425     }
00426         
00427             
00428     switch( frontOrientation )
00429     {
00430     
00431         case Clockwise:
00432             glFrontFace( GL_CW ) ;
00433             break ;
00434             
00435         case CounterClockwise:
00436             glFrontFace( GL_CCW ) ;
00437             break ;
00438     
00439     }
00440     
00441     
00442     switch ( glGetError() )
00443     {
00444     
00445         case GL_NO_ERROR:
00446             break ;
00447         
00448         case GL_INVALID_ENUM:
00449             throw OpenGLException( "OpenGLContext::setCulling : (orientation)"
00450                 "unexpected front orientation selection." ) ;
00451             break ;
00452                 
00453         case GL_INVALID_OPERATION:
00454             throw OpenGLException( "OpenGLContext::setCulling : (orientation)"
00455                 "incorrectly executed between the execution of glBegin and "
00456                 "the corresponding execution of glEnd." ) ;
00457             break ;
00458         
00459         default:
00460             throw OpenGLException( "OpenGLContext::setCulling (orientation) : "
00461                 "unexpected error reported." ) ;
00462             break ; 
00463                 
00464     }
00465             
00466 
00467     if ( autoEnable )
00468         setCullingStatus( true ) ;
00469 
00470 }
00471     
00472 
00473 void OpenGLContext::setFullScreenAntialiasingStatus( bool newStatus, 
00474     Ceylan::Uint8 samplesPerPixelNumber ) throw( OpenGLException )
00475 {
00476 
00477     if ( newStatus ) 
00478     {
00479         SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 
00480             /* Number of multisample buffers (0 or 1) */ 1 ) ;
00481             
00482         SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 
00483             samplesPerPixelNumber ) ;
00484             
00485     }
00486     else
00487     {
00488         SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 0 ) ;   
00489     }
00490     
00491 }
00492 
00493 
00494 void OpenGLContext::setDepthBufferStatus( bool newStatus ) throw()
00495 {
00496 
00497     if ( newStatus )
00498         glEnable( GL_DEPTH_TEST ) ;
00499     else
00500         glDisable( GL_DEPTH_TEST ) ;
00501         
00502 }
00503 
00504 
00505 void OpenGLContext::setDepthBufferSize( Ceylan::Uint8 bitsNumber, 
00506     bool autoEnable ) throw( OpenGLException )
00507 {
00508 
00509     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bitsNumber ) ;
00510     
00511     if ( autoEnable )   
00512         setDepthBufferStatus( true ) ;
00513 
00514 }
00515 
00516 
00517 void OpenGLContext::setViewPort( Length width, Length height, 
00518     const TwoDimensional::Point2D & lowerLeftCorner ) throw( OpenGLException )
00519 {
00520 
00521     _viewportWidth  = width  ;
00522     _viewportHeight = height ;
00523     
00524     glViewport( lowerLeftCorner.getX(), lowerLeftCorner.getY(), 
00525         width, height ) ;
00526 
00527     switch ( glGetError() )
00528     {
00529     
00530         case GL_NO_ERROR:
00531             break ;
00532         
00533         case GL_INVALID_VALUE:
00534             throw OpenGLException( "OpenGLContext::setViewPort : "
00535                 "either width or height is negative." ) ;
00536             break ;
00537                 
00538         case GL_INVALID_OPERATION:
00539             throw OpenGLException( "OpenGLContext::setViewPort : "
00540                 "incorrectly executed between the execution of glBegin and "
00541                 "the corresponding execution of glEnd." ) ;
00542             break ;
00543         
00544         default:
00545             throw OpenGLException( "OpenGLContext::setViewPort : "
00546                 "unexpected error reported." ) ;
00547             break ; 
00548                 
00549     }
00550     
00551     // Restore the aspect ratio of the projection :
00552     updateProjection() ; 
00553     
00554 }
00555 
00556 
00557 void OpenGLContext::setOrthographicProjection( GLLength width, 
00558     GLCoordinate near, GLCoordinate far ) throw ( OpenGLException )
00559 {
00560 
00561     _projectionMode  = Orthographic ;
00562     _projectionWidth = width ;
00563 
00564     glMatrixMode( GL_PROJECTION ) ;
00565     glLoadIdentity() ;
00566     
00567     // Centers projection box in (x,y) planes:
00568     
00569     GLCoordinate right = width / 2 ;
00570     
00571     // Enforce the viewport aspect ratio :
00572     GLCoordinate top = ( width * _viewportHeight ) / ( 2 * _viewportWidth ) ;
00573     
00574     glOrtho( /* left */ -right, /* right */ right, 
00575         /* bottom */ -top, /* top */ top,
00576         /* near */ near, /* far */ far ) ;
00577 
00578     switch ( glGetError() )
00579     {
00580     
00581         case GL_NO_ERROR:
00582             break ;
00583         
00584         case GL_INVALID_OPERATION:
00585             throw OpenGLException( "OpenGLContext::setOrthographicProjection : "
00586                 "incorrectly executed between the execution of glBegin and "
00587                 "the corresponding execution of glEnd." ) ;
00588             break ;
00589         
00590         default:
00591             LogPlug::warning( "OpenGLContext::setOrthographicProjection : "
00592                 "unexpected error reported." ) ;
00593             break ; 
00594                 
00595     }
00596 
00597 }
00598 
00599 
00600 void OpenGLContext::clearViewport() throw( OpenGLException )
00601 {
00602 
00603     glClear( GL_COLOR_BUFFER_BIT ) ;
00604 
00605     switch ( glGetError() )
00606     {
00607     
00608         case GL_NO_ERROR:
00609             break ;
00610         
00611         case GL_INVALID_VALUE:
00612             throw OpenGLException( "OpenGLContext::clearViewport : "
00613                 "invalid bit in specified clear mask." ) ;
00614             break ;
00615         
00616         case GL_INVALID_OPERATION:
00617             throw OpenGLException( "OpenGLContext::clearViewport : "
00618                 "incorrectly executed between the execution of glBegin and "
00619                 "the corresponding execution of glEnd." ) ;
00620             break ;
00621         
00622         default:
00623             LogPlug::warning( "OpenGLContext::clearViewport : "
00624                 "unexpected error reported." ) ;
00625             break ; 
00626                 
00627     }
00628     
00629 }   
00630 
00631 
00632 void OpenGLContext::clearDepthBuffer() throw( OpenGLException )
00633 {
00634 
00635     glClear( GL_DEPTH_BUFFER_BIT ) ;
00636 
00637     switch ( glGetError() )
00638     {
00639         case GL_NO_ERROR:
00640             break ;
00641         
00642         case GL_INVALID_VALUE:
00643             throw OpenGLException( "OpenGLContext::clearDepthBuffer : "
00644                 "invalid bit in specified clear mask." ) ;
00645             break ;
00646         
00647         case GL_INVALID_OPERATION:
00648             throw OpenGLException( "OpenGLContext::clearDepthBuffer : "
00649                 "incorrectly executed between the execution of glBegin and "
00650                 "the corresponding execution of glEnd." ) ;
00651             break ;
00652         
00653         default:
00654             LogPlug::warning( "OpenGLContext::clearDepthBuffer : "
00655                 "unexpected error reported." ) ;
00656             break ; 
00657                 
00658     }
00659     
00660 }
00661 
00662 
00663 const string OpenGLContext::toString( Ceylan::VerbosityLevels level ) 
00664     const throw() 
00665 {
00666     
00667     std::list<string> res ;
00668     
00669     res.push_back( "OpenGL context whose current selected flavour is " 
00670         + ToString( _flavour ) + "." ) ;
00671     
00672     OSDL::Video::BitsPerPixel redSize, greenSize, blueSize ;
00673     
00674     BitsPerPixel bpp = getColorDepth( redSize, greenSize, blueSize ) ;
00675     res.push_back( "Overall bit per pixel is " 
00676         + Ceylan::toNumericalString( bpp ) + "." ) ;
00677     
00678     res.push_back( "Red component size : "   
00679         + Ceylan::toNumericalString( redSize ) + " bits." ) ;
00680         
00681     res.push_back( "Green component size : " 
00682         + Ceylan::toNumericalString( greenSize ) + " bits." ) ;
00683         
00684     res.push_back( "Blue component size : "  
00685         + Ceylan::toNumericalString( blueSize ) + " bits." ) ;
00686     
00687     // Alpha ?
00688             
00689     return "Current OpenGL state is :" + Ceylan::formatStringList( res ) ;
00690     
00691 }
00692 
00693 
00694 string OpenGLContext::ToString( OpenGL::Flavour flavour ) throw() 
00695 {
00696 
00697     switch( flavour )
00698     {
00699     
00700         case OpenGL::None:
00701             return "no OpenGL" ;
00702             break ;
00703             
00704         case OpenGL::OpenGLFor2D:
00705             return "OpenGL for 2D" ;
00706             break ;
00707             
00708         case OpenGL::OpenGLFor3D:
00709             return "OpenGL for 3D" ;
00710             break ;
00711             
00712         case OpenGL::Reload:
00713             return "reload OpenGL context" ;
00714             break ;
00715             
00716         default:
00717             return "unknown flavour (" + Ceylan::toString( flavour ) 
00718                 + "), which is abnormal)" ;
00719             break ; 
00720             
00721     }
00722     
00723 }
00724 
00725 
00726 
00727 void OpenGLContext::updateProjection() throw( OpenGLException )
00728 {
00729 
00730     switch ( _projectionMode )
00731     {
00732     
00733         case Orthographic:
00734             // Forces recomputation of projection height :
00735             setOrthographicProjection( _projectionWidth,
00736                  _nearClippingPlane, _farClippingPlane ) ; 
00737             break ;
00738             
00739         default:
00740             throw OpenGLException( "OpenGLContext::updateProjection : "
00741                 "not implemented for current projection." ) ;
00742             break ;
00743                 
00744     }   
00745             
00746 }
00747 
00748 

Generated on Fri Mar 30 14:46:59 2007 for OSDL by  doxygen 1.5.1