# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: LicenseRef-NvidiaProprietary
#
# NVIDIA CORPORATION, its affiliates and licensors retain all intellectual
# property and proprietary rights in and to this material, related
# documentation and any modifications thereto. Any use, reproduction,
# disclosure or distribution of this material and related documentation
# without an express license agreement from NVIDIA CORPORATION or
# its affiliates is strictly prohibited.

project(nvsipl_camera)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -frtti")

set(SIPL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../include")
set(SIPL_QUERY_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../include/query/include")
set(NVSCI_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../include/nvsci")
set(NVMEDIA_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../include/nvmedia")
set(WFD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../include/WF")

# Hololink headers (FrameMetadata, etc.) used by HsbTransportMetadata
set(HOLOLINK_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../hololink/src/hololink/core")

include_directories(
    ${SIPL_INCLUDE_DIR}
    ${SIPL_QUERY_INCLUDE_DIR}
    ${NVSCI_INCLUDE_DIR}
    ${NVMEDIA_INCLUDE_DIR}
    ${WFD_INCLUDE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/common
    ${HOLOLINK_INCLUDE_DIR}
)

set(NVIDIA_LIB_HINTS
    /usr/lib/aarch64-linux-gnu/nvidia/
    /usr/lib/aarch64-linux-gnu/
)

find_library(NVSIPL_QUERY_LIB nvsipl_query HINTS ${NVIDIA_LIB_HINTS})
find_library(NVSIPL_CORE_LIB  nvsipl       HINTS ${NVIDIA_LIB_HINTS})
find_library(NVSCIBUF_LIB     nvscibuf     HINTS ${NVIDIA_LIB_HINTS})
find_library(NVSCISYNC_LIB    nvscisync    HINTS ${NVIDIA_LIB_HINTS})
find_library(CAM_FSYNC_LIB    NAMES cam_fsync nvcam_fsync HINTS ${NVIDIA_LIB_HINTS})
find_library(NVMEDIA_2D_LIB NAMES nvmedia2d nvmedia_2d HINTS ${NVIDIA_LIB_HINTS})
find_library(TEGRA_WFD_LIB    tegrawfd     HINTS ${NVIDIA_LIB_HINTS})

if(NVSIPL_CORE_LIB AND NVSIPL_QUERY_LIB)
    # nvpkcs11.h is not in the source tree; pass -DEMU_ON_DESKTOP=OFF for
    # cross-compilation with a full L4T sysroot that provides the header.
    option(EMU_ON_DESKTOP "Skip nvpkcs11 (not in source tree) for desktop/host builds" ON)

    # Core source files
    set(NVSIPL_CAMERA_SOURCES
        main.cpp
        CUtils.cpp
        CCamFsyncUtils.cpp
        CQueryAdapter.cpp
        CComposite.cpp
        CNvWfd.cpp
    )

    # L4T embedded flag — enables EGL display rendering, HSB metadata parsing,
    # and L4T-specific types (matches fusa tmake -DNV_EMBEDDED_L4T)
    option(NV_EMBEDDED_L4T "Enable L4T embedded code paths" ON)

    # When NV_EMBEDDED_L4T is enabled, add HSB metadata, EGL renderer, and
    # NvBufSurface helper sources.
    if(NV_EMBEDDED_L4T)
        # HSB transport metadata parsing and CRC validation — independent of
        # EGL display; needed whenever the HSB FPGA appends frame metadata.
        list(APPEND NVSIPL_CAMERA_SOURCES
            HsbTransportMetadata.cpp
        )

        # EGL renderer headers are vendored under common/ and nvbufsurface.h
        # lives in SIPL_INCLUDE_DIR, so no external header search is needed.
        # Only the link-time libraries (EGL, GLESv2, X11, nvbufsurface) must
        # be present on the target device.
        list(APPEND NVSIPL_CAMERA_SOURCES
            common/NvEglRenderer.cpp
            common/NvElement.cpp
            common/NvElementProfiler.cpp
            common/NvLogging.cpp
            NvNvSciBufHelper.cpp
        )

        # Find EGL/GL/X11 and nvbufsurface libraries required by EGL renderer
        find_library(EGL_LIB EGL HINTS ${NVIDIA_LIB_HINTS})
        find_library(GLESV2_LIB GLESv2 HINTS ${NVIDIA_LIB_HINTS})
        find_library(X11_LIB X11)
        find_library(NVBUFSURFACE_LIB nvbufsurface HINTS ${NVIDIA_LIB_HINTS})
        find_library(NVBUFSURFACE_NVSCI_LIB nvbufsurface_nvsci HINTS ${NVIDIA_LIB_HINTS})
    endif()

    add_executable(${PROJECT_NAME}
        ${NVSIPL_CAMERA_SOURCES}
    )

    if(EMU_ON_DESKTOP)
        target_compile_definitions(${PROJECT_NAME} PRIVATE EMU_ON_DESKTOP)
    endif()

    # Enable Camera HAL query path (matches fusa tmake build -DENABLE_CAMERA_HAL).
    # Required for --enable-camera-hal flag and newer platform configs (AR0234CS_HAWK etc.)
    option(ENABLE_CAMERA_HAL "Enable Camera HAL query path" ON)
    if(ENABLE_CAMERA_HAL)
        target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_CAMERA_HAL)
    endif()

    if(NV_EMBEDDED_L4T)
        target_compile_definitions(${PROJECT_NAME} PRIVATE NV_EMBEDDED_L4T)

        # HsbTransportMetadata.cpp uses ARMv8 CRC32 hardware intrinsics
        # (__crc32d, __crc32w, __crc32b) which require the +crc extension.
        if(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" OR CMAKE_CROSSCOMPILING)
            set_source_files_properties(HsbTransportMetadata.cpp
                PROPERTIES COMPILE_FLAGS "-march=armv8-a+crc")
        endif()

        # HsbTransportMetadata.cpp calls hololink::Hololink::deserialize_metadata
        # from the hololink_core static library. The top-level CMakeLists.txt
        # adds this subdirectory only after the hololink probe, so the target
        # is defined whenever NV_EMBEDDED_L4T builds reach this point.
        if(TARGET hololink_core)
            target_link_libraries(${PROJECT_NAME} hololink_core)
        else()
            message(FATAL_ERROR
                "NV_EMBEDDED_L4T is ON but the hololink_core target is not "
                "available. Install CUDA 13.2 headers and libfmt-dev to enable "
                "the hololink build, or set -DNV_EMBEDDED_L4T=OFF to skip the "
                "HSB metadata parser.")
        endif()
    endif()

    target_link_libraries(${PROJECT_NAME}
        ${NVSIPL_CORE_LIB}
        ${NVSIPL_QUERY_LIB}
        stdc++
        pthread
        rt
        dl
    )

    foreach(_lib NVSCIBUF_LIB NVSCISYNC_LIB CAM_FSYNC_LIB NVMEDIA_2D_LIB TEGRA_WFD_LIB)
        if(${_lib})
            target_link_libraries(${PROJECT_NAME} ${${_lib}})
        else()
            message(WARNING "${_lib} not found — some features may be unavailable.")
        endif()
    endforeach()

    # Link EGL/GL/X11/nvbufsurface libraries when NV_EMBEDDED_L4T is enabled
    if(NV_EMBEDDED_L4T)
        foreach(_lib EGL_LIB GLESV2_LIB X11_LIB NVBUFSURFACE_LIB NVBUFSURFACE_NVSCI_LIB)
            if(${_lib})
                target_link_libraries(${PROJECT_NAME} ${${_lib}})
            else()
                message(WARNING "${_lib} not found — EGL rendering may not work.")
            endif()
        endforeach()
    endif()

    # Install nvsipl_camera to /usr/sbin so it is on the default PATH
    # and matches the location expected by the runtime test infrastructure.
    install(TARGETS ${PROJECT_NAME}
        RUNTIME DESTINATION /usr/sbin
        COMPONENT applications
    )
else()
    message(WARNING "Required SIPL libraries not found. Skipping ${PROJECT_NAME}.")
endif()
