Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] New: Detect display scaling, cleanup in X11 API #1324

Open
wants to merge 32 commits into
base: 3.x
Choose a base branch
from

Conversation

leezer3
Copy link
Contributor

@leezer3 leezer3 commented Sep 6, 2021

Purpose of this PR

This PR adds detection of the current display scaling factor to OpenTK 3.x
The Windows, SDL2 and OS-X backends have been implemented.

It adds a single Vector2 to the DisplayDevice properties, containing the X / Y scaling factors of the display. What it doesn't do is to attempt to do anything with this- It's left for the developer to handle appropriately as they desire.

The Linux backend at the minute hasn't got any DPI / scale factor detection. From some digging, this (as seems usual) can be found in any one of 3-4 places, depending on the DE, WM etc.

It also does a considerable amount of cleanup and commenting in the X11 API.

Testing status

  • Windows and SLD2 self-tested.
  • OS-X self-tested on a non Retina display. User tested on a Retina display.

Comments

I'm ambivilant as to whether the backend should silently handle the scaling as 4.x does.
As 3.x is largely EOL however, this seems to be a simple quality of life addition, and allows those of us using 3.x to handle this better than at the minute.

#47

@leezer3
Copy link
Contributor Author

leezer3 commented Sep 6, 2021

Values were the wrong way round, but now confirmed as working on Retina.

@NogginBops NogginBops added the 3.x label Sep 6, 2021
@NogginBops NogginBops added this to the 3.3.3 milestone Sep 6, 2021
@NogginBops
Copy link
Member

Very nice addition to have!
I'll have to look at this more carefully at a later date, but we absolutely want to get something like this into OpenTK 3.

As usual the Linux backend is going to be quite a pain here right? No standard API to get the stuff you want.

Maintaining the platform backends is worthwhile as we think about the future versions of OpenTK where we long-term want to be more independent of current third-party libraries like GLFW.

@leezer3
Copy link
Contributor Author

leezer3 commented Sep 6, 2021

Nope sadly not.
There's an X-atom, which is set by some, a GTK window property and others I forget off the top of my head. All DE / WM dependant.

Retina is the one I'm concerned about, as most / all new Macs are this. Mac users don't tend to be the most technical either, unlike Linux :p

@leezer3
Copy link
Contributor Author

leezer3 commented Sep 7, 2021

Some more minor cleaning in the X11 driver bases, in preparation for possibly trying to read the X-atom.

The entire Linux backend however is somewhat of a mess, and I get the very strong suspicion that we could probably remove a bunch of it without doing any damage whatsoever. Last real update for most parts seems to have been ~2010.

TLDR:
I'm finding workarounds for stuff in Ubuntu 7.10, which went EOL over 11 years ago & XMing on Windows (Last updated 7-8 years ago & gone proprietary to boot)

I don't especially want to start a wholesale backend rewrite (not to mention that I'm hacking this together on the fly as I go along....) but at the same time, some of this needs to be dumped to make the thing more maintainable

@leezer3
Copy link
Contributor Author

leezer3 commented Sep 7, 2021

@NogginBops @varon A query:
How happy are you with dumping unused / unreferenced methods (as opposed to commented out stuff)?
The X11 drivers seem to have quite a few of these....

My instinct is to get rid of these as a total maintenence burden, but you might want to keep.

…nt resolution, not initial load resolution (#2)

* screen scaling value is now a dynamic value

* scalefactor of a displaydevice class is now from the displaydevice
class

* fix issue where sdl2 displaydevice initalizer accidentally had a
vector2 input
@andylin2004
Copy link

Bumping this--I was the other person who helped make the PR. Are there any updates on this PR or implementing this?

@NogginBops
Copy link
Member

NogginBops commented Sep 20, 2021

How happy are you with dumping unused / unreferenced methods (as opposed to commented out stuff)?
The X11 drivers seem to have quite a few of these....

Ideally this should be handled on a case by case basis. Some comments/code can be useful even if they are commented out as they contain some kind of knowledge that will be relevant to anyone touching the code. Other times they are just fluff and should be removed.
So if you start removing some of the stuff you feel can be removed we can look at that @leezer3 . :)

Is there some way to get a more proper X11 implementation for this PR or is that a huge workload?

@leezer3
Copy link
Contributor Author

leezer3 commented Sep 22, 2021

Added some basic X11 DPI detection and a bit of further junk removal.

This is how GLFW originally did it ( glfw/glfw@3b070ea ), along with polling the X11 resources.
At some stage (I'm not going to backtrack exactly when), they switched to the X11 resources only.

We don't currently have any code accessing the X11 resources, but this should work as a basic first step.
Not absolutely thrilled about the location of the scale factor, but se what you think @NogginBops

Copy link
Member

@NogginBops NogginBops left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is shaping up to being really nice!
Just found one little bug. :)

src/OpenTK/Platform/X11/X11DisplayDevice.cs Outdated Show resolved Hide resolved
src/OpenTK/Platform/X11/X11DisplayDevice.cs Outdated Show resolved Hide resolved
@leezer3
Copy link
Contributor Author

leezer3 commented Sep 23, 2021

Fudge, typo....
Will fix later.

Might as well check for zero physical w / h while I'm at itp

Presumably it got rewritten at some stage in the past and this abandoned....
@leezer3
Copy link
Contributor Author

leezer3 commented Sep 23, 2021

Dealt with.

Have also removed some more duplicate cruft- Plenty more of that to go, but probably is going to want a new PR for major cleaning....

@leezer3 leezer3 changed the title [3.x] New: Detect display scaling [3.x] New: Detect display scaling, cleanup in X11 API Sep 30, 2021
@leezer3
Copy link
Contributor Author

leezer3 commented Sep 30, 2021

Added some more brackets and a comment.
Some more junk removal for good measure.

@andylin2004
Copy link

Just wondering--how far are we with code review?

@NogginBops
Copy link
Member

I haven't looked at this since the last review.
Will try to look at it later today or tomorrow.

@leezer3
Copy link
Contributor Author

leezer3 commented Oct 16, 2021

Minor ping :)

I've added XML-doc to essentially all the X11 function imports we're actually using (so much easier to see what's going on), and done some further marginal junk removal. None of this is really relevant to the original core PR, but makes things a lot more useful in there for future changes & actually understanding what's happening.

Haven't really touched any serious cleanup / re-writes at the minute, as noted above that's really a future PR at some stage.

@@ -148,7 +146,6 @@ internal sealed class X11GLNative : NativeWindowBase
private readonly IntPtr EmptyCursor;

#pragma warning disable 414 // Field assigned but never used, we do that on purpose
private readonly bool xi2_supported;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this field removed and not the others here? To me it would only make sense to keep the all or remove them all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually use the version number itself here:

if (xi2_version >= 210)

As the opcode is technically part of the version number string, keeping it seemed logical too. Left the pragma there to suppress the fact we don't use it.

Could probably re-hack slightly to use the underlying variable this refers to inside the X11 mouse / keyboard driver, but that's heading towards the re-write.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think we could keep this field, it's unnecessary to remove it.
If we are really unlucky someone uses reflection to read the value of this variable.

@leezer3
Copy link
Contributor Author

leezer3 commented Nov 23, 2021

Ping @NogginBops anything else you want?

We've also just discovered what I think is an unrelated issue caused by X11 DnD in our fork, which I'm going to try and look into this week.
In an ideal world, don't want to start adding yet more junk to this PR.

@leezer3
Copy link
Contributor Author

leezer3 commented Dec 22, 2021

Bump.

One further small bugfix in the SDL2 backend, but nothing else of interest.

Copy link
Member

@NogginBops NogginBops left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apparently left a review half finished on this.
Here is what I had written at that time, not sure if it's entirely relevant.

If you could ping me again sometime between christmas and newyears I can probably take a closer look at this then.

src/OpenTK/Math/Vector3d.cs Show resolved Hide resolved
src/OpenTK/Platform/DisplayDeviceBase.cs Outdated Show resolved Hide resolved
@leezer3
Copy link
Contributor Author

leezer3 commented Dec 28, 2021

Ping @NogginBops
Couple more minor fixes pulled in, but essentially waiting on anything you want.

@leezer3
Copy link
Contributor Author

leezer3 commented Feb 15, 2022

Another ping @NogginBops

Copy link
Member

@NogginBops NogginBops left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made a more thorough review now.
Hopefully we can get this merged soon 🙂

Comment on lines +35 to +40
public abstract bool TryChangeResolution (DisplayDevice device, DisplayResolution resolution);
public abstract bool TryRestoreResolution (DisplayDevice device);
public abstract Vector2 GetDisplayScaling (DisplayIndex displayIndex);

// Gets the DisplayDevice that corresponds to the specified index.
public virtual DisplayDevice GetDisplay(DisplayIndex index)
public virtual DisplayDevice GetDisplay (DisplayIndex index)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a small style nitpick we tend to not have spaces between the method name and the parens.

Comment on lines +396 to +399
public override Vector2 GetDisplayScaling (DisplayIndex displayIndex)
{
return new Vector2 (1, 1);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we always return (1, 1) here?

(also the space between the method name and parens 🙂 )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not implemented in this specific backend at the minute. (2x native Linux backends....)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there plans to implement it in this backend?

Comment on lines +119 to +131
//Copy the current display mode and take a pointer to it
IntPtr displayMode = CG.CopyDisplayMode(currentDisplay);
//Pull out the scaled width and height
int scaledWidth = (int)CG.GetModeWidth(displayMode);
int scaledHeight = (int)CG.GetModeHeight(displayMode);
//Pull out the raw width and height
int rawWidth = (int)CG.GetModePixelWidth(displayMode);
int rawHeight = (int)CG.GetModePixelHeight(displayMode);
//Remember to release the display mode
CG.ReleaseDisplayMode(displayMode);

float pixelScaleW = (float)rawWidth / scaledWidth;
float pixelScaleH = (float)rawHeight / scaledHeight;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pixelScaleW and pixelScaleH are never used in this code? I'm guessing this is something that never got removed?

Comment on lines -1328 to +1286
else
{
return XCreateWindow(display, parent, x, y, width, height, border_width, depth,
(int)@class, visual, (IntPtr)valuemask, null);
}

return XCreateWindow(display, parent, x, y, width, height, border_width, depth,
(int)@class, visual, (IntPtr)valuemask, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to keep this else, attributes.HasValue has two outcomes and it not really a guard clause.

Comment on lines -388 to 395
else if (vsync_mesa_supported)
if (vsync_mesa_supported)
{
return Glx.Mesa.GetSwapInterval();
}
else if (vsync_sgi_supported)
if (vsync_sgi_supported)
{
return sgi_swap_interval;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should this no longer be an else-if chain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat depends on the style you want here, both are exactly the same in practice.
This way is IMHO cleaner (and is what ReSharper prefers)

Thoughts FWIW:
You first should check for the XExtension version of vsync, as this is the newest / most common method of doing things.
Checking for the mesa vysnc support is a reasonable fallback.
SGI_SWAPINTERVAL is mega old, and quite often broken, and should be ignored unless we have anything else.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should still be an else-if chain to make clear that two of these should not be true at the same time. I would be confused by this code if it was written without the else-if chaining.

src/OpenTK/Platform/X11/X11GLNative.cs Show resolved Hide resolved
Comment on lines -1011 to -1014
else if (e.ClientMessageEvent.message_type == _atom_xdnd_leave)
{
break;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove this code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to go back and check, but IIRC it can never be true from here.

@@ -30,5 +30,6 @@ internal interface IDisplayDeviceDriver
bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution);
bool TryRestoreResolution(DisplayDevice device);
DisplayDevice GetDisplay(DisplayIndex displayIndex);
Vector2 GetDisplayScaling (DisplayIndex displayIndex);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Space between method name and paren.

{
return null;
}
return AvailableDevices [(int)index];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Space between name and parens.

Comment on lines +64 to +70
float pixelScaleD, pixelScaleW, pixelScaleH;
//Get display DPI from SDL
SDL.GetDisplayDPI(d, out pixelScaleD, out pixelScaleW, out pixelScaleH);
//Convert to scale factor using default 96DPI
pixelScaleD /= 96.0f;
pixelScaleW /= 96.0f;
pixelScaleH /= 96.0f;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pixelScaleD, pixelScaleW, and pixelScaleH are never used here, guessing this is a mistake?

Experimental, not handled by Win or Mac yet...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants