From 7139f7baf0b81b7fa84449284ccc27d6fff7884c Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 7 Sep 2023 17:37:26 +0200 Subject: [PATCH 1/6] gl_renderer: use context attribs for every share context created --- src/gl_renderer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gl_renderer.c b/src/gl_renderer.c index 41cf0d3d..b73b8b02 100644 --- a/src/gl_renderer.c +++ b/src/gl_renderer.c @@ -130,6 +130,8 @@ static ATTR_PURE EGLConfig choose_config_with_pixel_format(EGLDisplay display, c return EGL_NO_CONFIG_KHR; } +static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + struct gl_renderer *gl_renderer_new_from_gbm_device( struct tracer *tracer, struct gbm_device *gbm_device, @@ -303,8 +305,6 @@ struct gl_renderer *gl_renderer_new_from_gbm_device( } } - static const EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - root_context = eglCreateContext(egl_display, forced_egl_config, EGL_NO_CONTEXT, context_attribs); if (root_context == EGL_NO_CONTEXT) { LOG_EGL_ERROR(eglGetError(), "Could not create EGL context for OpenGL ES. eglCreateContext"); @@ -567,7 +567,7 @@ EGLContext gl_renderer_create_context(struct gl_renderer *renderer) { ASSERT_NOT_NULL(renderer); pthread_mutex_lock(&renderer->root_context_lock); - context = eglCreateContext(renderer->egl_display, renderer->forced_egl_config, renderer->root_context, NULL); + context = eglCreateContext(renderer->egl_display, renderer->forced_egl_config, renderer->root_context, context_attribs); pthread_mutex_unlock(&renderer->root_context_lock); return context; @@ -602,7 +602,7 @@ int gl_renderer_make_this_a_render_thread(struct gl_renderer *renderer) { assert(is_render_thread == false); pthread_mutex_lock(&renderer->root_context_lock); - context = eglCreateContext(renderer->egl_display, renderer->forced_egl_config, renderer->root_context, NULL); + context = eglCreateContext(renderer->egl_display, renderer->forced_egl_config, renderer->root_context, context_attribs); pthread_mutex_unlock(&renderer->root_context_lock); if (context == EGL_NO_CONTEXT) { From 6e629b39e15f11a0c2eb099dd1e90dc4435e8edb Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 7 Sep 2023 17:39:18 +0200 Subject: [PATCH 2/6] gl_renderer: add _try_get_proc_address For trying to resolve a EGL/GL proc without printing an error message. Used by frame.c to resolve optional procs. --- src/gl_renderer.c | 6 ++++++ src/gl_renderer.h | 2 ++ src/plugins/gstreamer_video_player/frame.c | 5 ++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/gl_renderer.c b/src/gl_renderer.c index b73b8b02..fa54ed93 100644 --- a/src/gl_renderer.c +++ b/src/gl_renderer.c @@ -556,6 +556,12 @@ void *gl_renderer_get_proc_address(ASSERTED struct gl_renderer *renderer, const return get_proc_address(name); } +void *gl_renderer_try_get_proc_address(ASSERTED struct gl_renderer *renderer, const char *name) { + ASSERT_NOT_NULL(renderer); + ASSERT_NOT_NULL(name); + return try_get_proc_address(name); +} + EGLDisplay gl_renderer_get_egl_display(struct gl_renderer *renderer) { ASSERT_NOT_NULL(renderer); return renderer->egl_display; diff --git a/src/gl_renderer.h b/src/gl_renderer.h index d6c8160a..91aa24fe 100644 --- a/src/gl_renderer.h +++ b/src/gl_renderer.h @@ -61,6 +61,8 @@ EGLContext gl_renderer_create_context(struct gl_renderer *renderer); void *gl_renderer_get_proc_address(struct gl_renderer *renderer, const char *name); +void *gl_renderer_try_get_proc_address(ASSERTED struct gl_renderer *renderer, const char *name); + EGLDisplay gl_renderer_get_egl_display(struct gl_renderer *renderer); bool gl_renderer_supports_egl_extension(struct gl_renderer *renderer, const char *name); diff --git a/src/plugins/gstreamer_video_player/frame.c b/src/plugins/gstreamer_video_player/frame.c index 9d9291a0..281e0025 100644 --- a/src/plugins/gstreamer_video_player/frame.c +++ b/src/plugins/gstreamer_video_player/frame.c @@ -251,17 +251,16 @@ struct frame_interface *frame_interface_new(struct gl_renderer *renderer) { } // These two are optional. - // Might be useful in the future. #ifdef EGL_EXT_image_dma_buf_import_modifiers PFNEGLQUERYDMABUFFORMATSEXTPROC egl_query_dmabuf_formats = (PFNEGLQUERYDMABUFFORMATSEXTPROC - ) gl_renderer_get_proc_address(renderer, "eglQueryDmaBufFormatsEXT"); + ) gl_renderer_try_get_proc_address(renderer, "eglQueryDmaBufFormatsEXT"); if (egl_query_dmabuf_formats == NULL && supports_extended_imports) { LOG_ERROR("Could not resolve eglQueryDmaBufFormatsEXT egl procedure, even though it is listed as supported.\n"); supports_extended_imports = false; } PFNEGLQUERYDMABUFMODIFIERSEXTPROC egl_query_dmabuf_modifiers = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC - ) gl_renderer_get_proc_address(renderer, "eglQueryDmaBufModifiersEXT"); + ) gl_renderer_try_get_proc_address(renderer, "eglQueryDmaBufModifiersEXT"); if (egl_query_dmabuf_modifiers == NULL && supports_extended_imports) { LOG_ERROR("Could not resolve eglQueryDmaBufModifiersEXT egl procedure, even though it is listed as supported.\n"); supports_extended_imports = false; From f862e6fbecca6592c694a010bfcdd7c5d1449aba Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 7 Sep 2023 17:40:22 +0200 Subject: [PATCH 3/6] frame.c: don't print error messages two times --- src/plugins/gstreamer_video_player/frame.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/gstreamer_video_player/frame.c b/src/plugins/gstreamer_video_player/frame.c index 281e0025..f2ece259 100644 --- a/src/plugins/gstreamer_video_player/frame.c +++ b/src/plugins/gstreamer_video_player/frame.c @@ -233,20 +233,17 @@ struct frame_interface *frame_interface_new(struct gl_renderer *renderer) { PFNEGLCREATEIMAGEKHRPROC create_image = (PFNEGLCREATEIMAGEKHRPROC) gl_renderer_get_proc_address(renderer, "eglCreateImageKHR"); if (create_image == NULL) { - LOG_ERROR("Could not resolve eglCreateImageKHR EGL procedure.\n"); goto fail_destroy_context; } PFNEGLDESTROYIMAGEKHRPROC destroy_image = (PFNEGLDESTROYIMAGEKHRPROC) gl_renderer_get_proc_address(renderer, "eglDestroyImageKHR"); if (destroy_image == NULL) { - LOG_ERROR("Could not resolve eglDestroyImageKHR EGL procedure.\n"); goto fail_destroy_context; } PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture2d = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC ) gl_renderer_get_proc_address(renderer, "glEGLImageTargetTexture2DOES"); if (gl_egl_image_target_texture2d == NULL) { - LOG_ERROR("Could not resolve glEGLImageTargetTexture2DOES EGL procedure.\n"); goto fail_destroy_context; } From 7397aca9db22f0c28fac8b4ffb8db35720aea075 Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 7 Sep 2023 17:40:50 +0200 Subject: [PATCH 4/6] video player: fix egl format iterator for 0 supported formats --- src/plugins/gstreamer_video_player.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/gstreamer_video_player.h b/src/plugins/gstreamer_video_player.h index 02e6ed25..3773b471 100644 --- a/src/plugins/gstreamer_video_player.h +++ b/src/plugins/gstreamer_video_player.h @@ -200,7 +200,7 @@ ATTR_PURE int frame_interface_get_n_formats(struct frame_interface *interface); ATTR_PURE const struct egl_modified_format *frame_interface_get_format(struct frame_interface *interface, int index); #define for_each_format_in_frame_interface(index, format, interface) \ - for (const struct egl_modified_format *format = frame_interface_get_format((interface), 0), *guard = NULL; guard == NULL; \ + for (const struct egl_modified_format *format = frame_interface_get_n_formats(interface) > 0 ? frame_interface_get_format(interface, 0) : NULL, *guard = NULL; guard == NULL; \ guard = (void *) 1) \ for (size_t index = 0; index < frame_interface_get_n_formats(interface); index++, \ format = (index) < frame_interface_get_n_formats(interface) ? frame_interface_get_format((interface), (index)) : NULL) From f342f1018a67ace5fad3e8dc814091f2980aca62 Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 7 Sep 2023 17:41:51 +0200 Subject: [PATCH 5/6] video player: fix appsink caps Only set the formats supported by the appsink when we know the formats supported for EGL import. --- src/plugins/gstreamer_video_player/player.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/plugins/gstreamer_video_player/player.c b/src/plugins/gstreamer_video_player/player.c index 8c948cda..220e0055 100644 --- a/src/plugins/gstreamer_video_player/player.c +++ b/src/plugins/gstreamer_video_player/player.c @@ -916,17 +916,19 @@ static int init(struct gstplayer *player, bool force_sw_decoders) { // configure our caps // we only accept video formats that we can actually upload to EGL - GstCaps *caps = gst_caps_new_empty(); - for_each_format_in_frame_interface(i, format, player->frame_interface) { - GstVideoFormat gst_format = gst_video_format_from_drm_format(format->format); - if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) { - continue; - } + if (frame_interface_get_n_formats(player->frame_interface) > 0) { + GstCaps *caps = gst_caps_new_empty(); + for_each_format_in_frame_interface(i, format, player->frame_interface) { + GstVideoFormat gst_format = gst_video_format_from_drm_format(format->format); + if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) { + continue; + } - gst_caps_append(caps, gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, gst_video_format_to_string(gst_format), NULL)); + gst_caps_append(caps, gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, gst_video_format_to_string(gst_format), NULL)); + } + gst_app_sink_set_caps(GST_APP_SINK(sink), caps); + gst_caps_unref(caps); } - gst_app_sink_set_caps(GST_APP_SINK(sink), caps); - gst_caps_unref(caps); gst_app_sink_set_callbacks( GST_APP_SINK(sink), From 03b73ebe101004a03e5f4cc84ea990d210a30d84 Mon Sep 17 00:00:00 2001 From: Hannes Winkler Date: Thu, 7 Sep 2023 20:07:18 +0200 Subject: [PATCH 6/6] video player: use fallback list for pixel formats Use a fallback list consisting of ARGB8888, XRGB8888, YUYV, NV12, YUV420, YUV444, XYUV8888 if querying the supported formats for import is not supported. --- src/plugins/gstreamer_video_player/frame.c | 34 ++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/plugins/gstreamer_video_player/frame.c b/src/plugins/gstreamer_video_player/frame.c index f2ece259..c722a589 100644 --- a/src/plugins/gstreamer_video_player/frame.c +++ b/src/plugins/gstreamer_video_player/frame.c @@ -277,8 +277,38 @@ struct frame_interface *frame_interface_new(struct gl_renderer *renderer) { UNREACHABLE(); #endif } else { - n_formats = 0; - formats = NULL; + // If EGL doesn't support querying the supported formats & modifiers for import, + // use a static list of formats that mostly work. + // + // This can happen on ARM Mali for example: + // =================================== + // EGL information: + // version: "1.4 Midgard-"r18p0-01rel0"" + // vendor: "ARM" + // client extensions: "EGL_EXT_client_extensions EGL_EXT_platform_base EGL_KHR_client_get_all_proc_addresses EGL_KHR_platform_gbm EGL_MESA_platform_gbm EGL_KHR_platform_wayland EGL_EXT_platform_wayland" + // display extensions: "EGL_WL_bind_wayland_display EGL_KHR_partial_update EGL_KHR_image_pixmap EGL_EXT_image_dma_buf_import EGL_KHR_config_attribs EGL_KHR_image EGL_KHR_image_base EGL_KHR_fence_sync EGL_KHR_wait_sync EGL_KHR_gl_colorspace EGL_KHR_get_all_proc_addresses EGL_IMG_context_priority EGL_ARM_pixmap_multisample_discard EGL_ARM_implicit_external_sync EGL_KHR_gl_texture_2D_image EGL_KHR_gl_renderbuffer_image EGL_KHR_create_context EGL_KHR_surfaceless_context EGL_KHR_gl_texture_cubemap_image EGL_EXT_create_context_robustness" + // =================================== + // OpenGL ES 2.x information: + // version: "OpenGL ES 3.2 v1.r18p0-01rel0.db8fd8841edf74cef96ef24ce665edac" + // shading language version: "OpenGL ES GLSL ES 3.20" + // vendor: "ARM" + // renderer: "Mali-T860" + // =================================== + // + /// TODO: For each format, try creating a GBM bo and importing, to see if it + /// actually works. + static const struct egl_modified_format fallback_formats[] = { + {DRM_FORMAT_ARGB8888, DRM_FORMAT_MOD_INVALID, false}, + {DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_INVALID, false}, + {DRM_FORMAT_YUYV, DRM_FORMAT_MOD_INVALID, false}, + {DRM_FORMAT_NV12, DRM_FORMAT_MOD_INVALID, false}, + {DRM_FORMAT_YUV420, DRM_FORMAT_MOD_INVALID, false}, + {DRM_FORMAT_YUV444, DRM_FORMAT_MOD_INVALID, false}, + {DRM_FORMAT_XYUV8888, DRM_FORMAT_MOD_INVALID, false}, + }; + + n_formats = ARRAY_SIZE(fallback_formats); + formats = memdup(fallback_formats, sizeof(fallback_formats)); } interface->gbm_device = gbm_device;