PDA

View Full Version : wglCreateContext failing from time to time



Janko Jerinic
12-08-2008, 05:34 AM
Hi,

I have a problem regarding wglCreateContext() which I've been using on my last big project with success and for years before as well.

For testing purposes, I've built a blank C#, Windows Forms project and practically copied the code blocks I used for creating the HRC before. The weird thing is, in one application the code works fine and doesn't in another ?! I'm even using the same PIXELFORMATDESCRIPTOR, iPixelFormat is 9, ChoosePixelFormat, SetPixelFormat also work fine, but wglCreateContext returns 0 and last error is "The pixel format is invalid"!!

I'm copying the code for the form below, if anyone has the time
I'd love if anyone could try and run it, it's a simple form with
interops. The only goal would be to create a context successfully :)

Thanks!!

------------------- CODE BEGIN -------------------
public partial class OpenGLVideoDriverTest1 : Form
{
public OpenGLVideoDriverTest1()
{
InitializeComponent();

CreateOpenGLContext();
}

IntPtr _hDC, _hRC;
protected virtual void CreateOpenGLContext()
{
try
{
PIXELFORMATDESCRIPTOR pfd = new PIXELFORMATDESCRIPTOR();
pfd.Initialize();


_hDC = GetDC(Handle);
if (_hDC == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());

int iPixelformat = ChoosePixelFormat(_hDC, ref pfd);
if (iPixelformat == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());

if (SetPixelFormat(_hDC, iPixelformat, ref pfd) == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());

_hRC = wglCreateContext(_hDC);
if (_hRC == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());

if (wglMakeCurrent(_hDC, _hRC) == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());

wglMakeCurrent(IntPtr.Zero, IntPtr.Zero);
}
catch (Exception)
{
if (_hRC != IntPtr.Zero)
wglDeleteContext(_hRC);

if (_hDC != IntPtr.Zero)
ReleaseDC(Handle, _hDC);

throw;
}
}

#region OpenGL32.dll
[DllImport("opengl32.dll", SetLastError = true)]
public static extern System.IntPtr wglGetCurrentContext();
[DllImport("opengl32.dll", SetLastError = true)]
public static extern System.IntPtr wglGetCurrentDC();
[DllImport("opengl32.dll", SetLastError = true)]
public static extern System.IntPtr wglCreateContext(IntPtr hdc);
[DllImport("opengl32.dll", SetLastError = true)]
public static extern System.Int32 wglMakeCurrent(IntPtr hdc, IntPtr hglrc);
[DllImport("opengl32.dll", SetLastError = true)]
public static extern System.Int32 wglDeleteContext(IntPtr hglrc);
[DllImport("opengl32.dll", SetLastError = true)]
public static extern bool wglShareLists(IntPtr hglrcDest, IntPtr hglrsSrc);
#endregion

#region PIXELFORMATDESCRIPTOR
public const byte
PFD_TYPE_RGBA = 0,
PFD_TYPE_COLORINDEX = 1;

public const sbyte
PFD_MAIN_PLANE = 0,
PFD_OVERLAY_PLANE = 1,
PFD_UNDERLAY_PLANE = -1;

public const System.UInt32
PFD_DOUBLEBUFFER = 0x00000001,
PFD_STEREO = 0x00000002,
PFD_DRAW_TO_WINDOW = 0x00000004,
PFD_DRAW_TO_BITMAP = 0x00000008,
PFD_SUPPORT_GDI = 0x00000010,
PFD_SUPPORT_OPENGL = 0x00000020,
PFD_GENERIC_FORMAT = 0x00000040,
PFD_NEED_PALETTE = 0x00000080,
PFD_NEED_SYSTEM_PALETTE = 0x00000100,
PFD_SWAP_EXCHANGE = 0x00000200,
PFD_SWAP_COPY = 0x00000400,
PFD_SWAP_LAYER_BUFFERS = 0x00000800,
PFD_GENERIC_ACCELERATED = 0x00001000,
PFD_SUPPORT_DIRECTDRAW = 0x00002000;

public const System.UInt32
PFD_DEPTH_DONTCARE = 0x20000000,
PFD_DOUBLEBUFFER_DONTCARE = 0x40000000,
PFD_STEREO_DONTCARE = 0x80000000;

[StructLayout(LayoutKind.Sequential)]
public struct PIXELFORMATDESCRIPTOR
{
public ushort nSize, nVersion;
public uint dwFlags;
public byte
iPixelType, cColorBits, cRedBits, cRedShift,
cGreenBits, cGreenShift, cBlueBits, cBlueShift,
cAlphaBits, cAlphaShift, cAccumBits, cAccumRedBits,
cAccumGreenBits, cAccumBlueBits, cAccumAlphaBits,
cDepthBits, cStencilBits, cAuxBuffers, iLayerType, bReserved;
public uint dwLayerMask, dwVisibleMask, dwDamageMask;

public void Initialize()
{
nSize = (ushort)Marshal.SizeOf(this);
nVersion = 1;
dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
iPixelType = PFD_TYPE_RGBA;
cColorBits = 32;
cAccumBits = 32;
cDepthBits = 24;
cStencilBits = 8;
cAuxBuffers = 0;
iLayerType = 0; //PFD_MAIN_PLANE
bReserved = 0;
dwLayerMask = dwVisibleMask = dwDamageMask = 0;
}
}
#endregion

#region Functions from gdi32.dll
[DllImport("gdi32.dll", SetLastError = true)]
public unsafe static extern System.Int32 ChoosePixelFormat(IntPtr hdc, ref PIXELFORMATDESCRIPTOR ppfd);
[DllImport("gdi32.dll", SetLastError = true)]
public unsafe static extern System.Int32 SetPixelFormat(IntPtr hdc, System.Int32 iPixelFormat, ref PIXELFORMATDESCRIPTOR ppfd);
[DllImport("gdi32.dll", SetLastError = true)]
public static extern System.Int32 SwapBuffers(IntPtr hdc);
#endregion

#region Functions from user32.dll
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static unsafe extern System.Int32 ReleaseDC(IntPtr hWnd, IntPtr hDC);
#endregion

[DllImport("kernel32.dll")]
public static extern UInt32 GetLastError();
}
-------------------- CODE END --------------------

Janko Jerinic
12-08-2008, 07:06 AM
One interesting point though: I've said that the code work fine in my previous applications, with opengl32.dll that comes with Windows XP. The code above also works when I copy OpenGL32.dll that comes from GLIntercept to application's output folder! Once again, how can that be?

Thanks!

_NK47
12-08-2008, 07:59 AM
thats because you run on Intel apparently. (driver bug) and i have no idea what you mean by, "it doesnt work". you dont see anything or does it crash?

Uri Chumak
07-23-2009, 01:40 PM
Same.

Looks like first call to wglCreateContext always produce "Invalid pixel format".

Solution: call SetPixelFormat again after wglCreateContext and all will work fine.

P.S. Windows 7, NVidia, Intel.