Open main menu

Modular Backends

Revision as of 21:26, 30 April 2006 by Fingolfin (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Introduction

We are considering to change our backends to use a more modular approach to things. This would be reflect in both the implementations and also in the interface (i.e. OSystem).

The idea is that a more modular approach makes it easier to reuse code in backends. It also makes it possible to have generic default implementations of certain features, while still allowing backends to customize them if needed. This is also what makes it so interesting for the Small Devices Backend project.


Examples

Instead of talking at length about hypothetical advantages of this, let me give you some specific examples I hope to see eventually.

X11 backend

The X11 backend directly uses the X11 API to implement graphics output for ScummVM on any system that supports X11. But of course, being a backend, it also needs to provide a way to output audio. X11 doesn't offer an API for that (AFAIK, at least), so it has to use something else. Sadly, this limits its portability. Right now, it has code for any system that supports sys/soundcard.h resp. linux/soundcard.h (I think that means OSS,

With the modular system approach, we'd split it into a "graphics & input" module which was implemented based on X11, and a "sound" module implemented based on OSS.

Then if somebody wants to use it on a system which doesn't have OSS, they could either choose to use the "null" ("dummy" ? "empty" ?) sound module, or write their own sound module, based on whatever sound API is available on their platform.

And if somebody decides to write an fbcon graphics/input module at some point, they could still reuse the OSS module.

Timers

Another typical candidate for modularization is the Timer code. Currently, most backends are happy using our default Time class, which is based on OSystem::setTimerCallback method. But the Morphos backend actually needs a custom implementation. The results in a rather nasty hack.

If we were doing things in a somewhat more modularized fashion, then this would become much simpler: Essentially, we'd have a "timer" module, and a default implementation of that which would be 99% identical to our current timer code. The difference being that we make it explicitly possible to replace it. Most backends would simple keep using the default implementation by providing the optional OSystem::setTimerCallback method (probably in a different way, but let's not get too specific here). But porters could also add an alternate implementation if desired.

The higher level code would simply ask the backend once for the "timer manager" via a new OSystem::getTimerManager method (similar to the existing OSystem::getSavefileManager method). The result is virtually identical for the client code (only a bit in main.cpp has to be changed), and also virtually identical for porters


Requirements

Modularization must be done in such a way that it doesn't hurt porters -- after all it's meant to *help* them. But many ports are rather monolithic, and actually wouldn't benefit much from being modularized (e.g. the PSP, PS2, Dreamcast, etc. ports) compared to the current situation. I.e. it should be relatively pain free to transit to the new system, and not force anybody to reinvent the wheel.

In particular, we want to avoid bloat. Implementing new backends should becomes *easier* with the module approach, not harder. So we have to try to avod over design, and also should avoid breaking things down into too small bits, because then it becomes harder to maintain them. In particular, we probably still want to allow relatively "monolithic" implementations, by not forcing porters to split everything into multiple files (but maybe encouraging it).

It's usually a good idea to look at how SDL manages its backends & modules. For example, graphics, input and event code are usually all found in src/video/FOO.


Potential modules

Possible modules include

  • Graphics
  • Input (events) -> possibly have graphics, input & event code all in a single type of module, just like SDL does -- after all they are usually tightly tied together anyway.
  • Sound (possibly allow for custom mixer implementations. Maybe even make it possible to use MP)
  • Timers (the current code would be left as default implementation, but e.g. Morphos port could override it easily)
  • Mutexes (only used when timers & threads are involved, so could be part of that)
  • Virtual keyboard
  • Filesystem code (already modular, see backends/fs/)
  • SaveFileManager (already modular to an extent, but should be moved to backends/saves/)
  • Native MIDI drivers (already modular, backends/midi/)
  • Scaler code (see common/scaler*) -> we already share some scaler code, but that could probably be done in a better way, and maybe some more generic scalers could be added (e.g. a good & fast downscaler).


External Links