Skip to main content
GameDev.net gamedev.net
🔒 Locked

Cross-platform Extensions (porting from Linux -> Windows)

Started by Synival Aug 11, 2012 at 11:07 PM 13 replies 5.1k views
Original Post
Synival
Synival
I'm finally porting my game from Linux to Windows, and nothing from glext.h seems to be working. Under MinGW, I'm getting undefined references for just about everything:
[source lang="plain"]game/assets.c:178: error: ‘GL_VERTEX_SHADER’ undeclared (first use in this function)
game/assets.c:178: error: (Each undeclared identifier is reported only once
game/assets.c:178: error: for each function it appears in.)
game/assets.c:182: error: ‘GL_FRAGMENT_SHADER’ undeclared (first use in this function)[/source]
I'm using the following #includes:
[source lang="plain"]#ifdef _WIN32
#include "../win/dirent.h"
#else
#include
#endif
#include
#include
#include
#include
#include
#include
#include [/source]
...and here is the source code in question:
[source lang="plain"]...
/* load shaders. */
else if (strcasecmp (ext, "vert") == 0) {
if (shader_load (name, file, GL_VERTEX_SHADER))
return "";
}
else if (strcasecmp (ext, "frag") == 0) {
if (shader_load (name, file, GL_FRAGMENT_SHADER))
return "";
}[/source]
I've tried manually defining everything used from glext.h which, although it seems dangerous, does compile successfully, but doesn't link properly:
[source lang="plain"]game/maps.wo:maps.c:(.text+0x4711): undefined reference to _glCreateProgram'
game/maps.wo:maps.c:(.text+0x472c): undefined reference to
_glAttachShader'
game/maps.wo:maps.c:(.text+0x476d): undefined reference to _glAttachShader'
game/maps.wo:maps.c:(.text+0x477b): undefined reference to
_glLinkProgram'
game/maps.wo:maps.c:(.text+0x4789): undefined reference to _glUseProgram'
game/maps.wo:maps.c:(.text+0x479c): undefined reference to
_glGetUniformLocation'
game/maps.wo:maps.c:(.text+0x47bc): undefined reference to _glUniform1fv'
game/maps.wo:maps.c:(.text+0x47cf): undefined reference to
_glGetUniformLocation'
game/maps.wo:maps.c:(.text+0x4805): undefined reference to _glUniform1fv'
game/maps.wo:maps.c:(.text+0x4818): undefined reference to
_glGetUniformLocation'
game/maps.wo:maps.c:(.text+0x4882): undefined reference to _glUniform4fv'
game/maps.wo:maps.c:(.text+0x4895): undefined reference to
_glGetUniformLocation'
...[/source]
...and so on. All of the normal gl.h functions (glVertex3f, etc) link properly.
Everything in the game is written in C, not C++, but that shouldn't be a problem. From what I've read, it looks like I need to link to drivers provided by the video card, but if that's the case, I'd need to make a separate build for every graphics card? Please, please, please, tell me that's not the case
-- Synival
L. Spiro
L. Spiro
Windows® does not export functions beyond OpenGL 1.2 or so, and any functions in later versions need to be linked dynamically via wlgGetProcAddress().


L. Spiro
I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid
21st Century Moose
21st Century Moose
Extensions are nothing to do with the OS and everything to do with the driver and hardware, but you don't need a separate build for every gfx card.

Under Windows you generally don't have headers and libs for anything beyond GL1.1, so you need to fully use the extension loading mechanism to access higher level functionality. What this means is that you need to create a context then use wglGetProcAddress to access the entry points, as well as making sure that you've got a header containing all of the required defines and declarations.

This isn't particularly painful to do - e.g. look at one of the id Software GPL code releases for working examples - but it is rather tedious code grinding, so the general recommendation is to use something like GLEW for handling it all for you.
Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls. 
Synival
Synival
Ohhh, I think I get it. So I need to look up the function addresses individually for each extension call? I've found some examples of wglGetProcAddress to study... I'll try a few things, and report back if it works. Thanks!
-- Synival
Synival
Synival
Hmm, frustrating. This should be working theoretically, but now I'm getting these linker errors:
[source lang="plain"]i586-mingw32msvc-gcc /opt/SDL-1.2.13/bin/i586-mingw32msvc-sdl-config --cflags debug.wo demo.wo game/assets.wo game/downloads.wo game/maps.wo game/math.wo game/messages.wo game/models.wo game/protocol.wo game/render.wo game/shaders.wo game/sprites.wo game/stats.wo game/telnet.wo game/tiles.wo main.wo ui/audio.wo ui/buttons.wo ui/canvas.wo ui/desktop.wo ui/fonts.wo ui/frames.wo ui/hgl.wo ui/logs.wo ui/network.wo ui/scrollbars.wo ui/text.wo ui/textures.wo ui/utils.wo ui/windows.wo -o ../harmonia.exe /opt/SDL-1.2.13/bin/i586-mingw32msvc-sdl-config --libs -lSDL_image -lSDL_net -lSDL_mixer -lopengl32
ui/hgl.wo:hgl.c:(.text+0x19): undefined reference to _wglGetProcAddress'
ui/hgl.wo:hgl.c:(.text+0x59): undefined reference to
_wglGetProcAddress'
ui/hgl.wo:hgl.c:(.text+0x99): undefined reference to _wglGetProcAddress'
ui/hgl.wo:hgl.c:(.text+0xd9): undefined reference to
_wglGetProcAddress'
ui/hgl.wo:hgl.c:(.text+0x119): undefined reference to _wglGetProcAddress'
ui/hgl.wo:hgl.c:(.text+0x159): more undefined references to
_wglGetProcAddress' follow[/source]
I'm linking to opengl32 with the '-lopengl32' parameter. Could it be an issue with MinGW?

The code causing the error is a macro I set up for _WIN32:

[source lang="plain"]#ifdef _WIN32
#define hgl_bind(x, y, z)\
if ((x = (void *) wglGetProcAddress (z)) == NULL) {\
log_printf (LOG_ERROR, "Couldn't bind function '%s'.\n", z);\
global_hgl_errors++;\
}
#else
#define hgl_bind(x, y, z)\
x = y
#endif

[...]

/* bind every function! */
hgl_bind (hglAttachShader, glAttachShader, "glAttachShader");
hgl_bind (hglBindFramebuffer, glBindFramebuffer, "glBindFramebuffer");
hgl_bind (hglBindRenderbuffer, glBindRenderbuffer, "glBindRenderbuffer");
[...][/source]
-- Synival
Lazy Foo
Lazy Foo
Just use GLEW. You will get every function available on your system and it's easy to check your available functionality.

Compare your code to this (from my GLEW tutorial)
[source lang="cpp"] //Initialize GLEW
GLenum glewError = glewInit();
if( glewError != GLEW_OK )
{
printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
return false;
}

//Make sure OpenGL 2.1 is supported
if( !GLEW_VERSION_2_1 )
{
printf( "OpenGL 2.1 not supported!\n" );
return false;
}[/source]

Not only that it gives you some shortcuts. FBOs didn't get promoted to core until after 2.1, but I was still able to treat them as core in an OpenGL 2.1 context thanks to the syntactic sugar glew provides.

Edit: Also are you using what additional libraries besides OpenGL are you using? I know certain libraries like SOIL require it to be in the linker before OpenGL32.
Synival
Synival
My first solution was to use GLEW, but glewInit() failed in my native Linux build for whatever reason. I played around with it a while, but had no luck, so I decided to stick with what I have. The code is already far enough along that I shouldn't have to rewrite it. The new code works fine using glXGetProcAddress(), but for whatever reason, it's not linking wglGetProcAddress().

As for other libraries, I'm using SDL, SDL_image, SDL_net, and SDL_mixer.
-- Synival
Lazy Foo
Lazy Foo

My first solution was to use GLEW, but glewInit() failed in my native Linux build for whatever reason. I played around with it a while, but had no luck, so I decided to stick with what I have. The code is already far enough along that I shouldn't have to rewrite it. The new code works fine using glXGetProcAddress(), but for whatever reason, it's not linking wglGetProcAddress().

As for other libraries, I'm using SDL, SDL_image, SDL_net, and SDL_mixer.


SDL actually has the ability to get the address of and OpenGL function if you want to use that, but I would recommend getting glew working.

Although I would recommend getting glew working because it will be a huge pain to get all the OpenGL functionality for a modern OpenGL program. What exactly was the error glew was giving you?
Learn to make games with my SDL 2 Tutorials
Nairou
Nairou
If you're using OpenGL 3.x, GLEW will fail unless you set it's "experimental" flag. Alternately, I recommend using flextGL instead of GLEW.
Lazy Foo
Lazy Foo

If you're using OpenGL 3.x, GLEW will fail unless you set it's "experimental" flag. Alternately, I recommend using flextGL instead of GLEW.


That's strange, I managed to get GLEW to work with OpenGL 3.1 just fine as did the people testing my tutorial programs. I started the alpha test for the tutorial set back in January so I'm guessing this might have been an issue with older versions of GLEW.
Learn to make games with my SDL 2 Tutorials
Nairou
Nairou

That's strange, I managed to get GLEW to work with OpenGL 3.1 just fine as did the people testing my tutorial programs. I started the alpha test for the tutorial set back in January so I'm guessing this might have been an issue with older versions of GLEW.


To be more specific, GLEW fails during init while trying to get the list of available extensions, if you are using a OpenGL 3.x core profile, as it still uses the deprecated glGetString() function rather than glGetStringi().

The last time I used GLEW was a year ago, version 1.6.0, so it may have been fixed, but the GLEW changelog doesn't mention it.
Synival
Synival
The error I was getting was a "Missing GL Version" error on glewInit(). Couldn't figure out what it meant, but I had enough of a headache as it was porting everything else to Windows, so I took the path of least resistance. The SDL_GL_GetProcAddress() solution wasn't all that bad, truthfully. I'll see how it goes in future builds on other machines.

Regardless, I'm really excited to have the first Windows build of my game! What blows my mind even more is that I somehow got a Windows executable built under a Linux environment. It runs under wine, so I can do all my testing from here smile.png Some seriously crazy stuff, if you ask me. Anyway, if anyone's interested, they can check out the build here: http://www.harmonia-...rmonia_demo.zip
-- Synival
Lazy Foo
Lazy Foo

The error I was getting was a "Missing GL Version" error on glewInit().


Are you calling glewInit() after calling SDL_SetVideoMode()? There needs to be an active OpenGL context for GLEW to work.
Learn to make games with my SDL 2 Tutorials
Synival
Synival
Are you calling glewInit() after calling SDL_SetVideoMode()? There needs to be an active OpenGL context for GLEW to work.[/quote]

That could have been the issue, although I think I tried it. Probably not. I'll certainly look into using GLEW in the future or, when I have the time, convert what I already have into using it. Though this was an interesting exercise in low-level OpenGL programming, which I personally find fun. Still no clue why wglGetProcAddress wasn't linking. Then again, it's mind boggling that I was able to make a Windows build under Linux at all.
-- Synival
Synival
Synival
Well, after lots of mucking around with OpenGL in cross-platform builds, I finally switched to GLEW and now everything is working wonderfully. Linking the functions manually felt better, but it's just too difficult to manage in Windows, Mac OSX, and Linux builds together.

Edit: Although using SDL_GetProcAddress() was compiling/linking properly and providing no run-time errors, the function pointers were causing heap corruptions in Windows. I suspect the prototype declarations are platform-specific, or at least really really picky.
-- Synival

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.