//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// ExternalBufferTest:
//   Tests the correctness of external buffer ext extension.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
#include "util/EGLWindow.h"

#include "common/android_util.h"

#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
#    define ANGLE_AHARDWARE_BUFFER_SUPPORT
// NDK header file for access to Android Hardware Buffers
#    include <android/hardware_buffer.h>
#endif

namespace angle
{

class ExternalBufferTestES31 : public ANGLETest<>
{
  protected:
    ExternalBufferTestES31()
    {
        setWindowWidth(16);
        setWindowHeight(16);
        setConfigRedBits(8);
        setConfigGreenBits(8);
        setConfigBlueBits(8);
        setConfigAlphaBits(8);
        setConfigDepthBits(24);
    }

    AHardwareBuffer *createAndroidHardwareBuffer(size_t size, const GLubyte *data)
    {
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
        // The height and width are number of pixels of size format
        AHardwareBuffer_Desc aHardwareBufferDescription = {};
        aHardwareBufferDescription.width                = size;
        aHardwareBufferDescription.height               = 1;
        aHardwareBufferDescription.layers               = 1;
        aHardwareBufferDescription.format               = AHARDWAREBUFFER_FORMAT_BLOB;
        aHardwareBufferDescription.usage =
            AHARDWAREBUFFER_USAGE_CPU_READ_RARELY | AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER;
        aHardwareBufferDescription.stride = 0;

        // Allocate memory from Android Hardware Buffer
        AHardwareBuffer *aHardwareBuffer = nullptr;
        EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));

        void *mappedMemory = nullptr;
        EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
                                          -1, nullptr, &mappedMemory));

        // Need to grab the stride the implementation might have enforced
        AHardwareBuffer_describe(aHardwareBuffer, &aHardwareBufferDescription);

        if (data)
        {
            memcpy(mappedMemory, data, size);
        }

        EXPECT_EQ(0, AHardwareBuffer_unlock(aHardwareBuffer, nullptr));
        return aHardwareBuffer;
#else
        return nullptr;
#endif  // ANGLE_PLATFORM_ANDROID
    }

    void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
    {
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
        AHardwareBuffer_release(aHardwareBuffer);
#endif
    }

    void *lockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
    {
        void *data = nullptr;
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
        EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
                                          -1, nullptr, &data));
#endif
        return data;
    }

    void unlockAndroidHardwareBuffer(AHardwareBuffer *aHardwareBuffer)
    {
#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
        AHardwareBuffer_unlock(aHardwareBuffer, nullptr);
#endif
    }
};

// Testing subdata update with external buffer from AHB
TEST_P(ExternalBufferTestES31, BufferSubData)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
    constexpr uint8_t kBufferSize = 16;
    std::vector<GLubyte> initData(kBufferSize, 0xA);

    // Create the Image
    AHardwareBuffer *aHardwareBuffer;
    constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
    aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());

    GLBuffer buffer;
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
    glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                               eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
    ASSERT_GL_NO_ERROR();

    std::vector<GLubyte> expectedData(kBufferSize, 0xFF);

    glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
    glFinish();

    ASSERT_GL_NO_ERROR();

    // Inspect the data written into the buffer using CPU access.
    uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));

    for (uint32_t i = 0; i < kBufferSize; ++i)
    {
        EXPECT_EQ(data[i], 0xFF);
    }

    unlockAndroidHardwareBuffer(aHardwareBuffer);

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    buffer.reset();
    // Delete the source AHB
    destroyAndroidHardwareBuffer(aHardwareBuffer);
}

// Verify that subdata updates to an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31, SubDataDoesNotCauseOrphaning)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
    constexpr uint8_t kBufferSize = 16;
    std::vector<GLubyte> initData(kBufferSize, 0xA);

    // Create the AHB
    AHardwareBuffer *aHardwareBuffer;
    constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
    aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());

    // Create externalBuffer
    GLBuffer externalBuffer;
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, externalBuffer);
    glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                               eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
    ASSERT_GL_NO_ERROR();

    // Create a copy read buffer
    std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
    GLBuffer copyReadBuffer;
    glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
    glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
    ASSERT_GL_NO_ERROR();

    // Copy from copyReadBuffer to externalBuffer
    glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
    ASSERT_GL_NO_ERROR();

    // Update externalBuffer
    std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
    glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
    glFinish();
    ASSERT_GL_NO_ERROR();

    // Inspect the data written into the AHB, through externalBuffer, using CPU access.
    uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));

    for (uint32_t i = 0; i < kBufferSize; ++i)
    {
        EXPECT_EQ(data[i], 0xFF);
    }

    unlockAndroidHardwareBuffer(aHardwareBuffer);

    glBindBuffer(GL_COPY_READ_BUFFER, 0);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    copyReadBuffer.reset();
    externalBuffer.reset();
    // Delete the source AHB
    destroyAndroidHardwareBuffer(aHardwareBuffer);
}

// Testing dispatch compute shader external from source AHB
TEST_P(ExternalBufferTestES31, DispatchCompute)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage"));
    constexpr char kCS[] = R"(#version 310 es
    layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
    layout(std430, binding=0) buffer Output {
        uint data[];
    } bOutput;
    void main() {
        bOutput.data[gl_GlobalInvocationID.x] =
            gl_GlobalInvocationID.x * 3u;
    }
)";

    constexpr uint8_t kBufferSize = 16 * 4;
    std::vector<GLubyte> initData(kBufferSize, 0xA);

    // Create the Image
    AHardwareBuffer *aHardwareBuffer;
    constexpr GLbitfield kFlags = GL_MAP_READ_BIT;
    aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());

    GLBuffer buffer;
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
    glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                               eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);

    ASSERT_GL_NO_ERROR();

    GLProgram program;
    program.makeCompute(kCS);
    ASSERT_NE(program, 0U);
    ASSERT_GL_NO_ERROR();

    glUseProgram(program);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, buffer);
    glDispatchCompute(kBufferSize, 1, 1);
    glFinish();
    ASSERT_GL_NO_ERROR();

    // Inspect the data written into the buffer using CPU access.
    uint32_t *data = static_cast<uint32_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));

    for (uint32_t i = 0; i < (kBufferSize / sizeof(uint32_t)); ++i)
    {
        EXPECT_EQ(data[i], static_cast<uint32_t>(i * 3));
    }

    unlockAndroidHardwareBuffer(aHardwareBuffer);

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    buffer.reset();
    // Delete the source AHB
    destroyAndroidHardwareBuffer(aHardwareBuffer);
}

// Test interaction between GL_OES_mapbuffer and GL_EXT_external_buffer extensions.
TEST_P(ExternalBufferTestES31, MapBuffer)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
                       !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
    constexpr uint8_t kBufferSize = 16;
    std::vector<GLubyte> initData(kBufferSize, 0xFF);

    // Create the AHB
    AHardwareBuffer *aHardwareBuffer;
    constexpr GLbitfield kFlags = (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT);
    aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());

    GLBuffer buffer;
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
    glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                               eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);

    ASSERT_GL_NO_ERROR();

    // Inspect the data written into the buffer using CPU access.
    uint8_t *data = static_cast<uint8_t *>(
        glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, GL_MAP_READ_BIT_EXT));
    ASSERT_GL_NO_ERROR();

    for (uint32_t i = 0; i < kBufferSize; ++i)
    {
        EXPECT_EQ(data[i], 0xFF);
    }

    glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);

    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    buffer.reset();
    // Delete the source AHB
    destroyAndroidHardwareBuffer(aHardwareBuffer);
}

// Verify that mapping an external buffer backed by an AHB doesn't orphan the AHB
TEST_P(ExternalBufferTestES31, MapBufferDoesNotCauseOrphaning)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage") ||
                       !IsGLExtensionEnabled("GL_EXT_map_buffer_range"));
    constexpr uint8_t kBufferSize = 16;
    std::vector<GLubyte> initData(kBufferSize, 0xA);

    // Create the AHB
    AHardwareBuffer *aHardwareBuffer;
    constexpr GLbitfield kFlags =
        (GL_MAP_READ_BIT_EXT | GL_MAP_WRITE_BIT_EXT | GL_DYNAMIC_STORAGE_BIT_EXT);
    aHardwareBuffer = createAndroidHardwareBuffer(kBufferSize, initData.data());

    GLBuffer buffer;
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
    glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                               eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
    ASSERT_GL_NO_ERROR();

    // Create a copy read buffer
    std::vector<GLubyte> copyReadBufferData(kBufferSize, 0xB);
    GLBuffer copyReadBuffer;
    glBindBuffer(GL_COPY_READ_BUFFER, copyReadBuffer);
    glBufferData(GL_COPY_READ_BUFFER, kBufferSize, copyReadBufferData.data(), GL_STATIC_READ);
    ASSERT_GL_NO_ERROR();

    // Copy from copyReadBuffer to externalBuffer
    glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_SHADER_STORAGE_BUFFER, 0, 0, kBufferSize);
    ASSERT_GL_NO_ERROR();

    // Inspect the data written into the buffer using map buffer API.
    constexpr GLbitfield kMapFlags = (GL_MAP_WRITE_BIT_EXT | GL_MAP_INVALIDATE_BUFFER_BIT);
    uint8_t *mapData               = static_cast<uint8_t *>(
        glMapBufferRangeEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, kMapFlags));
    ASSERT_GL_NO_ERROR();
    EXPECT_NE(mapData, nullptr);
    glUnmapBufferOES(GL_SHADER_STORAGE_BUFFER);

    // Update externalBuffer
    std::vector<GLubyte> expectedData(kBufferSize, 0xFF);
    glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize, expectedData.data());
    glFinish();
    ASSERT_GL_NO_ERROR();

    // Inspect the data written into the AHB, through externalBuffer, using CPU access.
    uint8_t *data = static_cast<uint8_t *>(lockAndroidHardwareBuffer(aHardwareBuffer));

    for (uint32_t i = 0; i < kBufferSize; ++i)
    {
        EXPECT_EQ(data[i], 0xFF);
    }

    unlockAndroidHardwareBuffer(aHardwareBuffer);

    glBindBuffer(GL_COPY_READ_BUFFER, 0);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
    copyReadBuffer.reset();
    buffer.reset();
    // Delete the source AHB
    destroyAndroidHardwareBuffer(aHardwareBuffer);
}

// Verify that create and destroy external buffer backed by an AHB doesn't leak AHB
TEST_P(ExternalBufferTestES31, BufferDoesNotLeakAHB)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage"));

    // Create and destroy 128M AHB backed buffer in a loop. If we leak AHB, it will fail due to AHB
    // allocation failure before loop ends.
    constexpr size_t kBufferSize = 128 * 1024 * 1024;
    for (int loop = 0; loop < 1000; loop++)
    {
        // Create the AHB
        AHardwareBuffer *aHardwareBuffer;
        constexpr GLbitfield kFlags = GL_DYNAMIC_STORAGE_BIT_EXT;
        aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, nullptr);
        GLBuffer buffer;
        glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer);
        glBufferStorageExternalEXT(GL_SHADER_STORAGE_BUFFER, 0, kBufferSize,
                                   eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
        ASSERT_GL_NO_ERROR();
        buffer.reset();
        // Delete the source AHB
        destroyAndroidHardwareBuffer(aHardwareBuffer);
    }
}

// Test that checks buffer object state after calling glBufferStorageExternalEXT
TEST_P(ExternalBufferTestES31, getBufferParameter)
{
    ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_external_buffer") ||
                       !IsGLExtensionEnabled("GL_EXT_buffer_storage"));

    GLint64 value = -1;

    constexpr uint8_t kBufferSize = 3;
    std::vector<GLubyte> initData(kBufferSize, 0xA);

    // Create the Image
    AHardwareBuffer *aHardwareBuffer;
    constexpr GLbitfield kFlags = GL_MAP_WRITE_BIT;
    aHardwareBuffer             = createAndroidHardwareBuffer(kBufferSize, initData.data());

    GLBuffer buffer;
    glBindBuffer(GL_COPY_READ_BUFFER, buffer);
    glBufferStorageExternalEXT(GL_COPY_READ_BUFFER, 0, kBufferSize,
                               eglGetNativeClientBufferANDROID(aHardwareBuffer), kFlags);
    ASSERT_GL_NO_ERROR();

    /* Check the value of GL_BUFFER_SIZE. */
    glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_SIZE, &value);
    ASSERT_GL_NO_ERROR();
    ASSERT_EQ(kBufferSize, static_cast<GLint>(value));

    /* Check the value of GL_BUFFER_USAGE. */
    value = -1;
    glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_USAGE, &value);
    ASSERT_GL_NO_ERROR();
    ASSERT_EQ(GL_DYNAMIC_DRAW, value);

    /* Check the value of GL_BUFFER_IMMUTABLE_STORAGE_EXT. */
    value = -1;
    glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_IMMUTABLE_STORAGE_EXT, &value);
    ASSERT_GL_NO_ERROR();
    ASSERT_EQ(GL_TRUE, value);

    /* Check the value of GL_BUFFER_STORAGE_FLAGS_EXT. */
    value = -1;
    glGetBufferParameteri64v(GL_COPY_READ_BUFFER, GL_BUFFER_STORAGE_FLAGS_EXT, &value);
    ASSERT_GL_NO_ERROR();
    ASSERT_EQ(kFlags, value);

    /* Clean up. */
    glUnmapBuffer(GL_COPY_READ_BUFFER);
    glBindBuffer(GL_COPY_READ_BUFFER, 0);
}

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ExternalBufferTestES31);
ANGLE_INSTANTIATE_TEST_ES31(ExternalBufferTestES31);
}  // namespace angle
