unoplatform/uno · critical · InvalidOperationException

SetPixelFormat failed

Error message

SetPixelFormat failed

What it means

Immediately after ChoosePixelFormat succeeds, the wrapper calls SetPixelFormat(hdc, pixelFormat, &pfd); it returns 0 on failure and the wrapper throws InvalidOperationException. On Windows, SetPixelFormat can only succeed once per HDC — a second attempt on a DC whose pixel format is already set will fail. It can also fail if the pixel format index is invalid for the DC or the DC is invalid.

Source

Thrown at src/AddIns/Uno.WinUI.Graphics3DGL/Windows/WinUINativeOpenGLWrapper.cs:68

		pfd.cAlphaBits = 8;
		pfd.cDepthBits = 16;
		pfd.cStencilBits = 1; // anything > 0 is fine, we will most likely get 8
		pfd.iLayerType = WindowsRenderingNativeMethods.PFD_MAIN_PLANE;

		var pixelFormat = WindowsRenderingNativeMethods.ChoosePixelFormat(_hdc, ref pfd);

		// To inspect the chosen pixel format:
		// WindowsRenderingNativeMethods.PIXELFORMATDESCRIPTOR temp_pfd = default;
		// WindowsRenderingNativeMethods.DescribePixelFormat(_hdc, _pixelFormat, (uint)Marshal.SizeOf<WindowsRenderingNativeMethods.PIXELFORMATDESCRIPTOR>(), ref temp_pfd);

		if (pixelFormat == 0)
		{
			throw new InvalidOperationException("ChoosePixelFormat failed");
		}

		if (WindowsRenderingNativeMethods.SetPixelFormat(_hdc, pixelFormat, ref pfd) == 0)
		{
			throw new InvalidOperationException("SetPixelFormat failed");
		}

		_glContext = WindowsRenderingNativeMethods.wglCreateContext(_hdc);

		if (_glContext == IntPtr.Zero)
		{
			throw new InvalidOperationException("wglCreateContext failed");
		}
	}

	// https://sharovarskyi.com/blog/posts/csharp-win32-opengl-silknet/
	public bool TryGetProcAddress(string proc, out nint addr)
	{
		if (_opengl32.Value != IntPtr.Zero && NativeLibrary.TryGetExport(_opengl32.Value, proc, out addr))
		{
			return true;
		}

View on GitHub (pinned to 0418340488)

Solutions

  1. Reuse the existing pixel format if the DC already has one (call DescribePixelFormat to check) instead of calling SetPixelFormat again.
  2. Create a fresh HDC/HWND for a new GL context rather than reusing one whose pixel format is locked.
  3. Ensure the same HDC is passed to ChoosePixelFormat and SetPixelFormat.
Defensive patterns

Strategy: validation

Validate before calling

// A DC's pixel format can be set only once
if (WindowsRenderingNativeMethods.DescribePixelFormat(_hdc, 1, 0, ref default) == 0) { /* ok to set */ }

Prevention

When it happens

Trigger: SetPixelFormat called twice on the same HDC (e.g. GLCanvasElement re-initializing its context after a recreate); the HDC differs from the one passed to ChoosePixelFormat; the chosen index is out of range for the DC.

Common situations: Window/context re-creation reusing a DC whose pixel format was already set; multiple GL hosts sharing a window's DC; reinitializing the GL wrapper after a device-loss event.

Related errors


AI-assisted analysis of unoplatform/uno@0418340488 (2026-08-13). Data as JSON: /api/errors/24c5de7629907ba5. Report an issue: GitHub.