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.
Now that we have the display's context to hook into, we can use it to
construct other GL contexts and don't need a GdkSurface vfunc anymore.
This has the added benefit that backends can have different GdkGLContext
classes on the display and get new GLContexts generated from them, so
we get multiple GL backend support per GDK backend for free.
I originally wanted to make this a vfunc on GdkGLContextClass, but
it turns out all the abckends would just call g_object_new() anyway.
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.
... or more exactly: Only use paint contexts with
gdk_cairo_draw_from_gl().
Instead of paint contexts being the only contexts who call swapBuffer(),
any context can be used for this, when it's used with
begin_frame()/end_frame().
This removes 2 features:
1. We no longer need a big sharing hierarchy. All contexts are now
shared with gdk_display_get_gl_context().
2. There is no longer a difference between attached and non-attached
contexts. All contexts work the same way.
The vfunc is called to initialize GL and it returns a "base" context
that GDK then uses as the context all others are shared with. So the GL
context share tree now looks like:
+ context from init_gl
- context1
- context2
...
So this is a flat tree now, the complexity is gone.
The only caveat is that backends now need to create a GL context when
initializing GL so some refactoring was needed.
Two new functions have been added:
* gdk_display_prepare_gl()
This is public API and can be used to ensure that GL has been
initialized or if not, retrieve an error to display (or debug-print).
* gdk_display_get_gl_context()
This is a private function to retrieve the base context from
init_gl(). It replaces gdk_surface_get_shared_data_context().
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.
Add support to share the WGL context in GDK with the WGL context in GStreamer,
so that we can also use OpenGL in the gstreamer media backend to playback
videos. For now OpenGL/ES is not supported for this under Windows.
The process of setting this up in Windows is a little bit more involved, as:
* The OpenGL support in GstGL requires a GL 4.1 Core context, but we may just
get the GL version from wglCreateContextAttribsARB() that we pass into the
attributes, which is 3.2 by default. So, try to ask for a 4.1 Core context
first if we are asking for anything less.
* There is only one GstDisplay available for Windows, so we just use
gst_gl_display_new().
* We must explicitly tell libepoxy that we are using wglMakeCurrent() outside
of libepoxy that is being used in GdkGL, otherwise we would end up crashing
as the GL/WGL function pointers would become invalid.
* We must also deactivate temporarily the underlying WGL context that was made
current by gdk_gl_context_make_current() so that when
gst_gl_display_create_context() calls wglShareLists(), we won't get bitten
by error 0xaa (resource busy), as some drivers don't handle this well when
the GL context is current in another thread.
For the last two points we make use of macros defined by the platforms that the
build is done for to help us carry out the necessary tasks as needed.
Thanks to Matthew Waters for the info on integrating GstGL and windowing
toolkits on Windows.
Some GL drivers such as Mesa-D3D12 do not allow one to call SetPixelFormat() on
a given HDC if one pixel format has been already set for it, so first check the
HDC with GetPixelFormat() to see whether a pixel format has already been set
with the HDC, and only attempt to acquire the pixel format if one has not been
set.
This will fix running with GL/NGL on Windows using the Mesa drivers.
In GTK4, we are now defaulting to the OpenGL renderer with the Cairo renderer
only used as a fallback, so there is no point keeping the code paths that use
layered windows as layered windows do not work well with OpenGL nor Vulkan.
gdk_gl_context_has_framebuffer_blit() and gdk_gl_context_has_frame_terminator()
were only used by by GDK/Win32, and they do not provide performance advantages
in GTK master, so clean up the code a bit by dropping them.
Use the shared function that was added in the previous commit, to simplify
things.
Also make gdk_win32_surface_get_queued_window_rect() and
gdk_win32_surface_apply_queued_move_resize() back into static functions, since
they are now used only by the code in gdksurface-win32.c
Like the other backends, we ought to create our WGL/EGL GL contexts like
the following:
"Create a global GL context that connects all GL contexts on a display
and lets us share textures between them."
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.
We need to use GL_BGRA instead of GL_RGBA when doing glReadPixels() on
EGL on Windows (ANGLE) so that the red and blue bits won't be displayed
inverted.
Also fix the logic where we determine whether to bit blit or redraw
everything.
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.
We preiously did not apply the resizes and moves as they were previously
only done in the Cairo drawing context on Win32. Fix this by applying
this too in the GL drawing context.
We used to pass 2 regions to GdkDrawCotnext.end_frame() but code was
confusing what they meant. So we now don't do that anymore and only pass
the region that matters: The frame region.
This is an automatic rename of various things related
to the window->surface rename.
Public symbols changed by this is:
GDK_MODE_WINDOW
gdk_device_get_window_at_position
gdk_device_get_window_at_position_double
gdk_device_get_last_event_window
gdk_display_get_monitor_at_window
gdk_drag_context_get_source_window
gdk_drag_context_get_dest_window
gdk_drag_context_get_drag_window
gdk_draw_context_get_window
gdk_drawing_context_get_window
gdk_gl_context_get_window
gdk_synthesize_window_state
gdk_surface_get_window_type
gdk_x11_display_set_window_scale
gsk_renderer_new_for_window
gsk_renderer_get_window
gtk_text_view_buffer_to_window_coords
gtk_tree_view_convert_widget_to_bin_window_coords
gtk_tree_view_convert_tree_to_bin_window_coords
The commands that generated this are:
git sed -f g "GDK window" "GDK surface"
git sed -f g window_impl surface_impl
(cd gdk; git sed -f g impl_window impl_surface)
git sed -f g WINDOW_IMPL SURFACE_IMPL
git sed -f g GDK_MODE_WINDOW GDK_MODE_SURFACE
git sed -f g gdk_draw_context_get_window gdk_draw_context_get_surface
git sed -f g gdk_drawing_context_get_window gdk_drawing_context_get_surface
git sed -f g gdk_gl_context_get_window gdk_gl_context_get_surface
git sed -f g gsk_renderer_get_window gsk_renderer_get_surface
git sed -f g gsk_renderer_new_for_window gsk_renderer_new_for_surface
(cd gdk; git sed -f g window_type surface_type)
git sed -f g gdk_surface_get_window_type gdk_surface_get_surface_type
git sed -f g window_at_position surface_at_position
git sed -f g event_window event_surface
git sed -f g window_coord surface_coord
git sed -f g window_state surface_state
git sed -f g window_cursor surface_cursor
git sed -f g window_scale surface_scale
git sed -f g window_events surface_events
git sed -f g monitor_at_window monitor_at_surface
git sed -f g window_under_pointer surface_under_pointer
(cd gdk; git sed -f g for_window for_surface)
git sed -f g window_anchor surface_anchor
git sed -f g WINDOW_IS_TOPLEVEL SURFACE_IS_TOPLEVEL
git sed -f g native_window native_surface
git sed -f g source_window source_surface
git sed -f g dest_window dest_surface
git sed -f g drag_window drag_surface
git sed -f g input_window input_surface
git checkout NEWS* po-properties po docs/reference/gtk/migrating-3to4.xml
Rename all *window.[ch] source files.
This is an automatic operation, done by the following commands:
for i in $(git ls-files gdk | grep window); do
git mv $i $(echo $i | sed s/window/surface/);
git sed -f g $(basename $i) $(basename $i | sed s/window/surface/) ;
done
git checkout NEWS* po-properties po
This renames the GdkWindow class and related classes (impl, backend
subclasses) to surface. Additionally it renames related types:
GdkWindowAttr, GdkWindowPaint, GdkWindowWindowClass, GdkWindowType,
GdkWindowTypeHint, GdkWindowHints, GdkWindowState, GdkWindowEdge
This is an automatic conversion using the below commands:
git sed -f g GdkWindowWindowClass GdkSurfaceSurfaceClass
git sed -f g GdkWindow GdkSurface
git sed -f g "gdk_window\([ _\(\),;]\|$\)" "gdk_surface\1" # Avoid hitting gdk_windowing
git sed -f g "GDK_WINDOW\([ _\(]\|$\)" "GDK_SURFACE\1" # Avoid hitting GDK_WINDOWING
git sed "GDK_\([A-Z]*\)IS_WINDOW\([_ (]\|$\)" "GDK_\1IS_SURFACE\2"
git sed GDK_TYPE_WINDOW GDK_TYPE_SURFACE
git sed -f g GdkPointerWindowInfo GdkPointerSurfaceInfo
git sed -f g "BROADWAY_WINDOW" "BROADWAY_SURFACE"
git sed -f g "broadway_window" "broadway_surface"
git sed -f g "BroadwayWindow" "BroadwaySurface"
git sed -f g "WAYLAND_WINDOW" "WAYLAND_SURFACE"
git sed -f g "wayland_window" "wayland_surface"
git sed -f g "WaylandWindow" "WaylandSurface"
git sed -f g "X11_WINDOW" "X11_SURFACE"
git sed -f g "x11_window" "x11_surface"
git sed -f g "X11Window" "X11Surface"
git sed -f g "WIN32_WINDOW" "WIN32_SURFACE"
git sed -f g "win32_window" "win32_surface"
git sed -f g "Win32Window" "Win32Surface"
git sed -f g "QUARTZ_WINDOW" "QUARTZ_SURFACE"
git sed -f g "quartz_window" "quartz_surface"
git sed -f g "QuartzWindow" "QuartzSurface"
git checkout NEWS* po-properties
Remove all the old 2.x and 3.x version annotations.
GTK+ 4 is a new start, and from the perspective of a
GTK+ 4 developer all these APIs have been around since
the beginning.
Since on Windows we need to use a good amount of temporary GL contexts,
we need to switch back to the original GL contexts we were using when
we are done with the temporary GL contexts, otherwise multi-GL windows
will cause confusions causing display artifacts and crashes.
Also, use the GdkWin32GLContext::gl_hdc consistently throughout
the code and remove the GdkWin32Display::gl_hdc as Lukas K pointed out
that GdkWin32Display::gl_hdc becomes out-of-date and so the HDC that the
GL context is bound to becomes incorrect in sceanarios using multiple
windows with GtkGLArea/GdkGLArea items (which would cause the artifacts in
programs that use multiple windows with GtkGLArea/GdkGLArea items, and it
turns out that GdkWin32Display::gl_hdc is actually not necessary to help
keep track of the HDCs we use for our GL contexts.
This will also fix on Windows with GDK_GL=always, or when GSK's gl
renderer is used.
Partly based on patch from Lukas K <lu@0x83.eu>
https://bugzilla.gnome.org/show_bug.cgi?id=789213
There were some parts that need some updates after the refactoring in
GDKGL, so that the code will continue to build and run.
For gdkwindow-win32.c, comment out the parts where we check for use_gl
(which was removed), since we are going to move all drawing to OpenGL,
but don't remove/disable the whole portion as that transition is not
complete at this point.
There a is new GDKGL function that checks for the damaged area of the back
buffer, but since the notion of "damage" is for *NIX (GLX/EGL for
Wayland/mir), meaning that there is no such extension for Windows in this
regard, so we can't support this on Windows as-is, at least for now.
https://bugzilla.gnome.org/show_bug.cgi?id=773299
... instead of a gl context.
This requires some refactoring in the way we mark the shared context as
drawing: We now call begin_frame/end_frame() on it and ignore the call
on the main context.
Unfortunately we need to do this check in all vfuncs, which sucks. But I
haven't found a better way.
No visible changes as GL rendering is disabled at the moment.
What was done:
1. Move window->invalidate_for_new_frame to glcontext->begin_frame
This moves the code to where it is used (the GLContext) and prepares it
for being called where it is used when actually beginning to draw the
frame.
2. Get rid of buffer-age usage
We want to let the application render directly to the backbuffer.
Because of that, we cannot make any assumptions about the contents the
application renders outside the clip area.
In particular GskGLRenderer renders random stuff there but not actual
contents.
3. Pass the actual GL context
Previously, we passed the shared context to end_frame, now we pass the
actual GL context that the application uses for rendering. This is so
that the vfuncs could prepare the actual contexts for rendering (they
don't currently).
4. Simplify the code
The previous code set up the final drawing method in begin_frame.
Instead, we now just ensure the clip area is something we can render
and decide on the actual method in end_frame.
This is both more robust (we can change the clip area in between if we
want to) and less code.
Commit d249e77 (API: screen: Remove gdk_screen_is_composited()) attempted
to update the GDK-Win32 for the removal of the API, but some parts were
missed. This updates the code so that things continue to build and run.
https://bugzilla.gnome.org/show_bug.cgi?id=773299
Update the GDKGL implementation:
-Allow legacy contexts to be created.
-Use finer-grained attributes to ask for a pixel format when possible,
which also adds support for anti-aliasing
In fact the changes here are required for GTKGL to work properly on
Windows for 4.x.
Note that creation of gles contexts is not done here, as the system does
not support such contexts directly on Windows, but only through means such
as ANGLE, which is a totally different issue here.
https://bugzilla.gnome.org/show_bug.cgi?id=773528
Other portions of the GDK-Win32 backend make use of this function as
layered windows need to be disabled for GL windows and possibly other
parts, so make this function a private function that is available within
the backend.
https://bugzilla.gnome.org/show_bug.cgi?id=763285
Layered windows and GL do not work well together, so disable layered
windows when initiating a GdkGLContext, so that GtkGLArea programs can run
properly.
Also based on patch by LRN to address the issue.
https://bugzilla.gnome.org/show_bug.cgi?id=763080
We now have proper checks for gdk_screen_is_composited() and a proper
implementation for gdk_screen_get_rgba_visual() for Windows, so we
can remove the comments in this file stating that they aren't
available for Windows.
The existence of OpenGL implementations that do not provide the full
core profile compatibility because of reasons beyond the technical, like
llvmpipe not implementing floating point buffers, makes the existence of
GdkGLProfile and documenting the fact that we use core profiles a bit
harder.
Since we do not have any existing profile except the default, we can
remove the GdkGLProfile and its related API from GDK and GTK+, and sweep
the whole thing under the carpet, while we wait for an extension that
lets us ask for the most compatible profile possible.
https://bugzilla.gnome.org/show_bug.cgi?id=744407
Now that we have a two-stages GL context creation sequence, we can move
the profile to a pre-realize option, like the debug and forward
compatibility bits, or the GL version to use.
Emit an error if the profile is different.
This is a follow-up commit to commits cc45e82 (x11/gl: Ensure we use the
3.2 core profile) and 2d9081d (wayland/gl: Ensure we use the 3.2 core
profile), so that we do the same on GDK-Win32. Update variable names and
comments so that the code is clearer to people, as we still need a
temporary legacy WGL context first before we can use
wglCreateContextAttribsARB() to create a WGL core (3.2+) context.
https://bugzilla.gnome.org/show_bug.cgi?id=741946