PDA

View Full Version : Kick start OpenGL before setting pixel format



ppeterson
09-01-2005, 11:34 PM
I think some of you have already encountered the crash that occurs when you try to call SetPixelFormat before an OpenGL function is called. Apparently, it has to do with the fact that SetPixelFormat (and other pixel format functions) expect the OpenGL libraries to be linked but don't make the link themselves (see forum post (http://www.opengl.org/discussion_boards/cgi_directory/ultimatebb.cgi?ubb=get_topic;f=3;t=000957) ). Therefore, a dummy call to an OpenGL function before setting the pixel format is needed.

My problem is that not ANY OpenGL call seems to do the trick. It depends on the graphics hardware (driver). For instance, the call glFlush() is sufficient for a Matrox Millenium P650 but not on a Mobility Radeon 9000. Even more frustrating is that on the Radeon the dummy call with glFlush often works, but not always! Nothing more frightening than a bug that occurs at random :mad: .
I tried a call to wglSwapBuffers instead, which seems to give better results on both cards but how can I be sure that this particular call is more reliable?

Does any of you have experience with how to reliably "kick-start" OpenGL before setting the pixel format?

Greetings,
Pete.

andras
09-02-2005, 04:34 AM
I don't know what you guys are talking about (also looked at the other post). I've just created a new project in Visual Studio from scratch, here's the code:

//_________________________________
#include <windows.h>

void main() {
PIXELFORMATDESCRIPTOR pfd;
HDC hdc = ::GetDC(0);
HRESULT err = 0;

// get the number of pixelformats
err = ::DescribePixelFormat(hdc, 0, 0, 0);
if( err == 0 ) {
err = ::GetLastError();
}

// describe first
err = ::DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if( err == 0 ) {
err = ::GetLastError();
}

// set first
err = ::SetPixelFormat(hdc, 1, &pfd);
if( err == FALSE ) {
err = ::GetLastError();
}
}
//_________________________________

And guess what, it works perfectly...

knackered
09-03-2005, 05:54 AM
I've never encountered this before - and it doesn't make any kind of sense.
As far as I know, the pixel format functions aren't part of the opengl32 or the ICD, they're part of windows (<windows.h>).
The pixel format functions use the registry to find the ICD's on your machine, and then use the ICD's to advertise the pixel formats available. You then pass the pixel format index into the setpixelformat function which then causes the ICD to be loaded 'dynamically' (by using wglCreateContext which exists in opengl32.dll).

dorbie
09-04-2005, 12:46 AM
ppeterson, please explain what you are trying to do.

You need a valid OpenGL context before issuing OpenGL calls. You need to use WGL calls to get that valid context.

You can enumerate all pixel formats available etc, but you've posted something that makes no sense or at least shows some serious confusion over how your system works and without an explanation of your goals it may be difficult to assist you.

ppeterson
09-05-2005, 03:50 AM
I see the confusion. I never encountered this problem either until I started programming in .NET (C# to be precise). Probably should have mentioned this :eek: , though I wasn't sure whether this was a typical .NET problem because the other post I mentioned only speaks of "the MSVC linker".

However, I asure you the problem is real. I've seen examples of this dummy call in other peoples code (come to think of it, they used .NET too (more :eek: )) but never with a good explanation, just a fleeting remark that it was required to make it work. When I found the mentioned post I thought I was finally on to something.

I apologize if my lack of info caused confusion, and I too think that such a dummy call makes little sense so I'd like to get to the bottom if this. It was for this reason that I was wondering if other (.NET?) programmers could enlighten me.

As for what I'm doing: I've made a user control in which I can render an OpenGL scene. I've done similar things many times before in C++ so the code I use to set the pixel format, create a rendering context, etc. is pretty standard. It's that one damn dummy call that's bothering me.

Pete.

knackered
09-05-2005, 07:19 AM
If you're using C#, why are you using OpenGL?
You've obviously long since abandoned any portability concerns...

andras
09-05-2005, 07:59 AM
Originally posted by knackered:
If you're using C#, why are you using OpenGL?
You've obviously long since abandoned any portability concerns...Well, for one, C# is as portable as Java. Java is not platform independent, but it's a platform itself. Same with .NET, you just need the CLR (as you need JRE for Java) and that's all (and there's one for Unices too: Mono).
Also, portability is not the only thing why some might choose OpenGL. I'm not concerned about portability, yet I still use OpenGL. Do you think I'm nuts? :) )

Zengar
09-05-2005, 11:19 AM
.Net is nicely supported by the mono platform on unix-like systems. I believe that similar systems are the future of software. It's just that CLS is a badly designed language

Just a side notice :-)

ppeterson
09-05-2005, 09:47 PM
The choice to use C# was made long before I came along. I don't think any choice of programming language should deter you from using OpenGL for 3D rendering, though.

GPSnoopy
09-06-2005, 06:34 AM
I've never encountered such a problem when using C# and OpenGL.

PS: I was using GTKGL# + Tao (http://www.mono-project.com/Tao)

dorbie
09-06-2005, 03:48 PM
This still seems a bit vague, specifically what "dummy" call do you make and when w.r.t. creating a context.

This should be really straightforward, use WGL to make a context then call OpenGL once that context is made active. There's no other 'right' way to do it. I'm still not sure your confusion isn't over valid context creation.

(general note, please stay on topic or start your own thread, I already deleted one OT post but it would have made an interesting thread in itself).

ppeterson
09-06-2005, 10:00 PM
I'm happy to concede that the problem is not related to the linker. Maybe I was somewhat misled by the post mentioned in my first post.

I mentioned before I saw similar dummy calls in other peoples programs. Please see the C# basecode on Nehe\'s website (http://nehe.gamedev.net) marked NeHeGL C#, which is a nice example very similar to my project but more compact. Refer to file BaseGL.cs, line 123. There is such a "dummy call" (as I call it). Removing it results in a failure to create a rendering context (with wglCreateContext) and the dummy call must be done before the call to SetPixelFormat. Apart from that line, I can detect nothing suspicious in the rest of the code.

If it's not a linker problem, fine; it may turn out to be C# specific; but I still want to get to the bottom of it. And I really appreciate any help or clues you can give me.

tamlin
09-07-2005, 12:31 AM
I think it's as simple as the virtual machine being such a behemoth of a beast that it needs to delay-load DLL's, but for the wiggle functions to work opengl32.dll must alread have been loaded and created its hooks into GDI and extra (private) "TLS" (not really, but close enough) page(s).

Try doing just a simple LoadLibrary("opengl32.dll") and see if the problem doesn't go away. If it still fails, make really, really sure the DLL is really loaded, by trying to GetProcAddress something from it - f.ex. wglSwapBuffers.

++luck;

ppeterson
09-07-2005, 01:45 AM
Originally posted by tamlin:
Try doing just a simple LoadLibrary("opengl32.dll") and see if the problem doesn't go away.Thanks, tamlin! I replaced the dummy call line with a call to LoadLibrary("opengl32") and it has the same positive effect! Also, the LoadLibrary has to be done before the SetPixelFormat call, just as when I used a dummy call. Using LoadLibrary seems (or feels?) a lot neater, as well.

I'm now figuring out a way to check whether the opengl32 library is loaded, before actually loading it. Perhaps the REAL culprit is something else? Maybe a library called by opengl32 and not opengl32 itself? Haven't found a method yet that can query loaded dll's.

tamlin
09-07-2005, 03:02 AM
Originally posted by ppeterson:
Also, the LoadLibrary has to be done before the SetPixelFormat callCorrect, and even obvious, as that call needs the ICD.

I'm now figuring out a way to check whether the opengl32 library is loaded, before actually loading it.

I wouldn't bother. It's ref. counted. If you still want to check, FindModule().

Perhaps the REAL culprit is something else?

I don't think so. While I don't touch .NET myself, I'm convinced delay-loading is the problem. I suspect that environment imports half a gazillion DLL's, and without delay-loading most of them I'd expect startup-times for .NET applications to be around the same times a top fuel "car" needs for the quarter mile.

knackered
09-15-2005, 04:13 AM
Here's a pretty good (but old) article on how the ICD mechanism works:-
http://www.gamasutra.com/features/19971121/passmore_01.htm
Perhaps it may clear up some misconceptions.