Fix OpenGL canvas scaling algorithm in hidpi mode
AbandonedPublic

Authored by alvinhochun on Sep 25 2017, 4:36 PM.

Details

Reviewers
dkazakov
Group Reviewers
Krita
Maniphest Tasks
T2299: Make the canvas behave in HiDPI mode
Summary

The OpenGL canvas equivalent of D7973, except that there is no explicit QImage scaling code to be changed.

Most noticeable change is that it is now way crispier at 100% canvas zoom level under 2x dpi scale.

This does not fix instant preview (T7063).

@dkazakov making your review blocking since I think I should get your approval for this.

Diff Detail

Repository
R37 Krita
Lint
Lint Skipped
Unit
Unit Tests Skipped
alvinhochun created this revision.Sep 25 2017, 4:36 PM

Hi, @alvinhochun!

As far as I can tell, the patch is not correct from the global point of view. I mean it just workarounds a bigger problem: Qt automatically upscales the canvas widget, which is not good.

So the real fix should actually disable this upscaling, in which case scaleX and scaleY will have correct values. Right now, "official" zoom-level chosen in the GUI is not consistent with what the user sees on the canvas. Or I don't understand something.

The way how to test the issue:

  1. Disable "Use Same Aspect As Pixels" switch (at the bottom-right corner of the window)
  2. Create 100mm image.
  3. Select 100% zoom
  4. Use a old good physical ruler to measure the document size on your display, it should show about 100mm

Last time we tested Krita on HiDPI displays, the physical size of the document was about 200mm

alvinhochun added a comment.EditedSep 25 2017, 7:03 PM

The way how to test the issue:

  1. Disable "Use Same Aspect As Pixels" switch (at the bottom-right corner of the window)
  2. Create 100mm image.
  3. Select 100% zoom
  4. Use a old good physical ruler to measure the document size on your display, it should show about 100mm

    Last time we tested Krita on HiDPI displays, the physical size of the document was about 200mm

Well... short answer is: it doesn't work.

Long answer is that on my Surface Pro (2017) with 200% dpi scaling, I measures 27mm with HiDPI disabled and 54mm with HiDPI enabled, so it doesn't work either way. Disregarding the hidpi scaling, there should be something else preventing this from working properly, which should itself be a separate task.

But the zoom level setting with "Use Same Aspect As Pixels" on shouldn't be a difficult fix, just need to multiply the zoom level with the dpi scale factor so that 100% zoom would really mean pixel-perfect... which should also be taken care in a separate task in my opinion.

dkazakov requested changes to this revision.Oct 4 2017, 10:09 AM

Hi, @alvinhochun!

I did some tests on my HiDPI device and I have found the following:

Testcase:

  1. Activate "Use same aspect as pixels" mode (a button at the bottom-right corner)
  2. Set zoom to 100%
  3. Take a screenshot and measure the size of the image on a screenshot (in pixels). It should be the same as the size of the image.

Here is what I observed:

  1. In HiDPI mode the canvas is painted in 2.5-3 times scaled mode
  2. It happens not due to any Qt's internal scaling, but due to the fact that we set transformation matrices incorrectly. The coordinate system of the widget is measured in hardware pixels, but we use logical pixels instead. Here is a patch that partially fixes the problem. After the patch the scaling matrices become correct and the image becomes scaled right (although the offset part is still incorrect).

It means that your proposed patch doesn't fix any real problem, it just workarounds our incorrect scaling of the image. The real fix for the problem would be to fix model matrix, so that the scaleX and scaleY would have correct values again.

This revision now requires changes to proceed.Oct 4 2017, 10:09 AM

I propose the following roadmap/requirements for the correct HiDPI fix:

  1. KisZoomController's zoom is relative to the hardware pixles. It corresponds to what the user sees in GUI.
  2. As a consequence, KoDPI should measure DPI relative to hardware pixels as well (needs checking all the uses!)
  3. KoCanvasControllerWidget and the hierarchy of scrolling/mirroring classes use logical pixels for its work (questionable, but they interact with widgets a lot).
  4. KisCoordinatesConverter's "widget coordinate system" represents physical coordinates
  5. We add one more coordinates system to KisCoordinatesConverter: "widget logical", which represents logical coordinates.
  6. KisOpenGLCanvas2 uses physical coordinates for rendering
  7. All the tools accept input events and render in physical coordinates (questionable?) and use the new converter's methods for the conversion (that ensures easy display migration)
  8. I don't know what to do with KisQPainterCanvas. I guess, we cannot technically make it render in physical coordinates, so we should just decide how it should handle zoom.
alvinhochun abandoned this revision.Oct 4 2017, 3:17 PM