Browse Source

+ patch by Michalis Kamburelis to add GLX 1.4 support and new GLX extensions, resolves #19953

git-svn-id: trunk@18207 -
florian 14 years ago
parent
commit
c45222cd17
2 changed files with 519 additions and 26 deletions
  1. 81 10
      packages/opengl/examples/glxtest.pp
  2. 438 16
      packages/opengl/src/glx.pp

+ 81 - 10
packages/opengl/examples/glxtest.pp

@@ -13,7 +13,25 @@ program glxTest;
 uses glx,unix,x,xlib,xutil,gl,glu;
 
 var
-  attr: Array[0..8] of integer = (GLX_RGBA,GLX_RED_SIZE,1,GLX_GREEN_SIZE,1,GLX_BLUE_SIZE,1,GLX_DOUBLEBUFFER,none);
+  { Attributes to choose context with glXChooseVisual }
+  Attr: Array[0..8] of integer = (
+    GLX_RGBA,
+    GLX_RED_SIZE, 1,
+    GLX_GREEN_SIZE, 1,
+    GLX_BLUE_SIZE, 1,
+    GLX_DOUBLEBUFFER,
+    none);
+
+  { Attributes to choose context with glXChooseFBConfig.
+    Similar to Attr, but not exactly compatible. }
+  AttrFB: Array[0..10] of integer = (
+    GLX_X_RENDERABLE, 1 { true },
+    GLX_RED_SIZE, 1,
+    GLX_GREEN_SIZE, 1,
+    GLX_BLUE_SIZE, 1,
+    GLX_DOUBLEBUFFER, 1 { true },
+    none);
+
   visinfo: PXVisualInfo;
   cm: TColormap;
   winAttr: TXSetWindowAttributes;
@@ -64,22 +82,52 @@ begin
   end;
 end;
 
+procedure Error(const S: string);
+begin
+  Writeln(ErrOutput, 'Error: ', S);
+  Halt(1);
+end;
+
 var
-  errorBase,eventBase: integer;
   window_title_property: TXTextProperty;
   title: String;
+  FBConfig: TGLXFBConfig;
+  FBConfigs: PGLXFBConfig;
+  FBConfigsCount: Integer;
+
+  { Used with glXCreateContextAttribsARB to select 3.0 forward-compatible context }
+  Context30Forward: array [0..6] of Integer =
+  ( GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
+    GLX_CONTEXT_MINOR_VERSION_ARB, 0,
+    GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
+    None
+  );
 begin
-  initGlx();
   dpy := XOpenDisplay(nil);
   if(dpy = nil) then
-  writeLn('Error: Could not connect to X server');
+    Error('Could not connect to X server');
+
+  if not GLX_version_1_0(dpy) then
+    Error('GLX extension not supported');
 
-  if not (glXQueryExtension(dpy,errorBase,eventBase)) then
-  writeLn('Error: GLX extension not supported');
+  if GLX_version_1_3(dpy) then
+  begin
+    { use approach recommended since glX 1.3 }
+    FBConfigs := glXChooseFBConfig(dpy, DefaultScreen(dpy), AttrFB, FBConfigsCount);
+    if FBConfigsCount = 0 then
+      Error('Could not find FB config');
+
+    { just choose the first FB config from the FBConfigs list.
+      More involved selection possible. }
+    FBConfig := FBConfigs^;
+    visinfo := glXGetVisualFromFBConfig(dpy, FBConfig);
+  end else
+  begin
+    visinfo := glXChooseVisual(dpy, DefaultScreen(dpy), Attr);
+  end;
 
-  visinfo := glXChooseVisual(dpy,DefaultScreen(dpy), Attr);
   if(visinfo = nil) then
-  writeLn('Error: Could not find visual');
+    Error('Could not find visual');
 
   //Create a new colormap
   cm := XCreateColormap(dpy,RootWindow(dpy,visinfo.screen),visinfo.visual,AllocNone);
@@ -96,9 +144,32 @@ begin
   XSetWMName(dpy,win,@window_title_property);
 
   //Create an OpenGL rendering context
-  glXCont := glXCreateContext(dpy,visinfo,none,true);
+  if GLX_version_1_3(dpy) then
+  begin
+    writeln('Using GLX 1.3 code path');
+    { Uncomment two lines below to use GLX_ARB_create_context extension
+      to request OpenGL 3.0 forward-compatible context. This is just
+      a simple example, be aware of some shortcomings:
+
+      - In case of failure, glXCreateContextAttribsARB not only returns nil,
+        it also raises X error that by default simply breaks your program.
+        In a real program, you probably want to catch it (use XSetErrorHandler
+        to assign custom error handler) and retry glXCreateContextAttribsARB
+        with less restrictive attributes.
+
+      - In case of success, you will just see a black screen.
+        That's because the Redraw and Resize procedures defined in this program
+        actually use deprecated OpenGL calls, that are *not* available in
+        a forward-compatible context (glGetError would show actual errors). }
+//  if GLX_ARB_create_context(dpy, DefaultScreen(dpy)) then
+//    glXCont := glXCreateContextAttribsARB(dpy, FBConfig, 0, true, Context30Forward) else
+      { use approach recommended since glX 1.3 }
+      glXCont := glXCreateNewContext(dpy, FBConfig, GLX_RGBA_TYPE, 0, true);
+  end else
+    glXCont := glXCreateContext(dpy, visinfo, none, true);
+
   if(glXCont = nil) then
-  writeLn('Error: Could not create an OpenGL rendering context');
+    Error('Could not create an OpenGL rendering context');
 
   //Make it current
   glXMakeCurrent(dpy,win,glXCont);

+ 438 - 16
packages/opengl/src/glx.pp

@@ -84,16 +84,6 @@ const
   GLX_ACCUM_BLUE_SIZE                   = 16;
   GLX_ACCUM_ALPHA_SIZE                  = 17;
 
-  // GLX_EXT_visual_info extension
-  GLX_X_VISUAL_TYPE_EXT                 = $22;
-  GLX_TRANSPARENT_TYPE_EXT              = $23;
-  GLX_TRANSPARENT_INDEX_VALUE_EXT       = $24;
-  GLX_TRANSPARENT_RED_VALUE_EXT         = $25;
-  GLX_TRANSPARENT_GREEN_VALUE_EXT       = $26;
-  GLX_TRANSPARENT_BLUE_VALUE_EXT        = $27;
-  GLX_TRANSPARENT_ALPHA_VALUE_EXT       = $28;
-
-
   // Error codes returned by glXGetConfig:
   GLX_BAD_SCREEN                        = 1;
   GLX_BAD_ATTRIBUTE                     = 2;
@@ -108,7 +98,105 @@ const
   GLX_VERSION                           = 2;
   GLX_EXTENSIONS                        = 3;
 
-  // GLX_visual_info extension
+  // GLX 1.3 and later:
+  GLX_CONFIG_CAVEAT               = $20;
+  GLX_DONT_CARE                   = $FFFFFFFF;
+  GLX_X_VISUAL_TYPE               = $22;
+  GLX_TRANSPARENT_TYPE            = $23;
+  GLX_TRANSPARENT_INDEX_VALUE     = $24;
+  GLX_TRANSPARENT_RED_VALUE       = $25;
+  GLX_TRANSPARENT_GREEN_VALUE     = $26;
+  GLX_TRANSPARENT_BLUE_VALUE      = $27;
+  GLX_TRANSPARENT_ALPHA_VALUE     = $28;
+  GLX_WINDOW_BIT                  = $00000001;
+  GLX_PIXMAP_BIT                  = $00000002;
+  GLX_PBUFFER_BIT                 = $00000004;
+  GLX_AUX_BUFFERS_BIT             = $00000010;
+  GLX_FRONT_LEFT_BUFFER_BIT       = $00000001;
+  GLX_FRONT_RIGHT_BUFFER_BIT      = $00000002;
+  GLX_BACK_LEFT_BUFFER_BIT        = $00000004;
+  GLX_BACK_RIGHT_BUFFER_BIT       = $00000008;
+  GLX_DEPTH_BUFFER_BIT            = $00000020;
+  GLX_STENCIL_BUFFER_BIT          = $00000040;
+  GLX_ACCUM_BUFFER_BIT            = $00000080;
+  GLX_NONE                        = $8000;
+  GLX_SLOW_CONFIG                 = $8001;
+  GLX_TRUE_COLOR                  = $8002;
+  GLX_DIRECT_COLOR                = $8003;
+  GLX_PSEUDO_COLOR                = $8004;
+  GLX_STATIC_COLOR                = $8005;
+  GLX_GRAY_SCALE                  = $8006;
+  GLX_STATIC_GRAY                 = $8007;
+  GLX_TRANSPARENT_RGB             = $8008;
+  GLX_TRANSPARENT_INDEX           = $8009;
+  GLX_VISUAL_ID                   = $800B;
+  GLX_SCREEN                      = $800C;
+  GLX_NON_CONFORMANT_CONFIG       = $800D;
+  GLX_DRAWABLE_TYPE               = $8010;
+  GLX_RENDER_TYPE                 = $8011;
+  GLX_X_RENDERABLE                = $8012;
+  GLX_FBCONFIG_ID                 = $8013;
+  GLX_RGBA_TYPE                   = $8014;
+  GLX_COLOR_INDEX_TYPE            = $8015;
+  GLX_MAX_PBUFFER_WIDTH           = $8016;
+  GLX_MAX_PBUFFER_HEIGHT          = $8017;
+  GLX_MAX_PBUFFER_PIXELS          = $8018;
+  GLX_PRESERVED_CONTENTS          = $801B;
+  GLX_LARGEST_PBUFFER             = $801C;
+  GLX_WIDTH                       = $801D;
+  GLX_HEIGHT                      = $801E;
+  GLX_EVENT_MASK                  = $801F;
+  GLX_DAMAGED                     = $8020;
+  GLX_SAVED                       = $8021;
+  GLX_WINDOW                      = $8022;
+  GLX_PBUFFER                     = $8023;
+  GLX_PBUFFER_HEIGHT              = $8040;
+  GLX_PBUFFER_WIDTH               = $8041;
+  GLX_RGBA_BIT                    = $00000001;
+  GLX_COLOR_INDEX_BIT             = $00000002;
+  GLX_PBUFFER_CLOBBER_MASK        = $08000000;
+
+  // GLX 1.4 and later:
+  GLX_SAMPLE_BUFFERS              = $186a0; // 100000
+  GLX_SAMPLES                     = $186a1; // 100001
+
+  // Extensions:
+
+  // GLX_ARB_multisample
+  GLX_SAMPLE_BUFFERS_ARB             = 100000;
+  GLX_SAMPLES_ARB                    = 100001;
+
+  // GLX_ARB_create_context (http://www.opengl.org/registry/specs/ARB/glx_create_context.txt)
+  GLX_CONTEXT_DEBUG_BIT_ARB          = $00000001;
+  GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = $00000002;
+  GLX_CONTEXT_MAJOR_VERSION_ARB      = $2091;
+  GLX_CONTEXT_MINOR_VERSION_ARB      = $2092;
+  GLX_CONTEXT_FLAGS_ARB              = $2094;
+
+  // GLX_ARB_create_context_profile
+  GLX_CONTEXT_CORE_PROFILE_BIT_ARB   = $00000001;
+  GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = $00000002;
+  GLX_CONTEXT_PROFILE_MASK_ARB       = $9126;
+
+  // GLX_ARB_create_context_robustness
+  GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB  = $00000004;
+  GLX_LOSE_CONTEXT_ON_RESET_ARB      = $8252;
+  GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB = $8256;
+  GLX_NO_RESET_NOTIFICATION_ARB      = $8261;
+
+  // GLX_SGIS_multisample
+  GLX_SAMPLE_BUFFERS_SGIS            = 100000;
+  GLX_SAMPLES_SGIS                   = 100001;
+
+  // GLX_EXT_visual_info
+  GLX_X_VISUAL_TYPE_EXT                 = $22;
+  GLX_TRANSPARENT_TYPE_EXT              = $23;
+  GLX_TRANSPARENT_INDEX_VALUE_EXT       = $24;
+  GLX_TRANSPARENT_RED_VALUE_EXT         = $25;
+  GLX_TRANSPARENT_GREEN_VALUE_EXT       = $26;
+  GLX_TRANSPARENT_BLUE_VALUE_EXT        = $27;
+  GLX_TRANSPARENT_ALPHA_VALUE_EXT       = $28;
+
   GLX_TRUE_COLOR_EXT                    = $8002;
   GLX_DIRECT_COLOR_EXT                  = $8003;
   GLX_PSEUDO_COLOR_EXT                  = $8004;
@@ -129,7 +217,7 @@ type
   GLXPixmap = TXID;
   GLXDrawable = TXID;
   GLXContextID = TXID;
-  
+
   TXPixmap = XPixmap;
   TXFont = XFont;
   TXColormap = XColormap;
@@ -137,7 +225,16 @@ type
   TGLXContext = GLXContext;
   TGLXPixmap = GLXPixmap;
   TGLXDrawable = GLXDrawable;
+  // GLX 1.3 and later
+  TGLXFBConfigRec = record { internal, use only a pointer to this } end;
+  TGLXFBConfig = ^TGLXFBConfigRec;
+  { PGLXFBConfig is a pointer to TGLXFBConfig (which is also a pointer).
+    glX uses this to represent an array of FB configs. }
+  PGLXFBConfig = ^TGLXFBConfig;
+  TGLXFBConfigID = TXID;
   TGLXContextID = GLXContextID;
+  TGLXWindow = TXID;
+  TGLXPbuffer = TXID;
 
 var
   glXChooseVisual: function(dpy: PDisplay; screen: Integer; attribList: PInteger): PXVisualInfo; cdecl;
@@ -163,24 +260,320 @@ var
   glXQueryServerString: function(dpy: PDisplay; screen, name: Integer): PChar; cdecl;
   glXGetClientString: function(dpy: PDisplay; name: Integer): PChar; cdecl;
 
-  // Mesa GLX Extensions
+  // GLX 1.2 and later
+  glXGetCurrentDisplay: function: PDisplay; cdecl;
+
+  // GLX 1.3 and later
+  glXChooseFBConfig: function(dpy: PDisplay; screen: Integer; attribList: PInteger; var nitems: Integer): PGLXFBConfig; cdecl;
+  glXGetFBConfigAttrib: function(dpy: PDisplay; config: TGLXFBConfig; attribute: Integer; var value: Integer): Integer; cdecl;
+  glXGetFBConfigs: function(dpy: PDisplay; screen: Integer; var nelements: Integer): PGLXFBConfig; cdecl;
+  glXGetVisualFromFBConfig: function(dpy: PDisplay; config: TGLXFBConfig): PXVisualInfo; cdecl;
+  glXCreateWindow: function(dpy: PDisplay; config: TGLXFBConfig; win: X.TWindow; attribList: PInteger): TGLXWindow; cdecl;
+  glXDestroyWindow: procedure (dpy: PDisplay; window: TGLXWindow); cdecl;
+  glXCreatePixmap: function(dpy: PDisplay; config: TGLXFBConfig; pixmap: TXPixmap; attribList: PInteger): TGLXPixmap; cdecl;
+  glXDestroyPixmap: procedure (dpy: PDisplay; pixmap: TGLXPixmap); cdecl;
+  glXCreatePbuffer: function(dpy: PDisplay; config: TGLXFBConfig; attribList: PInteger): TGLXPbuffer; cdecl;
+  glXDestroyPbuffer: procedure (dpy: PDisplay; pbuf: TGLXPbuffer); cdecl;
+  glXQueryDrawable: procedure (dpy: PDisplay; draw: TGLXDrawable; attribute: Integer; value: PLongWord); cdecl;
+  glXCreateNewContext: function(dpy: PDisplay; config: TGLXFBConfig; renderType: Integer; shareList: TGLXContext; direct: boolean): TGLXContext; cdecl;
+  glXMakeContextCurrent: function(dpy: PDisplay; draw: TGLXDrawable; read: GLXDrawable; ctx: TGLXContext): boolean; cdecl;
+  glXGetCurrentReadDrawable: function: TGLXDrawable; cdecl;
+  glXQueryContext: function(dpy: PDisplay; ctx: TGLXContext; attribute: Integer; var value: Integer): Integer; cdecl;
+  glXSelectEvent: procedure (dpy: PDisplay; drawable: TGLXDrawable; mask: LongWord); cdecl;
+  glXGetSelectedEvent: procedure (dpy: PDisplay; drawable: TGLXDrawable; mask: PLongWord); cdecl;
+
+  // GLX 1.4 and later
+  glXGetProcAddress: function(procname: PChar): Pointer; cdecl;
+
+  // Extensions:
+
+  // GLX_ARB_get_proc_address
+  glXGetProcAddressARB: function(procname: PChar): Pointer; cdecl;
+
+  // GLX_ARB_create_context
+  glXCreateContextAttribsARB: function (dpy: PDisplay; config: TGLXFBConfig; share_context: TGLXContext; direct: boolean; attrib_list: PInteger): TGLXContext; cdecl;
+
+  // GLX_MESA_pixmap_colormap
   glXCreateGLXPixmapMESA: function(dpy: PDisplay; visual: PXVisualInfo; pixmap: XPixmap; cmap: XColormap): GLXPixmap; cdecl;
+
+  // Unknown Mesa GLX extension (undocumented in current GLX C headers?)
   glXReleaseBufferMESA: function(dpy: PDisplay; d: GLXDrawable): Boolean; cdecl;
   glXCopySubBufferMESA: procedure(dpy: PDisplay; drawbale: GLXDrawable; x, y, width, height: Integer); cdecl;
+
+  // GLX_SGI_video_sync
   glXGetVideoSyncSGI: function(var counter: LongWord): Integer; cdecl;
   glXWaitVideoSyncSGI: function(divisor, remainder: Integer; var count: LongWord): Integer; cdecl;
 
-
 // =======================================================
 //
 // =======================================================
 
+{
+  Safe checking of glX version and extension presence.
+
+  For each glX version, these functions check that
+  - glXQueryExtension indicates that glX extension is present at all on this display.
+  - glXQueryVersion indicates that (at least) this version is supported.
+  - all the entry points defined for this glX version were
+    successfully loaded from the library.
+    For now, all glX versions are fully backward-compatible,
+    so e.g. if GLX_version_1_3 is true, you know that also GLX_version_1_2
+    and GLX_version_1_1 etc. are true,
+    and all entry points up to glX 1.3 are assigned.
+
+  For each extension, these functions check that
+  - it is declared within glXQueryExtensionsString (which in turn means
+    that glXQueryExtensionsString must be available, which requires glX 1.1)
+  - all it's entry points were successfully loaded from library
+
+  As such, these functions are the safest way to check if given
+  extension/glX version is available.
+
+  Note that the availability of glX version and extension may depend
+  on the X display and (in case of extension) even screen number.
+}
+
+function GLX_version_1_0(Display: PDisplay): boolean;
+function GLX_version_1_1(Display: PDisplay): boolean;
+function GLX_version_1_2(Display: PDisplay): boolean;
+function GLX_version_1_3(Display: PDisplay): boolean;
+function GLX_version_1_4(Display: PDisplay): boolean;
+
+function GLX_ARB_get_proc_address(Display: PDisplay; Screen: Integer): boolean;
+function GLX_ARB_create_context(Display: PDisplay; Screen: Integer): boolean;
+function GLX_ARB_create_context_profile(Display: PDisplay; Screen: Integer): boolean;
+function GLX_ARB_create_context_robustness(Display: PDisplay; Screen: Integer): boolean;
+function GLX_ARB_multisample(Display: PDisplay; Screen: Integer): boolean;
+function GLX_EXT_visual_info(Display: PDisplay; Screen: Integer): boolean;
+function GLX_MESA_pixmap_colormap(Display: PDisplay; Screen: Integer): boolean;
+function GLX_SGI_video_sync(Display: PDisplay; Screen: Integer): boolean;
+function GLX_SGIS_multisample(Display: PDisplay; Screen: Integer): boolean;
+
 implementation
 
-uses GL, dynlibs;
+uses GL, dynlibs, GLExt { for glext_ExtensionSupported utility };
 
 {$LINKLIB m}
 
+function GLX_version_1_0(Display: PDisplay): boolean;
+var
+  IgnoredErrorb, IgnoredEvent, Major, Minor: Integer;
+begin
+  Result :=
+    { check is glX present at all for this display }
+    Assigned(glXQueryExtension) and
+    glXQueryExtension(Display, IgnoredErrorb, IgnoredEvent) and
+    { check glXQueryVersion, although there is no glX with version < 1 }
+    Assigned(glXQueryVersion) and
+    glXQueryVersion(Display, Major, Minor) and
+    (Major >= 1) and
+    { check entry points assigned }
+    Assigned(glXChooseVisual) and
+    Assigned(glXCreateContext) and
+    Assigned(glXDestroyContext) and
+    Assigned(glXMakeCurrent) and
+    Assigned(glXCopyContext) and
+    Assigned(glXSwapBuffers) and
+    Assigned(glXCreateGLXPixmap) and
+    Assigned(glXDestroyGLXPixmap) and
+    { Assigned(glXQueryExtension) and } { (already checked) }
+    { Assigned(glXQueryVersion) and } { (already checked) }
+    Assigned(glXIsDirect) and
+    Assigned(glXGetConfig) and
+    Assigned(glXGetCurrentContext) and
+    Assigned(glXGetCurrentDrawable) and
+    Assigned(glXWaitGL) and
+    Assigned(glXWaitX) and
+    Assigned(glXUseXFont)
+end;
+
+function GLX_version_1_1(Display: PDisplay): boolean;
+var
+  Major, Minor: Integer;
+begin
+  Result :=
+    { check previous version Ok }
+    GLX_version_1_0(Display) and
+    { check glXQueryVersion }
+    glXQueryVersion(Display, Major, Minor) and
+    ( (Major > 1) or ((Major = 1) and (Minor >= 1)) ) and
+    { check entry points assigned }
+    Assigned(glXQueryExtensionsString) and
+    Assigned(glXQueryServerString) and
+    Assigned(glXGetClientString);
+end;
+
+function GLX_version_1_2(Display: PDisplay): boolean;
+var
+  Major, Minor: Integer;
+begin
+  Result :=
+    { check previous version Ok }
+    GLX_version_1_1(Display) and
+    { check glXQueryVersion }
+    glXQueryVersion(Display, Major, Minor) and
+    ( (Major > 1) or ((Major = 1) and (Minor >= 2)) ) and
+    { check entry points assigned }
+    Assigned(glXGetCurrentDisplay);
+end;
+
+function GLX_version_1_3(Display: PDisplay): boolean;
+var
+  Major, Minor: Integer;
+begin
+  Result :=
+    { check previous version Ok }
+    GLX_version_1_2(Display) and
+    { check glXQueryVersion }
+    glXQueryVersion(Display, Major, Minor) and
+    ( (Major > 1) or ((Major = 1) and (Minor >= 3)) ) and
+    { check entry points assigned }
+    Assigned(glXChooseFBConfig) and
+    Assigned(glXGetFBConfigAttrib) and
+    Assigned(glXGetFBConfigs) and
+    Assigned(glXGetVisualFromFBConfig) and
+    Assigned(glXCreateWindow) and
+    Assigned(glXDestroyWindow) and
+    Assigned(glXCreatePixmap) and
+    Assigned(glXDestroyPixmap) and
+    Assigned(glXCreatePbuffer) and
+    Assigned(glXDestroyPbuffer) and
+    Assigned(glXQueryDrawable) and
+    Assigned(glXCreateNewContext) and
+    Assigned(glXMakeContextCurrent) and
+    Assigned(glXGetCurrentReadDrawable) and
+    Assigned(glXQueryContext) and
+    Assigned(glXSelectEvent) and
+    Assigned(glXGetSelectedEvent);
+end;
+
+function GLX_version_1_4(Display: PDisplay): boolean;
+var
+  Major, Minor: Integer;
+begin
+  Result :=
+    { check previous version Ok }
+    GLX_version_1_3(Display) and
+    { check glXQueryVersion }
+    glXQueryVersion(Display, Major, Minor) and
+    ( (Major > 1) or ((Major = 1) and (Minor >= 4)) ) and
+    { check entry points assigned }
+    Assigned(glXGetProcAddress);
+end;
+
+function GLX_ARB_get_proc_address(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_ARB_get_proc_address', GlxExtensions) and
+      Assigned(glXGetProcAddressARB);
+  end;
+end;
+
+function GLX_ARB_create_context(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_ARB_create_context', GlxExtensions) and
+      Assigned(glXCreateContextAttribsARB);
+  end;
+end;
+
+function GLX_ARB_create_context_profile(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_ARB_create_context_profile', GlxExtensions);
+  end;
+end;
+
+function GLX_ARB_create_context_robustness(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_ARB_create_context_robustness', GlxExtensions);
+  end;
+end;
+
+function GLX_ARB_multisample(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_ARB_multisample', GlxExtensions);
+  end;
+end;
+
+function GLX_EXT_visual_info(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_EXT_visual_info', GlxExtensions);
+  end;
+end;
+
+function GLX_MESA_pixmap_colormap(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_MESA_pixmap_colormap', GlxExtensions) and
+      Assigned(glXCreateGLXPixmapMESA);
+  end;
+end;
+
+function GLX_SGI_video_sync(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_SGI_video_sync', GlxExtensions) and
+      Assigned(glXGetVideoSyncSGI) and
+      Assigned(glXWaitVideoSyncSGI);
+  end;
+end;
+
+function GLX_SGIS_multisample(Display: PDisplay; Screen: Integer): boolean;
+var
+  GlxExtensions: PChar;
+begin
+  Result := GLX_version_1_1(Display);
+  if Result then
+  begin
+    GlxExtensions := glXQueryExtensionsString(Display, Screen);
+    Result := glext_ExtensionSupported('GLX_SGIS_multisample', GlxExtensions);
+  end;
+end;
+
 function GetProc(handle: PtrInt; name: PChar): Pointer;
 begin
   Result := GetProcAddress(handle, name);
@@ -224,10 +617,39 @@ begin
   glXQueryExtensionsString := GetProc(OurLibGL, 'glXQueryExtensionsString');
   glXQueryServerString := GetProc(OurLibGL, 'glXQueryServerString');
   glXGetClientString := GetProc(OurLibGL, 'glXGetClientString');
-  // Mesa GLX Extensions
+  // GLX 1.2 and later
+  glXGetCurrentDisplay := GetProc(OurLibGL, 'glXGetCurrentDisplay');
+  // GLX 1.3 and later
+  glXChooseFBConfig := GetProc(OurLibGL, 'glXChooseFBConfig');
+  glXGetFBConfigAttrib := GetProc(OurLibGL, 'glXGetFBConfigAttrib');
+  glXGetFBConfigs := GetProc(OurLibGL, 'glXGetFBConfigs');
+  glXGetVisualFromFBConfig := GetProc(OurLibGL, 'glXGetVisualFromFBConfig');
+  glXCreateWindow := GetProc(OurLibGL, 'glXCreateWindow');
+  glXDestroyWindow := GetProc(OurLibGL, 'glXDestroyWindow');
+  glXCreatePixmap := GetProc(OurLibGL, 'glXCreatePixmap');
+  glXDestroyPixmap := GetProc(OurLibGL, 'glXDestroyPixmap');
+  glXCreatePbuffer := GetProc(OurLibGL, 'glXCreatePbuffer');
+  glXDestroyPbuffer := GetProc(OurLibGL, 'glXDestroyPbuffer');
+  glXQueryDrawable := GetProc(OurLibGL, 'glXQueryDrawable');
+  glXCreateNewContext := GetProc(OurLibGL, 'glXCreateNewContext');
+  glXMakeContextCurrent := GetProc(OurLibGL, 'glXMakeContextCurrent');
+  glXGetCurrentReadDrawable := GetProc(OurLibGL, 'glXGetCurrentReadDrawable');
+  glXQueryContext := GetProc(OurLibGL, 'glXQueryContext');
+  glXSelectEvent := GetProc(OurLibGL, 'glXSelectEvent');
+  glXGetSelectedEvent := GetProc(OurLibGL, 'glXGetSelectedEvent');
+  // GLX 1.4 and later
+  glXGetProcAddress := GetProc(OurLibGL, 'glXGetProcAddress');
+  // Extensions
+  // GLX_ARB_get_proc_address
+  glXGetProcAddressARB := GetProc(OurLibGL, 'glXGetProcAddressARB');
+  // GLX_ARB_create_context
+  glXCreateContextAttribsARB := GetProc(OurLibGL, 'glXCreateContextAttribsARB');
+  // GLX_MESA_pixmap_colormap
   glXCreateGLXPixmapMESA := GetProc(OurLibGL, 'glXCreateGLXPixmapMESA');
+  // Unknown Mesa GLX extension
   glXReleaseBufferMESA := GetProc(OurLibGL, 'glXReleaseBufferMESA');
   glXCopySubBufferMESA := GetProc(OurLibGL, 'glXCopySubBufferMESA');
+  // GLX_SGI_video_sync
   glXGetVideoSyncSGI := GetProc(OurLibGL, 'glXGetVideoSyncSGI');
   glXWaitVideoSyncSGI := GetProc(OurLibGL, 'glXWaitVideoSyncSGI');