Open jkarneges opened 10 months ago
Even without explicitly using GPU APIs, platforms likely have a built-in scaling operation available in their 2D graphics APIs, which could be faster due to knowing platform details, being fused with other necessary copies along the buffer-to-screen path, or actually being GPU-based.
On Wayland, https://wayland.app/protocols/viewporter can be used to crop and scale a buffer. It doesn't provide a way to control the scaling algorithm, but probably would provide good results if you're careful to use an integer scale factor? If so it could be useful for software-rendered pixel art games.
It's not necessarily supported on all compositors. Though it probably should be. Mir doesn't seem to support it yet, anyway (https://github.com/MirServer/mir/issues/2599).
I'm not sure about other platforms.
On most platforms, you shouldn't need this just for handling hiDPI displays, since applications that don't advertise HiDPI support will be scaled automatically. Though the results are ugly with fractional scales. X11 doesn't really seem to have that though, and HiDPI can be a mess there.
X11 and Windows do not support intrinsic scaling
On Windows we're currently using BitBlt
(comments in SDL said this was the fastest solution when they tried it; but that was a while ago). Looks like https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-stretchblt may work here?
On macOS, would https://developer.apple.com/documentation/quartzcore/calayer/1410746-contentsscale be applicable? I'm not sure.
Anyway, if it works on some platforms, but isn't supported on others, or only sometimes is available, either:
softbuffer
could have it's own code to scale in software, as a fallback.For HiDPI uses, some platforms have a specific way to communicate what DPI scale an application should use, and for the application to indicate if it handles the scale itself or needs upscaling (for legacy software, mainly). That doesn't necessarily require handling from Softbuffer, but probably should be discussed in any documentation for this feature.
It's not necessarily supported on all compositors. Though it probably should be. Mir doesn't seem to support it yet, anyway (canonical/mir#2599).
It does now :D
On Android scaling is implicitly supported (and should be executed by the presentation hardware or software GPU compositing depending on the vendor/SoC). The default ANativeWindow_setBuffersGeometry()
that we call to set up a format and size on the backing buffers describes explicitly what happens when the "window" surrounding it (really just a Surface
in the compositor tree where the buffers is drawn) has different dimensions from the values passed in this call (i.e. scaling occurs).
The lower-level SurfaceControl.Transaction.setGeometry()
/ ASurfaceTransaction_setGeometry()
variants of this method more explicitly show how to select and scale a region of the source-buffer to put in a rectangle on the screen. With these methods now deprecated, setScale()
/setPosition()
/`setCrop()
/setBufferTransform()
make this even more clear.
The readme says:
When I first read this, it didn't occur to me that "post-processing effects" included scaling. I was thinking it was more about things like CRT simulation. Unfortunately, scaling is often a requirement due to high resolution displays. Anyone doing full frame redraws and desiring good performance (60fps+) will almost certainly need to operate on a smaller buffer that can be scaled up, which
pixels
can do. I couldn't get acceptable performance with softbuffer and software scaling, although admittedly I didn't try very hard on the scaling algorithm.I wonder if softbuffer could make an exception and support hardware scaling, if it wouldn't go against the spirit of the project. It feels like an almost table-stakes feature for most real world use.