true retina rendering on os/x
|Assignee:||Chris Cannam||% Done:|
Hi-dpi rendering already works fine on Linux and Windows, but OS/X is still problematic -- although textual elements are retina-ized, graphical rendering is still positively Minecraft.
This is because the view, and almost all layers, render onto pixmap backing store (at 1x resolution) before copying that to the widget (at what should be 2x, so ends up being unattractively scaled).
The fix is not as straightforward as I might hope. The view has a mixture of pixmap caching (for "scrollable" layers) and direct rendering (for layers that change depending on the position of the mouse).
We can generate a 2x pixmap for the scrollable cache and adjust the rect passed to the layer render() method accordingly, but that doesn't fix direct-renderers, and it doesn't help with the fact that layers will often call back on the view to establish its size and the mapping between (for example) x-coord and frame number. Also, this means that everything rendered to the scrollable cache ends up being scaled down, including text elements and the like, which we don't really want.
(Direct-renderers that actually render directly, using QPainter paths etc straight to the view, should be fine already. It's the direct-renderers that have their own pixmap caches, like the spectrogram, that are problematic.)
But conversely we can't just use a 1x cache because then any cached layers will end up low-res. Perhaps the very first thing we need to check is how far the view's scrollables cache is actually worthwhile in the first place -- which layer types benefit from it and by how much?
#1 Updated by Chris Cannam over 4 years ago
Sorts of layer:
- Scrollable, cheap to render:
TimeRulerLayer- could cache or render directly
- Scrollable, expensive, has own cache:
- Scrollable, expensive, lacks own cache:
TimeValueLayerin e.g. curve mode
- Non-scrollable, can be expensive, lacks own cache:
TimeValueLayerin e.g. point mode
- Non-scrollable, expensive, has own cache:
- Sometimes scrollable, expensive, has own cache:
Many layers are sometimes scrollable, e.g. note layers are scrollable if not the top layer (so that local features are not being highlighted). I think much of the theoretical utility of the scrollable cache lies in managing the cost when a very large number of translucent layers is present on the same view, in which situation usually all but the top one will get cached. But this will fail as soon as they are placed over a non-scrollable background layer like a spectrogram, since the scrollable cache only caches as far as the first non-scrollable layer.
#3 Updated by Chris Cannam over 4 years ago
... So it may be better to ensure that layers always get a NxN-scale pixmap to render into, not the View directly. That means they have essentially the same behaviour as on other platforms, although they will need to scale fonts back up again (other platforms have proportionately bigger fonts everywhere when running in hi-dpi environments).
Then we could perhaps create a fake View-stub object with suitably scaled versions of dimension reporting and axis scaling functions to pass in to the layer render call?
Memory usage will be much higher though...
#6 Updated by Chris Cannam over 4 years ago
Problems noted so far:
- Text rendered with drawVisibleText appears too small
- Much of the text in the vertical scale is too small
- The text in the time ruler is too small
- When mousing over a feature, the wrong feature is highlighted (although the right information is shown in the local feature identification box at top right)
- The zoom wheels are low-res
- It is noticeably slower to scroll
The layout is also very ugly in many other ways distinctive to the OS/X port, but this issue is about retina support only.