Search code examples
openglwinforms-interopmesa

Mesa3D doesn't like my context creation code?


Today I removed my dependence on OpenTK; my application no longer relies on OpenTK for creating an OpenGL context. However, my code no longer functions acceptably when running in Mesa 3D (the software-rendered implementation of OpenGL); my code runs, but the FPS is about 0.001 FPS (compared to about 16+FPS using OpenTK's context creation) and stuff that is normally drawn to a FBO is shown on the window, piece by piece as it is composed. Although running my code without Mesa 3D results in normal performance (on Windows 7), I'm worried it may just be coincidene that it works well. glGetError checks is showing no errors, which makes me think perhaps I'm doing something wrong in my context creation?

m_controlHandle = m_winForm.Handle; /* HWND */
m_controlDC = Win32.GetDC(m_controlHandle); /* HWND's DC*/
Win32.PixelFormatDescriptor pixelFormat = new Win32.PixelFormatDescriptor();
pixelFormat.Size = (short)Marshal.SizeOf(typeof(Win32.PixelFormatDescriptor));
pixelFormat.Version = 1;
pixelFormat.Flags =
    Win32.PixelFormatDescriptorFlags.DRAW_TO_WINDOW |
    Win32.PixelFormatDescriptorFlags.SUPPORT_OPENGL |
    Win32.PixelFormatDescriptorFlags.DOUBLEBUFFER;
pixelFormat.PixelType = Win32.PixelType.RGBA;
pixelFormat.ColorBits = 32;
pixelFormat.DepthBits = 0; /* yes, I don't use a depth buffer; 2D sprite game */
pixelFormat.LayerType = Win32.PixelFormatLayerType.MAIN_PLANE;
int formatCode = Win32.ChoosePixelFormat(m_controlDC, ref pixelFormat);
if (formatCode == 0)
    throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.SetPixelFormat(m_controlDC, formatCode, ref pixelFormat))
    throw new Win32Exception(Marshal.GetLastWin32Error());
m_openGLContext = Win32.wglCreateContext(m_controlDC);
if (m_openGLContext == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.wglMakeCurrent(m_controlDC, m_openGLContext))
    throw new Exception("Could not wglMakeCurrent.");

Is this correct? Any suggestions for tracking down what might be causing Mesa3D to suddenly go nutts?


Solution

  • Ok... I hope no one has to ever go through what I did trying to figure this out, so here's the solution:

    Although OpenTK will attempt to use wglChoosePixelFormatARB, it fails on Mesa 3D and falls back to ChoosePixelFormat. However, the function that OpenTK calls ChoosePixelFormat actually DllImports wglChoosePixelFormat and NOT ChoosePixelFormat.

    Yes, there are two versions of ChoosePixelFormat: one prefixed with wgl and one not prefixed. From OpenGL.org documentation:

    On the Win32 platform a number of platform specific function calls are duplicated in the OpenGL ICD mechanism and the GDI. This may cause confusion as they appear to be functionally identical, the only difference being whether wgl precedes the rest of the function name. To ensure correct operation of OpenGL use ChoosePixelformat, DescribePixelformat, GetPixelformat, SetPixelformat, and SwapBuffers, instead of the wgl equivalents, wglChoosePixelformat, wglDescribePixelformat, wglGetPixelformat, wglSetPixelformat, and wglSwapBuffers. In all other cases use the wgl function where available. Using the five wgl functions is only of interest to developers run-time linking to an OpenGL driver. Not using the functions as described may result in a black OpenGL window, or a correctly functioning application in Windows 9x that produces a black OpenGL window on Windows NT/2000.

    As I'm attempting to to run-time link to an OpenGL driver (Mesa 3D), the five wgl functions are of interest to me. Once I replaced my ChoosePixelFormat, SetPixelformat, and SwapBuffers with wglChoosePixelFormat, wglSetPixelformat, and wglSwapBuffers Mesa 3D worked excellently! Mystery solved.