| <chapter id="opengl"> | |
| <title>Wine and OpenGL</title> | |
| <para> | |
| Written by &name-lionel-ulmer; <email>&email-lionel-ulmer;</email>, | |
| last modification : 2000/06/13 | |
| </para> | |
| <para> | |
| (Extracted from <filename>wine/documentation/opengl</filename>) | |
| </para> | |
| <sect1 id="opengl-required"> | |
| <title>What is needed to have OpenGL support in Wine</title> | |
| <para> | |
| Basically, if you have a Linux OpenGL ABI compliant libGL | |
| (<ulink url="http://oss.sgi.com/projects/ogl-sample/ABI/"> | |
| http://oss.sgi.com/projects/ogl-sample/ABI/</ulink>) | |
| installed on your computer, you should everything that is | |
| needed. | |
| </para> | |
| <para> | |
| To be more clear, I will detail one step after another what | |
| the <command>configure</command> script checks. | |
| </para> | |
| <para> | |
| If, after Wine compiles, OpenGL support is not compiled in, | |
| you can always check <filename>config.log</filename> to see | |
| which of the following points failed. | |
| </para> | |
| <sect2> | |
| <title>Header files</title> | |
| <para> | |
| The needed header files to build OpenGL support in Wine are : | |
| </para> | |
| <variablelist> | |
| <varlistentry> | |
| <term><filename>gl.h:</filename></term> | |
| <listitem> | |
| <para>the definition of all OpenGL core functions, types and enumerants</para> | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><filename>glx.h:</filename></term> | |
| <listitem> | |
| <para>how OpenGL integrates in the X Window environment</para> | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><filename>glext.h:</filename></term> | |
| <listitem> | |
| <para>the list of all registered OpenGL extensions</para> | |
| </listitem> | |
| </varlistentry> | |
| </variablelist> | |
| <para> | |
| The latter file (<filename>glext.h</filename>) is, as of | |
| now, not necessary to build Wine. But as this file can be | |
| easily obtained from SGI | |
| (<ulink url="http://oss.sgi.com/projects/ogl-sample/ABI/glext.h"> | |
| http://oss.sgi.com/projects/ogl-sample/ABI/glext.h</ulink>), | |
| and that all OpenGL should provide one, I decided to keep it here. | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title>OpenGL library thread-safety</title> | |
| <para> | |
| After that, the script checks if the OpenGL library relies | |
| or not on the pthread library to provide thread safety (most | |
| 'modern' OpenGL libraries do). | |
| </para> | |
| <para> | |
| If the OpenGL library explicitely links in libpthread (you | |
| can check it with a <command>ldd libGL.so</command>), you | |
| need to force OpenGL support by starting | |
| <command>configure</command> with the | |
| <parameter>--enable-opengl</parameter> flag. | |
| </para> | |
| <para> | |
| The reason to this is that Wine contains some hacks done by | |
| Ove to cohabit with pthread that are known to work well in | |
| most of the cases (glibc 2.1.x). On the other hand, we never | |
| got Wine to work with glibc 2.0.6. Thus, I deemed preferable | |
| to play it safe : by default, I suppose that the hack won't | |
| work and that it's the user's responsability to enable it. | |
| </para> | |
| <para> | |
| Anyway, it should be pretty safe to build with | |
| <parameter>--enable-opengl</parameter>. | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title>OpenGL library itself</title> | |
| <para> | |
| To check for the presence of 'libGL' on the system, the | |
| script checks if it defines the | |
| <function>glXCreateContext</function> function. There should | |
| be no problem here. | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title>glXGetProcAddressARB function</title> | |
| <para> | |
| The core of Wine's OpenGL implementation (at least for all | |
| extensions) is the <function>glXGetProcAddressARB</function> | |
| function. Your OpenGL library needs to have this function | |
| defined for Wine to be able to support OpenGL. | |
| </para> | |
| <para> | |
| If your library does not provide it, you are out of luck. | |
| </para> | |
| <note> | |
| <para> | |
| this is not completely true as one could rewrite a | |
| <function>glXGetProcAddressARB</function> replacement | |
| using <function>dlopen</function> and friends, but well, | |
| telling people to upgrade is easier :-). | |
| </para> | |
| </note> | |
| </sect2> | |
| </sect1> | |
| <sect1 id="opengl-configure"> | |
| <title>How to configure</title> | |
| <para> | |
| Configuration is quite easy : once OpenGL support has been | |
| built in Wine, this internal OpenGL driver will be used each | |
| time an application tries to load | |
| <filename>opengl32.dll</filename>. | |
| </para> | |
| <para> | |
| Due to restrictions (that do not exist in Windows) on OpenGL | |
| contexts, if you want to prevent the screen to flicker when | |
| using OpenGL applications (all games are using double-buffered | |
| contexts), you need to set the following option in your | |
| <filename>~/.wine/config</filename> file | |
| in the [x11drv] section : | |
| </para> | |
| <programlisting> | |
| DesktopDoubleBuffered = Y | |
| </programlisting> | |
| <para> | |
| and to run Wine with the <parameter>--desktop</parameter> | |
| option. | |
| </para> | |
| </sect1> | |
| <sect1 id="opengl-works"> | |
| <title>How it all works</title> | |
| <para> | |
| The core OpenGL function calls are the same between Windows | |
| and Linux. So what is the difficulty to support it in Wine ? | |
| Well, there are two different problems : | |
| </para> | |
| <orderedlist> | |
| <listitem> | |
| <para> | |
| the interface to the windowing system is different for | |
| each OS. It's called 'GLX' for Linux (well, for X Window) | |
| and 'wgl' for Windows. Thus, one need first to emulate one | |
| (wgl) with the other (GLX). | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| the calling convention between Windows (the 'Pascal' | |
| convention or 'stdcall') is different from the one used on | |
| Linux (the 'C' convention or 'cdecl'). This means that | |
| each call to an OpenGL function must be 'translated' and | |
| cannot be used directly by the Windows program. | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| <para> | |
| Add to this some braindead programs (using GL calls without | |
| setting-up a context or deleting three time the same context) | |
| and you have still some work to do :-) | |
| </para> | |
| <sect2> | |
| <title>The Windowing system integration</title> | |
| <para> | |
| This integration is done at two levels : | |
| </para> | |
| <orderedlist> | |
| <listitem> | |
| <para> | |
| At GDI level for all pixel format selection routines (ie | |
| choosing if one wants a depth / alpha buffer, the size | |
| of these buffers, ...) and to do the 'page flipping' in | |
| double buffer mode. This is implemented in | |
| <filename>graphics/x11drv/opengl.c</filename> (all these | |
| functions are part of Wine's graphic driver function | |
| pointer table and thus could be reimplented if ever Wine | |
| works on another Windowing system than X). | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| In the <filename>OpenGL32.DLL</filename> itself for all | |
| other functionalities (context creation / deletion, | |
| querying of extension functions, ...). This is done in | |
| <filename>dlls/opengl32/wgl.c</filename>. | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| </sect2> | |
| <sect2> | |
| <title>The thunks</title> | |
| <para> | |
| The thunks are the Wine code that does the calling | |
| convention translation and they are auto-generated by a Perl | |
| script. In Wine's CVS tree, these thunks are already | |
| generated for you. Now, if you want to do it yourself, there | |
| is how it all works.... | |
| </para> | |
| <para> | |
| The script is located in <filename>dlls/opengl32</filename> | |
| and is called <command>make_opengl</command>. It requires | |
| Perl5 to work and takes two arguments : | |
| </para> | |
| <orderedlist> | |
| <listitem> | |
| <para> | |
| The first is the path to the OpenGL registry. Now, you | |
| will all ask 'but what is the OpenGL registry ?' :-) | |
| Well, it's part of the OpenGL sample implementation | |
| source tree from SGI (more informations at this URL : | |
| <ulink url="http://oss.sgi.com/projects/ogl-sample/"> | |
| http://oss.sgi.com/projects/ogl-sample/</ulink>. | |
| </para> | |
| <para> | |
| To summarize, these files contain human-readable but | |
| easily parsed information on ALL OpenGL core functions | |
| and ALL registered extensions (for example the | |
| prototype, the OpenGL version, ...). | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| the second is the OpenGL version to 'simulate'. This | |
| fixes the list of functions that the Windows application | |
| can link directly to without having to query them from | |
| the OpenGL driver. Windows is based, for now, on OpenGL | |
| 1.1, but the thunks that are in the CVS tree are | |
| generated for OpenGL 1.2. | |
| </para> | |
| <para> | |
| This option can have three values: | |
| <literal>1.0</literal>, <literal>1.1</literal> and | |
| <literal>1.2</literal>. | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| <para> | |
| This script generates three files : | |
| </para> | |
| <orderedlist> | |
| <listitem> | |
| <para> | |
| <filename>opengl32.spec</filename> gives Wine's linker | |
| the signature of all function in the | |
| <filename>OpenGL32.DLL</filename> library so that the | |
| application can link them. Only 'core' functions are | |
| listed here. | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| <filename>opengl_norm.c</filename> contains all the | |
| thunks for the 'core' functions. Your OpenGL library | |
| must provide ALL the function used in this file as these | |
| are not queried at run time. | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| <filename>opengl_ext.c</filename> contains all the | |
| functions that are not part of the 'core' functions. | |
| Contrary to the thunks in | |
| <filename>opengl_norm.c</filename>, these functions do | |
| not depend at all on what your libGL provides. | |
| </para> | |
| <para> | |
| In fact, before using one of these thunks, the Windows | |
| program first needs to 'query' the function pointer. At | |
| this point, the corresponding thunk is useless. But as | |
| we first query the same function in libGL and store the | |
| returned function pointer in the thunk, the latter | |
| becomes functional. | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| </sect2> | |
| </sect1> | |
| <sect1 id="opengl-problems"> | |
| <title>Known problems - shortcomings</title> | |
| <sect2> | |
| <title>Missing GLU32.DLL</title> | |
| <para> | |
| GLU is a library that is layered upon OpenGL. There is a | |
| 100% correspondence between the | |
| <filename>libGLU.so</filename> that is used on Linux and | |
| <filename>GLU32.DLL</filename>. | |
| </para> | |
| <para> | |
| As for the moment, I did not create a set of thunks to support this | |
| library natively in Wine (it would easy to do, but I am waiting for | |
| a better solution than adding another autogenerated thunk file), you | |
| can always download anywhere on the net (it's free) a | |
| <filename>GLU32.DLL</filename> file (by browsing, for example, | |
| <ulink url="http://ftpsearch.lycos.com/"> | |
| http://ftpsearch.lycos.com/</ulink>). | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title>OpenGL not detected at configure time</title> | |
| <para> | |
| See section (I) for a detailed explanation of the | |
| <filename>configure</filename> requirements. | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title>When running an OpenGL application, the screen flickers</title> | |
| <para> | |
| See section (II) for how to create the context | |
| double-buffered and thus preventing this flicker effect. | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title>Wine gives me the following error message : </title> | |
| <screen> | |
| Extension defined in the OpenGL library but NOT in opengl_ext.c... | |
| Please report (&email-lionel-ulmer;) ! | |
| </screen> | |
| <para> | |
| This means that the extension requested by the application | |
| is found in the libGL used by Linux (ie the call to | |
| <function>glXGetProcAddressARB</function> returns a | |
| non-<constant>NULL</constant> pointer) but that this string | |
| was NOT found in Wine's extension registry. | |
| </para> | |
| <para> | |
| This can come from two causes : | |
| </para> | |
| <orderedlist> | |
| <listitem> | |
| <para> | |
| The <filename>opengl_ext.c</filename> file is too old | |
| and needs to be generated again. | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| Use of obsolete extensions that are not supported | |
| anymore by SGI or of 'private' extensions that are not | |
| registered. An example of the former are | |
| <function>glMTexCoord2fSGIS</function> and | |
| <function>glSelectTextureSGIS</function> as used by | |
| Quake 2 (and apparently also by old versions of Half | |
| Life). If documentation can be found on these functions, | |
| they can be added to Wine's extension set. | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| <para> | |
| If you have this, run with <parameter>--debugmsg | |
| +opengl</parameter> and send me | |
| <email>&email-lionel-ulmer;</email> the TRACE. | |
| </para> | |
| </sect2> | |
| <sect2> | |
| <title><filename>libopengl32.so</filename> is built but it is still not working</title> | |
| <para> | |
| This may be caused by some missing functions required by | |
| <filename>opengl_norm.c</filename> but that your Linux | |
| OpenGL library does not provide. | |
| </para> | |
| <para> | |
| To check for this, do the following steps : | |
| </para> | |
| <orderedlist> | |
| <listitem> | |
| <para> | |
| create a dummy <filename>.c</filename> file : | |
| </para> | |
| <programlisting> | |
| int main(void) { | |
| return 0; | |
| } | |
| </programlisting> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| try to compile it by linking both libwine and | |
| libopengl32 (this command line supposes that you | |
| installed the Wine libraries in | |
| <filename>/usr/local/lib</filename>, YMMV) : | |
| </para> | |
| <programlisting> | |
| gcc dummy.c -L/usr/local/lib -lwine -lopengl32 | |
| </programlisting> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| if it works, the problem is somewhere else (and you can | |
| send me an email). If not, you could re-generate the | |
| thunk files for OpenGL 1.1 for example (and send me your | |
| OpenGL version so that this problem can be detected at | |
| configure time). | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| </sect2> | |
| </sect1> | |
| </chapter> | |
| <!-- Keep this comment at the end of the file | |
| Local variables: | |
| mode: sgml | |
| sgml-parent-document:("wine-doc.sgml" "set" "book" "part" "chapter" "") | |
| End: | |
| --> |