8000 Linux DRM - Fix issues with current implementation by Lorenzooone · Pull Request #3513 · SFML/SFML · GitHub
[go: up one dir, main page]

Skip to content

Conversation

@Lorenzooone
Copy link
Contributor
@Lorenzooone Lorenzooone commented May 28, 2025

Description

This PR fixes three issues I noticed while testing the DRM setup by myself:

  • A segmentation fault if the initDrm function fails (i.e. due to the file specified being the wrong one).
  • A segmentation fault if libEgl is not loaded (the program will still not work properly, to be clear... But at least now the user will be able to know why. Before this PR, SFML said nothing to the user, and it just crashed)
  • The lack of the ability to select which screen the program should target.

The first two points are fixed thanks to the new function inside DRMContext.cpp: getEglLoaded(), which returns whether Egl was dynamically loaded correctly.
The last point is solved by adding the SFML_DRM_CONNECTOR_ID environment variable, which SFML checks at runtime. If this variable is set, it will specify the ID for the connector (and the screen that is plugged into said connector).

Tasks

  • Tested on Linux
  • Tested on Windows
  • Tested on macOS
  • Tested on iOS
  • Tested on Android

How to test this PR?

To test this, a Linux environment without a Desktop active is required.
This can be achieved by using certain combinations on some devices, like CTRL + Alt + F3.

For point 1, to test this, simply set SFML_DRM_DEVICE to a bad file value (anything will work). It shouldn't crash inside DRMContext.

For point 2, launch a program in an environment without libegl1. I used a Raspberry Pi loaded with the Raspbian OS Lite image, with libgm1 and libgl1 installed, but without libegl1 installed. Again, the result is that it shouldn't crash inside DRMContext.
A helpful error message should also get printed.

For point 3, it requires a second monitor. Check the ID of the connector via the drm_info command, and then the user should be able to change the screen on which the application is displayed on.

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode({1280, 720}), "Minimal, complete and verifiable example");
    window.setFramerateLimit(60);

    while (window.isOpen())
    {
        while (const std::optional event = window.pollEvent())
        {
            if (event->is<sf::Event::Closed>())
                window.close();
        }

        window.clear();
        window.display();
    }
}

@eXpl0it3r
Copy link
Member
eXpl0it3r commented May 28, 2025

Not sure about SFML_DRM_CONNECTOR_ID...

  • SFML doesn't currently support selecting displays in a multi-monitor setups, this feels like a workaround
  • Doing some tricks with environment variables seems rather odd and not very end user (i.e. users of SFML powered applications) friendly

@github-project-automation github-project-automation bot moved this from Planned to In Review in SFML 3.1.0 May 28, 2025
@Lorenzooone
Copy link
Contributor Author
Lorenzooone commented May 28, 2025

Not sure about SFML_DRM_CONNECTOR_ID...

* SFML doesn't currently support selecting displays in a multi-monitor setups, this feels like a workaround

* Doing some tricks with environment variables seems rather odd and not very end user (i.e. users of SFML powered applications) friendly

While I agree that it is a "workaround", it's more needed than with other backends.

Let me give you the real world example which makes it needed as compared to the cases in which you have a window manager.
Say you have a laptop connected to an HDMI display. If you close the lid, all window managers will only focus on the HDMI display. Meaning you can select on which display a window will be shown.
Not only that, you can move a window between displays. You have a ton more freedom.
DRM is different, however. It will simply use the first display on the list of connectors for the specific card you selected to create a fullscreen surface. If that happens to be (like in my case) the internal laptop display, too bad! It will use the internal laptop display. And you cannot move your window around! The concept of window is an abstraction for DRM: it simply uses the full screen!
This is fundamentally broken, when compared to all other implementations.

I agree it is a "workaround" in the sense that I'd like to make it so this stuff is selectable by an end user with an SFML API interface (like I'd like it to be on other backends/systems). But until then, this is the only way.

With all of this said, DRM already uses a certain set of environment variables for determining display stuff on initialization.

  • SFML_DRM_DEVICE: determines which graphics card will be used.
  • SFML_DRM_MODE: determines which resolution will be set by default. Needed for non-fullscreen mode windows. As stated before, this is because the concept of a window is an abstraction for DRM, which simply uses the full screen.
  • SFML_DRM_REFRESH: determines which refresh rate will be set by default.

Bonus fun fact: if you have displays connected to different graphics cards, you will be able to select between them by using SFML_DRM_DEVICE. You just won't be able to if they share the graphics card (like in the example above).

Now, to be clear: I think these environment variables should be better documented. They're very important, and I've seen no notice of them anywhere in documentation. I may be wrong about that, but that is what I saw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Planned

Development

Successfully merging this pull request may close these issues.

3 participants

0