# Copyright 2014 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/buildflag_header.gni")
import("//build/config/android/config.gni")
import("//build/config/arm.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
import("//third_party/libaom/libaom_srcs.gni")
import("//third_party/libaom/options.gni")
import("//third_party/nasm/nasm_assemble.gni")

buildflag_header("libaom_buildflags") {
  header = "libaom_buildflags.h"

  flags = [ "ENABLE_LIBAOM=$enable_libaom" ]
}

# Sets the architecture name for building libaom.
if (current_cpu == "x86") {
  cpu_arch_full = "ia32"
} else if (current_cpu == "x64") {
  if (is_msan) {
    # TODO(johannkoenig): Check if MSAN builds pass. libaom is favoring
    # intrinsics over assembly.
    cpu_arch_full = "generic"
  } else {
    cpu_arch_full = "x64"
  }
} else if (current_cpu == "arm") {
  if (arm_use_neon) {
    cpu_arch_full = "arm-neon"
  } else if (is_android) {
    cpu_arch_full = "arm-neon-cpu-detect"
  } else {
    cpu_arch_full = "arm"
  }
} else if (current_cpu == "riscv64") {
  cpu_arch_full = "generic"
} else if (current_cpu == "loong64") {
  cpu_arch_full = "generic"
} else {
  cpu_arch_full = current_cpu
}

if (is_nacl) {
  platform_include_dir = "source/config/linux/generic"
} else {
  if (is_ios && current_cpu == "arm") {
    os_category = current_os
  } else if (is_posix || is_fuchsia) {
    # Should cover linux, fuchsia, mac, and the ios simulator.
    os_category = "linux"
  } else {  # This should only match windows.
    os_category = current_os
  }
  platform_include_dir = "source/config/$os_category/$cpu_arch_full"
}

libaom_include_dirs = [
  "source/config",
  platform_include_dir,
  "source/libaom",
]

config("libaom_config") {
  include_dirs = libaom_include_dirs
}

# This config is applied to targets that depend on libaom.
config("libaom_external_config") {
  include_dirs = [ "source/libaom" ]
}

if (current_cpu == "x86" || (current_cpu == "x64" && !is_msan)) {
  nasm_assemble("libaom_nasm") {
    sources = aom_dsp_common_asm_sse2
    sources += aom_dsp_common_asm_ssse3
    sources += aom_ports_asm_x86
    sources += aom_av1_encoder_asm_sse2
    sources += aom_dsp_encoder_asm_sse2
    if (current_cpu == "x64") {
      sources += aom_av1_encoder_asm_ssse3_x86_64
      sources += aom_dsp_encoder_asm_sse2_x86_64
      sources += aom_dsp_encoder_asm_ssse3_x86_64
    }
    defines = [ "CHROMIUM" ]
    include_dirs = libaom_include_dirs
  }

  # The following targets are deliberately source_set rather than
  # static_library. The :libaom target exposes these intrinsic implementations
  # via global function pointer symbols, which hides the object dependency at
  # link time. On Mac, this results in undefined references to the intrinsic
  # symbols.
  source_set("libaom_intrinsics_sse2") {
    # TODO(jianj): Align this with libvpx as this is not used there.
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (!is_win || is_clang) {
      cflags = [ "-msse2" ]
    }
    sources = aom_av1_common_intrin_sse2
    sources += aom_dsp_common_intrin_sse2
    sources += aom_av1_encoder_intrin_sse2
    sources += aom_dsp_encoder_intrin_sse2
  }

  source_set("libaom_intrinsics_sse3") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (!is_win || is_clang) {
      cflags = [ "-msse3" ]
    }
    sources = aom_av1_encoder_intrin_sse3
  }

  source_set("libaom_intrinsics_ssse3") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (!is_win || is_clang) {
      cflags = [ "-mssse3" ]
    }
    sources = aom_av1_common_intrin_ssse3
    sources += aom_av1_encoder_intrin_ssse3
    sources += aom_dsp_common_intrin_ssse3
    sources += aom_dsp_encoder_intrin_ssse3
  }

  source_set("libaom_intrinsics_sse4_1") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (!is_win || is_clang) {
      cflags = [ "-msse4.1" ]
    }
    sources = aom_av1_common_intrin_sse4_1
    sources += aom_dsp_common_intrin_sse4_1
    sources += aom_av1_encoder_intrin_sse4_1
    sources += aom_dsp_encoder_intrin_sse4_1
  }

  source_set("libaom_intrinsics_sse4_2") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (!is_win || is_clang) {
      cflags = [ "-msse4.2" ]
    }
    sources = aom_av1_encoder_intrin_sse4_2
  }

  source_set("libaom_intrinsics_avx") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (is_win) {
      cflags = [ "/arch:AVX" ]
    } else {
      cflags = [ "-mavx" ]
    }
    sources = aom_dsp_encoder_intrin_avx
  }

  source_set("libaom_intrinsics_avx2") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    configs += [ ":libaom_config" ]
    if (is_win) {
      cflags = [ "/arch:AVX2" ]
    } else {
      cflags = [ "-mavx2" ]
    }
    sources = aom_av1_common_intrin_avx2
    sources += aom_dsp_common_intrin_avx2
    sources += aom_av1_encoder_intrin_avx2
    sources += aom_dsp_encoder_intrin_avx2
  }
}

if (current_cpu == "arm64" || cpu_arch_full == "arm-neon" ||
    cpu_arch_full == "arm-neon-cpu-detect") {
  source_set("libaom_intrinsics_neon") {
    check_includes = false
    configs -= [ "//build/config/compiler:chromium_code" ]
    configs += [ "//build/config/compiler:no_chromium_code" ]
    if (current_cpu == "arm") {
      configs -= [ "//build/config/compiler:compiler_arm_fpu" ]
      cflags = [ "-mfpu=neon" ]
    }
    configs += [ ":libaom_config" ]

    sources = aom_av1_common_intrin_neon
    sources += aom_dsp_common_intrin_neon
    sources += aom_av1_encoder_intrin_neon
    sources += aom_dsp_encoder_intrin_neon
  }
}

static_library("libaom") {
  if (!is_debug && is_win) {
    configs -= [ "//build/config/compiler:default_optimization" ]
    configs += [ "//build/config/compiler:optimize_max" ]
  }
  configs -= [ "//build/config/compiler:chromium_code" ]
  configs += [ "//build/config/compiler:no_chromium_code" ]
  configs += [ ":libaom_config" ]

  sources = aom_av1_common_sources
  sources += aom_av1_decoder_sources
  sources += aom_dsp_common_sources
  sources += aom_dsp_decoder_sources
  sources += aom_mem_sources
  sources += aom_rtcd_sources
  sources += aom_scale_sources
  sources += aom_sources
  sources += aom_util_sources
  sources += aom_av1_encoder_sources
  sources += aom_dsp_encoder_sources
  if (use_libfuzzer) {
    # Note this is inherited from OSS-Fuzz where the fuzzers were being run
    # with a 2 GB total allocation limit.
    if (is_msan) {
      defines = [ "AOM_MAX_ALLOCABLE_MEMORY=536870912" ]
    } else {
      defines = [ "AOM_MAX_ALLOCABLE_MEMORY=1073741824" ]
    }

    # Also enable DO_RANGE_CHECK_CLAMP to suppress the noise of integer
    # overflows in the transform functions.
    defines += [ "DO_RANGE_CHECK_CLAMP=1" ]
  }
  deps = []
  if (current_cpu == "x86" || (current_cpu == "x64" && !is_msan)) {
    deps += [
      ":libaom_intrinsics_avx",
      ":libaom_intrinsics_avx2",
      ":libaom_intrinsics_sse2",
      ":libaom_intrinsics_sse3",
      ":libaom_intrinsics_sse4_1",
      ":libaom_intrinsics_sse4_2",
      ":libaom_intrinsics_ssse3",
      ":libaom_nasm",
    ]
  }
  if (current_cpu == "arm64" || cpu_arch_full == "arm-neon" ||
      cpu_arch_full == "arm-neon-cpu-detect") {
    deps += [ ":libaom_intrinsics_neon" ]
  }
  if (current_cpu == "arm64" || current_cpu == "arm") {
    # This is needed by all arm boards due to aom_arm_cpu_caps()
    sources +=
        [ "//third_party/libaom/source/libaom/aom_ports/arm_cpudetect.c" ]
  }
  if (is_android) {
    deps += [ "//third_party/android_ndk:cpu_features" ]
  }
  public_configs = [ ":libaom_external_config" ]
  public_deps = [ ":libaom_buildflags" ]
}

static_library("libaomrc") {
  if (!is_debug && is_win) {
    configs -= [ "//build/config/compiler:default_optimization" ]
    configs += [ "//build/config/compiler:optimize_max" ]
  }

  sources = [
    "//third_party/libaom/source/libaom/av1/ratectrl_rtc.cc",
    "//third_party/libaom/source/libaom/av1/ratectrl_rtc.h",
  ]
  configs -= [ "//build/config/compiler:chromium_code" ]
  configs += [ "//build/config/compiler:no_chromium_code" ]
  configs += [ ":libaom_config" ]

  public_configs = [ ":libaom_external_config" ]
  public_deps = [ ":libaom" ]
}

fuzzer_test("libaom_av1_dec_fuzzer") {
  sources = [ "source/libaom/examples/av1_dec_fuzzer.cc" ]
  seed_corpus = "fuzz/av1_dec_fuzzer_corpus"
  deps = [ ":libaom" ]
  additional_configs = [ ":libaom_config" ]
}