[vtk-developers] [LONG]Core-promoted OpenGL extensions management in VTK

Francois Bertel francois.bertel at kitware.com
Mon Feb 12 18:09:50 EST 2007


Hi,

This email is mainly for Ken Moreland as he implemented the OpenGL extension mechanism in VTK but if any of you has any comment or advice about the topic of this message, feel free to be part of the discussion.

1. Problem
2. Solution
3. Example in VTK
4. Implementation of vtkgl::LoadPromotedExtension
5. Other issues with glext.h and vtkgl.cxx
6. glext.h version

*******************************************************************
1. Problem
*******************************************************************

Crossing different documents about OpenGL extensions on different platforms (see references at the end), it seems that the good way to deal with core-promoted OpenGL extensions (I'm not talking about other extensions, just the core-promoted ones) is to first check for the OpenGL version for which it was promoted, and if this version is not supported check for the extension itself.

[1] describes how to use the OpenGL extension mechanism in VTK. In the OpenGL faq [2], there is a section about dealing with extensions on Windows: "23.070 How can I call extension routines on Microsoft Windows?" and another section to deal with extensions on Linux "23.080 How can I call extension routines on Linux?" There is also the description of the Linux ABI in [3]. Finally, there is a technical document to deal with extensions on a Mac [4].

The key statement comes from the Apple document:

[4] states that "it is worth noting that renderers may or may not support the extensions which the API functionality is based. For example if a renderer reports version 1.3, it may or may not support the GL_ARB_texture_env_combine or GL_EXT_texture_env_combine extensions, though the functionality this extension represents will be available through the core 1.3 API."

Example:

vtkOpenGLExtensionManager *manager;

// Test for the extension

int supports_GL_1_3=manager->ExtensionSupported("GL_VERSION_1_3");
int supports_multitexture;

if(supports_GL_1_3)
{
 supports_multitexture=1;
}
else
{
 supports_multitexture=manager->ExtensionSupported("GL_ARB_multitexture");
}

// If supported, load the functions of this extension

if(supports_multitexture)
{
 if(supports_GL_1_3)
  {
  manager->LoadExtension("GL_VERSION_1_3");
  }
else
  {
  manager->LoadExtension("GL_ARB_multitexture");
  }
}


The *problem* is that the code that uses this extension will have an if statement each time it uses it because the functions are different between the core API and the extension one:

if(supports_GL_1_3)
{
 vtkgl::ActiveTexture(vtkgl::TEXTURE0);
}
else
{
 vtkgl::ActiveTextureARB(vtkgl::TEXTURE0_ARB);
}

It is even worse when you start using several extensions at the same time, the number of if statements just explodes.

Of course, there is no issue if the extension only provides new capabilities without defining new function.

Examples:
* GL_ARB_texture_non_power_of_two defines new capabilities but does not define new token/macro or function.
* GL_ARB_texture_cube_map defines new token/macro but no new function.
* GL_ARB_multitexture defines new token/macro and functions.

*******************************************************************
2. Solution
*******************************************************************

My solution is to provide a new function that initializes the function pointers of the OpenGL API with the function pointers of the extension, *if* the OpenGL version is not supported.

Instead of vtkgl::LoadExtension, there will be a line like: vtkgl::LoadPromotedExtension("GL_ARB_multitexture",manager);

Example:

if(supports_multitexture)
{
 if(supports_GL_1_3)
  {
  manager->LoadExtension("GL_VERSION_1_3");
  }
 else
  {
  vtkgl::LoadPromotedExtension("GL_ARB_multitexture",manager);
  // or, if the function is added the the vtkOpenGLExtensionManager:
  manager->LoadPromotedExtension("GL_ARB_multitexture");
 }
}

Hence, the code that uses the extension will be only:

vtkgl::ActiveTexture(vtkgl::TEXTURE0);

No more if statements everywhere.


This function should be in VTK/Rendering: either in vtkOpenGLExtensionManager itself or in another file.

I attached some files vtkOpenGLPromotedExtensions.h/cxx I wrote to deal with this issue.
To compile it within VTK, do the following:
1. Save the files in VTK/Rendering
2. In VTK/Rendering/CMakeLists.txt, just list the cxx file and list it also in the ABSTRACT list to remove it from instantiator list.
3. In VTK/Rendering/Testing/CMakeLists.txt, add vtkOpenGLPromotedExtensions.h in the list of excluded files for HeaderTesting-Rendering.


*******************************************************************
3. Example in VTK
*******************************************************************

Typical example in VTK is VTK/VolumeRendering/vtkOpenGLVolumeTextureMapper3D.cxx

Right now, there is some dirty macro change in order to make texture3d working with a Mac: 3D textures are supported through OpenGL 1.2 but there is no GL_EXT_texture3D extension.

Current code is:

// Apple OS X doesn't have glTexImage3DEXT, but it does have glTexImage3D
#if defined(__APPLE__) && defined(GL_VERSION_1_2)
#ifdef TexImage3DEXT
#undef TexImage3DEXT
#endif
#define TexImage3DEXT TexImage3D
#ifdef TEXTURE_3D_EXT
#undef TEXTURE_3D_EXT
#endif
#define TEXTURE_3D_EXT TEXTURE_3D
#endif /* defined(__APPLE__) && defined(GL_VERSION_1_2) */

[...]

#if defined(__APPLE__) && defined(GL_VERSION_1_2)
  // Apple doesn't have glTexImage3D_EXT, so load
  // GL_VERSION_1_2 and use glTexImage3D instead.
  if (extensions->ExtensionSupported("GL_VERSION_1_2"))
    {
    if (vtkgl::LoadExtension("GL_VERSION_1_2", extensions))
      {
      supports_GL_EXT_texture3D = 1;
      }
    }
#else
  if(supports_GL_EXT_texture3D)
    {
    extensions->LoadExtension("GL_EXT_texture3D");
    }
#endif

[...]

vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0,
                      GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume1 );


I don't think there should be any platform specific code in this mapper (or in any mapper in general).

Right now, the right code should be:

this->Supports_GL_1_2=manager->ExtensionSupported("GL_VERSION_1_2");
int supports_texture3d;

if(this->Supports_GL_1_2)
{
 supports_texture3d=1;
}
else
{
 supports_texture3d=manager->ExtensionSupported("GL_EXT_texture3D");
}

// If supported, load the functions of this extension

if(supports_texture3d)
{
 if(this->Supports_GL_1_2)
  {
  manager->LoadExtension("GL_VERSION_1_2");
  }
else
  {
  manager->LoadExtension("GL_EXT_texture3D");
  }
}

[...]

 if(this->Supports_GL_1_2)
  {
vtkgl::TexImage3D( vtkgl::TEXTURE_3D, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0,
                           GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume1 );
  }
else
  {
 vtkgl::TexImage3DEXT( vtkgl::TEXTURE_3D_EXT, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0,
                           GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume1 );
  }

With the promoted extension mechanism I want to add, it would be:


this->Supports_GL_1_2=manager->ExtensionSupported("GL_VERSION_1_2");
int supports_texture3d;

if(this->Supports_GL_1_2)
{
 supports_texture3d=1;
}
else
{
 supports_texture3d=manager->ExtensionSupported("GL_EXT_texture3D");
}

// If supported, load the functions of this extension

if(supports_texture3d)
{
 if(this->Supports_GL_1_2)
  {
  manager->LoadExtension("GL_VERSION_1_2");
  }
else
  {
  vtkgl::LoadPromotedExtension("GL_EXT_texture3D",manager);
  }
}

[...]

vtkgl::TexImage3D( vtkgl::TEXTURE_3D, 0, GL_LUMINANCE8_ALPHA8, dim[0], dim[1], dim[2], 0,
                           GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, this->Volume1 );



*******************************************************************
4. Implementation of vtkgl::LoadPromotedExtension
*******************************************************************

I don't think there is a way to generate this function automatically from glext.h because the relationship between the OpenGL API and the core-promoted extensions does not exist in glext.h. So I wrote the code manually, with the help of some generated vtkgl.cxx.

Note that some extensions require special care:

In extension GL_ARB_shader_objects, some functions are translated in OpenGL2.0 into two different functions:

vtkgl::DeleteObjectARB becomes both vtkgl::DeleteProgram and vtkgl::DeleteShader.
vtkgl::GetObjectParameterivARB becomes both to vtkgl::GetProgramiv and vtkgl::GetShaderiv.
vtkgl::GetInfoLogARB becomes both vtkgl::GetProgramInfoLog and vtkgl::GetShaderInfoLog.

Some functions from the ARB extension were removed in OpenGL2.0: vtkgl::GetObjectParameterfiv, vtkgl::GetHandleARB

Some functions in OpenGL 2.0 did not exist in the GL_ARB_shader_objects extension and need to have some specific implementation vtkgl::IsProgram and  vtkgl::IsShader.

*******************************************************************
5. Other issues with glext.h and vtkgl.cxx
*******************************************************************

Going through all the extensions, I noticed that extensions GL_ARB_vertex_shader (GLSL) and GL_ARB_vertex_program (assembly language) share a couple of functions (glVertexAttrib*ARB and others). In glext.h, those functions are only listed in the GL_ARB_vertex_program extension section. It means that if you load the GLSL extension  (GL_ARB_vertex_shader), the function pointers for the glVertexAttrib*ARB functions will not be initialized.


*******************************************************************
6. glext.h version
*******************************************************************
In VTK, the current glext.h is the latest one from http://oss.sgi.com/projects/ogl-sample/registry (from 2005/06/20). It does not include OpenGL 2.1, the one from http://www.opengl.org/registry from (2006/11/27) includes OpenGL 2.1.  It is not clear for me which one is the last official canonical one. Should we update the VTK one with the one from opengl.org?


References:

[1] "OpenGL Extension Manager" on this page: http://www.vtk.org/Wiki/VTK_Shaders . Or directly: http://www.vtk.org/Wiki/images/3/35/VtkOpenGLExtensionManager_Overview.pdf
[2] http://www.opengl.org/resources/faq/technical/extensions.htm
[3] Linux ABI: http://oss.sgi.com/projects/ogl-sample/ABI
[4] http://developer.apple.com/technotes/tn2002/tn2080.html

Regards.

-- 
François Bertel, PhD  | Kitware Inc. Suite 204
1 (518) 371 3971 x113 | 28 Corporate Drive
                      | Clifton Park NY 12065, USA

-------------- next part --------------
A non-text attachment was scrubbed...
Name: core-promoted-extensions.tgz
Type: application/x-compressed-tar
Size: 6498 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtk-developers/attachments/20070212/95e90329/attachment-0001.bin>


More information about the vtk-developers mailing list