Hello all,
I'm trying to integrate my program into Wine source and having some difficulties with doing OpenGL calls. Namely, when I compile the program with mingw and with winegcc, it works flawlessly. But when I integrate it into Wine source tree (taking regedit as an example), stack appears smashed after OpenGL calls.
Here's what my command line looks like with winegcc (written by me manually):
# compilation winegcc -c wgl.c -o wgl.o -g -m32 -municode -DUNICODE -D_UNICODE -g # linking winegcc main.o wgl.o d3d8.o d3d9.o texture.o common.o demo-res.o -lopengl32 -ld3d8 -ld3d9 -ld3dx9 -lgdi32 -lgdiplus -lglu32 -lole32 -lshell32 -lmsvcrt -o 3d-demo.exe -g -m32 -municode
And the function where the crash happens looks like:
00012839 <initLightAndMaterial>: 12839: 55 push ebp 1283a: 89 e5 mov ebp,esp 1283c: 53 push ebx 1283d: 83 ec 24 sub esp,0x24 12840: e8 02 f1 ff ff call 11947 <__i686.get_pc_thunk.bx> 12845: 81 c3 17 5f 00 00 add ebx,0x5f17 1284b: b8 00 00 00 00 mov eax,0x0 12850: 89 45 e8 mov DWORD PTR [ebp-0x18],eax 12853: b8 00 00 00 00 mov eax,0x0 12858: 89 45 ec mov DWORD PTR [ebp-0x14],eax 1285b: b8 00 00 00 00 mov eax,0x0 12860: 89 45 f0 mov DWORD PTR [ebp-0x10],eax 12863: b8 00 00 80 3f mov eax,0x3f800000 12868: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 1286b: 8d 45 e8 lea eax,[ebp-0x18] 1286e: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 12872: c7 04 24 53 0b 00 00 mov DWORD PTR [esp],0xb53 12879: e8 92 f1 ff ff call 11a10 <glLightModelfv> 1287e: 83 ec 08 sub esp,0x8 12881: 8b 5d fc mov ebx,DWORD PTR [ebp-0x4] 12884: c9 leave 12885: c3 ret
And here's the command from Wine tree (generated by its build system):
# compilation /usr/lib/ccache/gcc-4.5 -c -o wgl.o wgl.c -I. -I../../include -I../../include/msvcrt -D__WINESRC__ -D_REENTRANT -fPIC \ -fno-builtin -Wall -pipe -fno-strict-aliasing -Wdeclaration-after-statement -Wempty-body \ -Wignored-qualifiers -Wstrict-prototypes -Wtype-limits -Wvla -Wwrite-strings -Wpointer-arith \ -Wlogical-op -gdwarf-2 -gstrict-dwarf -fno-omit-frame-pointer -g # linking ../../tools/winegcc/winegcc -o 3d-demo.exe.so -B../../tools/winebuild -fasynchronous-unwind-tables -mwindows \ -municode -mno-cygwin d3d8.o d3d9.o wgl.o main.o common.o texture.o demo.res -luser32 -lgdi32 \ -lgdiplus -lopengl32 -lglu32 -ld3d8 -ld3d9 -ld3dx9 -lole32 -lshell32 -lmsvcrt \ ../../libs/port/libwine_port.a
And the resulting function looks like
00014f8e <initLightAndMaterial>: 14f8e: 55 push ebp 14f8f: 89 e5 mov ebp,esp 14f91: 53 push ebx 14f92: 83 ec 24 sub esp,0x24 14f95: e8 8d c9 ff ff call 11927 <__i686.get_pc_thunk.bx> 14f9a: 81 c3 be 42 00 00 add ebx,0x42be 14fa0: b8 00 00 00 00 mov eax,0x0 14fa5: 89 45 e8 mov DWORD PTR [ebp-0x18],eax 14fa8: b8 00 00 00 00 mov eax,0x0 14fad: 89 45 ec mov DWORD PTR [ebp-0x14],eax 14fb0: b8 00 00 00 00 mov eax,0x0 14fb5: 89 45 f0 mov DWORD PTR [ebp-0x10],eax 14fb8: b8 00 00 80 3f mov eax,0x3f800000 14fbd: 89 45 f4 mov DWORD PTR [ebp-0xc],eax 14fc0: 8d 45 e8 lea eax,[ebp-0x18] 14fc3: 89 44 24 04 mov DWORD PTR [esp+0x4],eax 14fc7: c7 04 24 53 0b 00 00 mov DWORD PTR [esp],0xb53 14fce: e8 9d cb ff ff call 11b70 <glLightModelfv> 14fd3: 83 c4 24 add esp,0x24 14fd6: 5b pop ebx 14fd7: 5d pop ebp 14fd8: c3 ret
The C code for the function looked like
static void initLightAndMaterial(void) { const GLfloat globalAmbient[4]={0,0,0,1}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT,globalAmbient); }
And this is my Makefile.in (the function is defined in wgl.c): #--------------------------------------------- MODULE = 3d-demo.exe APPMODE = -mwindows -municode -mno-cygwin IMPORTS = user32 gdi32 gdiplus opengl32 glu32 d3d8 d3d9 d3dx9 ole32 shell32 msvcrt
C_SRCS = \ d3d8.c \ d3d9.c \ wgl.c \ main.c \ common.c \ texture.c
RC_SRCS = demo.rc
INSTALL_LIB = 3d-demo.exe 3d-demo #---------------------------------------
Apparently in-tree compilation assumes another calling convention for glLightModelfv here... What could be the reason for this? How should I set up my Makefile.in so that it generated a result compatible with opengl32 calling convention?
Thanks, Ruslan
On Aug 16, 2016, at 1:57 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
Hello all,
I'm trying to integrate my program into Wine source and having some difficulties with doing OpenGL calls. Namely, when I compile the program with mingw and with winegcc, it works flawlessly. But when I integrate it into Wine source tree (taking regedit as an example), stack appears smashed after OpenGL calls.
Apparently in-tree compilation assumes another calling convention for glLightModelfv here... What could be the reason for this? How should I set up my Makefile.in so that it generated a result compatible with opengl32 calling convention?
What headers are you including in the C code? This is probably a result of not having the proper declarations, which would be decorated with calling convention specifications.
-Ken
On Tue, Aug 16, 2016 at 10:30 PM, Ken Thomases ken@codeweavers.com wrote:
On Aug 16, 2016, at 1:57 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
Hello all,
I'm trying to integrate my program into Wine source and having some difficulties with doing OpenGL calls. Namely, when I compile the program with mingw and with winegcc, it works flawlessly. But when I integrate it into Wine source tree (taking regedit as an example), stack appears smashed after OpenGL calls.
Apparently in-tree compilation assumes another calling convention for glLightModelfv here... What could be the reason for this? How should I set up my Makefile.in so that it generated a result compatible with opengl32 calling convention?
What headers are you including in the C code? This is probably a result of not having the proper declarations, which would be decorated with calling convention specifications.
As I can see, the system <GL/gl.h> header is included (visible when I add an extra function argument and see the file referred to by the compiler in its error message). But I don't find gl.h in Wine source tree, so I guess this should be OK, no?
-Ken
On Aug 16, 2016, at 10:03 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
On Tue, Aug 16, 2016 at 10:30 PM, Ken Thomases ken@codeweavers.com wrote:
On Aug 16, 2016, at 1:57 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
Hello all,
I'm trying to integrate my program into Wine source and having some difficulties with doing OpenGL calls. Namely, when I compile the program with mingw and with winegcc, it works flawlessly. But when I integrate it into Wine source tree (taking regedit as an example), stack appears smashed after OpenGL calls.
Apparently in-tree compilation assumes another calling convention for glLightModelfv here... What could be the reason for this? How should I set up my Makefile.in so that it generated a result compatible with opengl32 calling convention?
What headers are you including in the C code? This is probably a result of not having the proper declarations, which would be decorated with calling convention specifications.
As I can see, the system <GL/gl.h> header is included (visible when I add an extra function argument and see the file referred to by the compiler in its error message). But I don't find gl.h in Wine source tree, so I guess this should be OK, no?
You need to *not* include the system header and instead include <wgl.h> and, usually, <wglext.h>.
-Ken
On Wed, Aug 17, 2016 at 6:27 AM, Ken Thomases ken@codeweavers.com wrote:
On Aug 16, 2016, at 10:03 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
On Tue, Aug 16, 2016 at 10:30 PM, Ken Thomases ken@codeweavers.com wrote:
On Aug 16, 2016, at 1:57 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
Hello all,
I'm trying to integrate my program into Wine source and having some difficulties with doing OpenGL calls. Namely, when I compile the program with mingw and with winegcc, it works flawlessly. But when I integrate it into Wine source tree (taking regedit as an example), stack appears smashed after OpenGL calls.
Apparently in-tree compilation assumes another calling convention for glLightModelfv here... What could be the reason for this? How should I set up my Makefile.in so that it generated a result compatible with opengl32 calling convention?
What headers are you including in the C code? This is probably a result of not having the proper declarations, which would be decorated with calling convention specifications.
As I can see, the system <GL/gl.h> header is included (visible when I add an extra function argument and see the file referred to by the compiler in its error message). But I don't find gl.h in Wine source tree, so I guess this should be OK, no?
You need to *not* include the system header and instead include <wgl.h> and, usually, <wglext.h>.
OK, this does appear to work. But I seem to now have to manually declare gluPerspective and other GLU functions I use, since Wine doesn't have anything like <wglu.h>, and the system header <GL/glu.h> conflicts with <wine/wgl.h> and <wine/wglext.h>. Am I missing something?
-Ken
On Aug 16, 2016, at 11:46 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
On Wed, Aug 17, 2016 at 6:27 AM, Ken Thomases ken@codeweavers.com wrote:
You need to *not* include the system header and instead include <wgl.h> and, usually, <wglext.h>.
OK, this does appear to work. But I seem to now have to manually declare gluPerspective and other GLU functions I use, since Wine doesn't have anything like <wglu.h>, and the system header <GL/glu.h> conflicts with <wine/wgl.h> and <wine/wglext.h>. Am I missing something?
I don't think you're missing anything. Wine implements glu32, but doesn't seem to have the header. That achieves binary compatibility but not source compatibility. Your best bet for a quick and dirty fix is, as you've surmised, to declare those yourself. Probably best to copy the needed function signatures from dlls/glu32 so they're exact matches, but be sure to copy the ones prefixed with "wine_" to get the proper declspecs and remove the prefix. So, for example, gluPerspective() is implemented as:
int WINAPI wine_gluPerspective(double arg0,double arg1,double arg2,double arg3) { … }
So you would need to declare:
int WINAPI gluPerspective(double arg0,double arg1,double arg2,double arg3);
The "WINAPI" is critical to get the calling convention correct.
As a related issue, Wine's glu32 implementation is actually intimately tied to X11. It links against the the libGLU from XQuartz or X.org. Therefore, it won't work with the Mac driver. You have to use the X11 driver.
-Ken
On Wed, Aug 17, 2016 at 8:58 AM, Ken Thomases ken@codeweavers.com wrote:
On Aug 16, 2016, at 11:46 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
On Wed, Aug 17, 2016 at 6:27 AM, Ken Thomases ken@codeweavers.com wrote:
You need to *not* include the system header and instead include <wgl.h> and, usually, <wglext.h>.
OK, this does appear to work. But I seem to now have to manually declare gluPerspective and other GLU functions I use, since Wine doesn't have anything like <wglu.h>, and the system header <GL/glu.h> conflicts with <wine/wgl.h> and <wine/wglext.h>. Am I missing something?
I don't think you're missing anything. Wine implements glu32, but doesn't seem to have the header. That achieves binary compatibility but not source compatibility. Your best bet for a quick and dirty fix is, as you've surmised, to declare those yourself. Probably best to copy the needed function signatures from dlls/glu32 so they're exact matches, but be sure to copy the ones prefixed with "wine_" to get the proper declspecs and remove the prefix. So, for example, gluPerspective() is implemented as:
int WINAPI wine_gluPerspective(double arg0,double arg1,double arg2,double arg3) { … }
So you would need to declare:
int WINAPI gluPerspective(double arg0,double arg1,double arg2,double arg3);
The "WINAPI" is critical to get the calling convention correct.
As a related issue, Wine's glu32 implementation is actually intimately tied to X11. It links against the the libGLU from XQuartz or X.org. Therefore, it won't work with the Mac driver. You have to use the X11 driver.
Would it be critical if I intend to send my addition as a patch for Wine? Should I avoid using glu32?
-Ken
On Aug 17, 2016, at 1:14 AM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
On Wed, Aug 17, 2016 at 8:58 AM, Ken Thomases ken@codeweavers.com wrote:
On Aug 16, 2016, at 11:46 PM, Ruslan Kabatsayev b7.10110111@gmail.com wrote:
On Wed, Aug 17, 2016 at 6:27 AM, Ken Thomases ken@codeweavers.com wrote:
You need to *not* include the system header and instead include <wgl.h> and, usually, <wglext.h>.
OK, this does appear to work. But I seem to now have to manually declare gluPerspective and other GLU functions I use, since Wine doesn't have anything like <wglu.h>, and the system header <GL/glu.h> conflicts with <wine/wgl.h> and <wine/wglext.h>. Am I missing something?
I don't think you're missing anything. Wine implements glu32, but doesn't seem to have the header. That achieves binary compatibility but not source compatibility. Your best bet for a quick and dirty fix is, as you've surmised, to declare those yourself. Probably best to copy the needed function signatures from dlls/glu32 so they're exact matches, but be sure to copy the ones prefixed with "wine_" to get the proper declspecs and remove the prefix. So, for example, gluPerspective() is implemented as:
int WINAPI wine_gluPerspective(double arg0,double arg1,double arg2,double arg3) { … }
So you would need to declare:
int WINAPI gluPerspective(double arg0,double arg1,double arg2,double arg3);
The "WINAPI" is critical to get the calling convention correct.
As a related issue, Wine's glu32 implementation is actually intimately tied to X11. It links against the the libGLU from XQuartz or X.org. Therefore, it won't work with the Mac driver. You have to use the X11 driver.
Would it be critical if I intend to send my addition as a patch for Wine? Should I avoid using glu32?
If you can easily avoid it, then, yes, do so.
-Ken