libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.99k stars 1.84k forks source link

device event filter system #10337

Open expikr opened 3 months ago

expikr commented 3 months ago

Motivation

Since SDL keeps track of device attach/detach events and their enumerations, it would be nice to be able to set a filter to exclude certain devices from triggering SDL events based on developer-definable rules, such as matching certain PID and VID combinations as an example.

While it is currently possible to achieve this functionality manually by monitoring the attached devices and build your own device handle black/whitelist, in this approach the processing must be done for every single event, imposing significant overhead for devices that produces a large number of reports in a short interval.

By integrating a device filter callback system into SDL, it allows the game developer to set conditions which SDL can use on device attach/detach events to build a table of ignored hardware handles, then SDL can simply drop the event processing entirely upon hardware events by checking against this table of ignored handles, sidestepping the performance overhead of needing to check against every single event down the pipeline.

Implementation Sketch

slouken commented 3 months ago

I think the functionality you're asking for is already available by using SDL hints. What devices and what subsystems are you trying to block?

expikr commented 3 months ago

Specifically PID0226/PID0227/PID0243 of VID1532, see this discussion.

As I said, the functionality is currently achievable via a downstream implementation, but imposes significant overhead to check on every event in the event queue. This proposal instead suggests accepting a callback that is evaluated upfront per attached device. Or are you referring to some other functionality that I've overlooked?

slouken commented 3 months ago

We can block the event, but we can't block the operating system from using the device, which is what I think you're asking for here.

expikr commented 3 months ago

I think you misunderstood, closing is a bit hasty when the points haven't been clarified.

I am talking about the SDL event queue, has nothing to do with blocking at the operating system level.

Simply not inserting events from the blacklisted device into the SDL event queue is the cleanest way to achieve this performantly.

This is not relevant to events that don't deal with device handles (e.g. character inputs or non-relative mouse motion)

Developers who wish to blacklist certain devices will already be using events that passes device handles, this proposal simply empowers them to do it in a way that makes more sense architecturally.

slouken commented 3 months ago

So in order to achieve this, you'd have to enable both raw mouse and keyboard input. But considering the user impact of that, users who aren't savvy and just got the latest keyboard from Razer would think your game is broken, and users who are savvy will go download a cheat to bypass SDL's blocking of the events (or your game's blocking of them, if you implement it yourself)

expikr commented 3 months ago

The onus is on the game designer to communicate incompatibility and make the experience palatable.

This proposal is purely about giving developers the ability to define "incompatible devices" and prevent them from flooding the SDL event queue with "incompatible messages" in the first place, rather than having to do your own filtering downstream with the associated performance overhead.

You cannot control players who go out of their way to circumvent with custom hardware or software bypasses, but this is a low-hanging fruit that empowers the developers to constrain the space of legitimacy.

In other words, instead of heavy-handedly banning tournament entrants for the crime of innocuously using an off-the-shelf product as intended, the developer can simply choose to make known hardware "incompatible" with the game, and if a player goes out of their way to circumvent it in a tournament then that is a much stronger signal of illicit intent.

But again, how the game designer should impose restrictions is not of our concern here, the point is to expose a framework that empowers them to do so performantly in an architecturally reasonable manner.

expikr commented 3 months ago

Consider also the use case of a whitelist. Say I'm writing software for a specific medical device with SDL, which also communicates via HID but has device-specific behaviour that I need to code for to be compatible.

With this proposal, I can simply set a callback function that returns false except when encountering the specific device that I'm targeting.

Would this not also be a reasonable use case, where it makes sense not having to do a whole bunch of downstream processing just to exclude the 99% of garbage events from incompatible devices?

Or some more complex requirements, like say I only want events from controllers that either has two sticks and not touchpad or one stick and a touchpad, this is also easier by defining it as a callback function that evaluates to true or false based on the device capabilities info.

slouken commented 3 months ago

There is already a hint for blocking HID devices but it only affects the HID API. There is also a hint to affect the joystick API. There isn’t anything similar for raw input, but it could be added. Rather than a new API for a rather specialized use case, I’d probably lean towards a hint for this as well.

I have lots of other work to do for the SDL3 release, and this can be added anytime, so I’m going to move it to the 3.x milestone. Feel free to submit a PR if you work out the details and user communication. It might actually make more sense to use device name rather than VID/PID, since that’s what SDL exposes, and is easier for users to understand.

AntTheAlchemist commented 3 months ago

I think we need to shy away from putting the burden of things like this into SDL when it can be done by the app developer. App-level filtering per event will not create overhead; user-input events are about 20 per second max? Eventually SDL will be so bloated, when will it stop? Let's focus on the cross-platform input/output stuff that makes SDL great and let the app-developers code whatever else they need.

expikr commented 3 months ago

user-input events are about 20 per second max?

Err, I think you're off by about three orders of magnitude there. Try 8000?

AntTheAlchemist commented 3 months ago

Err, I think you're off by about three orders of magnitude there.

Even 100 events per second is minimal overhead to filter the events in the app's event handler. This is something that should be app-developer level. SDL needs to focus on being a raw tool, not a game-engine.