[Scummvm-devel] SDL scaler refactoring
LionsPhil
lionsphil at gmail.com
Mon Aug 2 23:40:03 CEST 2010
Hi,
The current way scalers are implemented in SDL seems to be rather deeply
entangled with the backend as a whole; both rendering and co-ordinate
transforms for things like mouse events are calculated at the points of
use, with the scaling assumed to be a simple, integer multiplier with no
offset. This is problematic for the end goal of patch 2784961, which
eventually wants to centre the upscaled surface within an oversized
physical one, and for a related patch I've yet to submit (since it is a
largely useless addition on its own) which forces ScummVM to use the
desktop resolution if possible to avoid cheap and nasty TFT upscaling.
I propose that it might be better to refactor the scaling operations out
to an appropriate Scaler class which has virtual member functions for
performing game/hardware co-ordinate transforms, as well as the actual
graphical manipulation. In addition, this gives scalers a well-defined
context to stash any cacheable or precomputed resources (such as
centering offsets, or the lookup table used by the HQ scalers, which is
currently marked as FIXME for hanging around the whole time).
I'm hoping this'll stimulate some discussion with the people more deeply
familiar with the SDL backend, but as a starting point my plan of attack
would be (the backend should be left in a working state inbetween each
complete step):
- Factor out co-ordinate transforms to member functions of
OSystem_SDL; say mapHardwareToGame(xh, hy, &gx, &gy),
mapGameToHardware(gx, gy, &hx, &hy), still in terms of scaleFactor. (Not
allowing for 200->240 aspect correction, since that's currently a
separate pass?) I believe we will also need a mapHardwareToOverlay and
converse, since although the overlay forces the Normal1x scaler (in
internUpdateScreen), it may eventually require an offset to centre it
within an oversized physical surface. I believe the mouse layer should
always be on the same co-ordinate system as one or the other?
- Migrate the scaler functions into classes. Instead of setting
[new]scalerProc and [new]scaleFactor, the switch blocks of
setGraphicsMode and setGraphicsModeIntern would construct an instance of
an appropriate Scaler subclass. scalerProc is converted from a function
pointer to a virtual method call, and scaleFactor is set to a value
returned by scalerobject->scaleFactor().
- Migrate mapFooToBar methods from OSystem_SDL to the Scaler class,
and change calls appropriately. Determine the desired screen resolution
in loadGFXMode() by querying the Scaler object. Remove scaleFactor from
OSystem_SDL and the Scaler class.
By this point, everything about scaling co-ordinates (and graphics)
should be encapsulated within the Scaler subclass. This also allows us
to implement scalers with non-integer and variable scale factors,
without forcing floating point upon everything (as keeping scaleFactor
public would). In particular, given a Scaler base class along the lines
of (pseudocode):
class Scaler {
virtual void targetResolution(&w, &h);
virtual void mapFooToBar(...);
virtual void scale(...);
};
We can express current scalers, such as Normal2x:
class ScalerNormal2x : public Scaler {
ScalerNormal2x(int gameWidth, int gameHeight) { ... }
virtual void targetResolution { (return double the game dimensions) }
...
};
And new variable scalers, such as a best-fit aspect-maintaining stretch,
suitable for use with fixed resolution fullscreen (e.g. construct it
using the desktop resolution):
class ScalerStretchToFit : public Scaler {
ScalerStretchToFit(int gameWidth, int gameHeight, int targetWidth,
int targetHeight) { ... }
virtual void targetResolution { (return targetWidth and targetHeight) }
...
};
A future development to this may be allowing Scalers to handle their own
200->240 correction, to avoid a second pass. For example, if
StretchToFit were a simple nearest-neighbour sampling aiming for sharp
pixel boundaries, it could avoid the resampling performed by
stretch200To240().
So, if you've read through all this, thoughts? :)
--
LionsPhil
More information about the Scummvm-devel
mailing list