0

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)

Matthew
  • 3,951
  • 2
  • 21
  • 43

1 Answers1

2

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.

David Heffernan
  • 572,264
  • 40
  • 974
  • 1,389
  • Seriously? I checked everything but the darn string? Been at this for a few hours now... Thanks! Looks like I do need that sleep after all. http://m.memegen.com/qis49q.jpg – Matthew Feb 15 '17 at 06:10