简体   繁体   中英

Why should I call wglCreateContext twice per context if I'm using C#, and once per context if using C++?

I don't understand some of the pieces of the puzzle here. A C++ developer only has to call wglCreateContext once to setup a context (whether it be a dummy context, or their main context). AC# developer is recommended to call wglCreateContext twice to setup a context (and to ignore the result of the first call if it fails).

For example, here's an extract from OpenTK 's source code:

Handle = new ContextHandle(Wgl.Imports.CreateContext(window.DeviceContext));
if (Handle == ContextHandle.Zero)
    Handle = new ContextHandle(Wgl.Imports.CreateContext(window.DeviceContext));
if (Handle == ContextHandle.Zero)
    throw new GraphicsContextException(
        String.Format("Context creation failed. Wgl.CreateContext() error: {0}.",
            Marshal.GetLastWin32Error()));

As I understand it, opengl32.dll seems to override some of the APIs that gdi32.dll exposes (such as ChoosePixelFormat ), thus making it matter which order these DLLs get loaded. With C++, I think that means the order in which you link libraries is important. With C#, you don't link libraries, and DllImport does lazy loading and so I think calling the function twice somehow gets the ordering eventually right.

Can anyone confirm what's going on?

That is correct, one of the weird consequences of Microsoft's Installable Client Driver (ICD) / Mini Client Driver model for OpenGL. If you can manage to call a function from opengl32.dll that is not in gdi32.dll (there are a lot of them) you can get C# to import opengl32.dll 's symbol table over-top gdi32.

You could probably accomplish the same thing simply by calling glGetError (...) immediately before you begin the process of creating a context. Obviously it is an error to call glGetError (...) with no active context, but that is beside the point - you just need an API call that will get the ball rolling importing DLL symbols.

It is much easier in C/C++, because linkage to DLLs is resolved partially at build-time (DLL import order is established by library order in the linker switches). In C/C++, this issue is resolved simply by linking to gdi32.lib before opengl32.lib.

The idea is the same though, ChoosePixelFormat (...) has to be overridden by hardware vendor distributed OpenGL ICDs in order to match requested format parameters against a set of hardware accelerated pixel formats. If you use gdi32's version of ChoosePixelFormat (...) you will never get any hardware accelerated pixel formats, just the lousy software-based OpenGL 1.1 reference implementation that has been layered on top of GDI since Windows NT/95 OSR2. And obviously nobody wants that, because the reference implementation is not extendable, you are forever stuck with OpenGL 1.1 if you wind up with a GDI pixel format.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM