diff --git a/src/gl_renderer.c b/src/gl_renderer.c index 41cf0d3d..fa54ed93 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"); @@ -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; @@ -567,7 +573,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 +608,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) { 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.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) diff --git a/src/plugins/gstreamer_video_player/frame.c b/src/plugins/gstreamer_video_player/frame.c index 9d9291a0..c722a589 100644 --- a/src/plugins/gstreamer_video_player/frame.c +++ b/src/plugins/gstreamer_video_player/frame.c @@ -233,35 +233,31 @@ 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; } // 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; @@ -281,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; 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),