// Copyright 2023 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/AHBFunctions.h"

namespace dawn::native {

namespace {

// Convert from AHardwareBuffer_Format to wgpu::TextureFormat. Returns:
//  - The exact corresponding wgpu::TextureFormat if the AHardwareBuffer format matches channel and
//  bit count.
//  - External if the format miss-matches in channel count or bit count but is still usable as an
//  OpenGL or Vulkan texture in Dawn.
//  - Undefined if the format is not applicable for WebGPU to import as a texture.
wgpu::TextureFormat FormatFromAHardwareBufferFormat(uint32_t ahbFormat) {
    switch (ahbFormat) {
        // Formats with exact WebGPU representations
        case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
            return wgpu::TextureFormat::RGBA8Unorm;
        case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
            return wgpu::TextureFormat::RGBA16Float;
        case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
            return wgpu::TextureFormat::RGB10A2Unorm;
        case AHARDWAREBUFFER_FORMAT_D16_UNORM:
            return wgpu::TextureFormat::Depth16Unorm;
        case AHARDWAREBUFFER_FORMAT_D24_UNORM:
            return wgpu::TextureFormat::Depth24Plus;
        case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
            return wgpu::TextureFormat::Depth24PlusStencil8;
        case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
            return wgpu::TextureFormat::Depth32Float;
        case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
            return wgpu::TextureFormat::Depth32FloatStencil8;
        case AHARDWAREBUFFER_FORMAT_S8_UINT:
            return wgpu::TextureFormat::Stencil8;
        case AHARDWAREBUFFER_FORMAT_R8_UNORM:
            return wgpu::TextureFormat::R8Unorm;
        case AHARDWAREBUFFER_FORMAT_R16_UINT:
            return wgpu::TextureFormat::R16Uint;
        case AHARDWAREBUFFER_FORMAT_R16G16_UINT:
            return wgpu::TextureFormat::RG16Uint;

        // R8G8B8X8 is used in Vulkan as VK_FORMAT_R8G8B8A8_UNORM and GLES as GL_RGB8. In Vulkan the
        // alpha channel can be read and written but GL always treats it as opaque. Data can be
        // uploaded as if it's RGBA8.
        case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
            return wgpu::TextureFormat::RGBA8Unorm;

        // YUV formats are sampleable with external Vulkan samplers or as opaque samplers in GLES.
        // Treat them as OpaqueYCbCrAndroid.
        case AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420:
            return wgpu::TextureFormat::OpaqueYCbCrAndroid;
        case AHARDWAREBUFFER_FORMAT_YCbCr_P010:
            return wgpu::TextureFormat::OpaqueYCbCrAndroid;

        // RGB formats with no direct representation in WebGPU. They could be sampleable and
        // renderable in Vulkan and GLES but data uploads couldn't be supported without more work.
        case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
            return wgpu::TextureFormat::Undefined;
        case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
            return wgpu::TextureFormat::Undefined;

        // R10G10B10A10 maps to Vulkan format VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 and no
        // GLES format. Not supported with no known use case.
        case AHARDWAREBUFFER_FORMAT_R10G10B10A10_UNORM:
            return wgpu::TextureFormat::Undefined;

        // Can be used as a Vulkan buffer or bound to a GLES buffer using GL_EXT_external_buffer.
        // These use cases are not currently supported.
        case AHARDWAREBUFFER_FORMAT_BLOB:
            return wgpu::TextureFormat::Undefined;

        // Android drivers make use of formats outside of the defined enums to represent internal
        // YUV formats used by the camera and video decoder. Treat these all as external and
        // sampleable.
        default:
            return wgpu::TextureFormat::OpaqueYCbCrAndroid;
    }
}

}  // anonymous namespace

AHBFunctions::AHBFunctions() {
    if (!mNativeWindowLib.Open("libnativewindow.so") ||
        !mNativeWindowLib.GetProc(&Acquire, "AHardwareBuffer_acquire") ||
        !mNativeWindowLib.GetProc(&Release, "AHardwareBuffer_release") ||
        !mNativeWindowLib.GetProc(&Describe, "AHardwareBuffer_describe")) {
        mNativeWindowLib.Close();
    }
}

AHBFunctions::~AHBFunctions() = default;

bool AHBFunctions::IsValid() const {
    return mNativeWindowLib.Valid();
}

SharedTextureMemoryProperties GetAHBSharedTextureMemoryProperties(
    const AHBFunctions* ahbFunctions,
    ::AHardwareBuffer* aHardwareBuffer) {
    AHardwareBuffer_Desc aHardwareBufferDesc{};
    ahbFunctions->Describe(aHardwareBuffer, &aHardwareBufferDesc);

    SharedTextureMemoryProperties properties;
    properties.size = {aHardwareBufferDesc.width, aHardwareBufferDesc.height,
                       aHardwareBufferDesc.layers};
    properties.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
    if (aHardwareBufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER) {
        properties.usage |= wgpu::TextureUsage::RenderAttachment;
    }
    if (aHardwareBufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
        properties.usage |= wgpu::TextureUsage::TextureBinding;
    }
    if (aHardwareBufferDesc.usage & AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER) {
        properties.usage |= wgpu::TextureUsage::StorageBinding;
    }
    properties.format = FormatFromAHardwareBufferFormat(aHardwareBufferDesc.format);

    return properties;
}

}  // namespace dawn::native
