extension string rules

There is some discussion on the mac mailing list about extensions being integrated into future GL versions and being removed from the GL_EXTENSIONS string.

It causes problems for older programs. Isn’t there rules governing what should be in the string and when a string can be removed?

It comes down to not removing strings, thus the list becomes ever larger, or people write better code and make easy updates available.

This is a weakness of gl that needs attention.

V-man

i think the idea with next gen opengl (or whatever its pet name is) is that the old (pre-2.0) functionality is emulated/provided by a separate component (subdriver, if you will)… the way 3dlabs’ docs read, looks like there’s no reason why it can’t be - so you get backwards compatibility along with the new api. clean and invisible

This really shouldn’t be an issue. You start running into problems if you copy the extension string into a fixed size buffer. But that’s actually never necessary.
If you really want to copy it you should call strlen first and allocate a buffer that’s big enough. If you don’t, well your app is broken

Would it be safe to say that I think V-man was talking about future version of GL1.x?

Say GL_ARB_MULTITEXTURE gets dropped from the extension string, which could possibly happen because it is now part of the core of OpenGL. And a program is written to use that extension (say Quake III). If it were to be removed from the extension list, even though its functionality is still available, then Quake III won’t be able to use the multitexturing capabilities of your card because it can’t find the extension string, and wglGetProcAddress (or glXGetProcAddress ) won’t get glMultiTexCoord2fARB and whatnot. So Quake III turns your GF4 into a souped up Riva128

My suggestion would be to make a change as to how the glGetString command retrieves the extension list (like a glHint). The default of the GL_EXTENSION_LIST_SIZE is to report all supported extensions (including those added to the core), and you can hint to it that you know how to handle core extensions and have the driver only report those extensions not in the core. If the default of it is set to return all extension, old apps work fine. And you can tell it that your new app written today doesn’t need the 20+ added extensions that you know already exist as part of the core.

just my $0.02

Dan

I believe the rule is that all functions for GL level X is exposed in an implementation that claims to be version X, but extensions are only exposed if the hardware and drivers support it well.

It doesn’t make sense to support some extension that won’t actually work well in the hardware.

Originally posted by jwatte:
[b]I believe the rule is that all functions for GL level X is exposed in an implementation that claims to be version X, but extensions are only exposed if the hardware and drivers support it well.
[b]

You mean treat it as GL 1.1 + extensions?

If level X is 1.4 then certain drivers return extensions that are now integrated into 1.4 which in some sense doesn’t make sense.

If they decide to remove the extension
(Dan82181 got the point), then older games and apps are broken since they expect to find ARB_multitexture for example.

If some vendors don’t want to advertise certain extensions because they know it will lead to bad performance or crashes, then I dont know where that rule is written but Im aware of it thanks to Matt.

The point is that some people are confused/unhappy/want the extension to stay/want a better solution to this.

V-man

A few comments:

There is no “official” policy on removing items from extension strings. It is certainly possible for a driver to screw with its extension string however it sees fit. Backwards compatibility is usually a good reason to keep supporting old extensions, particularly since there is little to no cost in doing so. Vendors generally keep the old stuff around for this reason.

There is no official policy on supporting extension string entries for extensions sucked into the core. In recent revisions, NVIDIA has adopted an unofficial policy of exporting extension strings for features in the core if and only if the features are supported in hardware. Basically this comes down to the question: “if feature X wasn’t in the core, would we expose it as an extension”? For software-only features, the answer is generally no.

A few other appeals:

(1) PLEASE don’t copy the extension strings into a fixed-size buffer. You might think “2KB is big enough to hold any extension string”, but you’d be wrong.

(2) Make sure that when you query the GL version you consider the possibility of future OpenGL revisions, so you run your 1.3 path on 1.3 OR BETTER. Every time we rev our driver, there’s usually a couple apps that see the new version and fall back to their “1.0” path (it’s not 1.3, it’s not 1.2, it’s not 1.1, so it must be 1.0).

I think the general tendency is to keep “old” extension strings in for the reasons that several of you mention. If this is important to you, make sure you lobby your OpenGL vendors not to make these sort of changes.

I find it scary sometimes how people code their apps. There are silly mistakes like (1) and (2) above even made by people I would recognice as quite skilled. For a long time S3TC didn’t work in the OpenGL renderer for UT on ATi cards, until I digged into the source code of it. Instead of fully debugging it I made a quick hack to get it to work simply by setting SupportTC = 1; After I posted the “fixed” version on a few forums it didn’t take long until Epic released an official fixed version. It turned out their extension checking routine refused to go beyond 1024 bytes.
Another thing I’ve never understood why some people do, why copy at all?

Another thing I’ve never understood why some people do, why copy at all?

Well, actually, there is a good reason to do the copy. Granted, it happens to involve proven code that wouldn’t cause this problem.

If I were parsing the extension string, I would want to put it in a std::string rather than use the bare char . Since std::string is a string-by-value, it would do a copy from the char. Granted, it wouldn’t assume a fixed maximum size, so you wouldn’t get this problem.

Duh

const char* ext_string=NULL;

bool
is_supported(const char*const extension)
{
	if (ext_string==NULL)
	{
		ext_string=(const char*)glGetString(GL_EXTENSIONS);
	}

	uint ext_string_length=strlen(ext_string);
	uint ext_len=strlen(extension);

	uint o=0;    //offset into the extension list string

	while (o<ext_string_length)
	{
		//skip spaces
		while ((o<ext_string_length)&&(ext_string[o]==' ')) ++o;
		//check current extension identifier
		if (strncmp(ext_string+o,extension,ext_len)==0)
		{
			//check if this was the end of the extension identifier (GL_ARB_mu vs GL_ARB_multitexture)
			char lim=ext_string[o+ext_len];
			//space or zero termination characters are acceptable
			if ((lim==' ')&#0124; &#0124;(lim==0)) return(true);
		}
		//skip identifier (non-spaces)
		while ((o<ext_string_length)&&(ext_string[o]!=' ')) ++o;
	}
	//didn't find it
	return(false);
}

[This message has been edited by zeckensack (edited 10-24-2002).]

I think this is shorter, and it properly handles distinguishing EXT_ME_version from EXT_ME_version2 from FOO_EXT_ME_version etc.
Note that extension strings contain commas, as well as spaces…

#include <string.h>
#include <ctype.h>

inline bool isid( char ch ) {
return isalnum( ch ) | | (ch == ‘_’);
}

bool SupportsExtension( char const * name, char const * extStr = 0 )
{
if( !extStr ) {
extStr = glGetString( GL_EXTENSIONS );
}
if( !name | | !name[0] ) return false;
char const * found = strstr( ext, name );
if( !found ) return false;
char const * foundEnd = found + strlen( name );
if( found > ext && isid( found[-1] ) ) return SupportsExtension( name, foundEnd );
if( isid( *foundEnd ) ) return SupportsExtension( name, foundEnd );
return true;
}

Of course, I typed this in from memory, so it may or may not compile :slight_smile:

Minor nit: the extension string should not contain commas. From the spec:

The EXTENSIONS string contains a space separated list of extension names (the extension names themselves do not contain any spaces)

I doubt if you’ll see an extension string with a comma in it anytime soon, though. :slight_smile:

Originally posted by V-man:
[b]There is some discussion on the mac mailing list about extensions being integrated into future GL versions and being removed from the GL_EXTENSIONS string.

It causes problems for older programs. Isn’t there rules governing what should be in the string and when a string can be removed?

It comes down to not removing strings, thus the list becomes ever larger, or people write better code and make easy updates available.

This is a weakness of gl that needs attention.

V-man[/b]

It doesn’t require attention from the IHVs, it requires attention from the ISVs!!!

  1. If an extension is designed to work with some version of OpenGL, it usually says so in the spec, such as ‘written against the 1.2 spec’
  2. If an extension is integrated into the core in a later version, then there is no need for the IHV to expose the extension anymore!
  3. It’s become a mess because ISVs don’t code properly!!! (ie: IHV’s have to code for the poor coding of ISV’s – sorry if this steps on some toes!)

When you an app, you need to either pick a single version of OpenGL and use that with extensions OR go for a version with all the features you have integrated.

Leathal.

Originally posted by jwatte:
[b]I think this is shorter, and it properly handles distinguishing EXT_ME_version from EXT_ME_version2 from FOO_EXT_ME_version etc.
Note that extension strings contain commas, as well as spaces…

[quote]

#include <string.h>
#include <ctype.h>

inline bool isid( char ch ) {
return isalnum( ch ) | | (ch == ‘_’);
}

bool SupportsExtension( char const * name, char const * extStr = 0 )
{
if( !extStr ) {
extStr = glGetString( GL_EXTENSIONS );
}
if( !name | | !name[0] ) return false;
char const * found = strstr( ext, name );
if( !found ) return false;
char const * foundEnd = found + strlen( name );
if( found > ext && isid( found[-1] ) ) return SupportsExtension( name, foundEnd );
if( isid( *foundEnd ) ) return SupportsExtension( name, foundEnd );
return true;
}

Of course, I typed this in from memory, so it may or may not compile :-)[/b][/QUOTE]

Bah, how about some short easy to read code?

bool findExtension(char *extensions, char *extension){
char *str = extensions;
int len = strlen(extension);

while (str = strstr(str, extension)){
str += len;
if (*str == ’ ’ | | *str == ‘\0’) return true;
}
return false;
}

Is this some kind of shortest extensions checking code contest?

sub is_supported
{
return _[1] =~ /\b_[0]\b/
}

Originally posted by solarforge:

  1. If an extension is integrated into the core in a later version, then there is no need for the IHV to expose the extension anymore!
  2. It’s become a mess because ISVs don’t code properly!!! (ie: IHV’s have to code for the poor coding of ISV’s – sorry if this steps on some toes!)

[/b]

Sorry, this won’t work. Lets say I code an app based on OpenGL 1.4, and I look for the ARB_vertex_program extension and use it.

Now lets say ARB_vertex_program is integrated into the core in GL 1.5. My program checks for GL 1.4 support, and is OK. But, ARB_vertex_program is no longer advertised as an extension, so the app doesn’t know it is present. The app has no idea that it was integrated AFTER the app was released.

Just my .02:

If driver writers want to keep existing software working without changes, they should only increase the API/signature/footprint of the driver, not decrease it. That means that they should:

  1. Keep advertising supported extensions and function entry points
  2. Advertise the new version number and all new extensions and new function entry points.

Also note that usually extensions that get sucked into a new version will have their function names changed (dropping the _ARB/_EXT suffix etc.), so IMHO they are ‘new’ things with respect to the API/signature/footprint.

Of course software that doen’t follow a sane approach towards checking for versions (like reject higher versions when a certain version is required) cannot be guaranteed to keep working, but that is an obvious software bug!

Jean-Marc.

Just to be clear. There is no discussion of removing extensions from the extension string in Mac OS X. As folks have indicated that would break applications.

The question really was…

Should the extension XXX string be exported along with OpenGL version YYY if and only if all the cards that support XXX also support YYY and XXX comes out the same time as YYY. This will NOT likely occur in the future (due to the way extensions and hardware are released) and is likely only a problem when covering historical issues. If this case does come up we will make the a prudent judgement at the time (understanding the preference here has been to export both XXX and YYY).

I think that covers the Mac OS X issues, though the discussion here is a good one in any case.

Frankly speaking, removing extensions from the extension string isn’t necessary. Never. Unless your apps are broken.
This then can be fixed with one of the above code snippets.
There is one real reason for ‘processing’ the extension string and that’s displaying it in one form or another. If your app wants to handle arbitrary text output, it should better be prepared IMO.

Not sure if this matters, but in Win32 GL programming you really have no choice when it comes to core promoted extensions. You still have to treat them as extensions anyway. So on this side of things I don’t see any merit in even checking the gl version.

Another thing that might not matter:
I currently just use ***GetProcAddress for importing extensions that define new functions. If it returns NULL, the extension is not present. I only touch the extension string for extensions that don’t define new functions, such as GL_EXT_packed_pixels. Or for exts that do export functions, but I only need the tokens and ignore the entry points. Like GL_ARB_texture_compression.

Originally posted by zeckensack:
Another thing that might not matter:
I currently just use ***GetProcAddress for importing extensions that define new functions. If it returns NULL, the extension is not present. I only touch the extension string for extensions that don’t define new functions, such as GL_EXT_packed_pixels. Or for exts that do export functions, but I only need the tokens and ignore the entry points. Like GL_ARB_texture_compression.

This is not an especially good idea. If it’s in the driver but isn’t exposed there’s probably a good reason for that, most likely not completely implemented yet and/or not working.