Bug 25085 - cairo_push_group/pop_group/paint does not work properly with retina/Hi-DPI displays
Summary: cairo_push_group/pop_group/paint does not work properly with retina/Hi-DPI di...
Alias: None
Product: Xamarin Studio
Classification: Desktop
Component: General ()
Version: 5.7
Hardware: PC Mac OS
: --- normal
Target Milestone: master
Assignee: Cody Russell
Depends on:
Reported: 2014-12-04 16:26 UTC by Aaron Bockover [MSFT]
Modified: 2017-07-21 14:16 UTC (History)
3 users (show)

Is this bug a regression?: ---
Last known good build:

Retina circle on left, non-retina on right - make sure you zoom in the image to 100% (59.96 KB, image/png)
2014-12-04 16:26 UTC, Aaron Bockover [MSFT]
Real world implications of this bug (131.99 KB, image/png)
2014-12-04 16:29 UTC, Aaron Bockover [MSFT]

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Aaron Bockover [MSFT] 2014-12-04 16:26:46 UTC
Created attachment 8971 [details]
Retina circle on left, non-retina on right - make sure you zoom in the image to 100%

Not entirely sure where to file this, but it ultimately affects future work in Sketches.

The Cairo that we are shipping with Mono does not fully support retina/high DPI displays. The bug exists when creating a new surface via cairo_group_push[_with_content], rendering in the pushed surface context, then popping the group and painting.

The surface, when painted onto its parent, will be rendered with a backing scale factor of 1 instead of 2 (or whatever the actual backing scale factor is - 2 for current retina displays).

When debugging, I do notice that the surface that is created in the quartz backend is scaled properly (_cairo_quartz_surface_create_similar).

I suspect the following is happening (just a wild guess):

 - main surface has a user space dimension of 100x100, device space of 200x200 (scale factor of 2)
 - push_group to create similar surface: actual size is 200x200 (correct)
 - render into the group surface, everything looks okay
 - pop_group_to_source (probably ok)
 - paint: I wonder if paint thinks the image is too large (2x) for the user space (100x100) and scales the actual 200x200 (device) image down to 100x100; later in the paint path, the image is scaled back to device (200x200) resulting in pixelation

Attached is a screenshot.

Here's a link to sample code: https://gist.github.com/abock/c9cd8a5146f2ac0d1ce6
Comment 1 Aaron Bockover [MSFT] 2014-12-04 16:29:29 UTC
Created attachment 8972 [details]
Real world implications of this bug

This is a screenshot from Sketches - you can see the beautiful high-DPI editor font on the left, but the pixelated results font on the right (we are using push_group/<render>/pop_group_to_surface/paint_with_alpha to fade out results when they are invalidated and waiting for re-evaluation).
Comment 2 Aaron Bockover [MSFT] 2014-12-04 17:40:59 UTC
Cairo 1.14.0 introduces device scaling across the board.

The cairo_surface_set_device_scale API is new and should be used by GTK when creating the surface for the window.

Currently GTK likely does its own device scaling for the primary window surface which conflicts with using the new device scaling API in Cairo. This explains why the window surface supports "retina" today but sub surfaces do not.

With current GTK scaling of the window surface combined with a call to cairo_surface_set_device_scale with a 2x scale, the window surface ends up being scaled at 4x.