After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 683365 - Support high-density displays
Support high-density displays
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: X11
3.5.x
Other Linux
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2012-09-04 20:53 UTC by Alexander Larsson
Modified: 2013-08-13 22:37 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Export cairo_surface_set_device_scale (1.38 KB, patch)
2012-09-04 20:55 UTC, Alexander Larsson
none Details | Review
Initial version of UI scaling for hi density screens (39.24 KB, patch)
2012-09-04 20:55 UTC, Alexander Larsson
none Details | Review
Example of Nautilus scaled (177.05 KB, image/png)
2012-09-04 20:56 UTC, Alexander Larsson
  Details

Description Alexander Larsson 2012-09-04 20:53:50 UTC
Very high density display laptops are coming (Macbook pro retina version is the first, but more will come), and we don't handle them very well currently. We just show everything really really small.

Just bumping the DPI doesn't really help, because a *lot* of things in apps are currently specified in pixels. For instance, padding and border widths. Moving to specifying these in some pixel-independent unit is not a good idea, because fundamentally these primitives will be drawn to the screen in pixels, and several common primitives such as lines do not render well when not an integer multiple of pixels.

So, I think the iOS approach of pixel doubling is the only workable way. Basically, we treat the display as some integer factor of the real resolution. For example, a 2000x2000 screen would look like a 1000x1000 screen for applications, lettimg them work in a more "natural" pixel size which works on both high and low density screens. We then magnify all drawing such that cairo (text and vector) primitives render in the higher resolution.

Cairo has an internal feature of "device-scale" for surfaces. This is all we need to implement this in gdk. I just exported the _cairo_surface_set_device_scale function (although note that the docs for it says there are some parts of cairo that doesn't yet handle this correctly). Then i modified the Gdk X backend such that it magnifies pixels by 2 if you setenb GDK_SCALE.

Note, this patch is far from ready, its just a work in progress to see if this is workable.
Comment 1 Alexander Larsson 2012-09-04 20:55:08 UTC
Created attachment 223467 [details] [review]
Export cairo_surface_set_device_scale
Comment 2 Alexander Larsson 2012-09-04 20:55:23 UTC
Created attachment 223469 [details] [review]
Initial version of UI scaling for hi density screens
Comment 3 Alexander Larsson 2012-09-04 20:56:35 UTC
Created attachment 223470 [details]
Example of Nautilus scaled
Comment 4 Alexander Larsson 2012-09-04 20:57:48 UTC
As you can see in the nautilus example we sometimes get fuzzy scaled things, like icons and svg assets. We need to add highres versions of these. Should be easy to do for the svg based assets.
Comment 5 Matthias Clasen 2012-09-04 22:01:25 UTC
So, how would we use this in practice ?
Just set scale to 2 if real dpi is above some threshold like, say 200 ?
Comment 6 Benjamin Otte (Company) 2012-09-04 22:23:35 UTC
As I said in the RI bug, I think it's up to the X server to do export the setting. And until such a setting exists, I'm not really sure that GTK should support it.

In particular, because I think cairo-xlib should set the device scale and just export this as a getter on the surface, so that we can choose the right icon to draw.

I think GDK is entirely the wrong place to fix this.
Comment 7 Alexander Larsson 2012-09-05 07:29:57 UTC
In practice i think this needs to be a display setting. We can try to pick a default based on some dpi magic, but at the end of the day the user needs to be in control of it.

I kinda agree with Benjamin that this should ideally be an X feature. Basically, each screen (not monitor, it doesn't really work well to have different magnifications across windows that span multiple monitors) have a "subpixels" setting, which gives the number of subpixels per pixel (i.e. the scale). Then all the reported values for *everything* that currently reports pixels (window sizes/positions, monitor sizes, input coordinates, rendering operation position and sizes) in the scaled (i.e. smaller) coordinate space, while all traditional rendering operations automatically scale the operations as needed.

There also needs to be some opt-in X additions that let you actually access the full resolution. For drawing it might work by just using XRender with a scale factor, but you need to be able to e.g. set a highres cursor image, and possible other things.

However, even with that support in X, gdk needs some additional support. In fact, my patch really works like this already, only the magnification is done in the X gdk backend, not in the X server. So, the non-X specific parts of my patch (or something like that) are still needed. This is mainly:

* Exposing the scale in the gdk api so apps can be highres aware
* Allocate a large double buffer surface during drawing so that we don't lose the highres aspect when drawing
* Set the correct scaling factor on the cairo surface when drawing. In case X supports screen scaling this would only be needed for the case where we're rendering to the double buffer surface.
Comment 8 Benjamin Otte (Company) 2012-09-05 09:06:00 UTC
(In reply to comment #7)
> Basically, each screen (not monitor, it doesn't really work well to have
> different magnifications across windows that span multiple monitors) have a
> "subpixels" setting, which gives the number of subpixels per pixel (i.e. the
> scale).
>
Just out of interest, what happens if I connect one of those 800x600 projectors to my Retina Macbook to give a presentation?

> * Exposing the scale in the gdk api so apps can be highres aware
>
Doesn't cairo_surface_get_scale() already do that?

> * Allocate a large double buffer surface during drawing so that we don't lose
> the highres aspect when drawing
>
I'd expect cairo_surface_create_similar() and in turn gdk_window_create_similar_surface() to keep the scale that was set on the target argument, so this should work automatically (same for all the surfaces that we create using these functions elsewhere, like for dnd images).

> * Set the correct scaling factor on the cairo surface when drawing. In case X
> supports screen scaling this would only be needed for the case where we're
> rendering to the double buffer surface.
>
I believe this should also be covered by cairo_surface_create_similar(). You'd need special care when using image surfaces though as you suddenly want to scale the image surfaces during cairo_set_source_surface() and gdk_cairo_set_source_pixbuf()...
Comment 9 Alexander Larsson 2012-09-05 09:29:57 UTC
> Just out of interest, what happens if I connect one of those 800x600 projectors
> to my Retina Macbook to give a presentation?

Interesting question. I have no idea. Does OSX support different retina magnificatons on different monitors, and if so, does it allow windows to span both these windows?

One could have the apps render to one scaling only (the max scaling of all connected monitors, say), and then have the xserver or the compositing manager do a downscale of the screen area that scans out to the less highres monitors.

OSX in facts allow non-integer scaling in this way. Apps always render to an integer scaling factor, and the whole screen is kept thus in the framebuffer. But this can then be downscaled during scanout to get a non-integer scaling factor:

http://arstechnica.com/apple/2012/06/pixelpalooza-ars-reviews-the-15-retina-macbook-pro/3/

> Doesn't cairo_surface_get_scale() already do that?

cairo_surface_get_device_scale()? I don't think that is at the right level. You might want to know it for the whole GdkScreen, without any particular surface reference. Basically, the Gdk wrapper for the RandR level APIs should include this information. You use this on a level higher than the actual drawing when e.g. looking up different icon files based on the scale.
Comment 10 Benjamin Otte (Company) 2012-09-05 09:42:15 UTC
(In reply to comment #9)
> > Doesn't cairo_surface_get_scale() already do that?
> 
> cairo_surface_get_device_scale()? I don't think that is at the right level. You
> might want to know it for the whole GdkScreen, without any particular surface
> reference. Basically, the Gdk wrapper for the RandR level APIs should include
> this information. You use this on a level higher than the actual drawing when
> e.g. looking up different icon files based on the scale.
>
Yeah, agreed. We need a xxx_get_scale_factor() at the right level. And if we (X, Wayland, GTK) go the Apple route where there's just one per display and per-monitor scaling is done by the display server, then gdk_screen_get_scale_factor() is certainly the right place.
Comment 11 Alexander Larsson 2012-09-05 11:12:08 UTC
<ebassi> alex: apparently, osx 10.8 will trigger upscaling on a specific output if the density is greater than a threshold
<ebassi> because there are no retina external displays
<ebassi> windows straddling monitors are switched to a different mode depending on how much they straddle the line
Comment 12 Dave Airlie 2012-09-05 21:24:36 UTC
I've plugged in an external monitor here and macosx gives you a choice, best resolution for retina or for external (when cloned)

if you pick retina it will downscale the fullscreen retina into the output,
if you pick external it will go the other way.

I haven't tried side-by-side yet.
Comment 14 Daniel Svensson 2012-12-28 08:34:21 UTC
I don't suppose there's any quick and dirty crude hack to use higher resolution icons while this is getting fixed properly? I tried digging around the source code but as I'm unfamiliar with the architecture I was unable to find any good place to hunt for width/height differences. The icons, the slider theme knob (from svg), and my about image are the only problem I have. Widgets I draw on my own are crisp, text is crisp.
Comment 15 Alexander Larsson 2013-04-16 13:15:12 UTC
I wrote a strawman proposal here:
https://docs.google.com/document/d/1rvtiZb_Sm9C9718IoYQgnpzkirdl-wJZBBu_qLgaYyY/edit?usp=sharing
Comment 16 Brion Vibber 2013-04-22 18:05:03 UTC
Alex's proposal sounds excellent to me as a user and occasional desktop developer. This should provide similar behavior in mixed-density environments as what I see on Mac OS X and Chrome OS, and the idea of automatically scaling up X11 legacy apps unless they opt-in to high-DPI drawing should allow things to "just work" reasonably.
Comment 17 Alexander Larsson 2013-05-08 10:51:51 UTC
Initial wayland work posted at:
http://lists.freedesktop.org/archives/wayland-devel/2013-May/009073.html
Comment 18 Alexander Larsson 2013-06-28 12:36:56 UTC
An update on the status of this:
http://blogs.gnome.org/alexl/2013/06/28/hidpi-support-in-gnome/
Comment 19 Matthias Clasen 2013-08-13 22:37:37 UTC
This has mostly been merged