Add GetOpenGLScaleFactor() to abstract OpenGL coordinates scaling

The fix for OpenGL coordinates when using high DPI in b134589cbb (Fix
OpenGL samples when using HiDPI displays, 2019-08-06) did fix it for GTK
3 and macOS, but broke it for MSW and other platforms not using pixel
scaling, as window coordinates are the same as OpenGL ones there, while
GetContentScaleFactor() can still return values > 1 even on these
platforms.

Provide new GetOpenGLScaleFactor() function abstracting this platform
difference and use it in all OpenGL samples to make them work correctly
in high DPI under all platforms.

Closes https://github.com/wxWidgets/wxWidgets/pull/1944

Closes #17391.
This commit is contained in:
tm
2020-07-10 18:37:47 +02:00
committed by Vadim Zeitlin
parent 01d7fa8116
commit f6cc8ff52c
12 changed files with 50 additions and 7 deletions

View File

@@ -83,7 +83,7 @@ Changes in behaviour not resulting in compilation errors
- wxGLCanvas now uses physical pixels on high DPI displays under platforms - wxGLCanvas now uses physical pixels on high DPI displays under platforms
where they're different from logical ones (wxGTK3, wxOSX). Multiply logical where they're different from logical ones (wxGTK3, wxOSX). Multiply logical
coordinates, e.g. returned by wxWindow::GetSize() by GetContentScaleFactor() coordinates, e.g. returned by wxWindow::GetSize() by GetOpenGLScaleFactor()
before using them with OpenGL functions. before using them with OpenGL functions.
- wxGTK now uses wxID_NONE item ID for wxEVT_MENU_HIGHLIGHT events sent when - wxGTK now uses wxID_NONE item ID for wxEVT_MENU_HIGHLIGHT events sent when

View File

@@ -258,6 +258,11 @@ public:
// as a parameter // as a parameter
wxGLContextAttrs& GetGLCTXAttrs() { return m_GLCTXAttrs; } wxGLContextAttrs& GetGLCTXAttrs() { return m_GLCTXAttrs; }
// Return the factor to apply to transform window coordinates (e.g. sizes)
// to OpenGL coordinates: it can be different from 1 on the platforms where
// logical pixels are different from physical ones (i.e. wxGTK3 and wxOSX).
virtual double GetOpenGLScaleFactor() const;
// deprecated methods using the implicit wxGLContext // deprecated methods using the implicit wxGLContext
#if WXWIN_COMPATIBILITY_2_8 #if WXWIN_COMPATIBILITY_2_8
wxDEPRECATED( wxGLContext* GetContext() const ); wxDEPRECATED( wxGLContext* GetContext() const );

View File

@@ -60,6 +60,8 @@ public:
virtual bool SetBackgroundStyle(wxBackgroundStyle style) wxOVERRIDE; virtual bool SetBackgroundStyle(wxBackgroundStyle style) wxOVERRIDE;
virtual double GetOpenGLScaleFactor() const wxOVERRIDE;
// implement wxGLCanvasX11 methods // implement wxGLCanvasX11 methods
// -------------------------------- // --------------------------------

View File

@@ -100,7 +100,7 @@ public:
// implement wxGLCanvasBase methods // implement wxGLCanvasBase methods
virtual bool SwapBuffers() wxOVERRIDE; virtual bool SwapBuffers() wxOVERRIDE;
virtual double GetOpenGLScaleFactor() const wxOVERRIDE;
// Mac-specific functions // Mac-specific functions
// ---------------------- // ----------------------

View File

@@ -752,7 +752,7 @@ enum
platforms where wxWindow uses logical pixels, affected by the coordinate platforms where wxWindow uses logical pixels, affected by the coordinate
scaling, on high DPI displays. Thus, if you want to set the OpenGL view scaling, on high DPI displays. Thus, if you want to set the OpenGL view
port to the size of entire window, you must multiply the result returned by port to the size of entire window, you must multiply the result returned by
wxWindow::GetClientSize() by wxWindow::GetContentScaleFactor() before wxWindow::GetClientSize() by wxGLCanvas::GetOpenGLScaleFactor() before
passing it to @c glViewport(). Same considerations apply to other OpenGL passing it to @c glViewport(). Same considerations apply to other OpenGL
functions and other coordinates, notably those retrieved from wxMouseEvent functions and other coordinates, notably those retrieved from wxMouseEvent
in the event handlers. in the event handlers.
@@ -936,6 +936,23 @@ public:
*/ */
bool SetCurrent(const wxGLContext& context) const; bool SetCurrent(const wxGLContext& context) const;
/**
Returns the scale factor for transformation between logical and
physical OpenGL coordinates.
This factor is always 1 on the platforms where logical pixels are the
same as physical ones, in any DPI (such as MSW), but can be different
from it on the platforms where logical and physical pixels may differ
due to DPI scaling (such as GTK 3 or macOS).
To handle the differences between the platforms, always multiply the
values expressed in window coordinates (window sizes, mouse position
etc) by this factor before passing them to OpenGL functions.
@since 3.1.4
*/
double GetOpenGLScaleFactor() const;
/** /**
Swaps the double-buffer of this window, making the back-buffer the Swaps the double-buffer of this window, making the back-buffer the
front-buffer and vice versa, so that the output of the previous OpenGL front-buffer and vice versa, so that the output of the previous OpenGL

View File

@@ -349,7 +349,7 @@ void TestGLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event))
// multiple canvases: If we updated the viewport in the wxSizeEvent // multiple canvases: If we updated the viewport in the wxSizeEvent
// handler, changing the size of one canvas causes a viewport setting that // handler, changing the size of one canvas causes a viewport setting that
// is wrong when next another canvas is repainted. // is wrong when next another canvas is repainted.
const wxSize ClientSize = GetClientSize() * GetContentScaleFactor(); const wxSize ClientSize = GetClientSize() * GetOpenGLScaleFactor();
TestGLContext& canvas = wxGetApp().GetContext(this, m_useStereo); TestGLContext& canvas = wxGetApp().GetContext(this, m_useStereo);
glViewport(0, 0, ClientSize.x, ClientSize.y); glViewport(0, 0, ClientSize.x, ClientSize.y);

View File

@@ -280,7 +280,7 @@ void TestGLCanvas::OnSize(wxSizeEvent& event)
// This is OK here only because there is only one canvas that uses the // This is OK here only because there is only one canvas that uses the
// context. See the cube sample for that case that multiple canvases are // context. See the cube sample for that case that multiple canvases are
// made current with one context. // made current with one context.
const wxSize size = event.GetSize() * GetContentScaleFactor(); const wxSize size = event.GetSize() * GetOpenGLScaleFactor();
glViewport(0, 0, size.x, size.y); glViewport(0, 0, size.x, size.y);
} }

View File

@@ -306,7 +306,7 @@ void TestGLCanvas::ResetProjectionMode()
// or more than one wxGLContext in the application. // or more than one wxGLContext in the application.
SetCurrent(*m_glRC); SetCurrent(*m_glRC);
const wxSize ClientSize = GetClientSize() * GetContentScaleFactor(); const wxSize ClientSize = GetClientSize() * GetOpenGLScaleFactor();
// It's up to the application code to update the OpenGL viewport settings. // It's up to the application code to update the OpenGL viewport settings.
// In order to avoid extensive context switching, consider doing this in // In order to avoid extensive context switching, consider doing this in

View File

@@ -565,7 +565,7 @@ void MyGLCanvas::OnSize(wxSizeEvent& event)
SetCurrent(*m_oglContext); SetCurrent(*m_oglContext);
// It's up to the application code to update the OpenGL viewport settings. // It's up to the application code to update the OpenGL viewport settings.
const wxSize size = event.GetSize() * GetContentScaleFactor(); const wxSize size = event.GetSize() * GetOpenGLScaleFactor();
m_winHeight = size.y; m_winHeight = size.y;
m_oglManager->SetViewport(0, 0, size.x, m_winHeight); m_oglManager->SetViewport(0, 0, size.x, m_winHeight);

View File

@@ -376,6 +376,11 @@ bool wxGLCanvasBase::ParseAttribList(const int *attribList,
return true; return true;
} }
double wxGLCanvasBase::GetOpenGLScaleFactor() const
{
return 1.0;
}
// ============================================================================ // ============================================================================
// compatibility layer for OpenGL 3 and OpenGL ES // compatibility layer for OpenGL 3 and OpenGL ES
// ============================================================================ // ============================================================================

View File

@@ -271,4 +271,13 @@ void wxGLCanvas::GTKInitImplicitContext()
#endif // WXWIN_COMPATIBILITY_2_8 #endif // WXWIN_COMPATIBILITY_2_8
double wxGLCanvas::GetOpenGLScaleFactor() const
{
#ifdef __WXGTK3__
return GetContentScaleFactor();
#else
return 1.0;
#endif
}
#endif // wxUSE_GLCANVAS #endif // wxUSE_GLCANVAS

View File

@@ -562,6 +562,11 @@ bool wxGLCanvas::IsAGLMultiSampleAvailable()
return s_isMultiSampleAvailable != 0; return s_isMultiSampleAvailable != 0;
} }
double wxGLCanvas::GetOpenGLScaleFactor() const
{
return GetContentScaleFactor();
}
/* static */ /* static */
bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs) bool wxGLCanvasBase::IsDisplaySupported(const wxGLAttributes& dispAttrs)
{ {