freeglut_state.c
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:26k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2.  * freeglut_state.c
  3.  *
  4.  * Freeglut state query methods.
  5.  *
  6.  * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
  7.  * Written by Pawel W. Olszta, <olszta@sourceforge.net>
  8.  * Creation date: Thu Dec 16 1999
  9.  *
  10.  * Permission is hereby granted, free of charge, to any person obtaining a
  11.  * copy of this software and associated documentation files (the "Software"),
  12.  * to deal in the Software without restriction, including without limitation
  13.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  14.  * and/or sell copies of the Software, and to permit persons to whom the
  15.  * Software is furnished to do so, subject to the following conditions:
  16.  *
  17.  * The above copyright notice and this permission notice shall be included
  18.  * in all copies or substantial portions of the Software.
  19.  *
  20.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  23.  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  24.  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  25.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  26.  */
  27. #include <GL/freeglut.h>
  28. #include "freeglut_internal.h"
  29. /*
  30.  * TODO BEFORE THE STABLE RELEASE:
  31.  *
  32.  *  glutGet()               -- X11 tests passed, but check if all enums
  33.  *                             handled (what about Win32?)
  34.  *  glutDeviceGet()         -- X11 tests passed, but check if all enums
  35.  *                             handled (what about Win32?)
  36.  *  glutGetModifiers()      -- OK, but could also remove the limitation
  37.  *  glutLayerGet()          -- what about GLUT_NORMAL_DAMAGED?
  38.  *
  39.  * The fail-on-call policy will help adding the most needed things imho.
  40.  */
  41. /* -- LOCAL DEFINITIONS ---------------------------------------------------- */
  42. /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */
  43. #if TARGET_HOST_POSIX_X11
  44. /*
  45.  * Queries the GL context about some attributes
  46.  */
  47. static int fghGetConfig( int attribute )
  48. {
  49.   int returnValue = 0;
  50.   int result;  /*  Not checked  */
  51.   if( fgStructure.CurrentWindow )
  52.       result = glXGetFBConfigAttrib( fgDisplay.Display,
  53.                                      *(fgStructure.CurrentWindow->Window.FBConfig),
  54.                                      attribute,
  55.                                      &returnValue );
  56.   return returnValue;
  57. }
  58. #endif
  59. /* Check if the window is in full screen state. */
  60. static int fghCheckFullScreen(void)
  61. {
  62. #if TARGET_HOST_POSIX_X11
  63.     return fgStructure.CurrentWindow->State.IsFullscreen;
  64. #else
  65.     return 0;
  66. #endif
  67. }
  68. /* -- INTERFACE FUNCTIONS -------------------------------------------------- */
  69. /*
  70.  * General settings assignment method
  71.  */
  72. void FGAPIENTRY glutSetOption( GLenum eWhat, int value )
  73. {
  74.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutSetOption" );
  75.     /*
  76.      * XXX In chronological code add order.  (WHY in that order?)
  77.      */
  78.     switch( eWhat )
  79.     {
  80.     case GLUT_INIT_WINDOW_X:
  81.         fgState.Position.X = (GLint)value;
  82.         break;
  83.     case GLUT_INIT_WINDOW_Y:
  84.         fgState.Position.Y = (GLint)value;
  85.         break;
  86.     case GLUT_INIT_WINDOW_WIDTH:
  87.         fgState.Size.X = (GLint)value;
  88.         break;
  89.     case GLUT_INIT_WINDOW_HEIGHT:
  90.         fgState.Size.Y = (GLint)value;
  91.         break;
  92.     case GLUT_INIT_DISPLAY_MODE:
  93.         fgState.DisplayMode = (unsigned int)value;
  94.         break;
  95.     case GLUT_ACTION_ON_WINDOW_CLOSE:
  96.         fgState.ActionOnWindowClose = value;
  97.         break;
  98.     case GLUT_RENDERING_CONTEXT:
  99.         fgState.UseCurrentContext =
  100.             ( value == GLUT_USE_CURRENT_CONTEXT ) ? GL_TRUE : GL_FALSE;
  101.         break;
  102.     case GLUT_DIRECT_RENDERING:
  103.         fgState.DirectContext = value;
  104.         break;
  105.     case GLUT_WINDOW_CURSOR:
  106.         if( fgStructure.CurrentWindow != NULL )
  107.             fgStructure.CurrentWindow->State.Cursor = value;
  108.         break;
  109.     case GLUT_AUX:
  110.       fgState.AuxiliaryBufferNumber = value;
  111.       break;
  112.     case GLUT_MULTISAMPLE:
  113.       fgState.SampleNumber = value;
  114.       break;
  115.     default:
  116.         fgWarning( "glutSetOption(): missing enum handle %d", eWhat );
  117.         break;
  118.     }
  119. }
  120. #if TARGET_HOST_MS_WINDOWS
  121. /* The following include file is available from SGI but is not standard:
  122.  *   #include <GL/wglext.h>
  123.  * So we copy the necessary parts out of it to support the multisampling query
  124.  */
  125. #define WGL_SAMPLES_ARB                0x2042
  126. #endif
  127. /*
  128.  * General settings query method
  129.  */
  130. int FGAPIENTRY glutGet( GLenum eWhat )
  131. {
  132. #if TARGET_HOST_MS_WINDOWS
  133.     int returnValue ;
  134.     GLboolean boolValue ;
  135. #endif
  136.     int nsamples = 0;
  137.     switch (eWhat)
  138.     {
  139.     case GLUT_INIT_STATE:
  140.         return fgState.Initialised;
  141.     case GLUT_ELAPSED_TIME:
  142.         return fgElapsedTime();
  143.     }
  144.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGet" );
  145.     /* XXX In chronological code add order.  (WHY in that order?) */
  146.     switch( eWhat )
  147.     {
  148.     /* Following values are stored in fgState and fgDisplay global structures */
  149.     case GLUT_SCREEN_WIDTH:         return fgDisplay.ScreenWidth   ;
  150.     case GLUT_SCREEN_HEIGHT:        return fgDisplay.ScreenHeight  ;
  151.     case GLUT_SCREEN_WIDTH_MM:      return fgDisplay.ScreenWidthMM ;
  152.     case GLUT_SCREEN_HEIGHT_MM:     return fgDisplay.ScreenHeightMM;
  153.     case GLUT_INIT_WINDOW_X:        return fgState.Position.Use ?
  154.                                            fgState.Position.X : -1 ;
  155.     case GLUT_INIT_WINDOW_Y:        return fgState.Position.Use ?
  156.                                            fgState.Position.Y : -1 ;
  157.     case GLUT_INIT_WINDOW_WIDTH:    return fgState.Size.Use ?
  158.                                            fgState.Size.X : -1     ;
  159.     case GLUT_INIT_WINDOW_HEIGHT:   return fgState.Size.Use ?
  160.                                            fgState.Size.Y : -1     ;
  161.     case GLUT_INIT_DISPLAY_MODE:    return fgState.DisplayMode     ;
  162.     case GLUT_INIT_MAJOR_VERSION:   return fgState.MajorVersion    ;
  163.     case GLUT_INIT_MINOR_VERSION:   return fgState.MinorVersion    ;
  164.     case GLUT_INIT_FLAGS:           return fgState.ContextFlags    ;
  165.     case GLUT_INIT_PROFILE:         return fgState.ContextProfile  ;
  166. #if TARGET_HOST_POSIX_X11
  167.     /*
  168.      * The window/context specific queries are handled mostly by
  169.      * fghGetConfig().
  170.      */
  171.     case GLUT_WINDOW_NUM_SAMPLES:
  172. #ifdef GLX_VERSION_1_3
  173.         glGetIntegerv(GL_SAMPLES, &nsamples);
  174. #endif
  175.         return nsamples;
  176.     /*
  177.      * The rest of GLX queries under X are general enough to use a macro to
  178.      * check them
  179.      */
  180. #   define GLX_QUERY(a,b) case a: return fghGetConfig( b );
  181.     GLX_QUERY( GLUT_WINDOW_RGBA,                GLX_RGBA                );
  182.     GLX_QUERY( GLUT_WINDOW_DOUBLEBUFFER,        GLX_DOUBLEBUFFER        );
  183.     GLX_QUERY( GLUT_WINDOW_BUFFER_SIZE,         GLX_BUFFER_SIZE         );
  184.     GLX_QUERY( GLUT_WINDOW_STENCIL_SIZE,        GLX_STENCIL_SIZE        );
  185.     GLX_QUERY( GLUT_WINDOW_DEPTH_SIZE,          GLX_DEPTH_SIZE          );
  186.     GLX_QUERY( GLUT_WINDOW_RED_SIZE,            GLX_RED_SIZE            );
  187.     GLX_QUERY( GLUT_WINDOW_GREEN_SIZE,          GLX_GREEN_SIZE          );
  188.     GLX_QUERY( GLUT_WINDOW_BLUE_SIZE,           GLX_BLUE_SIZE           );
  189.     GLX_QUERY( GLUT_WINDOW_ALPHA_SIZE,          GLX_ALPHA_SIZE          );
  190.     GLX_QUERY( GLUT_WINDOW_ACCUM_RED_SIZE,      GLX_ACCUM_RED_SIZE      );
  191.     GLX_QUERY( GLUT_WINDOW_ACCUM_GREEN_SIZE,    GLX_ACCUM_GREEN_SIZE    );
  192.     GLX_QUERY( GLUT_WINDOW_ACCUM_BLUE_SIZE,     GLX_ACCUM_BLUE_SIZE     );
  193.     GLX_QUERY( GLUT_WINDOW_ACCUM_ALPHA_SIZE,    GLX_ACCUM_ALPHA_SIZE    );
  194.     GLX_QUERY( GLUT_WINDOW_STEREO,              GLX_STEREO              );
  195. #   undef GLX_QUERY
  196.     /* Colormap size is handled in a bit different way than all the rest */
  197.     case GLUT_WINDOW_COLORMAP_SIZE:
  198.         if( (fghGetConfig( GLX_RGBA )) || (fgStructure.CurrentWindow == NULL) )
  199.         {
  200.             /*
  201.              * We've got a RGBA visual, so there is no colormap at all.
  202.              * The other possibility is that we have no current window set.
  203.              */
  204.             return 0;
  205.         }
  206.         else
  207.         {
  208.           const GLXFBConfig * fbconfig =
  209.                 fgStructure.CurrentWindow->Window.FBConfig;
  210.           XVisualInfo * visualInfo =
  211.                 glXGetVisualFromFBConfig( fgDisplay.Display, *fbconfig );
  212.           const int result = visualInfo->visual->map_entries;
  213.           XFree(visualInfo);
  214.           return result;
  215.         }
  216.     /*
  217.      * Those calls are somewhat similiar, as they use XGetWindowAttributes()
  218.      * function
  219.      */
  220.     case GLUT_WINDOW_X:
  221.     case GLUT_WINDOW_Y:
  222.     case GLUT_WINDOW_BORDER_WIDTH:
  223.     case GLUT_WINDOW_HEADER_HEIGHT:
  224.     {
  225.         int x, y;
  226.         Window w;
  227.         if( fgStructure.CurrentWindow == NULL )
  228.             return 0;
  229.         XTranslateCoordinates(
  230.             fgDisplay.Display,
  231.             fgStructure.CurrentWindow->Window.Handle,
  232.             fgDisplay.RootWindow,
  233.             0, 0, &x, &y, &w);
  234.         switch ( eWhat )
  235.         {
  236.         case GLUT_WINDOW_X: return x;
  237.         case GLUT_WINDOW_Y: return y;
  238.         }
  239.         if ( w == 0 )
  240.             return 0;
  241.         XTranslateCoordinates(
  242.             fgDisplay.Display,
  243.             fgStructure.CurrentWindow->Window.Handle,
  244.             w, 0, 0, &x, &y, &w);
  245.         switch ( eWhat )
  246.         {
  247.         case GLUT_WINDOW_BORDER_WIDTH:  return x;
  248.         case GLUT_WINDOW_HEADER_HEIGHT: return y;
  249.         }
  250.     }
  251.     case GLUT_WINDOW_WIDTH:
  252.     case GLUT_WINDOW_HEIGHT:
  253.     {
  254.         XWindowAttributes winAttributes;
  255.         if( fgStructure.CurrentWindow == NULL )
  256.             return 0;
  257.         XGetWindowAttributes(
  258.             fgDisplay.Display,
  259.             fgStructure.CurrentWindow->Window.Handle,
  260.             &winAttributes
  261.         );
  262.         switch ( eWhat )
  263.         {
  264.         case GLUT_WINDOW_WIDTH:            return winAttributes.width ;
  265.         case GLUT_WINDOW_HEIGHT:           return winAttributes.height ;
  266.         }
  267.     }
  268.     /* I do not know yet if there will be a fgChooseVisual() function for Win32 */
  269.     case GLUT_DISPLAY_MODE_POSSIBLE:
  270.     {
  271.         /*  We should not have to call fgChooseFBConfig again here.  */
  272.         GLXFBConfig * fbconfig;
  273.         int isPossible;
  274.         fbconfig = fgChooseFBConfig();
  275.         if (fbconfig == NULL)
  276.         {
  277.             isPossible = 0;
  278.         }
  279.         else
  280.         {
  281.             isPossible = 1;
  282.             XFree(fbconfig);
  283.         }
  284.         return isPossible;
  285.     }
  286.     /* This is system-dependant */
  287.     case GLUT_WINDOW_FORMAT_ID:
  288.         if( fgStructure.CurrentWindow == NULL )
  289.             return 0;
  290.         return fghGetConfig( GLX_VISUAL_ID );
  291. #elif TARGET_HOST_MS_WINDOWS
  292.     case GLUT_WINDOW_NUM_SAMPLES:
  293.       glGetIntegerv(WGL_SAMPLES_ARB, &nsamples);
  294.       return nsamples;
  295.     /* Handle the OpenGL inquiries */
  296.     case GLUT_WINDOW_RGBA:
  297. #if defined(_WIN32_WCE)
  298.       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
  299. #else
  300.       glGetBooleanv ( GL_RGBA_MODE, &boolValue );
  301.       returnValue = boolValue ? 1 : 0;
  302. #endif
  303.       return returnValue;
  304.     case GLUT_WINDOW_DOUBLEBUFFER:
  305. #if defined(_WIN32_WCE)
  306.       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
  307. #else
  308.       glGetBooleanv ( GL_DOUBLEBUFFER, &boolValue );
  309.       returnValue = boolValue ? 1 : 0;
  310. #endif
  311.       return returnValue;
  312.     case GLUT_WINDOW_STEREO:
  313. #if defined(_WIN32_WCE)
  314.       boolValue = (GLboolean)0;  /* WinCE doesn't support this feature */
  315. #else
  316.       glGetBooleanv ( GL_STEREO, &boolValue );
  317.       returnValue = boolValue ? 1 : 0;
  318. #endif
  319.       return returnValue;
  320.     case GLUT_WINDOW_RED_SIZE:
  321.       glGetIntegerv ( GL_RED_BITS, &returnValue );
  322.       return returnValue;
  323.     case GLUT_WINDOW_GREEN_SIZE:
  324.       glGetIntegerv ( GL_GREEN_BITS, &returnValue );
  325.       return returnValue;
  326.     case GLUT_WINDOW_BLUE_SIZE:
  327.       glGetIntegerv ( GL_BLUE_BITS, &returnValue );
  328.       return returnValue;
  329.     case GLUT_WINDOW_ALPHA_SIZE:
  330.       glGetIntegerv ( GL_ALPHA_BITS, &returnValue );
  331.       return returnValue;
  332.     case GLUT_WINDOW_ACCUM_RED_SIZE:
  333. #if defined(_WIN32_WCE)
  334.       returnValue = 0;  /* WinCE doesn't support this feature */
  335. #else
  336.       glGetIntegerv ( GL_ACCUM_RED_BITS, &returnValue );
  337. #endif
  338.       return returnValue;
  339.     case GLUT_WINDOW_ACCUM_GREEN_SIZE:
  340. #if defined(_WIN32_WCE)
  341.       returnValue = 0;  /* WinCE doesn't support this feature */
  342. #else
  343.       glGetIntegerv ( GL_ACCUM_GREEN_BITS, &returnValue );
  344. #endif
  345.       return returnValue;
  346.     case GLUT_WINDOW_ACCUM_BLUE_SIZE:
  347. #if defined(_WIN32_WCE)
  348.       returnValue = 0;  /* WinCE doesn't support this feature */
  349. #else
  350.       glGetIntegerv ( GL_ACCUM_BLUE_BITS, &returnValue );
  351. #endif
  352.       return returnValue;
  353.     case GLUT_WINDOW_ACCUM_ALPHA_SIZE:
  354. #if defined(_WIN32_WCE)
  355.       returnValue = 0;  /* WinCE doesn't support this feature */
  356. #else
  357.       glGetIntegerv ( GL_ACCUM_ALPHA_BITS, &returnValue );
  358. #endif
  359.       return returnValue;
  360.     case GLUT_WINDOW_DEPTH_SIZE:
  361.       glGetIntegerv ( GL_DEPTH_BITS, &returnValue );
  362.       return returnValue;
  363.     case GLUT_WINDOW_BUFFER_SIZE:
  364.       returnValue = 1 ;                                      /* ????? */
  365.       return returnValue;
  366.     case GLUT_WINDOW_STENCIL_SIZE:
  367.       returnValue = 0 ;                                      /* ????? */
  368.       return returnValue;
  369.     case GLUT_WINDOW_X:
  370.     case GLUT_WINDOW_Y:
  371.     case GLUT_WINDOW_WIDTH:
  372.     case GLUT_WINDOW_HEIGHT:
  373.     {
  374.         /*
  375.          *  There is considerable confusion about the "right thing to
  376.          *  do" concerning window  size and position.  GLUT itself is
  377.          *  not consistent between Windows and UNIX/X11; since
  378.          *  platform independence is a virtue for "freeglut", we
  379.          *  decided to break with GLUT's behaviour.
  380.          *
  381.          *  Under UNIX/X11, it is apparently not possible to get the
  382.          *  window border sizes in order to subtract them off the
  383.          *  window's initial position until some time after the window
  384.          *  has been created.  Therefore we decided on the following
  385.          *  behaviour, both under Windows and under UNIX/X11:
  386.          *  - When you create a window with position (x,y) and size
  387.          *    (w,h), the upper left hand corner of the outside of the
  388.          *    window is at (x,y) and the size of the drawable area  is
  389.          *    (w,h).
  390.          *  - When you query the size and position of the window--as
  391.          *    is happening here for Windows--"freeglut" will return
  392.          *    the size of the drawable area--the (w,h) that you
  393.          *    specified when you created the window--and the coordinates
  394.          *    of the upper left hand corner of the drawable
  395.          *    area--which is NOT the (x,y) you specified.
  396.          */
  397.         RECT winRect;
  398.         freeglut_return_val_if_fail( fgStructure.CurrentWindow != NULL, 0 );
  399.         /*
  400.          * We need to call GetWindowRect() first...
  401.          *  (this returns the pixel coordinates of the outside of the window)
  402.          */
  403.         GetWindowRect( fgStructure.CurrentWindow->Window.Handle, &winRect );
  404.         /* ...then we've got to correct the results we've just received... */
  405. #if !defined(_WIN32_WCE)
  406.         if ( ( fgStructure.GameModeWindow != fgStructure.CurrentWindow ) && ( fgStructure.CurrentWindow->Parent == NULL ) &&
  407.              ( ! fgStructure.CurrentWindow->IsMenu ) )
  408.         {
  409.           winRect.left   += GetSystemMetrics( SM_CXSIZEFRAME );
  410.           winRect.right  -= GetSystemMetrics( SM_CXSIZEFRAME );
  411.           winRect.top    += GetSystemMetrics( SM_CYSIZEFRAME ) + GetSystemMetrics( SM_CYCAPTION );
  412.           winRect.bottom -= GetSystemMetrics( SM_CYSIZEFRAME );
  413.         }
  414. #endif /* !defined(_WIN32_WCE) */
  415.         switch( eWhat )
  416.         {
  417.         case GLUT_WINDOW_X:      return winRect.left                ;
  418.         case GLUT_WINDOW_Y:      return winRect.top                 ;
  419.         case GLUT_WINDOW_WIDTH:  return winRect.right - winRect.left;
  420.         case GLUT_WINDOW_HEIGHT: return winRect.bottom - winRect.top;
  421.         }
  422.     }
  423.     break;
  424.     case GLUT_WINDOW_BORDER_WIDTH :
  425. #if defined(_WIN32_WCE)
  426.         return 0;
  427. #else
  428.         return GetSystemMetrics( SM_CXSIZEFRAME );
  429. #endif /* !defined(_WIN32_WCE) */
  430.     case GLUT_WINDOW_HEADER_HEIGHT :
  431. #if defined(_WIN32_WCE)
  432.         return 0;
  433. #else
  434.         return GetSystemMetrics( SM_CYCAPTION );
  435. #endif /* defined(_WIN32_WCE) */
  436.     case GLUT_DISPLAY_MODE_POSSIBLE:
  437. #if defined(_WIN32_WCE)
  438.         return 0;
  439. #else
  440.         return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
  441.                                     PFD_MAIN_PLANE );
  442. #endif /* defined(_WIN32_WCE) */
  443.     case GLUT_WINDOW_FORMAT_ID:
  444. #if !defined(_WIN32_WCE)
  445.         if( fgStructure.CurrentWindow != NULL )
  446.             return GetPixelFormat( fgStructure.CurrentWindow->Window.Device );
  447. #endif /* defined(_WIN32_WCE) */
  448.         return 0;
  449. #endif
  450.     /* The window structure queries */
  451.     case GLUT_WINDOW_PARENT:
  452.         if( fgStructure.CurrentWindow         == NULL ) return 0;
  453.         if( fgStructure.CurrentWindow->Parent == NULL ) return 0;
  454.         return fgStructure.CurrentWindow->Parent->ID;
  455.     case GLUT_WINDOW_NUM_CHILDREN:
  456.         if( fgStructure.CurrentWindow == NULL )
  457.             return 0;
  458.         return fgListLength( &fgStructure.CurrentWindow->Children );
  459.     case GLUT_WINDOW_CURSOR:
  460.         if( fgStructure.CurrentWindow == NULL )
  461.             return 0;
  462.         return fgStructure.CurrentWindow->State.Cursor;
  463.     case GLUT_MENU_NUM_ITEMS:
  464.         if( fgStructure.CurrentMenu == NULL )
  465.             return 0;
  466.         return fgListLength( &fgStructure.CurrentMenu->Entries );
  467.     case GLUT_ACTION_ON_WINDOW_CLOSE:
  468.         return fgState.ActionOnWindowClose;
  469.     case GLUT_VERSION :
  470.         return VERSION_MAJOR * 10000 + VERSION_MINOR * 100 + VERSION_PATCH;
  471.     case GLUT_RENDERING_CONTEXT:
  472.         return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT
  473.                                          : GLUT_CREATE_NEW_CONTEXT;
  474.     case GLUT_DIRECT_RENDERING:
  475.         return fgState.DirectContext;
  476.     case GLUT_FULL_SCREEN:
  477.         return fghCheckFullScreen();
  478.     case GLUT_AUX:
  479.       return fgState.AuxiliaryBufferNumber;
  480.     case GLUT_MULTISAMPLE:
  481.       return fgState.SampleNumber;
  482.     default:
  483.         fgWarning( "glutGet(): missing enum handle %d", eWhat );
  484.         break;
  485.     }
  486.     return -1;
  487. }
  488. /*
  489.  * Returns various device information.
  490.  */
  491. int FGAPIENTRY glutDeviceGet( GLenum eWhat )
  492. {
  493.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutDeviceGet" );
  494.     /* XXX WARNING: we are mostly lying in this function. */
  495.     switch( eWhat )
  496.     {
  497.     case GLUT_HAS_KEYBOARD:
  498.         /*
  499.          * Win32 is assumed a keyboard, and this cannot be queried,
  500.          * except for WindowsCE.
  501.          *
  502.          * X11 has a core keyboard by definition, although it can
  503.          * be present as a virtual/dummy keyboard. For now, there
  504.          * is no reliable way to tell if a real keyboard is present.
  505.          */
  506. #if defined(_WIN32_CE)
  507.         return ( GetKeyboardStatus() & KBDI_KEYBOARD_PRESENT ) ? 1 : 0;
  508. #   if FREEGLUT_LIB_PRAGMAS
  509. #       pragma comment (lib,"Kbdui.lib")
  510. #   endif
  511. #else
  512.         return 1;
  513. #endif
  514. #if TARGET_HOST_POSIX_X11
  515.     /* X11 has a mouse by definition */
  516.     case GLUT_HAS_MOUSE:
  517.         return 1 ;
  518.     case GLUT_NUM_MOUSE_BUTTONS:
  519.         /* We should be able to pass NULL when the last argument is zero,
  520.          * but at least one X server has a bug where this causes a segfault.
  521.          *
  522.          * In XFree86/Xorg servers, a mouse wheel is seen as two buttons
  523.          * rather than an Axis; "freeglut_main.c" expects this when
  524.          * checking for a wheel event.
  525.          */
  526.         {
  527.             unsigned char map;
  528.             int nbuttons = XGetPointerMapping(fgDisplay.Display, &map,0);
  529.             return nbuttons;
  530.         }
  531. #elif TARGET_HOST_MS_WINDOWS
  532.     case GLUT_HAS_MOUSE:
  533.         /*
  534.          * MS Windows can be booted without a mouse.
  535.          */
  536.         return GetSystemMetrics( SM_MOUSEPRESENT );
  537.     case GLUT_NUM_MOUSE_BUTTONS:
  538. #  if defined(_WIN32_WCE)
  539.         return 1;
  540. #  else
  541.         return GetSystemMetrics( SM_CMOUSEBUTTONS );
  542. #  endif
  543. #endif
  544.     case GLUT_HAS_JOYSTICK:
  545.         return fgJoystickDetect ();
  546.     case GLUT_OWNS_JOYSTICK:
  547.         return fgState.JoysticksInitialised;
  548.     case GLUT_JOYSTICK_POLL_RATE:
  549.         return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.JoystickPollRate : 0;
  550.     /* XXX The following two are only for Joystick 0 but this is an improvement */
  551.     case GLUT_JOYSTICK_BUTTONS:
  552.         return glutJoystickGetNumButtons ( 0 );
  553.     case GLUT_JOYSTICK_AXES:
  554.         return glutJoystickGetNumAxes ( 0 );
  555.     case GLUT_HAS_DIAL_AND_BUTTON_BOX:
  556.         return fgInputDeviceDetect ();
  557.     case GLUT_NUM_DIALS:
  558.         if ( fgState.InputDevsInitialised ) return 8;
  559.         return 0;
  560.  
  561.     case GLUT_NUM_BUTTON_BOX_BUTTONS:
  562.         return 0;
  563.     case GLUT_HAS_SPACEBALL:
  564.         return fgHasSpaceball();
  565.     case GLUT_HAS_TABLET:
  566.         return 0;
  567.     case GLUT_NUM_SPACEBALL_BUTTONS:
  568.         return fgSpaceballNumButtons();
  569.     case GLUT_NUM_TABLET_BUTTONS:
  570.         return 0;
  571.     case GLUT_DEVICE_IGNORE_KEY_REPEAT:
  572.         return fgStructure.CurrentWindow ? fgStructure.CurrentWindow->State.IgnoreKeyRepeat : 0;
  573.     case GLUT_DEVICE_KEY_REPEAT:
  574.         return fgState.KeyRepeat;
  575.     default:
  576.         fgWarning( "glutDeviceGet(): missing enum handle %d", eWhat );
  577.         break;
  578.     }
  579.     /* And now -- the failure. */
  580.     return -1;
  581. }
  582. /*
  583.  * This should return the current state of ALT, SHIFT and CTRL keys.
  584.  */
  585. int FGAPIENTRY glutGetModifiers( void )
  586. {
  587.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutGetModifiers" );
  588.     if( fgState.Modifiers == INVALID_MODIFIERS )
  589.     {
  590.         fgWarning( "glutGetModifiers() called outside an input callback" );
  591.         return 0;
  592.     }
  593.     return fgState.Modifiers;
  594. }
  595. /*
  596.  * Return the state of the GLUT API overlay subsystem. A misery ;-)
  597.  */
  598. int FGAPIENTRY glutLayerGet( GLenum eWhat )
  599. {
  600.     FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutLayerGet" );
  601.     /*
  602.      * This is easy as layers are not implemented ;-)
  603.      *
  604.      * XXX Can we merge the UNIX/X11 and WIN32 sections?  Or
  605.      * XXX is overlay support planned?
  606.      */
  607.     switch( eWhat )
  608.     {
  609. #if TARGET_HOST_POSIX_X11
  610.     case GLUT_OVERLAY_POSSIBLE:
  611.         return 0;
  612.     case GLUT_LAYER_IN_USE:
  613.         return GLUT_NORMAL;
  614.     case GLUT_HAS_OVERLAY:
  615.         return 0;
  616.     case GLUT_TRANSPARENT_INDEX:
  617.         /*
  618.          * Return just anything, which is always defined as zero
  619.          *
  620.          * XXX HUH?
  621.          */
  622.         return 0;
  623.     case GLUT_NORMAL_DAMAGED:
  624.         /* XXX Actually I do not know. Maybe. */
  625.         return 0;
  626.     case GLUT_OVERLAY_DAMAGED:
  627.         return -1;
  628. #elif TARGET_HOST_MS_WINDOWS
  629.     case GLUT_OVERLAY_POSSIBLE:
  630. /*      return fgSetupPixelFormat( fgStructure.CurrentWindow, GL_TRUE,
  631.                                    PFD_OVERLAY_PLANE ); */
  632.       return 0 ;
  633.     case GLUT_LAYER_IN_USE:
  634.         return GLUT_NORMAL;
  635.     case GLUT_HAS_OVERLAY:
  636.         return 0;
  637.     case GLUT_TRANSPARENT_INDEX:
  638.         /*
  639.          * Return just anything, which is always defined as zero
  640.          *
  641.          * XXX HUH?
  642.          */
  643.         return 0;
  644.     case GLUT_NORMAL_DAMAGED:
  645.         /* XXX Actually I do not know. Maybe. */
  646.         return 0;
  647.     case GLUT_OVERLAY_DAMAGED:
  648.         return -1;
  649. #endif
  650.     default:
  651.         fgWarning( "glutLayerGet(): missing enum handle %d", eWhat );
  652.         break;
  653.     }
  654.     /* And fail. That's good. Programs do love failing. */
  655.     return -1;
  656. }
  657. int * FGAPIENTRY glutGetModeValues(GLenum eWhat, int * size)
  658. {
  659.   int * array;
  660. #if TARGET_HOST_POSIX_X11
  661.   int attributes[9];
  662.   GLXFBConfig * fbconfigArray;  /*  Array of FBConfigs  */
  663.   int fbconfigArraySize;        /*  Number of FBConfigs in the array  */
  664.   int attribute_name = 0;
  665. #endif
  666.   FREEGLUT_EXIT_IF_NOT_INITIALISED("glutGetModeValues");
  667.   array = NULL;
  668.   *size = 0;
  669.   switch (eWhat)
  670.     {
  671. #if TARGET_HOST_POSIX_X11
  672.     case GLUT_AUX:
  673.     case GLUT_MULTISAMPLE:
  674.       attributes[0] = GLX_BUFFER_SIZE;
  675.       attributes[1] = GLX_DONT_CARE;
  676.       switch (eWhat)
  677.         {
  678.         case GLUT_AUX:
  679.           /*
  680.             FBConfigs are now sorted by increasing number of auxiliary
  681.             buffers.  We want at least one buffer.
  682.           */
  683.           attributes[2] = GLX_AUX_BUFFERS;
  684.           attributes[3] = 1;
  685.           attributes[4] = None;
  686.           attribute_name = GLX_AUX_BUFFERS;
  687.           break;
  688.         case GLUT_MULTISAMPLE:
  689.           attributes[2] = GLX_AUX_BUFFERS;
  690.           attributes[3] = GLX_DONT_CARE;
  691.           attributes[4] = GLX_SAMPLE_BUFFERS;
  692.           attributes[5] = 1;
  693.           /*
  694.             FBConfigs are now sorted by increasing number of samples per
  695.             pixel.  We want at least one sample.
  696.           */
  697.           attributes[6] = GLX_SAMPLES;
  698.           attributes[7] = 1;
  699.           attributes[8] = None;
  700.           attribute_name = GLX_SAMPLES;
  701.           break;
  702.         }
  703.       fbconfigArray = glXChooseFBConfig(fgDisplay.Display,
  704.                                         fgDisplay.Screen,
  705.                                         attributes,
  706.                                         &fbconfigArraySize);
  707.       if (fbconfigArray != NULL)
  708.         {
  709.           int * temp_array;
  710.           int result;   /*  Returned by glXGetFBConfigAttrib. Not checked.  */
  711.           int previous_value;
  712.           int i;
  713.           temp_array = malloc(sizeof(int) * fbconfigArraySize);
  714.           previous_value = 0;
  715.           for (i = 0; i < fbconfigArraySize; i++)
  716.             {
  717.               int value;
  718.               result = glXGetFBConfigAttrib(fgDisplay.Display,
  719.                                             fbconfigArray[i],
  720.                                             attribute_name,
  721.                                             &value);
  722.               if (value > previous_value)
  723.                 {
  724.                   temp_array[*size] = value;
  725.                   previous_value = value;
  726.                   (*size)++;
  727.                 }
  728.             }
  729.           array = malloc(sizeof(int) * (*size));
  730.           for (i = 0; i < *size; i++)
  731.             {
  732.               array[i] = temp_array[i];
  733.             }
  734.           free(temp_array);
  735.           XFree(fbconfigArray);
  736.         }
  737.       break;
  738. #endif      
  739.     default:
  740.       break;
  741.     }
  742.   return array;
  743. }
  744. /*** END OF FILE ***/