// Copyright 2024 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/opengl/SharedTextureMemoryEGL.h"

#include <utility>

#include "src/dawn/native/opengl/DeviceGL.h"
#include "src/dawn/native/opengl/TextureGL.h"
#include "src/dawn/native/opengl/UtilsGL.h"

#if DAWN_PLATFORM_IS(ANDROID)
#include <android/hardware_buffer.h>

#include "src/dawn/native/AHBFunctions.h"
#endif  // DAWN_PLATFORM_IS(ANDROID)

namespace dawn::native::opengl {

ResultOrError<Ref<SharedTextureMemory>> SharedTextureMemoryEGL::Create(
    Device* device,
    StringView label,
    const SharedTextureMemoryAHardwareBufferDescriptor* descriptor) {
#if DAWN_PLATFORM_IS(ANDROID)
    const EGLFunctions& egl = device->GetEGL(false);
    DAWN_ASSERT(egl.HasExt(EGLExt::ImageNativeBuffer) && egl.HasExt(EGLExt::GetNativeClientBuffer));

    ::AHardwareBuffer* aHardwareBuffer = static_cast<struct AHardwareBuffer*>(descriptor->handle);
    DAWN_INVALID_IF(aHardwareBuffer == nullptr, "AHardwareBuffer is missing.");

    // Reflect the properties of the AHardwareBuffer.
    SharedTextureMemoryProperties properties =
        GetAHBSharedTextureMemoryProperties(device->GetOrLoadAHBFunctions(), aHardwareBuffer);
    DAWN_INVALID_IF(properties.format == wgpu::TextureFormat::Undefined,
                    "Unknown AHardwareBuffer format cannot be imported.");

    // If the format of the AHB is unknown due to not having an equivalent wgpu::TextureFormat or
    // being an unknowable Android video format, disable all usages except sampling.
    if (properties.format == wgpu::TextureFormat::OpaqueYCbCrAndroid) {
        properties.usage &= wgpu::TextureUsage::TextureBinding;
    }

    const EGLAttrib attribs[] = {
        EGL_NONE,
    };
    EGLClientBuffer clientBuffer = egl.GetNativeClientBuffer(aHardwareBuffer);
    ::EGLImage image = egl.CreateImage(device->GetEGLDisplay(), EGL_NO_CONTEXT,
                                       EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attribs);
    DAWN_INVALID_IF(image == nullptr, "EGLImage creation failed, 0x%X", egl.GetError());

    auto result = AcquireRef(new SharedTextureMemoryEGL(device, label, properties, image));
    result->Initialize();
    return result;
#else
    DAWN_UNREACHABLE();
#endif  // DAWN_PLATFORM_IS(ANDROID)
}

SharedTextureMemoryEGL::SharedTextureMemoryEGL(Device* device,
                                               StringView label,
                                               const SharedTextureMemoryProperties& properties,
                                               ::EGLImage image)
    : SharedTextureMemory(device, label, properties), mEGLImage(image) {}

void SharedTextureMemoryEGL::DestroyImpl(DestroyReason reason) {
    if (mEGLImage) {
        Device* device = ToBackend(GetDevice());
        const EGLFunctions& egl = device->GetEGL(false);

        egl.DestroyImage(device->GetEGLDisplay(), mEGLImage);
        mEGLImage = nullptr;
    }
}

ResultOrError<GLuint> SharedTextureMemoryEGL::GenerateGLTexture(const OpenGLFunctions& gl) {
    GLuint tex;
    DAWN_GL_TRY(gl, GenTextures(1, &tex));
    DAWN_GL_TRY(gl, BindTexture(GL_TEXTURE_2D, tex));
    DAWN_GL_TRY(gl, EGLImageTargetTexture2DOES(GL_TEXTURE_2D, mEGLImage));
    DAWN_GL_TRY(gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));

    return tex;
}

}  // namespace dawn::native::opengl
