libs: display: driver quirks mechanism

This mechanism comes from ffmpeg vaapi implementation, where they have
their own quirks.

A specific driver is identified by a substring present in the vendor
string. If that substring is found, a set of bitwise flags are store.
These flags can be accessed through the function
gst_vaapi_display_has_driver_quirks().

The purpose for this first quirks is to disable the put image try for
AMD Gallium driver (see [1]).

1. https://gitlab.freedesktop.org/gstreamer/gstreamer-vaapi/merge_requests/72
This commit is contained in:
Víctor Manuel Jáquez Leal 2020-01-16 11:49:21 +01:00
parent 7a186975cc
commit ee3d4c3206
4 changed files with 87 additions and 18 deletions

View file

@ -755,6 +755,55 @@ cleanup:
return success; return success;
} }
/* Ensures the VA driver vendor string was copied */
static gboolean
ensure_vendor_string (GstVaapiDisplay * display)
{
GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
const gchar *vendor_string;
GST_VAAPI_DISPLAY_LOCK (display);
if (!priv->vendor_string) {
vendor_string = vaQueryVendorString (priv->display);
if (vendor_string)
priv->vendor_string = g_strdup (vendor_string);
}
GST_VAAPI_DISPLAY_UNLOCK (display);
return priv->vendor_string != NULL;
}
static void
set_driver_quirks (GstVaapiDisplay * display)
{
GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
guint i;
/* *INDENT-OFF* */
static const struct
{
const char *match_string;
guint quirks;
} vaapi_driver_quirks_table[] = {
/* @XXX(victor): is this string enough to identify it */
{ "AMD", GST_VAAPI_DRIVER_QUIRK_NO_CHECK_SURFACE_PUT_IMAGE },
};
/* *INDENT-ON* */
if (!ensure_vendor_string (display))
return;
for (i = 0; i < G_N_ELEMENTS (vaapi_driver_quirks_table); i++) {
const char *match_str = vaapi_driver_quirks_table[i].match_string;
if (g_strstr_len (priv->vendor_string, strlen (priv->vendor_string),
match_str) != NULL) {
GST_INFO_OBJECT (display, "Matched driver string \"%s\", setting quirks "
"(%#x)", priv->vendor_string, vaapi_driver_quirks_table[i].quirks);
priv->driver_quirks |= vaapi_driver_quirks_table[i].quirks;
break;
}
}
}
static void static void
gst_vaapi_display_calculate_pixel_aspect_ratio (GstVaapiDisplay * display) gst_vaapi_display_calculate_pixel_aspect_ratio (GstVaapiDisplay * display)
{ {
@ -929,6 +978,8 @@ gst_vaapi_display_create (GstVaapiDisplay * display,
g_free (priv->display_name); g_free (priv->display_name);
priv->display_name = g_strdup (info.display_name); priv->display_name = g_strdup (info.display_name);
set_driver_quirks (display);
if (!ensure_image_formats (display)) { if (!ensure_image_formats (display)) {
gst_vaapi_display_destroy (display); gst_vaapi_display_destroy (display);
return FALSE; return FALSE;
@ -2033,23 +2084,6 @@ set_color_balance (GstVaapiDisplay * display, guint prop_id, gfloat v)
return TRUE; return TRUE;
} }
/* Ensures the VA driver vendor string was copied */
static gboolean
ensure_vendor_string (GstVaapiDisplay * display)
{
GstVaapiDisplayPrivate *const priv = GST_VAAPI_DISPLAY_GET_PRIVATE (display);
const gchar *vendor_string;
GST_VAAPI_DISPLAY_LOCK (display);
if (!priv->vendor_string) {
vendor_string = vaQueryVendorString (priv->display);
if (vendor_string)
priv->vendor_string = g_strdup (vendor_string);
}
GST_VAAPI_DISPLAY_UNLOCK (display);
return priv->vendor_string != NULL;
}
/** /**
* gst_vaapi_display_get_vendor_string: * gst_vaapi_display_get_vendor_string:
* @display: a #GstVaapiDisplay * @display: a #GstVaapiDisplay
@ -2119,3 +2153,18 @@ gst_vaapi_display_reset_texture_map (GstVaapiDisplay * display)
if ((map = klass->get_texture_map (display))) if ((map = klass->get_texture_map (display)))
gst_vaapi_texture_map_reset (map); gst_vaapi_texture_map_reset (map);
} }
/**
* gst_vaapi_display_get_driver_quirks:
* @display: a #GstVaapiDisplay
* @quirks: the #GstVaapiDriverQuirks bitwise to check
*
* Returns: %TRUE if @quirks are set in @display's driver
**/
gboolean
gst_vaapi_display_has_driver_quirks (GstVaapiDisplay * display, guint quirks)
{
g_return_val_if_fail (display != NULL, FALSE);
return (GST_VAAPI_DISPLAY_GET_PRIVATE (display)->driver_quirks & quirks);
}

View file

@ -87,6 +87,17 @@ G_BEGIN_DECLS
typedef struct _GstVaapiDisplayInfo GstVaapiDisplayInfo; typedef struct _GstVaapiDisplayInfo GstVaapiDisplayInfo;
typedef struct _GstVaapiDisplay GstVaapiDisplay; typedef struct _GstVaapiDisplay GstVaapiDisplay;
/**
* GstVaapiDriverQuirks:
* @GST_VAAPI_DRIVER_QUIRK_NO_CHECK_SURFACE_PUT_IMAGE: if driver
* crashes when try to put an image in a reused surface.
* https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2016
*/
typedef enum
{
GST_VAAPI_DRIVER_QUIRK_NO_CHECK_SURFACE_PUT_IMAGE = (1U << 0),
} GstVaapiDriverQuirks;
/** /**
* GstVaapiDisplayType: * GstVaapiDisplayType:
* @GST_VAAPI_DISPLAY_TYPE_ANY: Automatic detection of the display type. * @GST_VAAPI_DISPLAY_TYPE_ANY: Automatic detection of the display type.
@ -251,6 +262,9 @@ gst_vaapi_display_has_opengl (GstVaapiDisplay * display);
void void
gst_vaapi_display_reset_texture_map (GstVaapiDisplay * display); gst_vaapi_display_reset_texture_map (GstVaapiDisplay * display);
gboolean
gst_vaapi_display_has_driver_quirks (GstVaapiDisplay * display, guint quirks);
#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplay, gst_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstVaapiDisplay, gst_object_unref)
#endif #endif

View file

@ -131,6 +131,7 @@ struct _GstVaapiDisplayPrivate
guint has_vpp:1; guint has_vpp:1;
guint has_profiles:1; guint has_profiles:1;
guint got_scrres:1; guint got_scrres:1;
guint driver_quirks;
}; };
/** /**

View file

@ -1456,7 +1456,12 @@ extract_allowed_surface_formats (GstVaapiDisplay * display,
if (direction == GST_PAD_SRC) { if (direction == GST_PAD_SRC) {
res = gst_vaapi_surface_get_image (surface, image); res = gst_vaapi_surface_get_image (surface, image);
} else { } else {
res = gst_vaapi_surface_put_image (surface, image); if (!gst_vaapi_display_has_driver_quirks (display,
GST_VAAPI_DRIVER_QUIRK_NO_CHECK_SURFACE_PUT_IMAGE))
res = gst_vaapi_surface_put_image (surface, image);
else
res = TRUE; /* Let's say it's possible to upload
* all formats */
} }
if (res) if (res)
g_array_append_val (out_formats, img_format); g_array_append_val (out_formats, img_format);