Use &__ImageBase for the GTK DLL and GetModuleHandle (NULL)
for the application module. Then remove DllMain as it's not
necessary anymore.
References:
[1] Accessing the current module's HINSTANCE from a static library:
https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483
If we are querying the best supported pixel format for our HDC via
wglChoosePixelFormatARB() (i.e. we have the WGL_ARB_pixel_format extension),
it may return a pixel format that is different from the pixel format that we
used for the dummy context that we have setup, in order to, well, run
wglChoosePixelFormatARB(), which sadly requires a WGL context (HGLRC) to be
current in order to use it, which means the dummy HDC already has a pixel
format that has been set (notice that each HDC is only allowed to have its
pixel format to be set *once*). This is notably the case on Intel display
drivers.
Since we are emulating surfaceless GL contexts, we are using the dummy GL
context (and thus dummy HDC that is derived from the notification HWND used in
GdkWin32Display) for doing that, we would get into trouble if th actual HDC
from the GdkWin32Surface has a different pixel format set.
So, as a result, in order to fix this situation, we do the following:
* Create yet another dummy HWND in order to grab the HDC to query for the
capabilities the GL drivers support, and to call wglChoosePixelFormatARB() as
appropriate (or ChoosePixelFormat()) for the final pixel format that we use.
* Ditch the dummy GL context, HDC and HWND after obtaining the pixel format.
* Then set the final pixel format that we obtained onto the HDC that is derived
from the HWND used in GdkWin32Display for notifications, which will become our
new dummy HDC.
* Create a new dummy HGLRC for use with the new dummy HDC to emulate surfaceless
GL support.
This way, we can realize it and either print success information about
it or return NULL if that fails.
This makes it more likely that we fail early, which means we can then
initialize EGL.
When using GDK_DEBUG=gl-egl, we end up using GL, but that is not well supported:
Creating EGL context version 3.0 (debug:no, forward:no, legacy:yes, es:no)
Created EGL context[0000000000000004]
OpenGL version: 0.0 (legacy)
* GLSL version: (NULL)
* Max texture size: -1059701680
* Extensions checked:
- GL_KHR_debug: no
- GL_EXT_unpack_subimage: yes
- OES_vertex_half_float: no
** (gtk4-demo.exe:14324): WARNING **: 19:16:41.468: Compile failure in
vertex shader:
ERROR: 0:7: 'gl_Position' : undeclared identifier
---8<---
Use GLES when EGL implementation is ANGLE.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
As per Benjamin's suggestions, cleanup the previous implementation on
initializing the GLES context on Windows, so that we use more items that are
already in GDK proper and integrate two functions into one.
We are now able to create EGL contexts properly on Windows, but not GLES. This
tries to fix things by doing the following:
* Record the GL context type in a more proper fashion, using an Enum. This
makes things a bit cleaner.
* Force GLES-3.0+ contexts, since libANGLE requires this to properly work with
the shaders-its 2.0 contexts don't work well with our shaders.
The old code used repeated calls to `ToUnicodeEx` to populate
the translation table, which is slow and buggy. The new code
directly loads the layout driver DLLs from Windows.
See https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/4338
Use the debug envvar 'GDK_DEBUG=gl-egl' to determine whether we want to try to
initialize EGL first before trying WGL, as a means for people to more easily
enable EGL support on Windows to test EGL there (such as to debug the shaders,
for instance)
This will port the EGL code in GDK-Win32 to use the common GDK code to
initialize EGL. However, at the current state, although EGL is
correctly initialized, this code is disabled for now since
gdk_gl_context_make_current() fails as the shaders do not work for EGL
via libANGLE on Windows.
We can now clean things up in gdkglcontext-win32-egl.c as a result.
We have a global GdkGLBackendType now, just set it.
This way, using the variable forces the backend type, and we don't need
special code handling the env vars in the backends.
It also means setting the env var will now "work" on GDK backends that
don't even support that GL backend and simualte another GDK backend
having registered that GL backend already. So you can run
GDK_DEBUG=gl-wgl gtk4-demo
on test what Wayland will do when WGL is in use.
On Windows, GLES is not that widely available unless one installs wrapper
libraries such as libANGLE, so GLES/EGL support on Windows is used more like
a fallback mode if Desktop OpenGL (WGL) support is inadequate on the system.
Hence, unless one forces WGL or EGL, we will first try to initialize WGL, and
then try to initialize GLES if enabled and if WGL initialization failed, and
then just return whatever the last result we can obtain from these
initialization attempts, since unlike X11 EGL contexts, we do not have
separate modes for WGL except for legacy and non-legacy contexts.
It is basically not used by default and is pretty much broken at this point, so
it's about time to drop it.
Let's focus on fixing the OLE2 DnD protocol.
The dummy Win32 window that we use to capture display change events and
to create dummy WGL contexts was created with CS_OWNDC, so we really do
not need to (and should not) call ReleaseDC() on the HDC that we
obtained from it, so drop these calls.
Since the shaders need to be updated for using with GLES (libANGLE at
least), default to WGL for now. Unfortunately it is not that common for
Windows to have GLES support, in which the easiest way to obtain such
support is via Google's libANGLE.
This commit attempts to split GdkWin32GLContext into two parts, one for
WGL and the other for EGL (ANGLE), and attempts to simplify things a
bit, by:
* We are already creating a Win32 window to capture display changes,
so we can just use that to act as our dummy window that we use to
find out the pixel format that the system supports for WGL. We also
use it to obtain the dummy legacy WGL context that we will always
require to create our more advanced Core WGL contexts.
* Like what is done in X11, store up the WGL pixel format or the
EGLConfig in our GdkWin32Display.
* Ensure we do not create the dummy WGL context unnecessarily.
In this way, we can successfully create the WGL/EGL contexts, however
there are some issues at this point:
* For WGL, the code successfully initializes and realizes the WGL
Contexts, but for some reason things became invisible. When running
gtk4-demo, this can be verified by seeing the mouse cursor changing
when moved to spots where one can resize the window, although they
were invisible.
* For EGL, the code initializes EGL but could not realize the EGL
context as shaders failed to compile. It seems like the shader issue
is definitely outside the scope of this MR.
Instead of
Display::make_gl_context_current()
we now have
GLContext::clear_current()
GLContext::make_current()
This fits better with the backends (we can actually implement
clearCurrent on macOS now) and makes it easier to implement different GL
backends for backends (like EGL/GLX on X11).
We also pass a surfaceless boolean to make_current() so the calling code
can decide if a surface needs to be bound or not, because the backends
were all doing whatever, which was very counterproductive.
Make _gdk_win32_display_get_monitor_scale_factor() less complex, by:
* Drop the preceding underscore.
* Dropping an unused parameter.
* Using a GdkSurface instead of a HWND, as the HWND that we pass into
this function might have been taken from a GdkSurface, which are now
always created with CS_OWNDC. This means if a GdkSurface was passed
in, we ensure that we only acquire the DC from the HWND once, and do
not attempt to call ReleaseDC() on it.
* Store the HDC that we acquire from the GdkSurface's HWND into the
surface, and use that as the HDC we need for our GdkGLContext.
* Drop the gl_hwnd from GdkWin32Display, as that is really should be
stored in the GdkSurface.
* For functions that were updated, name GdkWin32Display variables as
display_win32 and GdkSurface variables as surface, to unify things.
* Stop calling ReleaseDC() on the HDC that we use for OpenGL, since
they were acquired from HWND's created with CS_OWNDC.
This allows us to use DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 for the
DPI awareness mode, which will help us to better support use cases with
multiple monitors. This is actualy a more advaned version of the
current PROCESS_PER_MONITOR_DPI_AWARE via using SetProcessDpiAwareness().
Note that this is not enabled by default, but also enabled via using
GDK_WIN32_PER_MONITOR_HIDPI, as in the PROCESS_PER_MONITOR_DPI_AWARE
case.
Note also, that appliation compatibility settings and DPI-awareness
manifests takes precedence over this API call, as before.
If GLES support is enabled on Windows, force GLES mode if we are running
on a ARM64 version of Windows (i.e. Windows 10 for ARM).
This is required as ARM64 versions of Windows only provide a software
implementation of OpenGL 1.1/1.2, which is not enough for our purposes.
Thus, we could make instead use the GLES support provided via Google's
libANGLE (which emulates OpenGL/ES 3 with Direct3D 9/11), so that we
can run GtkGLArea programs under OpenGL/ES in ARM64 versions of Windows.
Note that eventually we could update the libepoxy build files for Windows
to not check nor enable WGL when building for ARM64 Windows, as the WGL
items do not work, although they do build.
This is for adding a EGL-based renderer which is done via the ANGLE
project, which translate EGL calls to Direct3D 9/11. This is done as a
possible solution to issue #105, especially for cases where the needed
full GL extensions to map OpenGL to Direct3D is unavailable or
unreliable, or when the OpenGL implementation from the graphics drivers
are problematic.
To enable this, do the following:
-Build ANGLE and ensure the ANGLE libEGL.dll and libGLESv2.dll are
available. A sufficiently-recent ANGLE is needed for things to
work correctly--note that the copy of ANGLE that is included in
qtbase-5.10.1 is sufficient. ANGLE is licensed under a BSD 3-clause
license.
-Build libepoxy on Windows with EGL support enabled.
-Currently, prior to running GTK+ programs, the GDK_DEBUG envvar needs
to be set with gl-gles as at least one of the flags.
Known issues:
-Only OpenGL ES 3 is supported, ANGLE's ES 2 does not support the needed
extensions, notably GL_OES_vertex_array_object, but its ES 3 support is
sufficient.
-There is no autodetection or fallback mechanism to enable using
EGL/Angle automatically yet. There are no plans to do this in this
commit.
It's not a portable API, so remove it. The corresponding backend
specific functions are still available, if they were implemented, e.g.
gdk_macos_monitor_get_workarea() and gdk_x11_monitor_get_workarea().