kakashidinho / metalangle

MetalANGLE: OpenGL ES to Metal API translation layer
Other
461 stars 65 forks source link

scale versus native scale: difference between GLKit and MetalANGLE when display is zoomed #54

Open GrahamAsher opened 3 years ago

GrahamAsher commented 3 years ago

When using GLKit one has to use the native scale (the property UIScreen.main.nativeScale in Swift) and not the ordinary scale (UIScreen.main.scale) to avoid the view being cropped on iPhones when the user has selected zoomed display (Settings > Display & Brightness > Display Zoom > Set to Zoomed). This scale is used when converting to OpenGL coordinates in my test app.

However, the issue does not arise when using MetalANGLE. When I use MetalANGLE I can use UIScreen.main.scale at all times, whether or not the display is zoomed. I am not complaining ( am a very happy user of MetalANGLE), and it will be easy to explain the change to my users when moving to MetalANGLE, but it is an inconsistency between the two systems and there is therefore a case for removing the inconsistency.

For clarity, please note that this issue refers to display zoom (Settings > Display & Brightness > Display Zoom ) not zooming in for accessibility (Settings > Accessibility > Zoom).

kakashidinho commented 3 years ago

Sorry may I know how do you use UIScreen’s scale/nativeScale currently. MetalANGLE actually doesn’t interact with any of the above properties. It only interacts with CALayer.contentsScale/MGLKView.contentsScaleFactor.

GrahamAsher commented 3 years ago

@kakashidinho I use scale or nativeScale to calculate the transformation used in my rendering system to convert from my internal coordinate system based on notional pixels to the OpenGL coordinate system. Here's an example of the flow of control, using the case of a change of orientation between portrait and landscape:

My ViewController class initialises its m_ui_scale member, which is a double, like this

m_ui_scale = [[UIScreen mainScreen] nativeScale]; // when using GLKit, OR
m_ui_scale = [[UIScreen mainScreen] scale]; // when using MetalANGLE

The class receives notification of an orientation change in its viewWillTransitionToSize function:

-(void)viewWillTransitionToSize:(CGSize)aSize withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)aCoordinator
    {
    [super viewWillTransitionToSize:aSize withTransitionCoordinator:aCoordinator];
    if (!m_framework)
        return;
    [m_framework setMapWidth:aSize.width * m_ui_scale andHeight:aSize.height * m_ui_scale];
    }

It passes the width and height, multiplied by m_ui_scale, to my function to set the dimensions in pixels of the map to be drawn. Those dimensions are eventually used to calculate the transformation between pixels and the OpenGL coordinate set.

I suspect that the difference in behaviour is caused not by anything that MetalANGLE does, but by something it does not do. Perhaps GLKit makes an extra adjustment based on the native scale.

Please don't spend time on this unless there is an obvious fix. I would like the issue to be kept open if you wish, but with a low priority, because it doesn't cause any real difficulty.

kakashidinho commented 3 years ago

I think GLKit's view's default contentScaleFactor is set to [[UIScreen mainScreen] nativeScale]. Whereas, MetalANGLE's MGLKView's default contentScaleFactor is set to [[UIScreen mainScreen] scale].

The view's contentScaleFactor can be changed to the scale factor you want. It affects the rendering resolution of OpenGL.

Instead of

m_ui_scale = [[UIScreen mainScreen] nativeScale];
or m_ui_scale = [[UIScreen mainScreen] scale];

You can change it to:

m_ui_scale = yourView.contentScaleFactor;

Could you print this value when using GLKit and MetalANGLE? Let me know whether my assumption above is correct or not?

GrahamAsher commented 3 years ago

@kakashidinho Thanks for the suggestion. I found these values for contentScaleFactor on my iPhone 11 Pro:

Using GLKit: standard = 3.0, zoomed = 3.515625 Using MetalANGLE: standard = 3.0 zoomed = 3.0

Perhaps it would be a good idea to change MGLKView's default contentScaleFactor to the native scale for even better conformance with GLKit.

I'll now try using contentScaleFactor in both versions of my SDK to see if that's a better solution than my work-around.