Bug 510541 - [HighDPI] Autoscale problems with OGL canvas
Summary: [HighDPI] Autoscale problems with OGL canvas
Status: ASSIGNED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.7   Edit
Hardware: PC Windows NT
: P3 normal with 1 vote (vote)
Target Milestone: ---   Edit
Assignee: Platform-SWT-Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-01-16 22:15 EST by Lee Carver CLA
Modified: 2019-12-12 12:05 EST (History)
6 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lee Carver CLA 2017-01-16 22:15:42 EST
Autoscaling (new in Neon) seems to work fine for SWT widgets, but it poses a problem in OGL rendering.

https://github.com/eclipse/eclipse.platform.swt/commit/e02d49aefe42ac4c77b81048299ab069ddb5c2ba#diff-3f7fffce9718089b7671f258f1f20bba).

For the best OGL rendering, I need the OS's actual pixel size for the client area, not the autoscaled approximation.

I use a HiRES Levono with a 4K screen (3840x2160).  This leads the DPIUtil class to establish a deviceZoom of 200.  In org.eclipse.swt.widgets.Scrollable.getClientArea(), the value from getClientAreaInPixels() is autoScaleDown() (line 206).  This causes the returned client rectangle to be half the width and height of the actual pixels.  When these dimensions are used in the GL2.glViewport(), the rending space is the bottom left corner of the rectangle.  The effective canvas is 1/4 the available space.

Ideally, I should be able to get the raw client area that is provided by the OS canvas window.  One solution would be to make getClientAreaInPixels() a public method.  I do not like a solution to up-scale the down-scaled rectangle.  This would cause rounding errors that might limit the screen space or exceed the window clipping.  Neither are desirable.
Comment 1 Niraj Modi CLA 2017-01-17 03:20:41 EST
(In reply to Lee Carver from comment #0)
> Autoscaling (new in Neon) seems to work fine for SWT widgets, but it poses a
> problem in OGL rendering.
Can you share an SWT snippet for your use-case showing the problem, to reproduce at our end ?

> https://github.com/eclipse/eclipse.platform.swt/commit/
> e02d49aefe42ac4c77b81048299ab069ddb5c2ba#diff-
> 3f7fffce9718089b7671f258f1f20bba).
> 
> For the best OGL rendering, I need the OS's actual pixel size for the client
> area, not the autoscaled approximation.
SWT widgets are not much affected by autoscaled approximation of coordinates at high zoom at integer ScaleFactors.

Note: There exists option to disable the SWT level autoScaling by adding this VM argument in eclipse.ini or on the command line after -vmargs:
-Dswt.autoScale=false
Comment 2 Lee Carver CLA 2017-01-17 10:49:19 EST
The problem occurs in this sequence of code:


    Rectangle rect = canvas.getClientArea();
    gl.glViewport(0, 0, rect.width, rect.height);

If the client rectangle is subjected to DPIUtil.autosScaleDown() modifications, the glViewport is miss sized.  The call to glViewport requires the actual number of screen pixels in the canvas rectangle.
Comment 3 Lee Carver CLA 2017-01-17 10:51:12 EST
Turning off SWT level autoScaling for the entire process is not an acceptable answer.  Only the OGL canvas requires the devise level pixels.

The execution of SWT level autoScaling for other Eclipse widgets (non-OGL canvas) is great.
Comment 4 Niraj Modi CLA 2017-01-24 03:58:17 EST
(In reply to Lee Carver from comment #3)
> Turning off SWT level autoScaling for the entire process is not an
> acceptable answer.  Only the OGL canvas requires the devise level pixels.
> 
> The execution of SWT level autoScaling for other Eclipse widgets (non-OGL
> canvas) is great.

Apart for below mentioned call as in comment 2:
    Rectangle rect = canvas.getClientArea();
    gl.glViewport(0, 0, rect.width, rect.height);

Are there more any more scenario/api where you need to directly deal with actual pixel count ?
Comment 5 Lee Carver CLA 2017-01-24 09:09:45 EST
I found that I also needed to scale mouse events to handle selection on the OGL canvas.

https://github.com/google/depan/commit/817b066aa10c726dc769635e86189bd8d92b47e0
- Scale OGL canvas to actual pixels,

https://github.com/google/depan/commit/ea0e8e96300e1336bb9219d675ccd449782fa24a
- Multiple changes, mouse fixes near end in "picker" support methods.

https://github.com/google/depan/commit/7dcbc11f8065114d611bb0e1d32ce49232849543
- Cleanup fixes

My guess is that getting the actual mouse pixel is going to be a challenge, since the standard SWT mouse event handlers are used (addMouseListener(), etc., GLScene@151)

Perhaps the OGL canvas object (e.g. GLCanvas(parent, SWT.NO_BACKGROUND, data)) can be marked as unscaled so all interactions (getClientArea(), mouse events) for this rectangle are screen level pixels.
Comment 6 Niraj Modi CLA 2017-01-27 06:43:07 EST
Since HiDPI feature bug 479614, all bounds/dimension information exchanged with SWT APIs will be in Points(a coordinate system independent of device DPI) instead of previously supported Pixels(which varies as per device DPI)

As of today, only way to exchange Pixels information with SWT is by disabling this feature via options shared in comment 1(which applies to the entire application).
-----------------------------------------------------------------

I don't see a direct solution for the hybrid support(Point + Pixels both).
Possible workaround that exists is via consuming SWT internal APIs(downside of using internal API is they are subjected to change/removed without prior notice)

- Convert the Points information that you receive from SWT to Pixels using:
DPIUtils.autoScaleUp (Drawable drawable, Point point)
DPIUtils.autoScaleUp (Drawable drawable, Rectangle rect)
- Convert the Pixels information back to Points before sending it to SWT using:
DPIUtils.autoScaleDown (Drawable drawable, Point point)
DPIUtils.autoScaleDown (Drawable drawable, Rectangle rect)
[Note: You can pass the Display instance which is an implementation of Drawable]

Hope this helps.
Comment 7 Lee Carver CLA 2017-02-15 15:30:54 EST
Upscaling from "point" resolution to pixel resolution has multiple problems:

1) A small amount of screen space (top and right edge) becomes unavailable if the actual rectangle size is not an exact multiple of the point scaling factor.  

2) Mouse tracking and selection is slightly jerky, since some "points" are aliases for multiple pixels.

One alternative direction might be to add a small number of pixel-based APIs to the OGL Canvas widget.

My primary reason for this high resolution screen is to exploit that resolution for highly detailed renderings.  Having to effectively "give up" half of that resolution is not a satisfactory resolution.
Comment 8 Lee Carver CLA 2017-02-15 15:31:56 EST
Upscaling from "point" resolution to pixel resolution has multiple problems:

1) A small amount of screen space (top and right edge) becomes unavailable if the actual rectangle size is not an exact multiple of the point scaling factor.  

2) Mouse tracking and selection is slightly jerky, since some "points" are aliases for multiple pixels.

One alternative direction might be to add a small number of pixel-based APIs to the OGL Canvas widget.

My primary reason for this high resolution screen is to exploit that resolution for highly detailed renderings.  Having to effectively "give up" half of that resolution is not a satisfactory resolution.
Comment 9 Steven Darnell CLA 2018-06-04 18:36:23 EDT
Has there been any progress with HiDPI support and OpenGL in SWT over the past year?

I work on a production scientific RCP application that suffers from the problem Lee describes in Comment 0. What is the recommended way to resolve the Points/Pixel problem for GLCanvas?