BlueMonkMN's picture


Some Vista users are reporting problems, and I'm not sure if it's related to OpenTK or my own code. So far I know one user has version 6.0.6000.16386 of opengl32.dll, and is reporting the following error:
Error Screenshot

My own version of opengl.dll (5.1.2600.2180) on Windows XP works fine (I assume that's the significant DLL here). Is there possibly a compatibility problem working with different versions of opengl32.dll? Or just an OS problem?

The game in question was the same one linked in my previous post:
And the OpenTK code is based off of version 1166 from SubVersion.

(Edit: Also, what in the world is this "@" prefix I see on some of the parameters. I can't find any documentation on that for C#.)


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
BlueMonkMN's picture

1) Is there a good place to download pre-compiled GLFW and/or NeHe examples? A Google search didn't make that readily apparent. He said the Mono OpenTK samples worked, so isn't that an indication that OpenGL does work on his system?

2) It's really odd that was still failing on Vista64 because it was compiled for the x86 platform instead of AnyCPU this time. Shouldn't that have eliminated all those problems?

djk's picture

I tried to run it on my machine and it crashes in the constructor, because a GL.Viewport call in OnResize is being executed before the GLControl is created. Below is the stack trace from the cmd window. Hope this helps!

[edit] Ok, so the GLControl looks like it is initialized based on this stack trace, but in the debugger all the properties are null....

Selecting pixel format... System.NullReferenceException: Object reference not set to an instance of an object.
at OpenTK.Graphics.OpenGL.GL.Viewport(Int32 x, Int32 y, Int32 width, Int32 height)
at Display.OnResize(EventArgs e) in C:\Documents and Settings\dkingsley\My Documents\Visual Studio 2005\Projects\Game\Display.cs:line 167 at System.Windows.Forms.Control.OnSizeChanged(EventArgs e)
at System.Windows.Forms.Control.UpdateBounds(Int32 x, Int32 y, Int32 width, Int32 height, Int32 clientWidth, Int32 clientHeight)
at System.Windows.Forms.Control.UpdateBounds(Int32 x, Int32 y, Int32 width, Int32 height)
at System.Windows.Forms.Control.SetBoundsCore(Int32 x, Int32 y, Int32 width, Int32 height, BoundsSpecified specified)
at System.Windows.Forms.Control.ScaleControl(SizeF factor, BoundsSpecified specified)
at System.Windows.Forms.ScrollableControl.ScaleControl(SizeF factor, BoundsSpecified specified)
at System.Windows.Forms.Control.ScaleControl(SizeF includedFactor, SizeF excludedFactor, Control requestingControl)
at System.Windows.Forms.ContainerControl.Scale(SizeF includedFactor, SizeF excludedFactor, Control requestingControl)
at System.Windows.Forms.ContainerControl.PerformAutoScale(Boolean includedBounds, Boolean excludedBounds)
at System.Windows.Forms.ContainerControl.PerformNeededAutoScaleOnLayout() at System.Windows.Forms.ContainerControl.OnLayoutResuming(Boolean performLayout)
at System.Windows.Forms.Control.ResumeLayout(Boolean performLayout)
at OpenTK.GLControl.InitializeComponent()
at OpenTK.GLControl..ctor(GraphicsMode mode)
at Display..ctor(GameDisplayMode mode, Boolean windowed) in C:\Documents and Settings\dkingsley\My Documents\Visual Studio 2005\Projects\Game\Display.cs:line 136
at GameForm..ctor(GameDisplayMode mode, Boolean windowed, String title, Type initMapType, Type overlayMapType) in C:\Documents and Settings\dkingsley\My Documents\Visual Studio 2005\Projects\Game\GameForm.cs:line 118
at Project.Main() in C:\Documents and Settings\dkingsley\My Documents\Visual Studio 2005\Projects\Game\Project.cs:line 146

BlueMonkMN's picture

I posted another update at:

In this update, I added a frame rate limiter (60 FPS) and converted the ToInt32 calls to ToInt64 to try to help it run on Vista64. I also added a GL.Finish call in the OnResize function to try to prevent the error mentioned above.

I still don't understand why simply compiling for x86 wouldn't make this work on Vista64.

If anyone with Visual Studio 2008 or Visual C# Express 2008 is willing to help me look into any of these problems further, I'd really appreciate it. The complete source code is included with each ZIP file I've been posting. It's relatively easy to work with in Visual Studio. Of course everything works fine on my system, so it's really hard to debug these other problems here. For a technology that's supposed to be so cross-platform compatible, this conversion is turning out to be surprisingly incompatible even on the same platform.

the Fiddler's picture

I still don't understand why simply compiling for x86 wouldn't make this work on Vista64.
The exe worked as soon as I downloaded an 64bit version of FMOD. Did you compile both OpenTK and TVSGDK2 for x86?

Of course everything works fine on my system, so it's really hard to debug these other problems here. For a technology that's supposed to be so cross-platform compatible, this conversion is turning out to be surprisingly incompatible even on the same platform.
Most such problems are hard to debug ;) In my experience, OpenTK programs are surprisingly cross-platform (I've been able to run the same exe on everything ranging from Win98+software OpenGL to WinXP/Vista/Linux+Sis/Intel/Ati/Nvidia chips).

The stack trace above is a bit surprising: OnResize (a virtual method) is raised in the constructor of GLControl. I'm not sure if this is the norm, but you should place a check inside the Resize handler to avoid problems:

if (GraphicsContext.CurrentContext == null)

Regarding the access violation: the fact that it appears on .Net- and not on Mono-compiled binaries is not that strange. Generated code might be slightly different, and the problem might be masked on the latter - this doesn't mean that the problem doesn't exist, but rather that it doesn't manifest at the same time.

Without any other evidence, I would assume that the problem lies on the system of your tester. Either the video drivers or something else is causing problems. If it was a bug in OpenTK or .Net, it would have manifested on other systems too - but it hasn't.

Edit: I haven't been able something terribly out of the ordinary by single-stepping through the code. The "Selecting pixel format... Device context: 704713100" message appears many times because of some strange interaction between GraphicsContext creation (Display.cs:321) and Project::WriteLine and Project::Write (Project.cs:105).

Otherwise, things look normal.

BlueMonkMN's picture

I only compiled TVSGDK2.exe for x86. I figured that was the EXE that was loading FMOD so that would be the one that needs to be x86. I guess I don't quite understand the rules for running on a 64-bit platform.

the Fiddler's picture

I don't know what happens if you force one assembly into x86 mode and leave the rest as AnyCPU. I would guess it would force everything to x86 mode, but it looks as if this is not the case.

In any case, it's not hard to make TVSGDK2 compatible with both platforms: bundle both x86 and x64 FMOD dlls and add a static constructor to the FMOD wrappers. The constructor should check the underlying platform (if (IntPtr.Size == 4) { } else { }) and use LoadLibrary to pick the correct dll at runtime - that's all there is to it actually. For MacOS/Linux, you'd simply have to supply an exe.config file that maps FMOD to the correct .dylib / .so.

BlueMonkMN's picture

Well, it's not quite as simple as that. TVSGDK2 is not what I'm distributing. TVSGDK2 is just a sample of what SGDK2 can produce. And TVSGDK2 links to FMOD kind of as a "customization". SGDK2 does deliver FMOD as the suggested solution to use for implementing sound support for a project. But the project is free to refer to any DLL it wants to implement sound playback. So I need to not only figure out the rules for loading 32- and 64- bit DLLs into other applications, but somehow apply those rules the the applications generated by SGDK2.

I'm more interested in just supporting the 32-bit Windows platform for starters, and supporting it well, though it would be nice if I could support 64-bit Windows at least to a degree, if not optimally. If I were to compile a 32-bit version of OpenTK and deliver that with SGDK version 2.1, do you think I could at deliver some single solution that would work on both 32- and 64-bit Windows platforms until I find the need to optimize for both platforms, or do I really need to provide 32- and 64-bit versions just to be able to function on both platforms?

On to the next question: I'm not currently calling LoadLibrary at all, and neither, as far as I can tell, are the FMOD wrappers or OpenTK for that matter. I'm just using external function declarations in the .NET source code. It's kind of like the way OpenTK references opengl32.dll. That brings up another point. Does that same opengl32.dll work on both 32- and 64-bit platforms? Can I just use FMOD.dll the same way OpenTK is using opengl32.dll? I do see one reference to LoadLibrary in OpenTK, but it seems not to relate in any way to any other code as far as I can tell. It sets a static variable (opengl32Handle) which I don't see being used is never referenced anywhere.

the Fiddler's picture

To answer your question, yes, if you compile everything for x86 you'll be able to distribute a single app that works on both 32- and 64bit Windows. The opengl32 dll is not a problem, as 64bit systems contain both x86 and x64 images.

Regarding the call to LoadLibrary, there is more to it than meets the eye. When you call a DllImported function, the framework first loads the relevant unmanaged dll into the address space of your application (using LoadLibrary), and then proceeds with the call. You can short-circuit this process by calling LoadLibrary yourself - the framework doesn't care how the unmanaged library got there, it just checks whether it exists - which is a nice way to do "dynamic" DllImports on Windows: for example load a 32bit dll on 32bit platforms and a 64bit dll on 64bit platforms.

Mono on the other hand, provides an extension to the .Net framework to avoid this very issue: you create a dll.config (or exe.config) file that defines which unmanaged library to load on which platform.

As you can see, unmanaged dependencies are annoying to handle transparently...

BlueMonkMN's picture

1) I was not able to use this suggested code:

if (GraphicsContext.CurrentContext == null)

Is this equivalent (within a GLControl-derived object function)?

if (Context == null)

2) I tried compiling a new package with OpenTK and OpenTK.Utilities compiled for x86. Does this work on Vista64?
Why does opengl32.dll work for 32- and 64-bit architectures? Is opengl32.dll, contrary to the filename, a 64-bit DLL on Vista64? Why does OpenTK have to use LoadLibrary to load it if it's always the same file? Is it possible that the person with the problem copied Opengl32.dll from a machine with the wrong architecture and that's why there are AccessViolation exceptions?

the Fiddler's picture

1) No. The first scans the current thread for an opengl context. The latter returns the context "bound" to the relevant GLControl.

I've actually added this code to the previous zip you uploaded, so in fact it works (although the return clause is never hit on my machine - neither should it):

   // Display.cs:164
   protected override void OnResize(EventArgs e)
      if (OpenTK.Graphics.GraphicsContext.CurrentContext == null)
      GL.Viewport(0, 0, ClientSize.Width, ClientSize.Height);
      if (scaleNativeSize)
         System.Drawing.Size nativeSize = GetScreenSize(m_GameDisplayMode);
         GL.Ortho(0, nativeSize.Width, nativeSize.Height, 0, -1, 1);
         GL.Ortho(0, ClientSize.Width, ClientSize.Height, 0, -1, 1);

Does this not compile? What is the error?

2) I cannot test right now (I'm on Linux, preparing for a release), but will do so later ;-)

Regarding your other questions, 64bit windows ship with both 32bit and 64bit system libraries (opengl32.dll included). This is done to preserve compatibility with 32bit programs. The downside is that this roughly doubles the disk and memory requirements for x64 versions of Windows.

OpenTK uses LoadLibrary to insert opengl32.dll into the address space, so it can start loading OpenGL extensions. My understanding is that loading opengl32.dll dynamically is fairly common. This might be possible to avoid, but ot works well and I haven't found a reason to search for another method.

If your tester had copied an opengl32.dll with a wrong architecture, you would have seen an InvalidImageFormatException. I don't think this is the case here.