Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Linux/SDL2 Platform #16470

Closed

Conversation

JoshTheDerf
Copy link

@JoshTheDerf JoshTheDerf commented Feb 7, 2018

I've been working on this the past couple of days, and it's in a semi-almost-kindof-working state.
Basically, this is a direct port of Godot's Linux X11 platform to SDL2.

Admittedly, I'm not experienced with working in C++, SDL, or with Godot, so the code quality isn't great and I probably missed quite a few details. That said, the editor and 2D and 3D projects all appear to be working largely as normal, with no noticeable performance hits.

At the moment, these features are (poorly) implemented:

  • GL Context Creation & Rendering
  • Text Input (with IME support, mostly.)
  • Mouse Button Events
  • Mouse Movement Events
  • Mouse Scroll Events (Button Events)
  • Mouse Grab, kind of.
  • Window borderless, resize, minimize, and maximize functions, setters, getters, and events.
  • Window icon setting (kind of, all the icons end up grey for some reason.)
  • Custom cursors. (Number of built-in cursors is reduced, however.)
  • Wayland Support (SDL default.) 🎉

These features are not yet implemented:

  • Touch Input (Should be workable, I just don't have a way to test it.)
  • Drag and Drop
  • Request Attention (Not built into SDL 2, I'll need to roll a custom implementation.)
  • Set IME position. (Doesn't seem to work for me under X11 or SDL? IME input still works.)

There are likely quite a few bugs in...

  • Mouse grab / relative support.
  • Window event handling.
  • Keyboard handling. (Right now the unicode property is only populated when the user is inputting text for typing purposes, and this detection relies on a hack in set_ime_position.)

However, all in all a workable and clean implementation looks entirely achievable, which was the original reason I started working on this.

So, why do I want a SDL backend?
Well, it started as an accident. I was looking for a decent cross-platform GUI system that wasn't electron. I noticed the Godot Engine 3 announcement and took a look around out of boredom. While doing that I discovered that Godot's architecture and capabilities are ridiculously flexible and modular, which got me exited for the potential to use it to develop general-purpose desktop applications that can be distributed in small, self-contained bundles and don't eat up gobs and gobs of RAM.

However, in order to really be attractive to desktop developers (at least those who like their hip modern apps), there are a few features that Godot would need to support on all desktop platforms:

  • Borderless window drag.
  • Transparent windows.
  • Click-through transparency (ideally.)

Now, all of those features are difficult to implement and not present in Godot at the current time. The effort required to implement them is significant and doesn't go along with Godot's intended purpose.
But, those features are implemented in SDL2 and could be brought to Godot with comparably minimal effort.

Disadvantages:

  • Larger build size. (This could be potentially minimized with custom builds of SDL2.)
  • Dependence on third-party library for core features.
  • Slightly reduced featureset in non-critical areas. (Such as fewer system mouse cursors.)

Advantages:

  • Support for difficult-to-implement APIs, such as custom draggable regions, transparent windows, click through transparency, and proper IME handling.
  • Potential to unify significant portions of the codebase for individual platforms.
  • Wayland support on Linux.
  • Well explored and battle-tested codebase.
  • Integrated mouse, touch, joystick, keyboard, and related event handling.

What are y'all's thoughts? I don't think this codebase is mergable as is, but I'd love to see where it can go and start working out the bugs with people who know what they're doing.

@ghost ghost added the feature proposal label Feb 7, 2018
@Calinou Calinou changed the title [WIP | Discussion] Linux/SDL2 Platform [WIP] Linux/SDL2 Platform Feb 7, 2018
@ghost ghost added the topic:porting label Feb 7, 2018
@hpvb
Copy link
Member

hpvb commented Feb 7, 2018

I am a proponent of the idea of having SDL in Godot, I think that we have reinvented the wheel over the years (for good reasons in the past!). However adding SDL (even if it were to replace the X11 platform) without using the SDL abstractions in other places of the engine doesn't strike me as a good idea.

If we can ship with SDL on all targets and we have a decent way of using system SDL where appropriate this could be a huge thing. It is my opinion that adding SDL in this way, while keeping the OS abstractions, doesn't really give us the benefits an SDL platform could have, while adding a lot of code to the engine.

We would also have to be very careful about how we import SDL2 into the tree so we can build for platforms that don't normally have it. If we have SDL2 we should probably also make sure that on Steam we use the steam-supplied version of it.

Wayland support is nice also, I'll hold hold off on my work of adding the 'linuxbsd' platform with Wayland and X11 support until some consensus is reached on this topic.

To state my opinion on this idea in the simplest terms: Yay SDL, if we actually make Godot an SDL program. Adding SDL as an abstraction on top of our existing abstractions: Nah.

@RiverMesa
Copy link

RiverMesa commented Feb 7, 2018

Using system-supplied SDL2 can probably be done in the same way that it works with other libraries (SCons flags). In fact it would seem that SDL discourages use of custom SDL builds to some extent. @hpvb

SDL seems to support all of Godot's primary platforms (all desktop platforms including Haiku and BSD, all mobile platforms, and the web via Emscripten) and more that Godot currently doesn't support like Windows Phone. Not sure about UWP or Blackberry support, thogh.

It doesn't support any of the console platforms however this isn't really within Godot's concern given that it cannot officially support them anyway.

Another thing of note is that SDL supports multiple rendering backends, including Direct3D (on Windows), Vulkan (!), and some combination of OpenGL and OpenGL ES (importantly, both GLES2 and GLES3).

There's also some degree of audio handling in SDL, which again, is another area where the code could be simplified, but I don't know if there'd be any issues with that, particularly with regards to Godot 3's reworked audio system.

Lastly, a bunch of misc. functions (mostly those handled by the OS singleton) could be delegated to SDL, including clipboard support, thread management, timers, file I/O, power management).

It's a lot of stuff, basically. The question is whether or not it's better to replace all of that with SDL, or to keep Godot's current implementations.

@hpvb
Copy link
Member

hpvb commented Feb 7, 2018

SDL2 won't give us Direct3D or Vulkan support, only easy ways to get a context for those APIs. It probably won't do us much good. Let's not confuse this whole thing too much! :)

Your comment about shipping SDL itself kind of was what I meant is that we'd need to be careful. We'd still want to have an in-tree version of SDL, but how we actually determine whether or not to use it will be a little tricky as you said. On Steam we'd want to not use it for all platforms, but a stand-alone windows build probably does want to use it. On Linux we'd probably never really want to use a bundled one, but on MacOS and Windows we probably do. As I said "Careful" :)

As for consoles, there are SDL2 ports available for most consoles that you can get on request from the SDL guys if you can show you have an SDK license for the relevant platform. Icculus recently announced that a Switch port is now available for instance.

@MarianoGnu
Copy link
Contributor

take a look at #14622

@bruvzg
Copy link
Member

bruvzg commented Feb 7, 2018

However, in order to really be attractive to desktop developers (at least those who like their hip
there are a few features that Godot would need to support on all desktop platforms:

Borderless window drag.
Transparent windows.
Click-through transparency (ideally.)

Check #14622 for transparent windows, and borderless window drag (click-through behaviour depends on platform) on X11, windows and macOS. IIRC SDL2 do not have support for transparent windows, only shaped windows.

@hungrymonkey
Copy link
Contributor

hungrymonkey commented Feb 7, 2018

@RiverMesa I just here to inject

https://plus.google.com/+RyanGordon/posts/TB8UfnDYu4U

Even if you static link SDL2, ryan gordon already merged a way to dispatch different SDL2 libraries.

He assumes that devs would static link anyways, although he discourages it. (should had added this line)

@JoshTheDerf
Copy link
Author

JoshTheDerf commented Feb 7, 2018

@MarianoGnu @bruvzg Neat! I didn't see that! I believe SDL does all three, but using a mask image is the way to go about it.

@hpvb @RiverMesa While I'm sure it wouldn't be a bad idea to make Godot an SDL program, Godot's architecture is abstracted enough that it could be implemented little by little. If I can get the Linux support bug-squashed enough, the next step would be to move all the SDL specific code out and share it with the macOS and Windows code. I have heard that there are some issues with SDL and UWP, but essentially, right now if we just use it for implementing OS features, we only need to link to it on platforms we want to support. Any unsupported or unported platforms would continue working with the codebase they already have. We can use Scons to decide what to link in which way depending on the target platform.

Later on, once everything appears stable and well implemented, it might be worth adopting SDL in Godot's internals.

@MarianoGnu
Copy link
Contributor

shoudn't it be better to implement SDL as a VisualServer and keep it not platform specific? (or in case there's platform specific code still have it in VisualServer using defines)

@JoshTheDerf
Copy link
Author

@MarianoGnu SDL's primary functions in this case are not necessarily rendering, but rather window management and event handling. I believe that lies squarely in platform territory, not VisualServer's.

@MarianoGnu
Copy link
Contributor

got ya

@hpvb
Copy link
Member

hpvb commented Feb 8, 2018

@tribex that's the kind of consensus I was talking about. If we decide that's the ultimate goal then I'm all for it. I'm very much against layering SDLs abstractions over Godot's and leaving it like that though. So that will have to be decided by @reduz and @akien-mga I think.

Abstractions are always a little 'off' and a lot of time is spent making sure they are all similar enough that one Godot port works more or less the same as others. The same goes for SDL ports. However, Godot abstractions and SDL abstractions are not the same. So adding SDL just means we now have another platform to tweak and potentially have to make the wrapper similar to other Godot ports.

I'd really like to avoid this.

@JoshTheDerf
Copy link
Author

@hpvb I entirely understand your perspective and agree entirely, though perhaps my opinion on the matter isn't as strong as yours. I personally suspect that sharing SDL as an abstraction layer between most platforms would still be a step up from having to maintain distinct abstractions for each of those platforms' native APIs, even if it's not possible to support all of them with SDL alone. We use wrappers on all platforms already, so if we could drastically reduce the size and scope of those wrappers by using SDL, I'd consider it a win do long as we don't need to maintain the direct abstraction layers.

Also, although Godot and SDL's abstractions are not the same, they are remarkably similar. I was surprised while implementing this.

@reduz
Copy link
Member

reduz commented Feb 8, 2018

SDL is not gonna happen if it depends on me. We always have to deal with special things and weird behaviors on different platforms that SDL not only does not deal with, but will make MUCH more difficult to contributors to fix if they have to deal with an extra abstraction layer.

I know you can make a large part of the port using it, and we could even officialize it, but I hope it never becomes the default backend.

Godot also has little problems with managing platform specific code, we have at this point several contributors for each, and it keeps improving.

In other words, SDL makes sense for small to medium projects, but there are good reasons (read: it's impossible to cover all platform use cases with a single wrapper) why large projects such as Blender, Firefox, etc. do not rely on it.

@reduz
Copy link
Member

reduz commented Feb 8, 2018

Also our platform specific code is usually pretty small, and if somebody wants to implememt a feature that SDL supports and Godot does not, it's always easy to just copy the SDL code and put it on our codebase, given the compatible license.

@hpvb
Copy link
Member

hpvb commented Feb 8, 2018

My opinion on the matter is that if it's not going to be the official abstraction layer we shouldn't have it at all as we'd get all the downsides without any of the upsides.

@reduz
Copy link
Member

reduz commented Feb 8, 2018

Think about this rationally. Imagine a situation where we use SDL2 and drop the existing backends. What happens every time we need a platform specific feature not available on SDL2? (Something it happens often) . We have the following scenarios:

  1. we use an hybrid of SDL2 and our own platform abstraction code. This is nasty and beats the purpose of using SDL.
  2. We contribute our changes back to SDL: Then, users need to wait for a new SDL version to test new Godot features, or use their bleeding edge, which may have other bugs unrelated to Godot. Also means one more layer of agreement with the SDL devs, to see whether they want the feature, how they want it, etc.
  3. We keep a fork of SDL and contribute our stuff from time to time: Solves most problems, but then it's more work to maintain and merge from their releases.

Added to that, the problem is that we may need to add something that SDL does not support and, while for us it's something specific with a simple use, while adding this function to SDL may involve creating a large API with all the functions that are needed for abstraction.

I'm sorry, no matter how I try to think of ways we could use SDL, it's always more disadvantages than advantages..

@JoshTheDerf
Copy link
Author

JoshTheDerf commented Feb 8, 2018

@hpvb Yeah, I'd have to agree. The whole idea is to simplify things. Maintaining SDL alongside other APIs would be an exercise in futility, and frustrating to users, especially since we couldn't really add new features to the SDL port without implementing them for other platforms as well.

@reduz Allow me to address your concerns a bit here:

We always have to deal with special things and weird behaviors on different platforms that SDL not only does not deal with.

Could you clarify what some of these might be? SDL's goal is to deal with as many of these behaviors as possible. If it doesn't deal with something, then it should either be a bug or unrelated to SDL. So far I haven't come across anything in my limited testing.

but will make MUCH more difficult to contributors to fix if they have to deal with an extra abstraction layer.

Well, if we had in-tree source for SDL, they could go there to make fixes or normalize things, and potentially contribute those patches back to upstream SDL. Also it's worth noting that there are considerably more eyes on SDL trying to find and fix bugs than on Godot. I'd almost guarantee that you'll find more developers that are familiar with SDL then you will that are familiar with X11, Wayland, macOS/Cocoa, UWP, and win32 APIs and the quirks between them.

I know you can make a large part of the port using it, and we could even officialize it, but I hope it never becomes the default backend.

I think I'm approaching about 90% X11->SDL so far, and there aren't any blockers to implementing the rest.

Godot also has little problems with managing platform specific code, we have at this point several contributors for each, and it keeps improving.

Indeed, but in particular, event handling is a major pain point, especially with X11. Most of the bugs in this port are likely due to me giving up trying to understand the X11 API and its usage in the platform wrapper and just going with a rough idea of what I thought it was. The macOS platform was a bit better, but not great. Now, admittedly, the X11 API is certifiably terrible,

In other words, SDL makes sense for small to medium projects, but there are good reasons (read: it's impossible to cover all platform use cases with a single wrapper) why large projects such as Blender, Firefox, etc. do not rely on it.

While I can't really speak for the decisionmakers for Firefox and Blender, I would like to point out that, like Godot, they've been around for years and year, far longer than SDL has been around in any half-decent form (2.0.0 was released in August of 2013) and have highly specific requirements, as opposed to a game engine where it has to support most anything a development team might want to do.

Think about this rationally. Imagine a situation where we use SDL2 and drop the existing backends. What happens every time we need a platform specific feature not available on SDL2? (Something it happens often) . We have the following scenarios:

Hmm. Perhaps you're misreading my intent here?
I'm not suggesting we remove the individual platforms and platform code. Rather, those platforms could share a common input / window management layer through SDL. Platform-specific code would still be entirely necessary for implementing new features or features that are outside of SDL's scope (such as os::move_to_trash and such), and would most likely not need to interface with SDL whatsoever. If we need access directly to platform resources, SDL can provide direct access to those handles.

We keep a fork of SDL and contribute our stuff from time to time: Solves most problems, but then it's more work to maintain and merge from their releases.

This would likely be the simplest solution, probably done by maintaining an in-source tree like we already do for bullet, enet, libvorbis, etc. Personally, I think the effort required to maintain and merge from releases would be significantly less than implementing the huge number of bug fixes they provide ourselves.

Added to that, the problem is that we may need to add something that SDL does not support and, while for us it's something specific with a simple use, while adding this function to SDL may involve creating a large API with all the functions that are needed for abstraction.

Should that be required, yes, it would be a genuine concern. I'd love to see an example of something like that though.

If nothing else, allow this branch to be an example of whether or not SDL could work for Godot.

@hpvb
Copy link
Member

hpvb commented Feb 8, 2018

Maybe I'll contact icculus to see if maybe we can work something out. Maybe we can get some kind of working relationship with the SDL team for a workflow that could work for us.

@JoshTheDerf JoshTheDerf force-pushed the feature/linux-platform-sdl2 branch from f0e3352 to 8183933 Compare February 8, 2018 12:04
@vnen
Copy link
Member

vnen commented Feb 8, 2018

probably done by maintaining an in-source tree like we already do for bullet, enet, libvorbis, etc.

Just to address this, while we do keep their sources inside this repository, we avoid the most we can to change anything in those libraries, because updating and merging from upstream becomes more difficult. We usually only do minimal changes if needed to make them build for every target platform.

@JoshTheDerf
Copy link
Author

@vnen Got it, makes sense. :)

@reduz
Copy link
Member

reduz commented Feb 8, 2018

Could you clarify what some of these might be?

There are lots of little things, like handling safe saving (save and rename using known atomic functions), getting special OS specific dirs for editor files, special options to handle DLLs on windows or pipes on linux, hacks to allow editor window to bring itself to front (which is disallowed by default in most OSs) and many more small little things that i can't remember right now. For mobile, we have a lot of custom stuff for OS ingegration (like how we draw files from the apk), same for webassembly.
None of those things make much sense in SDL and I am not sure they care about them as they are high level hacks. In the future, also need to better integrate to compositors to properly embed the game window.

Also for audio, SDL is just not good and never was, as the abatraction is too high level and each OS requests for data in very specific ways.

Again, not worth the trouble. Current state for Godot platforms is really good, so there is no reason to divert responsability to an external provider to save work.

This is I hope you understand that I am not denying that there car be small advantages. I just try to make clear that that there are considerable disadvantages that makes it not worth it. Many are not even code related, as I mentioned before.

@JoshTheDerf
Copy link
Author

JoshTheDerf commented Feb 8, 2018

handling safe saving (save and rename using known atomic functions),
getting special OS specific dirs for editor files, special options to handle DLLs on windows or pipes on linux,
For mobile, we have a lot of custom stuff for OS integration (like how we draw files from the apk), same for webassembly.

So what I'm referring to right now is just window management and event handling, which wouldn't affect how we implement the above-listed features. In regards to what @hpvb said, going all-in on SDL, I understand your concern here.

hacks to allow editor window to bring itself to front (which is disallowed by default in most OSs)

This one might require access to the native window handle, but is by no means impossible.

Also for audio, SDL is just not good and never was, as the abstraction is too high level and each OS requests for data in very specific ways.

Agreed, SDL would not be a good choice for audio.
I may be pushing SDL a bit here just because the alternative would be for me to implement (most likely sub-par) Wayland support and window hit testing features myself for all platforms which I'm way too lazy and inexperienced to do.

Anyway, if your final answer is a solid no, then I'll redirect my efforts elsewhere.

@hpvb
Copy link
Member

hpvb commented Feb 8, 2018

@tribex I've already started some work on Wayland support. If that's your ultimate goal just hang on a little while and it'll appear!

@JoshTheDerf
Copy link
Author

JoshTheDerf commented Feb 8, 2018

@hpvb Hooray! That would be awesome. It would be nice if the Linux platform could support both transparently, but I understand if that would require moving heaven-and-earth to do.

I just started implementing (read, copy-pasting from SDL) something like SDL's hit-test system to properly move borderless windows on X11.

@hpvb
Copy link
Member

hpvb commented Feb 8, 2018

@tribex that's exactly what I'm doing. X11 will become a driver for the 'linuxbsd' platform. At runtime we'll dlopen() Wayland or x libs based on availability.

@hpvb
Copy link
Member

hpvb commented Feb 8, 2018

I'd like to thank @tribex for this work and for bringing this topic up for discussion with an actually mostly working implementation. Given what was said on the topic for the moment I'm closing this pull request.

I really hope you won't take this as a discouragement from continuing to contribute to the engine in other areas. I'd like to invite you to join us on IRC in case you want to make another large contribution like this (and I hope you will!) in the future to avoid disappointment after having done work.

@hpvb hpvb closed this Feb 8, 2018
@JoshTheDerf
Copy link
Author

@hpvb No worries. :)
I'll be hanging out in the IRC channels, though my timezone is a bit wonky.

@ghost
Copy link

ghost commented Nov 8, 2023

There are lots of little things, like handling safe saving (save and rename using known atomic functions), getting special OS specific dirs for editor files, special options to handle DLLs on windows or pipes on linux, hacks to allow editor window to bring itself to front (which is disallowed by default in most OSs) and many more small little things that i can't remember right now. For mobile, we have a lot of custom stuff for OS ingegration (like how we draw files from the apk), same for webassembly. None of those things make much sense in SDL and I am not sure they care about them as they are high level hacks. In the future, also need to better integrate to compositors to properly embed the game window.

Again, not worth the trouble. Current state for Godot platforms is really good, so there is no reason to divert responsability to an external provider to save work.

Many commercial engines use SDL, though statically linked (it has a neat mechanism to override itself even when statically linked), only on Linux, even if it might be used as a cross-platform abstraction.
This proves is that the de-facto windowing API for Linux is SDL, they are the only ones that seem committed to backward compatibility, and it's proven judging from their effort of maintaining a stable ABI and things like sdl12-compat (and soon sdl2-compat).
I can run 2003 builds of Linux games using modern display and audio protocols thanks to it.
It's not that Godot developers aren't good enough to make a decent Linux port, it's that SDL is the necessary overlay for long term compatibility.
This is especially critical right now when this engine is being adopted more and more, and game developers don't certainly have to maintain the Linux builds for the years to come.

Also for audio, SDL is just not good and never was, as the abstraction is too high level and each OS requests for data in very specific ways.

What SDL cares about is PCM sample data pushed via callback in real time, also it has now a very good resampler if the OS sound system doesn't support the sample rate required by the engine.
I admittedly don't know at which level Godot sound operates, so i don't know if SDL might be suited for this task.
What i know is that calling Linux specific libraries is wrong for the reasons mentioned before, OpenAL can be an option, they also have maintained their ABI for quite some years.

Sorry for the necro.

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

Successfully merging this pull request may close these issues.

10 participants