On certain GL drivers on Windows (e.g. those for Intel Arc) we see that
creation of a shared context based on our wrapped WGL context (from
`glutin`) fails with `ERROR_BUSY`:
0:00:00.509113900 29460 000001E07A782CC0 DEBUG glcontext gstglcontext.c:1227:gst_gl_context_create_thread:<glcontextwgl0> Creating thread
0:00:00.509352100 29460 000001E07A782CC0 FIXME glcontext gstglcontext.c:2041:gst_gl_wrapped_context_get_config:<glwrappedcontext0> wrapped context could not retrieve config. The application may be missing a call to gst_gl_context_fill_info() or the specific platform implemention is not implemented for retrieving the config from a wrapped OpenGL context.
0:00:00.543157300 29460 000001E07A782CC0 INFO glcontext gstglcontext_wgl.c:402:gst_gl_context_wgl_choose_format:<glcontextwgl0> chosen config gst-gl-context-config, platform=(GstGLPlatform)GST_GL_PLATFORM_WGL, red-size=(int)8, blue-size=(int)8, green-size=(int)8, alpha-size=(int)8, depth-size=(int)24, stencil-size=(int)8, native-visual-id=(uint)5, surface-type=(GstGLConfigSurfaceType)GST_GL_CONFIG_SURFACE_TYPE_WINDOW;
0:00:00.543770000 29460 000001E07A782CC0 INFO glcontext gstglcontext.c:1322:gst_gl_context_create_thread:<glcontextwgl0> Attempting to create opengl context. user chosen api(s) (any), compiled api support (opengl opengl3) display api (any)
0:00:00.553201100 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:186:gst_gl_context_wgl_create_context: gl context created: 65537
0:00:00.613589500 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:214:gst_gl_context_wgl_create_context:<glcontextwgl0> Available WGL extensions WGL_EXT_depth_float WGL_ARB_buffer_region WGL_ARB_extensions_string WGL_ARB_make_current_read WGL_ARB_pixel_format WGL_ARB_pbuffer WGL_EXT_extensions_string WGL_EXT_swap_control WGL_ARB_multisample WGL_ARB_pixel_format_float WGL_ARB_framebuffer_sRGB WGL_ARB_create_context WGL_ARB_create_context_profile WGL_EXT_pixel_format_packed_float WGL_EXT_create_context_es_profile WGL_EXT_create_context_es2_profile WGL_NV_DX_interop WGL_NV_DX_interop2 WGL_ARB_robustness_application_isolation WGL_ARB_robustness_share_group_isolation WGL_ARB_create_context_robustness WGL_ARB_context_flush_control
0:00:00.614036500 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 4.5 context
0:00:00.631649700 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 4.4 context
0:00:00.650484600 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 4.3 context
0:00:00.669332300 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 4.2 context
0:00:00.687633700 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 4.1 context
0:00:00.706444500 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 4.0 context
0:00:00.725763400 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 3.3 context
0:00:00.745413200 29460 000001E07A782CC0 DEBUG glcontext gstglcontext_wgl.c:235:gst_gl_context_wgl_create_context:<glcontextwgl0> trying to create a GL 3.2 context
0:00:00.781065300 29460 000001E07A782CC0 WARN glcontext gstglcontext.c:1326:gst_gl_context_create_thread:<glcontextwgl0> Failed to create context
0:00:00.781358600 29460 000001E076862100 INFO glcontext gstglcontext.c:1079:gst_gl_context_create:<glcontextwgl0> gl thread created
0:00:00.781584200 29460 000001E076862100 DEBUG glcontext gstglcontext.c:746:gst_gl_context_finalize:<glcontextwgl0> End of finalize
0:00:00.781787700 29460 000001E076862100 WARN glbasefilter gstglbasefilter.c:608:gst_gl_base_filter_find_gl_context_unlocked:<gluploadelement0> error: failed to share contexts through wglShareLists 0xaa
0:00:00.782145700 29460 000001E076862100 INFO glcontext gstglcontext.c:349:gst_gl_context_new: creating a context for display <gldisplay0>, user choice:(null)
0:00:00.782381300 29460 000001E076862100 DEBUG glcontext gstglcontext.c:383:gst_gl_context_new:<glcontextwgl1> Done creating context for display <gldisplay0> (user_choice:(null))
0:00:00.782632900 29460 000001E076862100 DEBUG glcontext gstglcontext.c:1058:gst_gl_context_create:<glcontextwgl1> other_context:<glwrappedcontext0>
0:00:00.782921300 29460 000001E076862100 INFO glwindow gstglwindow.c:295:gst_gl_window_new: creating a window, user choice:(null)
0:00:00.783246300 29460 000001E076862100 DEBUG glcontext gstglcontext.c:956:gst_gl_context_set_window:<glcontextwgl1> window:<glwindowwin32-1>
0:00:00.783815200 29460 000001E07A782D00 DEBUG glcontext gstglcontext.c:1227:gst_gl_context_create_thread:<glcontextwgl1> Creating thread
0:00:00.784130000 29460 000001E07A782D00 FIXME glcontext gstglcontext.c:2041:gst_gl_wrapped_context_get_config:<glwrappedcontext0> wrapped context could not retrieve config. The application may be missing a call to gst_gl_context_fill_info() or the specific platform implemention is not implemented for retrieving the config from a wrapped OpenGL context.
thread 'main' panicked at examples\src\bin\..\glupload.rs:755:44:
called `Result::unwrap()` on an `Err` value: Received error from /GstPipeline:pipeline0/GstGLSinkBin:glsinkbin0/GstGLUploadElement:gluploadelement0: failed to share contexts through wglShareLists 0xaa (debug: Some("../gst-libs/gst/gl/gstglbasefilter.c(608): gst_gl_base_filter_find_gl_context_unlocked (): /GstPipeline:pipeline0/GstGLSinkBin:glsinkbin0/GstGLUploadElement:gluploadelement0"))
This happens because the context is made "current" inside
the `winit` loop before asynchronous GL initialization inside
GStreamer creates a shared context for contexts replied to
`NeedContext("gst.gl.app_context")`. `wglShareLists()` requires neither
context to be current on separate threads. As we have a `Surface` on
the `glutin` side, we're not uncurrenting it anymore, and instead want
to perform GStreamer initialization up-front without a thread, or on a
separate `GLContext`.
One way to prevent GStreamer from creating yet another context on top
of our wrapped context asynchronously, is by creating a new shared GL
context based on our wrapped (WGL) context ourselves.
By adding that context to `GLDisplay` (that we provide in the
relevant `gst.gl.GLDisplay` context query) instead of via the
`gst.gl.app_context` `NeedContext` query, the underlying initialization
code no longer attempts to create a shared context because it
will use the one from `GLDisplay` directly (specifically in e.g.
`gst_gl_base_filter_find_gl_context_unlocked()`).
The preferred way however is to reply this new shared context to
a `Query` for the `gst.gl.local_context` context, which arbitrary
applications can achieve by inserting a pad probe on one of the pads
in the pipeline. GL elements and functions like the one mentioned above
call into `gst_gl_query_local_gl_context()` which performs this query in
both directions, before reading contexts from `GLDisplay` or ultimately
sending a `NeedContext` message outlined above.
With this patch the initialization flow becomes clear from the logs,
where the above lines that will call `wglShareLists()` are now called
directly when `gl_context.create(wrapped_context)` is called in our
Rust code.
In theory, since `GLContext` tracks whether it is current and on
which thread, the upsteam source should emit an error of sorts when
`wglShareLists()` is called on a thread where this `other_context` in
`gst_gl_context_create(_thread)` was not yet current, to not make such
mistakes go unnoticed as most drivers (i.e. AMD's) seem to not make an
issue out of it.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1486>
WGL does not have the concept of a `Display` connection, presumably
because there's always only one compositor active. All interop
and sharing is happening from the `Context` afterwards.
After all `glutin` doesn't have a pointer inside `RawDisplay::Wgl`,
and upstream `gstreamer` code creates a dummy display on Win32.
WINRT is not taken into account & tested yet.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1468>
Using terminate() kills the whole process instead of just stopping the event loop, so we're back to the 'old' way.
However, if the provided function finishes too early, that can also fail (will call stop() on a not-yet-running NSApp).
Creating a delegate and waiting for the callback makes sure NSApp is running before the actual main() is called.
Also, for whatever reason only tutorials were changed to use terminate(). Now both tutorials and examples are
using identical code.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1378>
Enables subclassing gst_rtsp_server::RTSPAuth and overriding its
authenticate/check/generate_authenticate_header methods
Also add new methods in RTSPContext to retrieve RTSP request/response, and to
get/replace tokens.
Additionally, added RTSPMessage with methods to add an authentication
header to a request / retrieve authentication parameters from a
response.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1359>
Glutin completely detached from `winit` in the `0.30` upgrade, concerning
itself exclusively with OpenGL and WSI APIs around it and leaving any
windowing system interop to the `raw-window-handle` crate specifically
designed for this purpose.
This untanglement massively cleans up and simplifies the `glutin`
codebase, and expands on surfaceless rendering as well as drawing to
simple views (textures) on the screen as is common on Android, without
having control over the entire "window" and event loop.
Some winit boilerplate is however still provided as part of the
`glutin-winit` crate. Most of the `glutin`+`winit` flow in this
`glupload` example is adopted from `glutin`'s example, following
platform-specific initialization sequences that heavily clutter the code
(only creating a window upfront on Windows, only forcing transparency on
macOS, and trying various fallback attributes to create a context).
At the same time `winit`'s `Event::Resumed` and `Event::Suspended`
event strategy is adopted: this event was previously for Android and
iOS exclusively - where window handles come and go at the merit of
the OS, rather than existing for the lifetime of the application -
but is now emitted on all platforms for consistency. A `Surface` (via
`RawWindowHandle`) is only available and usable after `Event::Resumed`,
where we can create a GL surface and "current" the context on that
surface for rendering. This is where the `GstPipeline` will be set
to `Playing` so that data starts flowing. The inverse should happen in
`Event::Suspended` where the `Surface` has to be given up again after
un-currenting, before giving control back to the OS to free the rest of
the resources. This will however be implemented when Android is brought
online for these examples.
Finally, now that the `gst-gl-egl` and `gst-gl-x11` features turn on
the relevant features in `glutin` and `winit`, it is now possible to
easily test `x11` on Wayland (over XWayland) without even unsetting
`WAYLAND_DISPLAY`, by simply compiling the whole stack without EGL/
Wayland support (on the previous example `winit` would always default to
a Wayland handle, while `glupload` could only create `GstGLDisplayX11`).
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1336>
This is what you get with an untyped API. `glGetError()` further down
the line was returning `GL_INVALID_OPERATION` and failing other calls
after `load()` in the `glutin 0.31` upgrade. This turns out to be
[returned by `glGetProgramiv`] when the `program` that is passed in
does not refer to a program object. Which was the case here, where the
fragment shader identifier was passed in instead.
Just in case we insert a few extra asserts that check the result of
`glGetError()` to catch such issues earlier on in the chain, instead of
postponing them and falsely accusing code that runs later.
[returned by `glGetProgramiv`]: https://registry.khronos.org/OpenGL-Refpages/es2.0/xhtml/glGetProgramiv.xml#errors
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1336>
`GstGLDisplayWayland` calls GstGLDisplayEGL::from_gl_display()` under
the hood (which calls `GstGLDisplayEGL::from_native()`, which calls
`eglGetPlatformDisplay()`) to retrieve the underlying `EGLDisplay`
handle, which thus far seems to be the same value as `glutin`. However,
newer `glutin 0.31` passes attributes to this function resulting in a
different handle, causing all kinds of trouble further down the line
when sharing resources between `glutin` and `gstreamer-rs` that both
operate on a distinct `EGLDisplay`.
Furthermore `GstGLDisplayEGL` thinks that it uniquely owns the
handle returned by `eglGetPlatformDisplay()` and _does not_ set
`.foreign_display = TRUE` (which `GstGLDisplayEGL::with_egl_display()`
would), causing it to call `eglTerminate()` as soon as the
`GstGLDisplay` is destroyed, leaving `glutin` dysfunctional.
To solve all of this, simply remove this wrongly-behaving class from the
example as it is not suitable for sharing an `EGLDisplay` with `glutin`.
It might however be interesting to create a different example that
showcases how to use raw window handles instead of EGL/GLX handles,
however only Wayland and any platform on EGL like Android, via
`GstGLDisplayEGL::from_native()`, support this.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1336>
It is annoying to see only a single line of error when debugging a chain
of (e.g. `anyhow::Context::context()`-created) errors, and have a
zero exit-code while at it.
Instead Rust supports returning a `Result` type straight from main which
is `Debug`- instead of `Display`-printed, so that - in the case of
`anyhow::Error` - all nested (via `.source()`) `Error`s are printed in
backtrace-like form, and the exit code is appropriately non-zero.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1336>
In preparation to make a more specialized VideoFrameGL this extracts
common helper functions valid for all VideoFrames into a trait that can
be implemented without too much code duplication.
Note that this is a breaking change, now VideoFrame and VideoFrameRef
cannot really be used without include the gst_video prelude.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1312>