P/Invoking "wglChoosePixelFormatARB" Unbalances the Stack

613 Views Asked by At

I am trying to use some pinvokes to set up a wgl context for some unit tests, but (so far) one of my methods unbalances the stack.

What I have done is to first create a window and get its DC. This all works as I am talking to the kernel32, user32, gdi32 libraries. I am wanting to draw to a pbuffer with OpenGL, and in order to create the PB, I need to use the extensions. Which requires that I have a context... This is all sadly normal and working so far.

The problem comes when I am trying to create the pbuffer. When I try get the configurations using wglChoosePixelFormatARB, this appears to unbalance the stack. I have just executed another ARB method (wglGetExtensionsStringARB) earlier to check the extensions - and that works fine using the same parent DC.

So, on to code... My delegate looks like this:

[UnmanagedFunctionPointer(CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public delegate bool wglChoosePixelFormatARBDelegate(
    IntPtr dc,
    [In] int[] attribIList,
    [In] float[] attribFList,
    uint maxFormats,
    [Out] int[] pixelFormats,
    out uint numFormats);

I find it like this:

[DllImport(opengl32)]
public static extern IntPtr wglGetProcAddress(string lpszProc);
// ...
var ptr = wglGetProcAddress("wglCreatePbufferARB");
wglCreatePbufferARB = Marshal.GetDelegateForFunctionPointer(ptr, typeof(wglChoosePixelFormatARBDelegate));

And I am invoking it like this:

var iAttrs = new int[]
{
    Wgl.WGL_ACCELERATION_ARB, Wgl.WGL_FULL_ACCELERATION_ARB,
    Wgl.WGL_DRAW_TO_WINDOW_ARB, Wgl.TRUE,
    Wgl.WGL_SUPPORT_OPENGL_ARB, Wgl.TRUE,
    Wgl.NONE, Wgl.NONE
};
var fAttrs = new float[2];
var piFormats = new int[1];
uint nFormats;
wglChoosePixelFormatARB(
    parentDC, 
    iAttrs,
    fAttrs, 
    (uint)piFormats.Length, 
    piFormats, 
    out nFormats);
if (nFormats == 0)
{
    return IntPtr.Zero;
}

var pbuf = extensions.wglCreatePbufferARB(parentDC, piFormats[0], 1, 1, null);

The native side of this is (which is not exported):

BOOL WINAPI wglChoosePixelFormatARB (
    HDC hdc, 
    const int *piAttribIList, 
    const FLOAT *pfAttribFList, 
    UINT nMaxFormats, 
    int *piFormats,
    UINT *nNumFormats);

And the function def is this:

typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (
    HDC hdc, 
    const int *piAttribIList, 
    const FLOAT *pfAttribFList, 
    UINT nMaxFormats, 
    int *piFormats, 
    UINT *nNumFormats);

The code looks OK to me, but there must be something wrong :) I hope someone can point out my error.

In case more code is required, I have it all here in a single file that is just a plain console app: https://gist.github.com/mattleibow/755eba3c8ff5eafb9549842a0abb0426

(the code has large chunks of comments, this is just because I am busy porting from C++ to C#. And a third of the code is just the dllimports/structs/enums)

1

There are 1 best solutions below

1
David Heffernan On BEST ANSWER

The function declaration looks reasonable but it seems that you are simply importing the wrong function.

You want wglChoosePixelFormatARB but actually import wglCreatePbufferARB. This smells like a class copy/paste SNAFU.

Fix this by correcting the name that you pass to GetProcAddress.