PDA

View Full Version : extension string rules



V-man
10-23-2002, 10:06 AM
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

mattc
10-23-2002, 10:23 AM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif

zeckensack
10-23-2002, 01:12 PM
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 http://www.opengl.org/discussion_boards/ubb/wink.gif

Dan82181
10-23-2002, 02:03 PM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif ) won't get glMultiTexCoord2fARB and whatnot. So Quake III turns your GF4 into a souped up Riva128 http://www.opengl.org/discussion_boards/ubb/redface.gif

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

jwatte
10-23-2002, 02:26 PM
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.

V-man
10-23-2002, 03:02 PM
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

pbrown
10-23-2002, 07:47 PM
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.

Humus
10-24-2002, 02:23 AM
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. http://www.opengl.org/discussion_boards/ubb/rolleyes.gif
Another thing I've never understood why some people do, why copy at all?

Korval
10-24-2002, 09:23 AM
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.

zeckensack
10-24-2002, 09:36 AM
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)&amp;&amp;(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==' ')&amp;#0124; &amp;#0124;(lim==0)) return(true);
}
//skip identifier (non-spaces)
while ((o<ext_string_length)&amp;&amp;(ext_string[o]!=' ')) ++o;
}
//didn't find it
return(false);
}

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

jwatte
10-24-2002, 10:35 AM
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 ) &amp;#0124; &amp;#0124; (ch == '_');
}

bool SupportsExtension( char const * name, char const * extStr = 0 )
{
if( !extStr ) {
extStr = glGetString( GL_EXTENSIONS );
}
if( !name &amp;#0124; &amp;#0124; !name[0] ) return false;
char const * found = strstr( ext, name );
if( !found ) return false;
char const * foundEnd = found + strlen( name );
if( found > ext &amp;&amp; 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 :-)

pbrown
10-24-2002, 05:55 PM
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. :-)

solarforge
10-24-2002, 07:00 PM
Originally posted by V-man:
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


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.

Humus
10-24-2002, 11:32 PM
Originally posted by jwatte:
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 &amp;&amp; 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 :-)

Bah, how about some short easy to read code? http://www.opengl.org/discussion_boards/ubb/smile.gif




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

while (str = strstr(str, extension)){
str += len;
if (*str == ' ' &amp;#0124; &amp;#0124; *str == '\0') return true;
}
return false;
}

Bob
10-25-2002, 02:26 AM
Is this some kind of shortest extensions checking code contest?



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

bakery2k
10-25-2002, 03:29 AM
Originally posted by solarforge:

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!)

[/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.

JML
10-25-2002, 05:55 AM
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.

GeoffStahl
10-25-2002, 07:16 AM
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.

zeckensack
10-25-2002, 10:12 AM
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.

Humus
10-25-2002, 10:28 AM
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.

V-man
10-25-2002, 11:20 AM
Originally posted by Humus:
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.

Good point, but that should only be an issue on beta drivers. Publicly released ones should be fixed up ... and if their not ... kaboom!

I'm currently using the very same method as zecken.
The way I did it is I created some global functions for extension groups. For example if you want multitexturing, I call

GetMultitexturingExtensions()

And it tries to get all the relevent function pointers and returns error flags.

V-man

zeckensack
10-25-2002, 11:29 AM
Originally posted by Humus:
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. Might be, I don't know.
EXT_texture_3d on a Geforce 2 could be one of these cases if glTexImage3DEXT is exported by the driver.
I didn't have to deal with these cases so far. I'll think about it http://www.opengl.org/discussion_boards/ubb/smile.gif

Oh, and if it's not working at all, why should it be in the export table? There may be cases like this but they're probably temporary solutions that get fixed with a driver revision. Which is exactly where the responsibility lies, I think.

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

WhatEver
10-25-2002, 12:01 PM
I made my post a little more clear

The only way this validator could fail is if an extension name is above 128 characters...and that will NEVER happen. The only thing this validator doesn't do is search for tabs, linefeeds and carriage returns. As far as I know the extensions are suppose to be seperated by single spaces ' ' not white space.



S3Dbool s3dValidateExtension(const S3Dchar* sext)
{
S3Dchar sNameString[128];
S3Duint Pos=0;

while(s3dParseUpToChar(sNameString, (S3Dchar*)glGetString(GL_EXTENSIONS), ' ', &amp;Pos))
{
if(strcmp(sext, sNameString)==0)
{
return true;
}
}

return false;
}

sNameString is where the extension name is stored. It's checked to see if it's matched with sext. sext is the extension name you provide.

If querying glGetString is slow, then my method is slow...oh well http://www.opengl.org/discussion_boards/ubb/smile.gif.

Der, I could pass the pointer returned by (S3Dchar*)glGetString(GL_EXTENSIONS) to a char data type pointer. In that case my validator would be full proof and fast.

[This message has been edited by WhatEver (edited 10-26-2002).]

[This message has been edited by WhatEver (edited 10-26-2002).]

jwatte
10-25-2002, 09:06 PM
Humus:

I initially wrote something very similar to your code, but then got paranoid about extensions that have some odd _PRE_-fix. You can easily add that by testing the character before the match, unless the match is the first character of the input string. Add these special cases and you end up with what I posted :-)

Also, whitespace means tab, return, space, horizontal tab and linefeed... unless by the ambiguous word "space" they mean literally the ASCII character with value 32 (decimal).

Tom Nuydens
10-25-2002, 10:27 PM
Originally posted by jwatte:
Also, whitespace means tab, return, space, horizontal tab and linefeed... unless by the ambiguous word "space" they mean literally the ASCII character with value 32 (decimal).

They don't. I've had problems with Wildcats that turned out to be due to newline characters in the extension string. In fact, they're the only cards I've ever encountered with more than one whitespace character between extensions and/or with whitespace at the start of the extension string.

They also expose the imaging subset as "ARB_imaging" instead of "GL_ARB_imaging", but I imagine not too many people are going to lose any sleep over that one http://www.opengl.org/discussion_boards/ubb/smile.gif

-- Tom

Humus
10-26-2002, 12:24 AM
Originally posted by zeckensack:
Oh, and if it's not working at all, why should it be in the export table?

Well, the driver team needs them for testings. The only really "safe" method is to check the extension string.

The way I do things is to have one huge function in a glExtensions.cpp file I share between projects that initalizes every extension I've decided to add to it. Like this:




.h file:
extern bool GL_EXT_fog_coord;

.cpp file:

bool GL_EXT_fog_coord = false;

...

if (GL_EXT_fog_coord = isExtensionSupported("GL_EXT_fog_coord")){
glFogCoordfEXT = (PFNGLFOGCOORDFEXTPROC) wglGetProcAddress("glFogCoordfEXT");
glFogCoorddEXT = (PFNGLFOGCOORDDEXTPROC) wglGetProcAddress("glFogCoorddEXT");
glFogCoordfvEXT = (PFNGLFOGCOORDFVEXTPROC) wglGetProcAddress("glFogCoordfvEXT");
glFogCoorddvEXT = (PFNGLFOGCOORDDVEXTPROC) wglGetProcAddress("glFogCoorddvEXT");
glFogCoordPointerEXT = (PFNGLFOGCOORDPOINTEREXTPROC) wglGetProcAddress("glFogCoordPointerEXT");
}

Humus
10-26-2002, 12:27 AM
Originally posted by jwatte:
Humus:

I initially wrote something very similar to your code, but then got paranoid about extensions that have some odd _PRE_-fix. You can easily add that by testing the character before the match, unless the match is the first character of the input string. Add these special cases and you end up with what I posted :-)

Hmm, that's true, but probably not very common though. Maybe if someone creates a GL_GL_EXT_blabla extensions or something it might fail.

zeckensack
10-26-2002, 03:37 AM
Hmm okay, let's not turn this into a "My ext loading code is bigger than yours" contest. Btw, mine handles leading spaces and multiple spaces, and can properly seperate GL_funky from GL_funky_too http://www.opengl.org/discussion_boards/ubb/biggrin.gif

*ahem*
The purpose of these snippets in the context of this thread would be to demonstrate that you can at least recognize and use exts without ever copying the extension string to another buffer. Which is why I personally don't mind big and littered extension lists. Shouldn't cause a clean app any trouble.

This of course kind of nullifies the point of removing extensions (or not introducing new core features as extensions).

No problem -> no solution required. At least that's how I feel about it.

jwatte
10-26-2002, 12:17 PM
> Oh, and if it's not working at all, why
> should it be in the export table?

Because most vendors write ONE GL driver for MANY different products. Suppose the GF2 and the GF3 both use the same OpenGL DLL. The export table clearly needs to contain all the GF3 functions, but the driver can choose to publish only extensions for what it wants to expose at run-time.

Some control panels even contain check boxes for which extensions to export (such as KTX_buffer_region).

V-man
10-26-2002, 08:29 PM
Originally posted by jwatte:
Some control panels even contain check boxes for which extensions to export (such as KTX_buffer_region).

That's probably because the driver needs to do some behind the scene job for such extensions, so it could be for efficiency or something.

Otherwise, there's no point in giving the option to swicth it off.

The question is, if it's not advertized in GL_EXTENSION, does GetProcAddress return a valid address. Is searching for a string really important if you *can* just use GetProcAddress?

V-man

mcraighead
10-26-2002, 08:55 PM
If it's not in the extensions string, USE AT YOUR OWN RISK.

If it's not there, we probably didn't intend to expose it.

You *must* check the extensions string to write a correct application.

- Matt

marcus256
10-29-2002, 02:38 PM
Originally posted by mcraighead:
You *must* check the extensions string to write a correct application.

How do you check for wglGetExtensionsStringEXT & wglGetExtensionsStringARB ?? I currently do it by checking if wglGetProcAddress returns NULL or not.

I know I'm lazy, but I also do this for wglSwapIntervalEXT. What are the chanses for my code failing if wglGetProcAddress("wglSwapIntervalEXT") returns a proper address, and I call the function?

Humus
10-29-2002, 03:29 PM
Originally posted by marcus256:
How do you check for wglGetExtensionsStringEXT & wglGetExtensionsStringARB ?? I currently do it by checking if wglGetProcAddress returns NULL or not.

I know I'm lazy, but I also do this for wglSwapIntervalEXT. What are the chanses for my code failing if wglGetProcAddress("wglSwapIntervalEXT") returns a proper address, and I call the function?



This is an exception from the rule, as stated by the spec:



Applications should call wglGetProcAddress to see whether or not wglGetExtensionsStringARB is supported


For other WGL extensions though you'll have to call wglGetExtensionsString and parse it like you'd do with normal extensions.

pbrown
10-29-2002, 04:55 PM
Originally posted by jwatte:
> Oh, and if it's not working at all, why
> should it be in the export table?

Because most vendors write ONE GL driver for MANY different products. Suppose the GF2 and the GF3 both use the same OpenGL DLL. The export table clearly needs to contain all the GF3 functions, but the driver can choose to publish only extensions for what it wants to expose at run-time.

Some control panels even contain check boxes for which extensions to export (such as KTX_buffer_region).

NVIDIA drivers will generally not expose extension functions through wglGetProcAddress() if the corresponding extenion is not supported, even if such functions are present (for other devices) in the unified driver. I wouldn't rely on that behavior, though.

GPSnoopy
10-30-2002, 02:29 AM
Vulpine has released a patch for their GLmark benchmarking utility that allows it to be compatible with the upcomming NV30. The NV30 specific update:
Extension Strings longer than 2048 Bytes are now allowed (required for NV30 compatibility)

from http://www.vulpine.de/demos_benchmark.html

http://www.opengl.org/discussion_boards/ubb/eek.gif http://www.opengl.org/discussion_boards/ubb/eek.gif http://www.opengl.org/discussion_boards/ubb/eek.gif

You can almost believe that it's a feature they added or something. Why didn't they just tell they fixed a mammoth bug in their app? http://www.opengl.org/discussion_boards/ubb/biggrin.gif
Tell me they didn't simply replaced "char [2048] by "char [4096]". http://www.opengl.org/discussion_boards/ubb/rolleyes.gif

mattc
10-30-2002, 04:23 PM
spot on, GPSnoopy http://www.opengl.org/discussion_boards/ubb/smile.gif lol http://www.opengl.org/discussion_boards/ubb/smile.gif lol http://www.opengl.org/discussion_boards/ubb/smile.gif