google / google/filament

Pixel format compatibility problem on Windows

Open
#4,775 3 comments 0 reactions 1 assignee Assigned to @bejado View on GitHub
windows
Dominant language
C++
Stars
20.5k
Forks
2.3k
Avg merge
2d 16h
Merged PRs (30d)
74

Description

**Describe the bug**
[TL;DR](https://github.com/google/filament/blob/84142ac50679493e1f5356ecf9f2210099d1c025/filament/backend/src/opengl/platforms/PlatformWGL.cpp#L214):
```
SetPixelFormat(swapChain->hDc, pixelFormat, &mPfd);
```
`SetPixelFormat` can only be called once for a particular window on Windows. This behavior is specified in WinAPI docs. Meaning `createSwapChain` expects a window that doesn't have pixel format set. If this is a requirement, docs for SwapChain probably must mention that. What's more misleading, is that example explains how to get it from SDL, but the problem is that SDL always call `SetPixelFormat` for its windows meaning Filament's call always ignored.

The issue might be related to https://github.com/google/filament/issues/1921

**Expected behavior**
Documentation should probably mention this Windows-specific behavior.

I'm unsure what would be a better solution without breaking Filament's API.

Maybe users should provide context explicitly, just like shared context can be passed for a driver to be created. Because window creation seems to be out of Filament's scope, it must be specified that 24bit depth buffer and OpenGL 4.1 required (for OpenGL backend).

**Logs**
```
in void __cdecl filament::PlatformWGL::makeCurrent(struct filament::backend::Platform::SwapChain *,struct filament::backend::Platform::SwapChain *) noexcept:245
reason: wglMakeCurrent() failed. hdc = FFFFFFFFE8010DB8

Windows error code: 2000. (null)
```

**Desktop:**
- OS: Windows 10 x64
- GPU: NVIDIA RTX 2080Ti, some Intel GPU, some AMD GPU (If required, I can look them up better)
- Backend: OpenGL

#### Usecase
I use Filament as a main rendering engine that controls window buffers (non-headless `SwapChain`) and Skia as a secondary rendering option for 2D that outputs into a Filament texture in its own rendering thread. For that to work I use shared OpenGL contexts.

On Linux platforms, this seemed to work, while on some Windows machines there was a black screen instead of a proper output. `stderr` had errors that Pixel Format was not compatible. Apparently, some drivers might select different and incompatible pixel formats for my SDL window and hidden Filament `STATIC` `dummy` window. I figured I could enforce same values as in Filament's `PIXELFORMATDESCRIPTOR` through `SDL_GL_SetAttribute`, but no, just matching those numbers with FIlament's doesn't work on different machines either.

#### Workaround
So here's what I do now: I create this same window Filament uses internally to figure out [exactly the same pixel format](https://github.com/borodust/aw-filament/blob/bbf67c11249c7d682131952dfc9749162222120a/src/lib/adapter/pixel-format/pixel_format_win.c#L39) Filament receives, and set those values as SDL's GL attrib hints.
This seems to work across different vendors.

This looks like a very brittle solution that relies on internal knowledge of Filament and how it exactly fills `PIXELFORMATDESCRIPTOR`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.