Bug 69796

Summary: HiDPI scaling not working with quartz cairo_surface_create_similar() implementation
Product: cairo Reporter: Alexander Larsson <alexl>
Component: quartz backendAssignee: Andrea Canciani <ranma42>
Status: RESOLVED MOVED QA Contact: cairo-bugs mailing list <cairo-bugs>
Severity: normal    
Priority: medium CC: brion, dsvensson, freedesktop
Version: unspecified   
Hardware: x86-64 (AMD64)   
OS: Mac OS X (All)   
Whiteboard:
i915 platform: i915 features:
Bug Depends on:    
Bug Blocks: 68382    
Attachments: Provisional patch to cairo to go along with GDK quartz backend changes
back buffer scale variant

Description Alexander Larsson 2013-09-25 08:30:53 UTC
Gtk+ 3.10 uses a back-buffer surface for doing scrolling, rather than clipping and self-surface copying. This causes problems on the Quartz backend, because the back buffer (created by cairo_surface_create_similar()) does not inherit the NSWindow.backingScaleFactor of the window surface passed to create_similar().

This means that the offscreen buffer will be a lower resolution than the actual window resolution and when we draw it to the window it will be upscaled and blurry.

In the cairo master cairo_surface_create_similar() already inherits the device-scale from the other surface, and the quartz backend need to do this similarly, by allocating a larger CGBitmap, and either setting the cairo device scale, or pushing the device scale to a lower quartz level (CGContext?).
Comment 1 Daniel Svensson 2014-01-04 00:24:49 UTC
Perhaps the description needs to be improved for this bug to be fixed, just speculating. I've looked at it a bit but I don't know the code base at all so the threshold of starting working on it was a bit high, so for me this is the case. Don't know what the timeframe of cairo 1.14 is, but this bug has heavy impact on Gtk on Mac OS X, with everything in a GtkScrolledWindow, tooltips, drag-n-drop etc being blurry.
Comment 2 Emmanuele Bassi (:ebassi) 2014-11-16 19:00:58 UTC
looking around at various sources, it seems that we should do:

  CGContextScaleCTM (cgc, scaleFactor, scaleFactor);

when creating the CGBitmapContext inside cairo_quartz_surface_create(), where scaleFactor is the device scale factor for the surface.
Comment 3 Brion Vibber 2014-11-16 19:32:03 UTC
(In reply to Emmanuele Bassi from comment #2)
> looking around at various sources, it seems that we should do:
> 
>   CGContextScaleCTM (cgc, scaleFactor, scaleFactor);
> 
> when creating the CGBitmapContext inside cairo_quartz_surface_create(),
> where scaleFactor is the device scale factor for the surface.

Tried that manually, it scales up the rendering size but when it gets drawn it's double-sized (so most everything's offscreen in gdkgears demo). Still needs something else...
Comment 4 Brion Vibber 2014-11-17 00:57:35 UTC
Created attachment 109576 [details] [review]
Provisional patch to cairo to go along with GDK quartz backend changes

Provisional fix for cairo scaling on Quartz backend

CGContexts by default apply a device scaling factor, which ends up interfering with the device_scale that is set on cairo at higher levels of the stack (eg in GDK).

Undoing it here makes behavior more consistent with X11, as long as the caller sets the device scale appropriately in cairo.
    
See GDK quartz patches on https://bugzilla.gnome.org/show_bug.cgi?id=740199 that fix the scaling on that end.
Comment 5 Christoph Reiter 2015-07-19 09:52:08 UTC
Created attachment 117242 [details] [review]
back buffer scale variant

For completeness, here is a cairo only fix which increases the cairo back buffer and scales it using CGContextScaleCTM.

Brion's patches work as well here and makes set_device_scale() work as with X11, while with this it gets added on top of the osx scaling.
Comment 6 Christian Hergert 2015-09-01 02:28:25 UTC
I just tested the second patch here (https://bugs.freedesktop.org/attachment.cgi?id=117242). It seems to fix my issues with pixelcache creating the wrongly scaled surface for textview/treeview.

What needs to be done to get this upstream in cairo master?
Comment 7 Behdad Esfahbod 2015-09-01 10:37:43 UTC
Let's see if Bryce can help...
Comment 8 Andrea Canciani 2015-09-07 13:26:55 UTC
The patches contains some typos, but they are trivial to fix.
Since this patch breaks the normal 1-to-1 mapping of the units, which is assumed to hold in most of the code elsewhere, it would be very desirable to make it possible to test it. I believe that the most effective way to do this is to add a new target in boilerplate/cairo-boilerplate-quartz.c, so that the whole test suite can run on surfaces with HiDPI enabled.

In particular, I expect that everything works just fine as long as Quartz is doing the rendering, but I am worried that fallbacks might break (I'm not sure if the implementation of map-to-image would still be valid).
Comment 9 Christoph Reiter 2015-10-18 10:28:38 UTC
Comment on attachment 117242 [details] [review]
back buffer scale variant

Marking my patch as obsolete as GTK+ depends on the device scale for extracting the pixel data from surfaces (not sure if it should, but there is no public API to get a CGImage out of cairo afaik) and this breaks it..
Comment 10 GitLab Migration User 2018-08-25 13:58:45 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/299.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.