From 75fbfa1ecebf7fb6fd3afed60d2e9cbcb1cfcc04 Mon Sep 17 00:00:00 2001
From: Ludovico de Nittis <ludovico.denittis@collabora.com>
Date: Fri, 17 Apr 2020 18:48:09 +0200
Subject: [PATCH] Add automated graphics verification for VA-API

Add a check similarly to the VDPAU one that we already have.

Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com>
---
 bin/system-info.c                           |  3 +-
 bin/system-info.md                          |  3 ++
 helpers/check-va-api.c                      | 12 ++++++-
 steam-runtime-tools/graphics-test-defines.h |  3 ++
 steam-runtime-tools/graphics.c              | 24 +++++++++++--
 steam-runtime-tools/graphics.h              |  3 +-
 tests/graphics.c                            | 20 +++++++++++
 tests/meson.build                           |  2 ++
 tests/mock-bad-check-va-api.c               | 37 +++++++++++++++++++++
 tests/mock-good-check-va-api.c              | 36 ++++++++++++++++++++
 10 files changed, 137 insertions(+), 6 deletions(-)
 create mode 100644 tests/mock-bad-check-va-api.c
 create mode 100644 tests/mock-good-check-va-api.c

diff --git a/bin/system-info.c b/bin/system-info.c
index e198914d2..903dde23e 100644
--- a/bin/system-info.c
+++ b/bin/system-info.c
@@ -469,7 +469,8 @@ print_graphics_details(JsonBuilder *builder,
 
       rendering_interface = srt_graphics_get_rendering_interface (g->data);
       if (rendering_interface != SRT_RENDERING_INTERFACE_VULKAN &&
-          rendering_interface != SRT_RENDERING_INTERFACE_VDPAU)
+          rendering_interface != SRT_RENDERING_INTERFACE_VDPAU &&
+          rendering_interface != SRT_RENDERING_INTERFACE_VAAPI)
         {
           json_builder_set_member_name (builder, "library-vendor");
           srt_graphics_library_is_vendor_neutral (g->data, &library_vendor);
diff --git a/bin/system-info.md b/bin/system-info.md
index a9d8a2593..c0ee32e98 100644
--- a/bin/system-info.md
+++ b/bin/system-info.md
@@ -414,6 +414,9 @@ keys:
         **vdpau**
         :   VDPAU
 
+        **va-api**
+        :   VA-API
+
         The values are objects with the following string keys:
 
         **renderer**
diff --git a/helpers/check-va-api.c b/helpers/check-va-api.c
index d0467d74b..b7ccc506e 100644
--- a/helpers/check-va-api.c
+++ b/helpers/check-va-api.c
@@ -40,12 +40,14 @@
 enum
 {
   OPTION_HELP = 1,
+  OPTION_VERBOSE,
   OPTION_VERSION,
 };
 
 struct option long_options[] =
 {
   { "help", no_argument, NULL, OPTION_HELP },
+  { "verbose", no_argument, NULL, OPTION_VERBOSE },
   { "version", no_argument, NULL, OPTION_VERSION },
   { NULL, 0, NULL, 0 }
 };
@@ -89,6 +91,7 @@ main (int argc,
 
 #define do_vaapi_or_exit(expr) if (! _do_vaapi (#expr, expr)) goto out;
 
+  bool verbose = false;
   int opt;
   int surfaces_count = 2;
   int ret = 1;
@@ -105,7 +108,7 @@ main (int argc,
   VASurfaceID *surfaces = NULL;
   VAImageFormat image_format;
   VAProfile *profiles = NULL;
-  VAConfigID config;
+  VAConfigID config = VA_INVALID_ID;
   VAContextID context = VA_INVALID_ID;
   VABufferID misc_buf_id = VA_INVALID_ID;
   VABufferID pipeline_param_buf_id = VA_INVALID_ID;
@@ -123,6 +126,10 @@ main (int argc,
             usage (0);
             break;
 
+          case OPTION_VERBOSE:
+            verbose = true;
+            break;
+
           case OPTION_VERSION:
             /* Output version number as YAML for machine-readability,
              * inspired by `ostree --version` and `docker version` */
@@ -180,6 +187,9 @@ main (int argc,
 
   do_vaapi_or_exit (vaInitialize (va_display, &major_version, &minor_version));
 
+  if (verbose)
+    printf ("%s\n", vaQueryVendorString (va_display));
+
   /* Test the ability to get the supported profiles and that they are not more than
    * the maximum number from the implementation */
   max_profiles = vaMaxNumProfiles (va_display);
diff --git a/steam-runtime-tools/graphics-test-defines.h b/steam-runtime-tools/graphics-test-defines.h
index e0cbaf6fb..a53de0fd3 100644
--- a/steam-runtime-tools/graphics-test-defines.h
+++ b/steam-runtime-tools/graphics-test-defines.h
@@ -36,3 +36,6 @@
 #define SRT_TEST_GOOD_VDPAU_RENDERER "G3DVL VDPAU Driver Shared Library version 1.0\n"
 #define SRT_TEST_BAD_VDPAU_MESSAGES "Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory\n\
 vdp_device_create_x11 (display, screen, &device, &vdp_get_proc_address) failed: 1\n"
+#define SRT_TEST_GOOD_VAAPI_RENDERER "Mesa Gallium driver 20.0.4 for AMD Radeon RX 5700 XT (NAVI10, DRM 3.36.0, 5.6.3-arch1-1, LLVM 9.0.1)\n"
+#define SRT_TEST_BAD_VAAPI_MESSAGES "libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)\n\
+vaInitialize (va_display, &major_version, &minor_version) failed: unknown libva error (-1)\n"
diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c
index 44f8e165b..b53eaa20a 100644
--- a/steam-runtime-tools/graphics.c
+++ b/steam-runtime-tools/graphics.c
@@ -505,6 +505,7 @@ _argv_for_graphics_test (const char *helpers_path,
           case SRT_RENDERING_INTERFACE_GLESV2:
           case SRT_RENDERING_INTERFACE_VULKAN:
           case SRT_RENDERING_INTERFACE_VDPAU:
+          case SRT_RENDERING_INTERFACE_VAAPI:
           default:
             g_critical ("GLX window system only makes sense with GL "
                         "rendering interface, not %d",
@@ -529,6 +530,7 @@ _argv_for_graphics_test (const char *helpers_path,
 
           case SRT_RENDERING_INTERFACE_VULKAN:
           case SRT_RENDERING_INTERFACE_VDPAU:
+          case SRT_RENDERING_INTERFACE_VAAPI:
             /* They don't set platfomstring, just set argv later. */
             break;
 
@@ -547,6 +549,7 @@ _argv_for_graphics_test (const char *helpers_path,
 
           case SRT_RENDERING_INTERFACE_VULKAN:
           case SRT_RENDERING_INTERFACE_VDPAU:
+          case SRT_RENDERING_INTERFACE_VAAPI:
           default:
             /* e.g. Vulkan (when implemented) */
             g_critical ("EGL window system only makes sense with a GL-based "
@@ -603,6 +606,16 @@ _argv_for_graphics_test (const char *helpers_path,
         g_ptr_array_add (argv, g_strdup ("--verbose"));
         break;
 
+      case SRT_RENDERING_INTERFACE_VAAPI:
+        argv = _srt_get_helper (helpers_path, multiarch_tuple, "check-va-api",
+                                flags, error);
+
+        if (argv == NULL)
+          goto out;
+
+        g_ptr_array_add (argv, g_strdup ("--verbose"));
+        break;
+
       default:
         g_return_val_if_reached (NULL);
         break;
@@ -796,10 +809,11 @@ _srt_check_library_vendor (const char *multiarch_tuple,
   SrtLibraryIssues issues;
   const char * const *dependencies;
 
-  /* Vulkan and VDPAU are always vendor-neutral, so it doesn't make sense to check it.
+  /* Vulkan, VDPAU and VA-API are always vendor-neutral, so it doesn't make sense to check it.
    * We simply return SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN */
   if (rendering_interface == SRT_RENDERING_INTERFACE_VULKAN ||
-      rendering_interface == SRT_RENDERING_INTERFACE_VDPAU)
+      rendering_interface == SRT_RENDERING_INTERFACE_VDPAU ||
+      rendering_interface == SRT_RENDERING_INTERFACE_VAAPI)
     goto out;
 
   switch (window_system)
@@ -1014,6 +1028,7 @@ _srt_check_graphics (const char *helpers_path,
         break;
 
       case SRT_RENDERING_INTERFACE_VDPAU:
+      case SRT_RENDERING_INTERFACE_VAAPI:
         /* The test here tries to draw an offscreen X11 window */
         non_zero_wait_status_issue = SRT_GRAPHICS_ISSUES_CANNOT_DRAW;
         break;
@@ -1078,6 +1093,7 @@ _srt_check_graphics (const char *helpers_path,
         break;
 
       case SRT_RENDERING_INTERFACE_VDPAU:
+      case SRT_RENDERING_INTERFACE_VAAPI:
         /* The output is in plan text, nothing to do here */
         break;
 
@@ -1189,6 +1205,7 @@ _srt_check_graphics (const char *helpers_path,
         break;
 
       case SRT_RENDERING_INTERFACE_VDPAU:
+      case SRT_RENDERING_INTERFACE_VAAPI:
         if (output != NULL)
           renderer_string = output;
         break;
@@ -1259,7 +1276,7 @@ srt_graphics_get_issues (SrtGraphics *self)
  *  or vendor-specific, and if vendor-specific, attempt to guess the vendor
  *
  * Return whether the entry-point library for this graphics stack is vendor-neutral or vendor-specific.
- * Vulkan and VDPAU are always vendor-neutral, so this function will always return %TRUE for them.
+ * Vulkan, VDPAU and VA-API are always vendor-neutral, so this function will always return %TRUE for them.
  *
  * Returns: %TRUE if the graphics library is vendor-neutral, %FALSE otherwise.
  */
@@ -1274,6 +1291,7 @@ srt_graphics_library_is_vendor_neutral (SrtGraphics *self,
 
   return (self->rendering_interface == SRT_RENDERING_INTERFACE_VULKAN ||
           self->rendering_interface == SRT_RENDERING_INTERFACE_VDPAU ||
+          self->rendering_interface == SRT_RENDERING_INTERFACE_VAAPI ||
           self->library_vendor == SRT_GRAPHICS_LIBRARY_VENDOR_GLVND);
 }
 
diff --git a/steam-runtime-tools/graphics.h b/steam-runtime-tools/graphics.h
index e74c20786..31400d750 100644
--- a/steam-runtime-tools/graphics.h
+++ b/steam-runtime-tools/graphics.h
@@ -117,10 +117,11 @@ typedef enum
   SRT_RENDERING_INTERFACE_GLESV2,
   SRT_RENDERING_INTERFACE_VULKAN,
   SRT_RENDERING_INTERFACE_VDPAU,
+  SRT_RENDERING_INTERFACE_VAAPI,
   /* ... possible future additions: GLESV1, GLESV3? */
 } SrtRenderingInterface;
 
-#define SRT_N_RENDERING_INTERFACES (SRT_RENDERING_INTERFACE_VDPAU + 1)
+#define SRT_N_RENDERING_INTERFACES (SRT_RENDERING_INTERFACE_VAAPI + 1)
 
 const char *srt_graphics_get_multiarch_tuple (SrtGraphics *self);
 SrtGraphicsIssues srt_graphics_get_issues (SrtGraphics *self);
diff --git a/tests/graphics.c b/tests/graphics.c
index 0f63ee26a..d04c84213 100644
--- a/tests/graphics.c
+++ b/tests/graphics.c
@@ -2166,6 +2166,26 @@ static const GraphicsTest graphics_test[] =
     .vendor_neutral = TRUE,
   },
 
+  {
+    .description = "good va-api",
+    .window_system = SRT_WINDOW_SYSTEM_X11,
+    .rendering_interface = SRT_RENDERING_INTERFACE_VAAPI,
+    .issues = SRT_GRAPHICS_ISSUES_NONE,
+    .multiarch_tuple = "mock-good",
+    .renderer_string = SRT_TEST_GOOD_VAAPI_RENDERER,
+    .vendor_neutral = TRUE,
+  },
+
+  {
+    .description = "bad va-api",
+    .window_system = SRT_WINDOW_SYSTEM_X11,
+    .rendering_interface = SRT_RENDERING_INTERFACE_VAAPI,
+    .issues = SRT_GRAPHICS_ISSUES_CANNOT_DRAW,
+    .multiarch_tuple = "mock-bad",
+    .messages = SRT_TEST_BAD_VAAPI_MESSAGES,
+    .exit_status = 1,
+    .vendor_neutral = TRUE,
+  },
 };
 
 static void
diff --git a/tests/meson.build b/tests/meson.build
index 260adff8f..f45f8bee9 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -179,9 +179,11 @@ executable(
 # Helpers with no dependencies and one source file of the same name
 # as the helper itself.
 foreach helper : [
+  'mock-bad-check-va-api',
   'mock-bad-check-vdpau',
   'mock-bad-check-vulkan',
   'mock-bad-vulkaninfo',
+  'mock-good-check-va-api',
   'mock-good-check-vdpau',
   'mock-good-vulkaninfo',
   'mock-hanging-wflinfo',
diff --git a/tests/mock-bad-check-va-api.c b/tests/mock-bad-check-va-api.c
new file mode 100644
index 000000000..cca06c169
--- /dev/null
+++ b/tests/mock-bad-check-va-api.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2020 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+int
+main (int argc,
+      char **argv)
+{
+  // Give bad output
+  fprintf (stderr, "libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)\n");
+  fprintf (stderr, "vaInitialize (va_display, &major_version, &minor_version) failed: unknown libva error (-1)\n");
+  return 1;
+}
+
diff --git a/tests/mock-good-check-va-api.c b/tests/mock-good-check-va-api.c
new file mode 100644
index 000000000..fd73038c0
--- /dev/null
+++ b/tests/mock-good-check-va-api.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2020 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+int
+main (int argc,
+      char **argv)
+{
+  // Give good output
+  printf ("Mesa Gallium driver 20.0.4 for AMD Radeon RX 5700 XT (NAVI10, DRM 3.36.0, 5.6.3-arch1-1, LLVM 9.0.1)\n");
+  return 0;
+}
+
-- 
GitLab