. "${GRIMOIRE}/config_query_multi.function" &&
. "${GRIMOIRE}/MESON_CONFIGURE" &&

sort_list() {
  set -- $(printf '%s\n' "$@" | sort -fu)
  echo "$@"
}

check_driver() {
  [ -z "$MESA_DRIVERS" ] && return 1
  [ -z "$drivers" ] && return 1
  list_find "$MESA_DRIVERS" "$@"
}

check_gallium() {
  [ -z "$MESA_GALLIUM" ] && return 1
  [ -z "$AVAILABLE_GALLIUM" ] && return 1
  list_find "$MESA_GALLIUM" none && return 1
  [ "$#" -eq 0 ] && return 0
  list_find "$MESA_GALLIUM" "$@"
}

check_platform() {
  [ -z "$MESA_PLATFORMS" ] && return 1
  list_find "$MESA_PLATFORMS" "$@"
}

check_layers() {
  [ -z "$MESA_VULKAN_LAYERS" ] && return 1
  [ -z "$AVAILABLE_LAYERS" ] && return 1
  list_find "$MESA_VULKAN_LAYERS" none && return 1
  [ "$#" -eq 0 ] && return 0
  list_find "$MESA_VULKAN_LAYERS" "$@"
}

check_vulkan() {
  [ -z "$MESA_VULKAN" ] && return 1
  [ -z "$AVAILABLE_VULKAN" ] && return 1
  list_find "$MESA_VULKAN" none && return 1
  [ "$#" -eq 0 ] && return 0
  list_find "$MESA_VULKAN" "$@"
}

config_query_multi MESA_PLATFORMS "Which window systems to support?" \
                   wayland \
                   x11 \
                   &&

config_query_multi MESA_ARCH "Which hardware platforms to support?" \
                   ARM \
                   x86 \
                   &&

local vendors="VMware" &&
local drivers &&
local MESA_DRIVERS &&

if list_find "$MESA_ARCH" x86 ;then
  vendors="$vendors AMD Intel Nvidia Microsoft-WSL"
fi &&
if list_find "$MESA_ARCH" ARM ;then
  vendors="$vendors Freedreno Imagination Mali Nvidia RaspberryPi"
fi &&

vendors="$(sort_list $vendors)" &&

config_query_multi MESA_HW "Which graphics vendor hardware to support?" \
                   $vendors \
                   &&

for vendor in ${MESA_HW} ;do
  case "$vendor" in
    AMD) drivers="$drivers amdgpu radeon" ;;
    Imagination) drivers="$drivers etnaviv" ;;
    Mali) drivers="$drivers lima panfrost" ;;
    Qualcomm) drivers="$drivers freedreno" ;;
    Intel) drivers="$drivers intel" ;;
    Nvidia)
      if list_find "$MESA_ARCH" x86 ;then
        drivers="$drivers nouveau"
      fi &&
      if list_find "$MESA_ARCH" ARM ;then
        drivers="$drivers tegra"
      fi
      ;;
    RaspberryPi) drivers="$drivers rpi" ;;
    Microsoft-WSL) drivers="$drivers WSL" ;;
    VMware) drivers="$drivers vmware-mks-stats" ;;
  esac
done &&

drivers="$(sort_list $drivers)" &&

local num_drivers="$(set -- $drivers; echo $#)" &&
if [ $num_drivers -gt 1 ] ;then
  config_query_multi MESA_DRIVERS_CHOICE "Which drivers to support?" \
                     all \
                     $drivers \
                     &&
  MESA_DRIVERS="$MESA_DRIVERS_CHOICE"
else
  MESA_DRIVERS="$drivers"
fi

if list_find "$MESA_DRIVERS" all ;then
  MESA_DRIVERS="$drivers"
fi

# ensure that MESA_DRIVERS contains no newlines because sorcery's
# persistent_add functions cannot correctly handle newlines
MESA_DRIVERS="$(echo $MESA_DRIVERS | tr '\n' ' ')" &&

if check_driver etnaviv WSL ;then
  config_query MESA_VULKAN_EXPERIMENTAL "Enable experimental vulkan drivers?" n
fi &&

# only suggest drivers for specified hardware
local AVAILABLE_GALLIUM="llvmpipe softpipe svga virgl zink" &&
local AVAILABLE_VULKAN="swrast virtio" &&
local AVAILABLE_LAYERS="device-select intel-nullhw overlay screenshot" &&
local AVAILABLE_TOOLS="dlclose-skip drm-shim glsl nir zink" &&
MESA_DRM=""

if check_driver amdgpu ;then
  MESA_DRM="$MESA_DRM AMD" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN amd" &&
  config_query MESA_AMD_LLVM "Use LLVM for the AMD drivers?" y
fi &&

if check_driver radeon ;then
  MESA_DRM="$MESA_DRM RADEON" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM r300 r600 radeonsi"
fi &&

if check_driver intel ;then
  MESA_DRM="$MESA_DRM INTEL" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM i915 iris crocus" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN intel intel_hasvk" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS intel intel-ui"
fi &&

if check_driver etnaviv ;then
  MESA_DRM="$MESA_DRM ETNAVIV" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM etnaviv" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN etnaviv" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS etnaviv"
fi &&

if check_driver freedreno ;then
  MESA_DRM="$MESA_DRM FREEDRENO" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM freedreno" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN freedreno" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS freedreno"
fi &&

if check_driver lima ;then
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM lima" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS lima"
fi &&

if check_driver nouveau ;then
  MESA_DRM="$MESA_DRM NOUVEAU" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM nouveau" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN nouveau" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS nouveau"
fi &&

if check_driver panfrost ;then
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM panfrost" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN panfrost" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS panfrost"
fi &&

if check_driver rpi ;then
  MESA_DRM="$MESA_DRM VC4" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM v3d vc4" &&
  AVAILABLE_VULKAN="$AVAILABLE_VULKAN broadcom" &&
  AVAILABLE_TOOLS="$AVAILABLE_TOOLS freedreno"
fi &&

if check_driver tegra ;then
  MESA_DRM="$MESA_DRM TEGRA" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM tegra"
fi &&

if check_driver vmware ;then
  MESA_DRM="$MESA_DRM vmwgfx" &&
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM vmware"
fi &&

if check_driver WSL ;then
  AVAILABLE_GALLIUM="$AVAILABLE_GALLIUM d3d12" &&
  if [[ "$MESA_VULKAN_EXPERIMENTAL" == "y" ]] ;then
    AVAILABLE_VULKAN="$AVAILABLE_VULKAN microsoft-experimental"
  fi
fi &&

AVAILABLE_GALLIUM="$(sort_list $AVAILABLE_GALLIUM)" &&
AVAILABLE_TOOLS="$(sort_list $AVAILABLE_TOOLS)" &&
AVAILABLE_VULKAN="$(sort_list $AVAILABLE_VULKAN)" &&

config_query_multi MESA_GALLIUM_CHOICE "Which gallium (accelerated) drivers to build?" \
                   none \
                   all \
                   $AVAILABLE_GALLIUM \
                   &&

MESA_GALLIUM="$MESA_GALLIUM_CHOICE" &&

if [ -n "$MESA_GALLIUM" ] && ! list_find "$MESA_GALLIUM" none ;then
  if list_find "$MESA_GALLIUM" all ;then
    MESA_GALLIUM="$AVAILABLE_GALLIUM"
  fi &&

  config_query MESA_GALLIUM_HUD "Enable HUD block/NIC I/O HUD status support?" n &&

  if check_gallium vmware ;then
    if ! check_gallium svga ;then
      message "The vmware driver requires gallium svga; adding gallium svga." &&
      MESA_GALLIUM="$MESA_GALLIUM svga"
    fi
  fi &&

  if check_gallium llvmpipe softpipe ;then
    if check_driver WSL ;then
      config_query MESA_GALLIUM_D3D10 "Build gallium Direct3D10 (WDDM UMD) frontend?" n
    fi
  fi &&

  if check_gallium d3d12 ;then
    config_query MESA_GALLIUM_D3D12_PIPELINE "Build gallium with Direct3D12 graphics pipeline support?" n &&
    config_query MESA_GALLIUM_D3D12_VIDEO "Build gallium with Direct3D12 video support?" n
  fi &&

  config_query MESA_RUSTICL "Build gallium rusticl (OpenCL) frontend (requires rust)?" n &&

  if [[ "$MESA_RUSTICL" == "y" ]] ;then
    local AVAILABLE_MESA_RUSTICL_DRIVERS &&
    AVAILABLE_MESA_RUSTICL_DRIVERS="asahi freedreno radeonsi" &&

    config_query_multi MESA_RUSTICL_DRIVERS "Which drivers to enable with rusticl by default?" \
                       auto \
                       ${AVAILABLE_MESA_RUSTICL_DRIVERS}
  fi &&

  # EGL requires DRI, which is only enabled if gallium is enabled
  if check_platform "$MESA_PLATFORMS" wayland ;then
    # Walyand requires EGL support
    MESA_EGL=y &&
    persistent_add MESA_EGL
  else
    config_query MESA_EGL "Enable EGL platform support?" n
  fi &&

  if [[ "$MESA_EGL" == "y" ]] ;then
    local egldefaults="drm surfaceless" &&
    if check_platform x11 ;then
      egldefaults="$egldefaults x11"
    fi &&
    if check_platform wayland ;then
      egldefaults="$egldefaults wayland"
    fi &&
    if check_driver WSL ;then
      egldefaults="$egldefaults windows"
    fi &&
    egldefaults="$(sort_list $egldefaults)"
    config_query_list MESA_EGL_DEFAULT "Which window system should EGL assume for EGL_DEFAULT_DISPLAY" \
                      auto \
                      $egldefaults
  fi
fi &&

config_query_multi MESA_VULKAN_CHOICE "Which Vulkan drivers to build?" \
                   none \
                   all \
                   $AVAILABLE_VULKAN \
                   &&

MESA_VULKAN="$MESA_VULKAN_CHOICE" &&

if [ -n "$MESA_VULKAN" ] && ! list_find "$MESA_VULKAN" none ;then
  if list_find "$MESA_VULKAN" all ;then
    MESA_VULKAN="$AVAILABLE_VULKAN"
  fi &&

  config_query_multi MESA_VULKAN_LAYERS_CHOICE "Which Vulkan layers to build?" \
                     none \
                     all \
                     $AVAILABLE_LAYERS \
                     &&

  MESA_VULKAN_LAYERS="$MESA_VULKAN_LAYERS_CHOICE" &&

  if list_find "$MESA_VULKAN_LAYERS" none ;then
    MESA_VULKAN_LAYERS="none"
  fi &&
  if list_find "$MESA_VULKAN_LAYERS" all ;then
    MESA_VULKAN_LAYERS="$AVAILABLE_LAYERS"
  fi &&

  config_query MESA_XLIB_LEASE "Enable VK_EXT_acquire_xlib_display?" n
fi &&

config_query MESA_SHADER_CACHE "Support on-disk shader caching?" n &&

config_query MESA_GLES1 "Support OpenGL ES 1.x?" n &&
config_query MESA_GLES23 "Support OpenGL ES 2.x and 3.x?" n &&
config_query MESA_OPENGL "Enable desktop OpenGL support?" y &&
config_query MESA_GBM "Enable generic buffer management (GBM) support?" n &&

config_query_list MESA_GLX_CHOICE "Which GLX build type (dri recommended)?" \
                  disabled \
                  dri \
                  xlib \
                  &&

MESA_GLX="$MESA_GLX_CHOICE"

if list_find "${MESA_GLX}" "disabled"; then
  MESA_GLX="disabled"
else
  config_query MESA_GLX_DIRECT "Enable direct rendering in GLX and EGL for DRI?" y &&
  config_query MESA_GLX_READONLY "Read-only GLX (disable writable .text section) on x86 (decreases performance)?" n
fi &&

if [[ "$MESA_EGL" == "y" ]] || ! list_find "$MESA_GLX" disabled ;then
  config_query MESA_GLVND "Enable OpenGL vendor-neutral dispatch (GLVND) support?" n
fi &&

config_query MESA_SPIRV_DXIL "Build support for the SPIR-V to DXIL library?" n &&

config_query_multi MESA_TOOLS_CHOICE "Which tools to build?" \
                   none \
                   all \
                   $AVAILABLE_TOOLS \
                   &&

MESA_TOOLS="$MESA_TOOLS_CHOICE" &&

if list_find "$MESA_TOOLS" all ;then
  MESA_TOOLS="$AVAILABLE_TOOLS"
fi

local perfetto_sources=""
if list_find "$MESA_DRIVERS" freedreno ;then
  perfetto_sources="$perfetto_sources intel"
fi &&
if list_find "$MESA_DRIVERS" intel ;then
  perfetto_sources="$perfetto_sources intel"
fi &&
if list_find "$MESA_DRIVERS" panfrost ;then
  perfetto_sources="$perfetto_sources intel"
fi &&
  perfetto_sources="$(sort_list $perfetto_sources)" &&
if [ -n "$perfetto_sources" ] ;then
  config_query MESA_PERFETTO "Enable performance analysis with Perfetto" n &&
  if [[ "$MESA_PERFETTO" == "y" ]] ;then
    config_query_multi MESA_PERFETTO_SOURCES "Perfetto datasources to build" \
                       auto \
                       $perfetto_sources
  fi
fi &&

config_query MESA_TEFLON "Enable TensorFlow Lite delegate" n &&
config_query MESA_GPUVIS "Enable tracing markers for gpuvis" n &&

if check_vulkan intel intel_hasvk ;then
  config_query MESA_INTEL_RT "Build Intel raytracing support (on supported hardware)?" n
fi &&

config_query_multi MESA_VIDEO_CODECS "Which codecs to build?" \
                   none \
                   all \
                   all_free \
                   av1dec \
                   av1enc \
                   h264dec \
                   h264enc \
                   h265dec \
                   h265enc \
                   vc1dec \
                   vp9dec \
                   &&

config_query MESA_XMLCONFIG "Enable custom xmlconfig (driconf) support (requires expat)?" n &&

# declare global persistent variables
persistent_add MESA_DRM &&
persistent_add MESA_GALLIUM &&
persistent_add MESA_GLX &&
persistent_add MESA_TOOLS &&
persistent_add MESA_VULKAN &&
persistent_add MESA_VULKAN_LAYERS &&

# Clean up
persistent_remove MESA_OPENCL_SPIRV &&
persistent_remove MESA_GALLIUM_XA &&
persistent_remove MESA_GALLIUM_D3D9 &&
persistent_remove MESA_OPENCL_ENABLE &&
persistent_remove MESA_OPENCL &&
persistent_remove MESA_OSMESA
