Accéder au contenu principal

retro-gtk: The Future, Marty!

Let's come back to retro-gtk. In the previous articles I explained how bad retro-gtk was, what I did to start improving it and more importantly what I did to prepare the terrain for further development. This article will detail the aforementioned planed improvements!

Unless stated otherwise, I don't plan these changes to be part of retro-gtk 0.14 and I have no idea when they will be implemented. If I say anything you know to be wrong or if you know something which could help the library's development, please share it in the comments!

Stabilization of the API

As stated in the previous article, I want retro-gtk's API to stop breaking as much as it did in the past. Starting with 0.14, we will avoid API and ABI breaks as much as possible, and if we do any we will document them properly. The API should be stable but given that some big changes are coming I don't feel comfortable promising proper stability just yet.

Gitlab

I requested to move retro-gtk to GNOME's GitLab. This would allow retro-gtk to stop parasiting gnome-games' Bugzilla and live its own life. This is particularly important as retro-gtk is expected to become more stable and hence more used. I hope it will be done before 0.14 get released.

Meson! 😃

I started porting retro-gtk's build system to Meson, nothing is on master yet and I am studying Meson as I do the port. I hope it will be done before 0.14 get released.

Y U NO Rust‽

The library has two major constraints: it has to use the low-level Libretro C API and it has to expose an introspected GObject C API. As far as I know Rust supports both these constraints, but I don't know Rust yet and the Vala code needed to be ported to some low-level language so I could develop the library more freely and make it move forward.

Rust support of GObject — even though it is very promising — is still in development, so porting retro-gtk to it while I had to learn the language would have delayed the needed low-level language port. I may port parts of the library to Rust later, once I took the time to learn it and once the GObject integration matured. I expect a C to Rust transition to be less painful while maintaining the ABI than the Vala to C was.

Hardware Rendering and Shaders

Currently retro-gtk renders the video output of the core by converting it with custom code and drawing it with Cairo. It was quick and easy to implement with the knowledge I had back then and it did the job so I let it that way so far, even though it's very clearly far from optimal. retro-gtk should instead use hardware acceleration to render the video.

The only problem is that I still know nothing about graphics APIs such as OpenGL. 🙂 I hope the learning curve won't be too steep, if you have any knowledge to share, please do! I'll rely on Emanuele's GtkGLArea presentation and Anton's OpenGL 4 Tutorials to start working.

This would allow retro-gtk to render the cores' video with shaders, such as CRT shaders, Game Boy shaders and more!

I plan to work on this during SUSE Hack Week 16, so it may land in 0.14! 🙂

Hardware Rendering for the Cores

Libretro defines RETRO_ENVIRONMENT_SET_HW_RENDER and struct retro_hw_render_callback to allow the cores to request a hardware rendering interface to the frontend. Some Libretro cores can't work without it, so retro-gtk should implement it.

This would allow retro-gtk (and by extension Games) to run Nintendo 64 emulators and many more Libretro cores it can't yet!

I also plan to work on it during SUSE Hack Week 16.

Gamepad Handling

retro-gtk handles some controllers internally via RetroCoreView, but it doesn't handle gamepads directly and rely on the application to implement gamepad objects. I am currently exporting the gamepad handling code of Games into its own library, it may be a good opportunity to let retro-gtk handle all its controllers — gamepad included — internally, avoiding to expose too much of its internals. I am not sure whether it is a good idea or not yet.

Run the Core in a Subproccess

This is by far the biggest change planned for retro-gtk, I have absolutely no idea when it will be implemented: I would like retro-gtk to run Libretro cores into their own subprocesses. I would like this to not change the API — or as little as possible — which is made easier by the new higher level API as it reduces the surface the IPC must cover, moving more of the code in the subprocess. Here are the effects I expect such a change to have.

Calling Back Core Support Improvements

As each core would be alone in its subprocess we can be sure of which core is calling back, so there is no need to track its identity, making retro-gtk able to handle Libretro cores calling back from a different thread. As a result the API is expected to be more asynchronous.

Avoid Static Memory Collisions

When a module is loaded twice in a process it is actually loaded just once, making the two instances sharing the same static memory space. Most Libretro cores where once standalone games or applications, hence they were free to use static variables and sometimes did so. Some of this is still present in some Libretro cores, making them buggy when two instances try to access the same static memory. retro-gtk avoid these clashes in a very dirty way: the module is copied to a temporary file which is loaded instead, tricking the loading mechanism in actually loading is twice… I hope that loading each module from a different process will solve that, but I really have no idea if it will: if you know anything about this please contact me.

Improved Stability

We could make retro-gtk resilient to crashes of the subprocess, whether it is caused by the Libretro core or the lower layers of retro-gtk, the applications could handle this as they want for example by kindly notifying the users. I hope it won't make debugging the cores harder and that meaningful backtraces and other useful debugging information will remain obtainable.

Improved Security?

libseccomp could be used in the subprocess to avoid the cores to run unauthorized syscalls, which could be used to mitigate exploits and other 0days. The problem is that we can't know which syscalls the Libretro cores need so it may be tricky to filter enough but not too much. It still needs some reflection.

Regarding Performances

On one hand, performances could get improved as the UI and the Libretro core would run on two different CPU cores at the same time. On the other hand, high performance IPCs are tricky to get right, especially as I have next to no experience in that field. Copies and locks should be avoided as much as possible but I don't expect to avoid them all. This strategy turned out well for web browsers so I can only hope it will here too. 🙂

Unit Testing, Code Coverage ans Non-Regression Tests

Because we should do all of that, period. Special Libretro cores may have to be crafted for testing, but we should use already existing ones as much as possible to avoid accidentally writing ones not following precisely Libretro's semantic and working only in retro-gtk.

Core Integration Tests and Non-Regression Tests

It would be really useful for retro-gtk to distribute a Libretro core integration testing tool. Games would no doubt benefit from it as we already encountered regressions in Libretro cores we ship with its Flatpak version, which is particularly bad when it causes your user's saves to be lost.

Conclusion

This article concludes the mini-series about retro-gtk. I hope this library to become the best way to build a GTK+ based Libretro frontend, and if all of these features get implemented I am sure it will be! 😊

Commentaires

  1. About guaranteeing API stability in a library, I have this advice: it's important to be able to do refactorings later, the APIs developed now are maybe not convenient 5 years later. Don't hesitate to bump the major/API version, making the new version parallel-installable with the previous major versions (like GTK+ 3 and GTK+ 4), to do refactorings and improving the API. I think it's important to have clean code.

    I think that a lot of library developers don't want to change the API once it's declared stable, so after a decade like this, applications still need to use horrible APIs, and as a result there can be more bugs since the code in the application is less clear, etc.

    See the section “Iterative API design and stability guarantees” in the Tepl intro:
    https://developer.gnome.org/tepl/unstable/intro.html

    Developing Tepl this way is like a new freedom for me. And apps using older versions of Tepl still work fine.

    RépondreSupprimer

Enregistrer un commentaire

Posts les plus consultés de ce blog

Librem 5 ❤️ GNOME 3.32

I am glad to announce that the tooling I am working on since the beginning of the year is ready to be used!Thanks to new features introduced into libhandy 0.0.3 and 0.0.4 and thanks to a few fixes to Adwaita in GTK+ 3.24.1, you can make GTK+ 3 apps adaptive to work both on the desktop and on the upcoming GNOME-based Librem 5 phone.We are early in the GNOME 3.32 release schedule and the Librem 5 will be released a bit after it, so if you want your apps to work on the Librem 5, now is the best time: use libhandy 0.0.4 and up, use GTK+ 3.24.1 and up and target GNOME 3.32! A few apps like Fractal, Podcasts, Calls and Chatty are already using libhandy's adaptive capabilities, and other apps are working on their adaptive transition like Contacts, Games, Geary and Settings (all are works in progress). libhandy is available in Debian Unstable and Arch's AUR repository, and I wish it would be in Fedora already to let GNOME Settings' CI pass.For the moment, libhandy is a GTK+ 3 widg…

GTK+ Apps on Phones

As some of you may already know, I recently joined Purism to help developing GTK+ apps for the upcoming Librem 5 phone.Purism and GNOME share a lot of ideas and values, so the GNOME HIG and GNOME apps are what we will focus on primarily: we will do all we can to not fork nor to reinvent the wheel but to help allowing existing GTK+ applications to work on phones.How Fit are Existing GTK+ Apps?Phones are very different from laptops and even tablets: their screen is very small and their main input method is a single thumb on a touchscreen. Luckily, many GNOME applications are touch-friendly and are fit for small screens. Many applications present you a tree of information you can browse and I see two main layouts used by for GNOME applications to let you navigate it.A first kind of layout is found in applications like Documents, I'll call it stack UI: it uses all the available space to display the collection of information sources (in that case, documents), clicking an element from t…

One Widget to Adapt Them All and to The Librem 5 Port Them

In my previous article I shared my plans to help porting existing GTK+ applications to Purism's upcoming Librem 5 phone without having to fork them. This article will present the GTK+ widget I developed for Purism to make this happen.For more information on what Purism is working on for the Librem 5, please check Nicole Faerber's latest article.C'est pas sorcierThe underlying idea is to allow applications to dynamically switch between the two main GNOME application layouts: a row of panels — each panel being the view of an element from the previous one — and a stack of panels. The goal isn't to changes applications using the stack paradigm but the ones using the row one, allowing them to reach smaller sizes and to be usable on constrained sizes while keeping their initial paradigm and design when the screen space is sufficient. The development cost to port the applications to this adaptive design should be as low as possible.To achieve that, I wrote a GTK+ widget which…