examples/glupload: Provide new shared `GLContext` via pad probe
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.