Re: pyopengl extension detection.

Roman Valov <[email protected]> Fri, 8 Nov 2013 18:13:53 +0400
Newsgroups gmane.comp.python.opengl.devel
Message-ID <CAELN+SS6CitxxQf0-crx0Ea-h9mppR8YSgAPvSZtSUzwLxQXxQ@mail.gmail.com>
--001a11c1ba042fe3fd04eaaaff65
Content-Type: multipart/alternative; boundary=001a11c1ba042fe3f804eaaaff63

--001a11c1ba042fe3f804eaaaff63
Content-Type: text/plain; charset=ISO-8859-1

Hello, Mike.


Here is a preview of patch for platform-specific extensions. It supports
only GLX platform,
since I want to get your review of my design decisions. Once it will be
done, I will update
the patch with WGL support and put stubs for other platforms.

So, each platform implementation should provide 'getExtensionsString'
method to list
available platform-specific extensions in space-separated string. Both, GLX
and WGL
ways provide this list in this form.

In case of GLX implementation definition of method is surrounded with
try-except
block, because code tries to import 'glXQueryExtensionsString' and
'glXGetCurrentDisplay'
functions from GL-dll and according to spec these functions are defined in
version
1.1 and 1.2 of GLX-spec respectively.

Thus in case GLX implementation doesn't provide a method for querying
extensions,
code will define a method returning empty string. Non-extensible and stub
platforms
should do the same.

Next, base platform implementation defines 'hasPlatformExtension' method
which
acts like 'extensions.hasGLExtension' function except it won't perform
logging. I was
trying to avoid platform-specific code and circular dependencies with
'OpenGL.platform'
in 'OpenGL.extensions' module, thus all code resides in 'OpenGL.platform'
sub-package.
However, cached 'contextdata' for 'GL_EXTENSIONS' will also be used for
platform-specific extensions.

Once notable difference between 'hasGLExtension' and 'hasPlatformExtension'
is that
buffer for extensions list is by default initialized with 'None' to
distinguish with '[]' which
means no extensions available.

In addition, I've removed one of calls to 'checkExtension' in
'constructFunction' method,
because it seems redundant for me. Fix me, if I wrong.


Best Regards, Roman.



On Mon, Nov 4, 2013 at 8:46 PM, Mike C. Fletcher <[email protected]>wrote:

> On 11/02/2013 10:11 AM, Roman Valov wrote:
>
>> Ok, Mike.. the actual question to you is in last paragraph.
>>
>>
>> Here is update with my review of the problem with wglSwapIntervalEXT and
>> wglGetSwapIntervalEXT.
>> Seems that problem is driven by two diffrent factors:
>>
>> 1) Wrapper code generator (gengl.py) doesn't set 'extension' parameter
>> for 'createBaseFunction'.
>>
>> Thus OpenGL/platform/baseplatform.py code tries to load extension
>> functions from platform.GL library
>> which actually doesn't have them in common case and as a result I've got
>> these functions unresolved.
>>
>> 2) BasePlatform.checkExtension code relies only on
>> glGetString(GL_EXTENSIONS).
>>
>> I've tested extension WGL_EXT_swap_control on NV and Intel gpu platforms.
>> In fact only
>> on NV platform this extension was listed in glGetString(GL_EXTENSIONS)
>> result. According
>> to specs:
>>
>> http://www.opengl.org/registry/specs/EXT/wgl_extensions_string.txt
>> http://www.opengl.org/registry/specs/ARB/wgl_extensions_string.txt
>> http://www.opengl.org/wiki/Load_OpenGL_Functions#
>> Platform-specific_Extensions
>>
>> one would to use wglGetExtensionsStringXXX to check for WGL extensions.
>> On both platforms I've used
>> required extension was listed in wglGetGetExtensionsString output. As I
>> see on GLX there is similar
>> functionality provided by glXQueryExtensionsString. Which also aren't
>> taken into account in PyOpenGL.
>>
>>
>>
>> So, my plan is firstly to fix gengl.py and later add method for
>> platform-specific extensions check.
>> But now I'm stuck with gengl.py doesn't produce the same _WGL_NV.py that
>> is commited to bzr.
>> Besides header file path in comments (which is minor issue), I see
>> whitespaces differences and
>> moreover, in myself-generated _WGL_NV.py there are no 'GLAPI' symbol.
>> Could you say anything
>> about that symbol? Was it added by hand or was it included in previous
>> versions of wglext.h?
>>
>
>
> gengl.py was probably last run many years ago now, and the versions of the
> underlying libraries you're using (basically pyglet) are likely different
> than the ones I used way back then.  GLAPI is basically a macro that marks
> a function for DLL export, it *shouldn't* affect anything in our wrappers.
>
> Note that I'm about 50% of the way through an API generator based on the
> Khronos XML API spec, i.e. generating the wrappers from the thing that
> defines these APIs formally (and which is used to generate the headers that
> gengl and get_gl_extensions are parsing). That *should* generate all of
> WGL, GLX, EGL, GL, and GLES in full, and should keep them up-to-date going
> forward in a robust and maintainable fashion.  I'll integrate your changes
> for wglGetExtensionsString and glXQueryExtensionsString when I get to the
> point of generating the WGL, GLX and EGL wrappers from the specs. The new
> generators won't actually alter the support code (e.g. platform), so a
> patch to those *should* carry across.
>
> I *wouldn't* suggest spending much time on fixing gengl.py based
> generation, because it has always proven rather fragile (which is why I
> don't use it for the core), even if it were working today, I'm unlikely to
> keep using it if I can use the XML registry to generate the functions.
>
> The WGL, GLX and the like extensions will be declared in the same manner
> as the GL ones, so you'll get the "extension" parameter set properly when
> regenerated.
>
> Hope that helps,
> Mike
>
>

--001a11c1ba042fe3f804eaaaff63
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Hello, Mike.<div><br></div><div><br></div><div>Here is a p=
review of patch for platform-specific extensions. It supports only GLX plat=
form,</div><div>since I want to get your review of my design decisions. Onc=
e it will be done, I will update</div>

<div>the patch with WGL support and put stubs for other platforms.</div><di=
v><br></div><div>So, each platform implementation should provide &#39;getEx=
tensionsString&#39; method to list=A0</div><div>available platform-specific=
 extensions in space-separated string. Both, GLX and WGL</div>

<div>ways provide this list in this form.</div><div><br></div><div>In case =
of GLX implementation definition of method is surrounded with try-except</d=
iv><div>block, because code tries to import &#39;glXQueryExtensionsString&#=
39; and &#39;glXGetCurrentDisplay&#39;</div>

<div>functions from GL-dll and according to spec these functions are define=
d in version</div><div>1.1 and 1.2 of GLX-spec respectively.</div><div><br>=
</div><div>Thus in case GLX implementation doesn&#39;t provide a method for=
 querying extensions,</div>

<div>code will define a method returning empty string. Non-extensible and s=
tub platforms</div><div>should do the same.</div><div><br></div><div>Next, =
base platform implementation defines &#39;hasPlatformExtension&#39; method =
which</div>

<div>acts like &#39;extensions.hasGLExtension&#39; function except it won&#=
39;t perform logging. I was</div><div>trying to avoid platform-specific cod=
e and circular dependencies with &#39;OpenGL.platform&#39;</div><div>in &#3=
9;OpenGL.extensions&#39; module, thus all code resides in &#39;OpenGL.platf=
orm&#39; sub-package.</div>

<div>However, cached &#39;contextdata&#39; for &#39;GL_EXTENSIONS&#39; will=
 also be used for</div><div>platform-specific extensions.</div><div><br></d=
iv><div>Once notable difference between &#39;hasGLExtension&#39; and &#39;h=
asPlatformExtension&#39; is that</div>

<div>buffer for extensions list is by default initialized with &#39;None&#3=
9; to distinguish with &#39;[]&#39; which</div><div>means no extensions ava=
ilable.</div><div><br></div><div>In addition, I&#39;ve removed one of calls=
 to &#39;checkExtension&#39; in &#39;constructFunction&#39; method,</div>

<div>because it seems redundant for me. Fix me, if I wrong.</div><div><br><=
/div><div><br></div><div>Best Regards, Roman.</div><div><br></div><div clas=
s=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On Mon, Nov 4, 2013 at=
 8:46 PM, Mike C. Fletcher <span dir=3D"ltr">&lt;<a href=3D"mailto:mcfletch=
@vrplumber.com" target=3D"_blank">[email protected]</a>&gt;</span> wro=
te:<br>

<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">On 1=
1/02/2013 10:11 AM, Roman Valov wrote:<br>
<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p=
x #ccc solid;padding-left:1ex">
Ok, Mike.. the actual question to you is in last paragraph.<br>
<br>
<br>
Here is update with my review of the problem with wglSwapIntervalEXT and wg=
lGetSwapIntervalEXT.<br>
Seems that problem is driven by two diffrent factors:<br>
<br>
1) Wrapper code generator (gengl.py) doesn&#39;t set &#39;extension&#39; pa=
rameter for &#39;createBaseFunction&#39;.<br>
<br>
Thus OpenGL/platform/baseplatform.<u></u>py code tries to load extension fu=
nctions from platform.GL library<br>
which actually doesn&#39;t have them in common case and as a result I&#39;v=
e got these functions unresolved.<br>
<br>
2) BasePlatform.checkExtension code relies only on glGetString(GL_EXTENSION=
S).<br>
<br>
I&#39;ve tested extension WGL_EXT_swap_control on NV and Intel gpu platform=
s. In fact only<br>
on NV platform this extension was listed in glGetString(GL_EXTENSIONS) resu=
lt. According<br>
to specs:<br>
<br>
<a href=3D"http://www.opengl.org/registry/specs/EXT/wgl_extensions_string.t=
xt" target=3D"_blank">http://www.opengl.org/<u></u>registry/specs/EXT/wgl_<=
u></u>extensions_string.txt</a><br>
<a href=3D"http://www.opengl.org/registry/specs/ARB/wgl_extensions_string.t=
xt" target=3D"_blank">http://www.opengl.org/<u></u>registry/specs/ARB/wgl_<=
u></u>extensions_string.txt</a><br>
<a href=3D"http://www.opengl.org/wiki/Load_OpenGL_Functions#Platform-specif=
ic_Extensions" target=3D"_blank">http://www.opengl.org/wiki/<u></u>Load_Ope=
nGL_Functions#<u></u>Platform-specific_Extensions</a><br>
<br>
one would to use wglGetExtensionsStringXXX to check for WGL extensions. On =
both platforms I&#39;ve used<br>
required extension was listed in wglGetGetExtensionsString output. As I see=
 on GLX there is similar<br>
functionality provided by glXQueryExtensionsString. Which also aren&#39;t t=
aken into account in PyOpenGL.<br>
<br>
<br>
<br>
So, my plan is firstly to fix gengl.py and later add method for platform-sp=
ecific extensions check.<br>
But now I&#39;m stuck with gengl.py doesn&#39;t produce the same _WGL_NV.py=
 that is commited to bzr.<br>
Besides header file path in comments (which is minor issue), I see whitespa=
ces differences and<br>
moreover, in myself-generated _WGL_NV.py there are no &#39;GLAPI&#39; symbo=
l. Could you say anything<br>
about that symbol? Was it added by hand or was it included in previous vers=
ions of wglext.h?<br>
</blockquote>
<br>
<br></div></div>
gengl.py was probably last run many years ago now, and the versions of the =
underlying libraries you&#39;re using (basically pyglet) are likely differe=
nt than the ones I used way back then. =A0GLAPI is basically a macro that m=
arks a function for DLL export, it *shouldn&#39;t* affect anything in our w=
rappers.<br>


<br>
Note that I&#39;m about 50% of the way through an API generator based on th=
e Khronos XML API spec, i.e. generating the wrappers from the thing that de=
fines these APIs formally (and which is used to generate the headers that g=
engl and get_gl_extensions are parsing). That *should* generate all of WGL,=
 GLX, EGL, GL, and GLES in full, and should keep them up-to-date going forw=
ard in a robust and maintainable fashion. =A0I&#39;ll integrate your change=
s for wglGetExtensionsString and glXQueryExtensionsString when I get to the=
 point of generating the WGL, GLX and EGL wrappers from the specs. The new =
generators won&#39;t actually alter the support code (e.g. platform), so a =
patch to those *should* carry across.<br>


<br>
I *wouldn&#39;t* suggest spending much time on fixing gengl.py based genera=
tion, because it has always proven rather fragile (which is why I don&#39;t=
 use it for the core), even if it were working today, I&#39;m unlikely to k=
eep using it if I can use the XML registry to generate the functions.<br>


<br>
The WGL, GLX and the like extensions will be declared in the same manner as=
 the GL ones, so you&#39;ll get the &quot;extension&quot; parameter set pro=
perly when regenerated.<br>
<br>
Hope that helps,<br>
Mike<br>
<br>
</blockquote></div><br></div></div>

--001a11c1ba042fe3f804eaaaff63--
--001a11c1ba042fe3fd04eaaaff65
Content-Type: text/x-patch; charset=US-ASCII; 
	name="pyopengl-platform-specific-extensions.r00.diff"
Content-Disposition: attachment; 
	filename="pyopengl-platform-specific-extensions.r00.diff"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_hnrgqrmh0

PT09IG1vZGlmaWVkIGZpbGUgJ09wZW5HTC9wbGF0Zm9ybS9iYXNlcGxhdGZvcm0ucHknCi0tLSBP
cGVuR0wvcGxhdGZvcm0vYmFzZXBsYXRmb3JtLnB5CTIwMTMtMDItMDEgMDQ6NTc6NDkgKzAwMDAK
KysrIE9wZW5HTC9wbGF0Zm9ybS9iYXNlcGxhdGZvcm0ucHkJMjAxMy0xMS0wOCAxMzoyNDoyNiAr
MDAwMApAQCAtNzgsNiArNzgsNyBAQAogICAgIERFRkFVTFRfRlVOQ1RJT05fVFlQRSA9IE5vbmUK
ICAgICBHTFVUX0dVQVJEX0NBTExCQUNLUyA9IEZhbHNlCiAgICAgRVhURU5TSU9OU19VU0VfQkFT
RV9GVU5DVElPTlMgPSBGYWxzZQorICAgIFBMQVRGT1JNX1NQRUNJRklDX0VYVEVOU0lPTlMgPSBO
b25lCiAgICAgCiAgICAgZGVmIGluc3RhbGwoIHNlbGYsIG5hbWVzcGFjZSApOgogICAgICAgICAi
IiJJbnN0YWxsIHRoaXMgcGxhdGZvcm0gaW5zdGFuY2UgaW50byB0aGUgcGxhdGZvcm0gbW9kdWxl
IiIiCkBAIC0xMzUsMjMgKzEzNiwxOSBAQAogICAgICAgICBpZiBleHRlbnNpb24gPT0gJ0dMX1ZF
UlNJT05fR0xfMV8xJzoKICAgICAgICAgICAgIGV4dGVuc2lvbiA9IE5vbmUKICAgICAgICAgaWYg
ZXh0ZW5zaW9uIGFuZCBub3Qgc2VsZi5jaGVja0V4dGVuc2lvbiggZXh0ZW5zaW9uICk6Ci0gICAg
ICAgICAgICByYWlzZSBBdHRyaWJ1dGVFcnJvciggIiIiRXh0ZW5zaW9uIG5vdCBhdmFpbGFibGUi
IiIgKQorICAgICAgICAgICAgcmFpc2UgQXR0cmlidXRlRXJyb3IoICIiIk5vIGV4dGVuc2lvbiAl
ciIiIiUoZXh0ZW5zaW9uLCkpCiAgICAgICAgIGFyZ1R5cGVzID0gWyBzZWxmLmZpbmFsQXJnVHlw
ZSggdCApIGZvciB0IGluIGFyZ1R5cGVzIF0KICAgICAgICAgaWYgZXh0ZW5zaW9uIGFuZCBub3Qg
c2VsZi5FWFRFTlNJT05TX1VTRV9CQVNFX0ZVTkNUSU9OUzoKLSAgICAgICAgICAgICMgd2hhdCBh
Ym91dCB0aGUgVkVSU0lPTiB2YWx1ZXM/Pz8KLSAgICAgICAgICAgIGlmIHNlbGYuY2hlY2tFeHRl
bnNpb24oIGV4dGVuc2lvbiApOgotICAgICAgICAgICAgICAgIHBvaW50ZXIgPSBzZWxmLmdldEV4
dGVuc2lvblByb2NlZHVyZSggYXNfOF9iaXQoZnVuY3Rpb25OYW1lKSApCi0gICAgICAgICAgICAg
ICAgaWYgcG9pbnRlcjoKLSAgICAgICAgICAgICAgICAgICAgZnVuYyA9IHNlbGYuZnVuY3Rpb25U
eXBlRm9yKCBkbGwgKSgKLSAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdFR5cGUsCi0gICAg
ICAgICAgICAgICAgICAgICAgICAqYXJnVHlwZXMKLSAgICAgICAgICAgICAgICAgICAgKSgKLSAg
ICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXIKLSAgICAgICAgICAgICAgICAgICAgKQotICAg
ICAgICAgICAgICAgIGVsc2U6Ci0gICAgICAgICAgICAgICAgICAgIHJhaXNlIEF0dHJpYnV0ZUVy
cm9yKCAiIiJFeHRlbnNpb24gJXIgYXZhaWxhYmxlLCBidXQgbm8gcG9pbnRlciBmb3IgZnVuY3Rp
b24gJXIiIiIlKGV4dGVuc2lvbixmdW5jdGlvbk5hbWUpKQorICAgICAgICAgICAgcG9pbnRlciA9
IHNlbGYuZ2V0RXh0ZW5zaW9uUHJvY2VkdXJlKCBhc184X2JpdChmdW5jdGlvbk5hbWUpICkKKyAg
ICAgICAgICAgIGlmIHBvaW50ZXI6CisgICAgICAgICAgICAgICAgZnVuYyA9IHNlbGYuZnVuY3Rp
b25UeXBlRm9yKCBkbGwgKSgKKyAgICAgICAgICAgICAgICAgICAgcmVzdWx0VHlwZSwKKyAgICAg
ICAgICAgICAgICAgICAgKmFyZ1R5cGVzCisgICAgICAgICAgICAgICAgKSgKKyAgICAgICAgICAg
ICAgICAgICAgcG9pbnRlcgorICAgICAgICAgICAgICAgICkKICAgICAgICAgICAgIGVsc2U6Ci0g
ICAgICAgICAgICAgICAgcmFpc2UgQXR0cmlidXRlRXJyb3IoICIiIk5vIGV4dGVuc2lvbiAlciIi
IiUoZXh0ZW5zaW9uLCkpCisgICAgICAgICAgICAgICAgcmFpc2UgQXR0cmlidXRlRXJyb3IoICIi
IkV4dGVuc2lvbiAlciBhdmFpbGFibGUsIGJ1dCBubyBwb2ludGVyIGZvciBmdW5jdGlvbiAlciIi
IiUoZXh0ZW5zaW9uLGZ1bmN0aW9uTmFtZSkpCiAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICBm
dW5jID0gY3R5cGVzbG9hZGVyLmJ1aWxkRnVuY3Rpb24oCiAgICAgICAgICAgICAgICAgc2VsZi5m
dW5jdGlvblR5cGVGb3IoIGRsbCApKApAQCAtMjMzLDYgKzIzMCwxMSBAQAogICAgICAgICAgICAg
aWYgbW9kdWxlOgogICAgICAgICAgICAgICAgIHJlc3VsdC5fX21vZHVsZV9fID0gbW9kdWxlCiAg
ICAgICAgIHJldHVybiByZXN1bHQKKyAgICBkZWYgaGFzUGxhdGZvcm1FeHRlbnNpb24oIHNlbGYs
IHNwZWNpZmllciApOgorICAgICAgICBpZiBzZWxmLlBMQVRGT1JNX1NQRUNJRklDX0VYVEVOU0lP
TlMgaXMgTm9uZToKKyAgICAgICAgICAgIHNlbGYuUExBVEZPUk1fU1BFQ0lGSUNfRVhURU5TSU9O
UyA9IHNlbGYuZ2V0RXh0ZW5zaW9uc1N0cmluZygpLnNwbGl0KCkKKyAgICAgICAgcmVzdWx0ID0g
c3BlY2lmaWVyIGluIHNlbGYuUExBVEZPUk1fU1BFQ0lGSUNfRVhURU5TSU9OUworICAgICAgICBy
ZXR1cm4gcmVzdWx0CiAgICAgZGVmIGNoZWNrRXh0ZW5zaW9uKCBzZWxmLCBuYW1lICk6CiAgICAg
ICAgICIiIkNoZWNrIHdoZXRoZXIgdGhlIGdpdmVuIGV4dGVuc2lvbiBpcyBzdXBwb3J0ZWQgYnkg
Y3VycmVudCBjb250ZXh0IiIiCiAgICAgICAgIGlmIG5vdCBuYW1lIG9yIG5hbWUgPT0gJ0dMX1ZF
UlNJT05fR0xfMV8xJzoKQEAgLTI1MCw3ICsyNTIsNyBAQAogICAgICAgICAgICAgY3VycmVudCA9
IHNldC5nZXQoIG5hbWUgKQogICAgICAgICAgICAgaWYgY3VycmVudCBpcyBOb25lOgogICAgICAg
ICAgICAgICAgIGZyb20gT3BlbkdMIGltcG9ydCBleHRlbnNpb25zCi0gICAgICAgICAgICAgICAg
cmVzdWx0ID0gZXh0ZW5zaW9ucy5oYXNHTEV4dGVuc2lvbiggbmFtZSApCisgICAgICAgICAgICAg
ICAgcmVzdWx0ID0gc2VsZi5oYXNQbGF0Zm9ybUV4dGVuc2lvbiggbmFtZSApIG9yIGV4dGVuc2lv
bnMuaGFzR0xFeHRlbnNpb24oIG5hbWUgKQogICAgICAgICAgICAgICAgIHNldFtuYW1lXSA9IHJl
c3VsdCAKICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0CiAgICAgICAgICAgICByZXR1cm4g
Y3VycmVudAoKPT09IG1vZGlmaWVkIGZpbGUgJ09wZW5HTC9wbGF0Zm9ybS9nbHgucHknCi0tLSBP
cGVuR0wvcGxhdGZvcm0vZ2x4LnB5CTIwMTItMDktMDEgMDU6MzU6MjcgKzAwMDAKKysrIE9wZW5H
TC9wbGF0Zm9ybS9nbHgucHkJMjAxMy0xMS0wOCAxMzoxNjo0NSArMDAwMApAQCAtNzMsMyArNzMs
MTcgQEAKICAgICAgICAgcmV0dXJuIGN0eXBlcy5jX3ZvaWRfcChjdHlwZXMuYWRkcmVzc29mKHBv
aW50ZXIpKQogICAgIAogICAgIHNhZmVHZXRFcnJvciA9IHN0YXRpY21ldGhvZCggT3BlbkdMLmds
R2V0RXJyb3IgKQorCisgICAgdHJ5OgorICAgICAgICBnbFhRdWVyeUV4dGVuc2lvbnNTdHJpbmcg
PSBHTC5nbFhRdWVyeUV4dGVuc2lvbnNTdHJpbmcKKyAgICAgICAgZ2xYUXVlcnlFeHRlbnNpb25z
U3RyaW5nLnJlc3R5cGUgPSBjdHlwZXMuY19jaGFyX3AKKworICAgICAgICBnbFhHZXRDdXJyZW50
RGlzcGxheSA9IEdMLmdsWEdldEN1cnJlbnREaXNwbGF5CisgICAgICAgIGdsWEdldEN1cnJlbnRE
aXNwbGF5LnJlc3R5cGUgPSBjdHlwZXMuY192b2lkX3AKKworICAgICAgICBkZWYgZ2V0RXh0ZW5z
aW9uc1N0cmluZyhzZWxmKToKKyAgICAgICAgICAgIHJldHVybiBzZWxmLmdsWFF1ZXJ5RXh0ZW5z
aW9uc1N0cmluZyhzZWxmLmdsWEdldEN1cnJlbnREaXNwbGF5KCksIGN0eXBlcy5jX2ludCgwKSkK
KyAgICBleGNlcHQ6CisgICAgICAgIGRlZiBnZXRFeHRlbnNpb25zU3RyaW5nKHNlbGYpOgorICAg
ICAgICAgICAgcmV0dXJuICcnCisKCg==
--001a11c1ba042fe3fd04eaaaff65
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

------------------------------------------------------------------------------
November Webinars for C, C++, Fortran Developers
Accelerate application performance with scalable programming models. Explore
techniques for threading, error checking, porting, and tuning. Get the most 
from the latest Intel processors and coprocessors. See abstracts and register
http://pubads.g.doubleclick.net/gampad/clk?id=60136231&iu=/4140/ostg.clktrk
--001a11c1ba042fe3fd04eaaaff65
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
PyOpenGL Homepage
http://pyopengl.sourceforge.net
_______________________________________________
PyOpenGL-Devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pyopengl-devel

--001a11c1ba042fe3fd04eaaaff65--