This introduces an ALSA library, with dedicated helpers for handling
playback and capture. It handles ALSA device identification and
configuration as well as a run loop with callback mechanisms for feeding
output data and handling input data.

This library paves the way for testing audio going through display
connectors, such as HDMI.

Signed-off-by: Paul Kocialkowski <[email protected]>
---
 configure.ac                                       |   3 +
 .../intel-gpu-tools/intel-gpu-tools-docs.xml       |   1 +
 lib/Makefile.am                                    |   7 +
 lib/igt.h                                          |   1 +
 lib/igt_alsa.c                                     | 624 +++++++++++++++++++++
 lib/igt_alsa.h                                     |  60 ++
 6 files changed, 696 insertions(+)
 create mode 100644 lib/igt_alsa.c
 create mode 100644 lib/igt_alsa.h

diff --git a/configure.ac b/configure.ac
index 50aa86b5..e66273a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -219,6 +219,9 @@ if test "x$enable_chamelium" = xyes; then
        AC_DEFINE(HAVE_CHAMELIUM, 1, [Enable Chamelium support])
 fi
 
+PKG_CHECK_MODULES(ALSA, [alsa], [alsa=yes], [alsa=no])
+AM_CONDITIONAL(HAVE_ALSA, [test "x$alsa" = xyes])
+
 # -----------------------------------------------------------------------------
 #                      Configuration options
 # -----------------------------------------------------------------------------
diff --git a/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml 
b/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml
index c77159cf..0c34e4a5 100644
--- a/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml
+++ b/docs/reference/intel-gpu-tools/intel-gpu-tools-docs.xml
@@ -16,6 +16,7 @@
   <chapter>
     <title>API Reference</title>
     <xi:include href="xml/drmtest.xml"/>
+    <xi:include href="xml/igt_alsa.xml"/>
     <xi:include href="xml/igt_audio.xml"/>
     <xi:include href="xml/igt_aux.xml"/>
     <xi:include href="xml/igt_chamelium.xml"/>
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5ea08314..3ff14f66 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -38,6 +38,13 @@ lib_source_list +=           \
        $(NULL)
 endif
 
+if HAVE_ALSA
+lib_source_list +=             \
+       igt_alsa.c              \
+       igt_alsa.h              \
+       $(NULL)
+endif
+
 AM_CPPFLAGS = -I$(top_srcdir)
 AM_CFLAGS = \
            $(CWARNFLAGS) \
diff --git a/lib/igt.h b/lib/igt.h
index a75d2db7..ebf92349 100644
--- a/lib/igt.h
+++ b/lib/igt.h
@@ -35,6 +35,7 @@
 #include "igt_dummyload.h"
 #include "igt_fb.h"
 #include "igt_frame.h"
+#include "igt_alsa.h"
 #include "igt_audio.h"
 #include "igt_gt.h"
 #include "igt_kms.h"
diff --git a/lib/igt_alsa.c b/lib/igt_alsa.c
new file mode 100644
index 00000000..d8bd0873
--- /dev/null
+++ b/lib/igt_alsa.c
@@ -0,0 +1,624 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *  Paul Kocialkowski <[email protected]>
+ */
+
+#include "config.h"
+
+#include <alsa/asoundlib.h>
+
+#include "igt.h"
+
+#define HANDLES_MAX    8
+
+/**
+ * SECTION:igt_alsa
+ * @short_description: Library with ALSA helpers
+ * @title: ALSA
+ * @include: igt_alsa.h
+ *
+ * This library contains helpers for ALSA playback and capture.
+ */
+
+struct alsa {
+       snd_pcm_t *output_handles[HANDLES_MAX];
+       int output_handles_count;
+       int output_sampling_rate;
+       int output_channels;
+
+       int (*output_callback)(void *data, short *buffer, int samples);
+       void *output_callback_data;
+       int output_samples_trigger;
+
+       snd_pcm_t *input_handle;
+       int input_sampling_rate;
+       int input_channels;
+
+       int (*input_callback)(void *data, short *buffer, int samples);
+       void *input_callback_data;
+       int input_samples_trigger;
+};
+
+static void alsa_error_handler(const char *file, int line, const char 
*function,
+                              int err, const char *fmt, ...)
+{
+       if (err)
+               igt_debug("[ALSA] %s: %s\n", function, snd_strerror(err));
+}
+
+/**
+ * alsa_init:
+ * Allocate and initialize an alsa structure and configure the error handler.
+ *
+ * Returns: A newly-allocated alsa structure
+ */
+struct alsa *alsa_init(void)
+{
+       struct alsa *alsa;
+
+       alsa = malloc(sizeof(struct alsa));
+       memset(alsa, 0, sizeof(struct alsa));
+
+       /* Redirect errors to igt_debug instead of stderr. */
+       snd_lib_error_set_handler(alsa_error_handler);
+
+       return alsa;
+}
+
+static char *alsa_resolve_indentifier(const char *device_name, int skip)
+{
+       snd_ctl_card_info_t *card_info;
+       snd_pcm_info_t *pcm_info;
+       snd_ctl_t *handle = NULL;
+       const char *pcm_name;
+       char *identifier = NULL;
+       char name[32];
+       int card;
+       int dev;
+       int ret;
+
+       snd_ctl_card_info_alloca(&card_info);
+       snd_pcm_info_alloca(&pcm_info);
+
+       card = -1;
+
+       /* First try to open the device as-is. */
+       if (!skip) {
+               ret = snd_ctl_open(&handle, device_name, 0);
+               if (!ret) {
+                       identifier = strdup(device_name);
+                       goto resolved;
+               }
+       }
+
+       do {
+               ret = snd_card_next(&card);
+               if (ret < 0 || card < 0)
+                       break;
+
+               snprintf(name, sizeof(name), "hw:%d", card);
+
+               ret = snd_ctl_open(&handle, name, 0);
+               if (ret < 0)
+                       continue;
+
+               ret = snd_ctl_card_info(handle, card_info);
+               if (ret < 0) {
+                       snd_ctl_close(handle);
+                       handle = NULL;
+                       continue;
+               }
+
+               dev = -1;
+
+               do {
+                       ret = snd_ctl_pcm_next_device(handle, &dev);
+                       if (ret < 0 || dev < 0)
+                               break;
+
+                       snd_pcm_info_set_device(pcm_info, dev);
+                       snd_pcm_info_set_subdevice(pcm_info, 0);
+
+                       ret = snd_ctl_pcm_info(handle, pcm_info);
+                       if (ret < 0)
+                               continue;
+
+                       pcm_name = snd_pcm_info_get_name(pcm_info);
+                       if (!pcm_name)
+                               continue;
+
+                       ret = strncmp(device_name, pcm_name,
+                                     strlen(device_name));
+
+                       if (ret == 0) {
+                               if (skip > 0) {
+                                       skip--;
+                                       continue;
+                               }
+
+                               snprintf(name, sizeof(name), "hw:%d,%d", card,
+                                        dev);
+
+                               identifier = strdup(name);
+                               goto resolved;
+                       }
+               } while (dev >= 0);
+
+               snd_ctl_close(handle);
+               handle = NULL;
+       } while (card >= 0);
+
+resolved:
+       if (handle)
+               snd_ctl_close(handle);
+
+       return identifier;
+}
+
+/**
+ * alsa_open_output:
+ * @alsa: The target alsa structure
+ * @device_name: The name prefix of the output device(s) to open
+ *
+ * Open ALSA output devices whose name prefixes match the provided name prefix.
+ *
+ * Returns: An integer equal to zero for success and negative for failure
+ */
+int alsa_open_output(struct alsa *alsa, const char *device_name)
+{
+       snd_pcm_t *handle;
+       char *identifier;
+       int skip;
+       int index;
+       int ret;
+
+       skip = alsa->output_handles_count;
+       index = alsa->output_handles_count;
+
+       while (index < HANDLES_MAX) {
+               identifier = alsa_resolve_indentifier(device_name, skip++);
+               if (!identifier)
+                       break;
+
+               ret = snd_pcm_open(&handle, identifier, SND_PCM_STREAM_PLAYBACK,
+                                  SND_PCM_NONBLOCK);
+               if (ret < 0) {
+                       free(identifier);
+                       continue;
+               }
+
+               igt_debug("Opened output %s\n", identifier);
+
+               alsa->output_handles[index++] = handle;
+               free(identifier);
+       }
+
+       if (index == 0)
+               return -1;
+
+       alsa->output_handles_count = index;
+
+       return 0;
+}
+
+/**
+ * alsa_open_input:
+ * @alsa: The target alsa structure
+ * @device_name: The name of the input device to open
+ *
+ * Open the ALSA input device whose name matches the provided name prefix.
+ *
+ * Returns: An integer equal to zero for success and negative for failure
+ */
+int alsa_open_input(struct alsa *alsa, const char *device_name)
+{
+       snd_pcm_t *handle;
+       char *identifier;
+       int ret;
+
+       identifier = alsa_resolve_indentifier(device_name, 0);
+
+       ret = snd_pcm_open(&handle, device_name, SND_PCM_STREAM_CAPTURE,
+                          SND_PCM_NONBLOCK);
+       if (ret < 0)
+               goto complete;
+
+       igt_debug("Opened input %s\n", identifier);
+
+       alsa->input_handle = handle;
+
+       ret = 0;
+
+complete:
+       free(identifier);
+
+       return ret;
+}
+
+/**
+ * alsa_close_output:
+ * @alsa: The target alsa structure
+ *
+ * Close all the open ALSA outputs.
+ */
+void alsa_close_output(struct alsa *alsa)
+{
+       snd_pcm_t *handle;
+       int i;
+
+       for (i = 0; i < alsa->output_handles_count; i++) {
+               handle = alsa->output_handles[i];
+               if (!handle)
+                       continue;
+
+               snd_pcm_close(handle);
+               alsa->output_handles[i] = NULL;
+       }
+
+       alsa->output_handles_count = 0;
+}
+
+/**
+ * alsa_close_output:
+ * @alsa: The target alsa structure
+ *
+ * Close the open ALSA input.
+ */
+void alsa_close_input(struct alsa *alsa)
+{
+       snd_pcm_t *handle = alsa->input_handle;
+       if (!handle)
+               return;
+
+       snd_pcm_close(handle);
+       alsa->input_handle = NULL;
+}
+
+static bool alsa_test_configuration(snd_pcm_t *handle, int channels,
+                            int sampling_rate)
+{
+       snd_pcm_hw_params_t *params;
+       int ret;
+
+       snd_pcm_hw_params_alloca(&params);
+
+       ret = snd_pcm_hw_params_any(handle, params);
+       if (ret < 0)
+               return false;
+
+       ret = snd_pcm_hw_params_test_rate(handle, params, sampling_rate, 0);
+       if (ret < 0)
+               return false;
+
+       ret = snd_pcm_hw_params_test_channels(handle, params, channels);
+       if (ret < 0)
+               return false;
+
+       return true;
+}
+
+/**
+ * alsa_test_output_configuration:
+ * @alsa: The target alsa structure
+ * @channels: The number of channels to test
+ * @sampling_rate: The sampling rate to test
+ *
+ * Test the output configuration specified by @channels and @sampling_rate
+ * for the output devices.
+ *
+ * Returns: A boolean indicating whether the test succeeded
+ */
+bool alsa_test_output_configuration(struct alsa *alsa, int channels,
+                                   int sampling_rate)
+{
+       snd_pcm_t *handle;
+       bool ret;
+       int i;
+
+       for (i = 0; i < alsa->output_handles_count; i++) {
+               handle = alsa->output_handles[i];
+
+               ret = alsa_test_configuration(handle, channels, sampling_rate);
+               if (!ret)
+                       return false;
+       }
+
+       return true;
+}
+
+/**
+ * alsa_test_input_configuration:
+ * @alsa: The target alsa structure
+ * @channels: The number of channels to test
+ * @sampling_rate: The sampling rate to test
+ *
+ * Test the input configuration specified by @channels and @sampling_rate
+ * for the input device.
+ *
+ * Returns: A boolean indicating whether the test succeeded
+ */
+bool alsa_test_input_configuration(struct alsa *alsa, int channels,
+                                  int sampling_rate)
+{
+       return alsa_test_configuration(alsa->input_handle, channels,
+                                      sampling_rate);
+}
+
+/**
+ * alsa_configure_output:
+ * @alsa: The target alsa structure
+ * @channels: The number of channels to test
+ * @sampling_rate: The sampling rate to test
+ *
+ * Configure the output devices with the configuration specified by @channels
+ * and @sampling_rate.
+ */
+void alsa_configure_output(struct alsa *alsa, int channels,
+                          int sampling_rate)
+{
+       snd_pcm_t *handle;
+       int ret;
+       int i;
+
+       for (i = 0; i < alsa->output_handles_count; i++) {
+               handle = alsa->output_handles[i];
+
+               ret = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE,
+                                        SND_PCM_ACCESS_RW_INTERLEAVED,
+                                        channels, sampling_rate, 0, 0);
+               igt_assert(ret >= 0);
+       }
+
+       alsa->output_channels = channels;
+       alsa->output_sampling_rate = sampling_rate;
+}
+
+/**
+ * alsa_configure_input:
+ * @alsa: The target alsa structure
+ * @channels: The number of channels to test
+ * @sampling_rate: The sampling rate to test
+ *
+ * Configure the input device with the configuration specified by @channels
+ * and @sampling_rate.
+ */
+void alsa_configure_input(struct alsa *alsa, int channels,
+                         int sampling_rate)
+{
+       snd_pcm_t *handle;
+       int ret;
+
+       handle = alsa->input_handle;
+
+       ret = snd_pcm_set_params(handle, SND_PCM_FORMAT_S16_LE,
+                                SND_PCM_ACCESS_RW_INTERLEAVED, channels,
+                                sampling_rate, 0, 0);
+       igt_assert(ret >= 0);
+
+       alsa->input_channels = channels;
+       alsa->input_sampling_rate = sampling_rate;
+
+}
+
+/**
+ * alsa_register_output_callback:
+ * @alsa: The target alsa structure
+ * @callback: The callback function to call to fill output data
+ * @callback_data: The data pointer to pass to the callback function
+ * @samples_trigger: The required number of samples to trigger the callback
+ *
+ * Register a callback function to be called to fill output data during a run.
+ * The callback is called when @samples_trigger samples are required.
+ *
+ * The callback should return an integer equal to zero for success and negative
+ * for failure.
+ */
+void alsa_register_output_callback(struct alsa *alsa,
+                                  int (*callback)(void *data, short *buffer, 
int samples),
+                                  void *callback_data, int samples_trigger)
+{
+       alsa->output_callback = callback;
+       alsa->output_callback_data = callback_data;
+       alsa->output_samples_trigger = samples_trigger;
+}
+
+/**
+ * alsa_register_input_callback:
+ * @alsa: The target alsa structure
+ * @callback: The callback function to call when input data is available
+ * @callback_data: The data pointer to pass to the callback function
+ * @samples_trigger: The required number of samples to trigger the callback
+ *
+ * Register a callback function to be called when input data is available 
during
+ * a run. The callback is called when @samples_trigger samples are available.
+ *
+ * The callback should return an integer equal to zero for success, negative 
for
+ * failure and positive to indicate that the run should stop.
+ */
+void alsa_register_input_callback(struct alsa *alsa,
+                                 int (*callback)(void *data, short *buffer, 
int samples),
+                                 void *callback_data, int samples_trigger)
+{
+       alsa->input_callback = callback;
+       alsa->input_callback_data = callback_data;
+       alsa->input_samples_trigger = samples_trigger;
+}
+
+/**
+ * alsa_run:
+ * @alsa: The target alsa structure
+ * @duration_ms: The maximum duration of the run in milliseconds
+ *
+ * Run ALSA playback and capture on the input and output devices for at
+ * most @duration_ms milliseconds, calling the registered callbacks when 
needed.
+ *
+ * Returns: An integer equal to zero for success, positive for a stop caused
+ * by the input callback and negative for failure
+ */
+int alsa_run(struct alsa *alsa, int duration_ms)
+{
+       snd_pcm_t *handle;
+       short *output_buffer = NULL;
+       short *input_buffer = NULL;
+       int output_limit;
+       int output_total = 0;
+       int output_counts[alsa->output_handles_count];
+       bool output_ready = false;
+       int output_channels;
+       int output_trigger;
+       int input_limit;
+       int input_total = 0;
+       int input_count = 0;
+       int input_channels;
+       int input_trigger;
+       bool reached;
+       int index;
+       int count;
+       int avail;
+       int i;
+       int ret;
+
+       output_limit = alsa->output_sampling_rate * duration_ms / 1000;
+       output_channels = alsa->output_channels;
+       output_trigger = alsa->output_samples_trigger;
+       output_buffer = malloc(sizeof(short) * output_channels *
+                              output_trigger);
+
+       if (alsa->input_callback) {
+               input_limit = alsa->input_sampling_rate * duration_ms / 1000;
+               input_trigger = alsa->input_samples_trigger;
+               input_channels = alsa->input_channels;
+               input_buffer = malloc(sizeof(short) * input_channels *
+                                     input_trigger);
+       }
+
+       do {
+               reached = true;
+
+               if (output_total < output_limit) {
+                       reached = false;
+
+                       if (!output_ready) {
+                               output_ready = true;
+
+                               for (i = 0; i < alsa->output_handles_count; i++)
+                                       output_counts[i] = 0;
+
+                               ret = 
alsa->output_callback(alsa->output_callback_data,
+                                                           output_buffer,
+                                                           output_trigger);
+                               if (ret < 0)
+                                       goto complete;
+                       }
+
+                       for (i = 0; i < alsa->output_handles_count; i++) {
+                               handle = alsa->output_handles[i];
+
+                               if (output_counts[i] < output_trigger &&
+                                   snd_pcm_avail(handle) > 0) {
+                                       index = output_counts[i] *
+                                               output_channels;
+                                       count = output_trigger -
+                                               output_counts[i];
+                                       avail = snd_pcm_avail(handle);
+
+                                       count = avail < count ? avail : count;
+
+                                       ret = snd_pcm_writei(handle,
+                                                            
&output_buffer[index],
+                                                            count);
+                                       if (ret < 0) {
+                                               ret = snd_pcm_recover(handle,
+                                                                     count, 0);
+                                               if (ret < 0)
+                                                       goto complete;
+                                       }
+
+                                       output_counts[i] += ret;
+                               }
+                       }
+
+                       output_ready = false;
+
+                       for (i = 0; i < alsa->output_handles_count; i++)
+                               if (output_counts[i] < output_trigger)
+                                       output_ready = true;
+
+                       if (!output_ready)
+                               output_total += output_trigger;
+
+               }
+
+               if (alsa->input_callback && input_total < input_limit) {
+                       reached = false;
+
+                       if (input_count == input_trigger) {
+                               input_count = 0;
+
+                               ret = 
alsa->input_callback(alsa->input_callback_data,
+                                                          input_buffer,
+                                                          input_trigger);
+                               if (ret != 0)
+                                       goto complete;
+                       }
+
+                       handle = alsa->input_handle;
+
+                       if (input_count < input_trigger &&
+                           (snd_pcm_avail(handle) > 0 || input_total == 0)) {
+                               index = input_count * input_channels;
+                               count = input_trigger - input_count;
+                               avail = snd_pcm_avail(handle);
+
+                               count = avail > 0 && avail < count ? avail :
+                                       count;
+
+                               ret = snd_pcm_readi(handle,
+                                                   &input_buffer[index],
+                                                   count);
+                               if (ret == -EAGAIN) {
+                                       ret = 0;
+                               } else if (ret < 0) {
+                                       ret = snd_pcm_recover(handle, count, 0);
+                                       if (ret < 0)
+                                               goto complete;
+                               }
+
+                               input_count += ret;
+                               input_total += ret;
+                       }
+               }
+       } while (!reached);
+
+       ret = 0;
+
+complete:
+       if (output_buffer)
+               free(output_buffer);
+
+       if (input_buffer)
+               free(input_buffer);
+
+       return ret;
+}
diff --git a/lib/igt_alsa.h b/lib/igt_alsa.h
new file mode 100644
index 00000000..9911ddde
--- /dev/null
+++ b/lib/igt_alsa.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2017 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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.
+ *
+ * Authors:
+ *  Paul Kocialkowski <[email protected]>
+ */
+
+#ifndef IGT_ALSA_H
+#define IGT_ALSA_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "igt.h"
+#include <stdbool.h>
+
+struct alsa;
+
+struct alsa *alsa_init(void);
+int alsa_open_output(struct alsa *alsa, const char *device_name);
+int alsa_open_input(struct alsa *alsa, const char *device_name);
+void alsa_close_output(struct alsa *alsa);
+void alsa_close_input(struct alsa *alsa);
+bool alsa_test_output_configuration(struct alsa *alsa, int channels,
+                                   int sampling_rate);
+bool alsa_test_input_configuration(struct alsa *alsa, int channels,
+                                  int sampling_rate);
+void alsa_configure_output(struct alsa *alsa, int channels,
+                          int sampling_rate);
+void alsa_configure_input(struct alsa *alsa, int channels,
+                         int sampling_rate);
+void alsa_register_output_callback(struct alsa *alsa,
+                                  int (*callback)(void *data, short *buffer, 
int samples),
+                                  void *callback_data, int samples_trigger);
+void alsa_register_input_callback(struct alsa *alsa,
+                                 int (*callback)(void *data, short *buffer, 
int samples),
+                                 void *callback_data, int samples_trigger);
+int alsa_run(struct alsa *alsa, int duration_ms);
+
+#endif
-- 
2.14.0

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to