Bug 1373 - Support High-DPI across Platforms and Modules
Summary: Support High-DPI across Platforms and Modules
Alias: None
Product: General
Classification: JogAmp
Component: generic (show other bugs)
Version: 2.5.0
Hardware: All all
: P4 major
Assignee: Sven Gothel
Depends on: 741 1120 1130 1322 1351 1358 1374 1421 1422
  Show dependency treegraph
Reported: 2019-04-04 21:00 CEST by Sven Gothel
Modified: 2023-07-12 01:18 CEST (History)
0 users

See Also:
SCM Refs:
cfc35549810d3a0fb5eeb866c9450417e48cd8a1 43dc472c4797f34e4079028a5eb04bc420c11c2a 1d4c077b29a69fd13526dfd25d00ee87c0d5b3fe ab6d84721e2a15550289e14b751e06701bd68726 6eb13066996e94b2fe40bf64e74ea43d8f4e9171 97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef 7982cc52344c025c40da45fd4b946056a63bc855 309cd9fb55d57739f08147840165910f59c4b432 cfe56e9e6bda15873fefce6f03d343ccdfc51f9b 9d1e7c9adca97780a5b45b135c5693cffee218fc fd575243e2c8754bc4580526de05462761c320ab e01bfdc83c70ca63d52dee086a5c8584d7662252 80ccc1f98f0c1391acc6d27de82eac97ca1c27b9 900c35c6a49e0d53e38dd07da709bf81e28abd3e
Workaround: ---


Note You need to log in before you can comment on or make changes to this bug.
Description Sven Gothel 2019-04-04 21:00:49 CEST

Comment 1 Sven Gothel 2019-04-04 23:45:24 CEST
It shall be noted that the overall High-DPI problem only exists
due to applications using fixed dimensions in pixel-space
instead of using normalized vectors, millimeters and actual DPI.

With the availability of high resolution monitors beyond 
the historical ~80 dpi capability, 
High-DPI screens of 160 dpi and higher became available.

Hence pixel sized artifacts and whole windows were 'shrunk' 
when based on ~80 dpi screens by: 160/80 on both dimensions.
Meaning the content was cut to quarter size roughly in total.

Hence Apple introduced their 'pixelScale' to their OSX with the 
advent of their first High-DPI screen Retina.
They simply set 'pixelScale' to 2 to multiply the window dimensions
and even created a mode to scale the pixel framebuffer content 
to the actual double sized framebuffer target. 
The latter soothed the GPU requirements as their performance was lagging
the boosted DPI. GPU's would need to cover 4x more pixels.

Today this should not matter really anymore
and users are advised to use a 'good' screen layout based 
on the monitor size and DPI.
The content should be rendered at native full resolution of course,
which also helps with natural anti-aliasing.

However, many OS and toolkit API's are using a fixed 90 DPI pixel based 
layout optionally or by default.

Hence our NativeWindow specification uses 'window units':
   * Returns the width of the client area excluding insets (window decorations) in window units.
   * @return width of the client area in window units
   * @see NativeSurface#getSurfaceWidth()
  public int getWidth();

and our NativeSurface is using actual 'pixel units'
   * Returns the width of the client area excluding insets (window decorations) in pixel units.
   * @return width of the client area in pixel units
   * @see NativeWindow#getWidth()
   * @see #convertToWindowUnits(int[])
  public int getSurfaceWidth();


OSX uses a monitor related 'float[2] pixelScale', 
which we have adopted in bug 1120 and OSX High-DPI fix in bug 741.

Our groundwork for High-DPI support indeed has been done for bug 741.


See also: AWT Java 9+ related: 'JEP 263: HiDPI Graphics on Windows and Linux' 
Comment 2 Sven Gothel 2023-02-02 23:46:48 CET
We have added support for Windows and X11,
reading the respective UI 'soft' scale factor of the respective 
OS setting as explained in Bug 1374 Comment 7.

Remaining task would be the following,
noted in Bug 1374 Comment 12:


Requirement of mapping window-units  <-> pixel-units
taking the monitor viewport layout into account.

X11/Windows: A simple scaling of the window-units position is not suitable due to multiple monitors,
i.e. a window-units gap will be created and fullscreen/spanning coordinates will be wrong.

TODO: Implement seamless conversion of units incl. monitor viewport mapping
- X11, Windows: Recalculate monitor window-units viewport (native is pixels)
- MacOS Recalculate monitor pixel-units viewport (native is 'points', aka window-units)

Impact will be to have the ability to use either pixel- or window-units
for positioning and size and hence be fully platform independent.
Comment 3 Sven Gothel 2023-07-12 01:04:44 CEST
NEWT Soft-PixelScale (Windows and X11) p1 - p6
- cfc35549810d3a0fb5eeb866c9450417e48cd8a1
- 43dc472c4797f34e4079028a5eb04bc420c11c2a
- 1d4c077b29a69fd13526dfd25d00ee87c0d5b3fe
- ab6d84721e2a15550289e14b751e06701bd68726
- 6eb13066996e94b2fe40bf64e74ea43d8f4e9171
- 97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef


commit cfc35549810d3a0fb5eeb866c9450417e48cd8a1

    NEWT Soft-PixelScale (p1): WindowImpl: Separate window and pixel units for size and position via atomic-replacable int arrays
    NEWT's Soft-PixelScale supports software pixel-scale by multiplying the underlying surface pixel-size with the scale-factor
    and dividing the window position and size by same scale-factor.
    Hence the window position and size space is kept virtually steady at virtually assumed DPI 96 at higher actual screen DPI
    and the surface size is adjusted.
    This window- and pixel-unit separation also includes all callbacks for the native driver implementations,
    hence the changes native code - allowing to determine whether window- or pixel-units were given.


commit 43dc472c4797f34e4079028a5eb04bc420c11c2a

    NEWT Soft-PixelScale (p2): MonitorDevice: Add getOrientationTo(..) to determine the orientation of this monitor to the other incl. the 'move_diff'
    move_diff int[2] to store the move delta for each axis from this-monitor to the other
    This will be utilized when a NEWT window moved across monitors to signal the move_diff,
    which helps to properly adjust the new position.
    Tested: All 4 monitor crossings right_of, left_of, above and below.
    TODO: Test and support a 'diagonal' move, i.e. move_diff on both axis.


commit 97b79ad351e48e7d3c6f9c95bacdf4f9d5d158ef

    NEWT Soft-PixelScale (p6): Implement Soft-PixelScale for X11 and Windows ... (working state)
    - Using Soft-PixelScale mode, i.e. converting all given window-units to pixel-units for native GDI/X11 ops
    - Using scaled pixel-sized surface
    - Adjusting NEWT's Monitor's window-unit viewport value to pixel-scale
    For X11:
    - Using global scale factor from environment variable, either: "GDK_SCALE", "QT_SCALE_FACTOR" or "SOFT_SCALE".
      The latter is for testing only.
      See https://wiki.archlinux.org/title/HiDPI
    For Windows:
    - Using actual monitor's pixel-scale via native SHC API (Shellscaling API, shcore.dll)
    - SurfaceScaleUtils.getGlobalPixelScaleEnv() reads a float value from given env names, first come, first serve
    - MonitorModeProps.streamInMonitorDevice(..): Add `invscale_wuviewport` argument to scale wuvieport for soft-pixel-scale
    - TestGearsNEWT: Enhance GL2 demo to be suitable for manual tests, this since my Windows KVM machine doesn't support ES2
    - TestGLContextDrawableSwitch10NEWT: Add a few more test constraints .. working
    - Manually on a Windows virtual machine (KVM) using
      - 2 virtualized 'Video QXL' cards and
      - and 'remote-viewer' to see the 2 monitors
        since `Virtual Machine Manager` build-in doesn't support
        - remote-viewer spice://localhost:5917
    - Manually on a Linux machine w/ SOFT_SCALE
    - Both, X11 and Windows
      - Place window on each monitor
      - Move window across monitors w/ pixel-scale change (or not)
    - TODO: Test and fix utilization with AWT, i.e. NewtCanvasAWT
Comment 4 Sven Gothel 2023-07-12 01:05:56 CEST
commit 7982cc52344c025c40da45fd4b946056a63bc855 (tag: v2.4.0, soft_scale_2)

    NEWT Soft-PixelScale (p7): get{Global->}PixelScaleEnv(..): Support per monitor values w/ QT_SCREEN_SCALE_FACTORS syntax, use for X11
    Per-monitor values are parsed if value is not a float and stored
    in a given Map<String,float[2]>, parallel to a detected global_pixel_scale_xy.
    The per-monitor value syntax matches QT_SCREEN_SCALE_FACTORS,
    i.e. the regular expression '(<string>=<float>;)+',
    e.g. QT_SCREEN_SCALE_FACTORS='DP-1=1.25;DP-2=1.25;HDMI-1=1.25;'
    The per-monitor value is preferred and on X11 stored within the MonitorDevice,
    matching the MonitorDevice's name.
    The following env-var names are searched on X11:
Comment 5 Sven Gothel 2023-07-12 01:09:50 CEST
commit 309cd9fb55d57739f08147840165910f59c4b432

    HiDPI: TestGearsES2NEWT: Show MonitorDevice properties, validating pixelScale

commit cfe56e9e6bda15873fefce6f03d343ccdfc51f9b

    HiDPI: NEWT/MacOS: WindowDriver.sizeScreenPosInsetsChanged() is called w/ client-area in windowUnits (*fix regression*)

commit 9d1e7c9adca97780a5b45b135c5693cffee218fc

    HiDPI AWT/NEWT: Propagate AWT enforced pixelScale via setSurfaceScale() blocking native change by monitor-pixelScale (Windows, X11)

commit fd575243e2c8754bc4580526de05462761c320ab

    SurfaceScaleUtils: Remove unused isZero(..)

commit e01bfdc83c70ca63d52dee086a5c8584d7662252

    HiDPI: Revert WindowImpl.applySoftPixelScale()'s if( DEBUG...) { ..; dumpStack(); }

commit 80ccc1f98f0c1391acc6d27de82eac97ca1c27b9

    HiDPI: Complete testing on Windows (AWT, NEWT, AWT+NEWT): AWT pixel scale propagated properly to our AWT GLCanvas and NEWT

Comment 6 Sven Gothel 2023-07-12 01:15:18 CEST
commit 900c35c6a49e0d53e38dd07da709bf81e28abd3e

    HiDPI: Revise AWT GLCanvas/GLJPanel ScalableSurface: No setSurfaceScale(), have AWT toolkit define pixelScale only (simplification)
    This aligns with Glenn's initial AWT patch commit e5e7514d649cd7dd28bbb8e04b72338dc09c2c83, i.e. removing redundancies...
    Tested on Linux, Windows and MacOS w/ GLCanvas, GLJPanel and GLWindow using pixelScale values:
    - Linux: 1, 2
    - Windows: 1, 1.25, 2
    - MacOS: 1, 2
Comment 7 Sven Gothel 2023-07-12 01:18:38 CEST
Additional reference