//
// Copyright 2021 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.
//
// CLMemory.cpp: Implements the cl::Memory class.
//

#include "common/unsafe_buffers.h"

#include <angle_cl.h>

#include "libANGLE/CLBitField.h"
#include "libANGLE/CLBuffer.h"
#include "libANGLE/CLContext.h"
#include "libANGLE/CLMemory.h"
#include "libANGLE/cl_utils.h"

#include <cstring>
#include <type_traits>

namespace cl
{

namespace
{

MemFlags InheritMemFlags(MemFlags flags, Memory *parent)
{
    if (parent != nullptr)
    {
        const MemFlags parentFlags = parent->getFlags();
        const MemFlags access(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY);
        const MemFlags hostAccess(CL_MEM_HOST_WRITE_ONLY | CL_MEM_HOST_READ_ONLY |
                                  CL_MEM_HOST_NO_ACCESS);
        const MemFlags hostPtrFlags(CL_MEM_USE_HOST_PTR | CL_MEM_ALLOC_HOST_PTR |
                                    CL_MEM_COPY_HOST_PTR);
        if (flags.excludes(access))
        {
            flags.set(parentFlags.mask(access));
        }
        if (flags.excludes(hostAccess))
        {
            flags.set(parentFlags.mask(hostAccess));
        }
        flags.set(parentFlags.mask(hostPtrFlags));
    }
    return flags;
}

}  // namespace

angle::Result Memory::setDestructorCallback(MemoryCB pfnNotify, void *userData)
{
    mDestructorCallbacks.add(pfnNotify, userData);
    return angle::Result::Continue;
}

angle::Result Memory::getInfo(MemInfo name,
                              size_t valueSize,
                              void *value,
                              size_t *valueSizeRet) const
{
    static_assert(
        std::is_same<cl_uint, cl_bool>::value && std::is_same<cl_uint, cl_mem_object_type>::value,
        "OpenCL type mismatch");

    cl_uint valUInt       = 0u;
    void *valPointer      = nullptr;
    const void *copyValue = nullptr;
    size_t copySize       = 0u;

    switch (name)
    {
        case MemInfo::Type:
            valUInt   = ToCLenum(getType());
            copyValue = &valUInt;
            copySize  = sizeof(valUInt);
            break;
        case MemInfo::Flags:
            copyValue = &mFlags;
            copySize  = sizeof(mFlags);
            break;
        case MemInfo::Size:
            copyValue = &mSize;
            copySize  = sizeof(mSize);
            break;
        case MemInfo::HostPtr:
            copyValue = &mHostPtr;
            copySize  = sizeof(mHostPtr);
            break;
        case MemInfo::MapCount:
            valUInt   = mMapCount;
            copyValue = &valUInt;
            copySize  = sizeof(valUInt);
            break;
        case MemInfo::ReferenceCount:
            valUInt   = getRefCount();
            copyValue = &valUInt;
            copySize  = sizeof(valUInt);
            break;
        case MemInfo::Context:
            valPointer = mContext->getNative();
            copyValue  = &valPointer;
            copySize   = sizeof(valPointer);
            break;
        case MemInfo::AssociatedMemObject:
            valPointer = Memory::CastNative(mParent.get());
            copyValue  = &valPointer;
            copySize   = sizeof(valPointer);
            break;
        case MemInfo::Offset:
            copyValue = &mOffset;
            copySize  = sizeof(mOffset);
            break;
        case MemInfo::UsesSVM_Pointer:
            valUInt   = CL_FALSE;  // TODO(jplate) Check for SVM pointer anglebug.com/42264535
            copyValue = &valUInt;
            copySize  = sizeof(valUInt);
            break;
        case MemInfo::Properties:
            copyValue = mProperties.data();
            copySize  = mProperties.size() * sizeof(decltype(mProperties)::value_type);
            break;
        default:
            ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
    }

    if (value != nullptr)
    {
        // CL_INVALID_VALUE if size in bytes specified by param_value_size is < size of return type
        // as described in the Memory Object Info table and param_value is not NULL.
        if (valueSize < copySize)
        {
            ANGLE_CL_RETURN_ERROR(CL_INVALID_VALUE);
        }
        if (copyValue != nullptr)
        {
            ANGLE_UNSAFE_TODO(std::memcpy(value, copyValue, copySize));
        }
    }
    if (valueSizeRet != nullptr)
    {
        *valueSizeRet = copySize;
    }
    return angle::Result::Continue;
}

Memory::~Memory()
{
    mDestructorCallbacks.invoke(this);
}

Memory::Memory(const Buffer &buffer,
               Context &context,
               PropArray &&properties,
               MemFlags flags,
               size_t size,
               void *hostPtr)
    : mContext(&context),
      mProperties(std::move(properties)),
      mFlags(flags.excludes(CL_MEM_READ_WRITE | CL_MEM_READ_ONLY | CL_MEM_WRITE_ONLY)
                 ? cl::MemFlags{flags.get() | CL_MEM_READ_WRITE}
                 : flags),
      mHostPtr(flags.intersects(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
      mImpl(nullptr),
      mSize(size),
      mMapCount(0u)
{
    ANGLE_CL_IMPL_TRY(context.getImpl().createBuffer(buffer, hostPtr, &mImpl));
}

Memory::Memory(const Buffer &buffer, Buffer &parent, MemFlags flags, size_t offset, size_t size)
    : mContext(parent.mContext),
      mFlags(InheritMemFlags(flags, &parent)),
      mHostPtr(parent.mHostPtr != nullptr
                   ? ANGLE_UNSAFE_TODO(static_cast<char *>(parent.mHostPtr) + offset)
                   : nullptr),
      mParent(&parent),
      mOffset(offset),
      mImpl(nullptr),
      mSize(size),
      mMapCount(0u)
{
    ANGLE_CL_IMPL_TRY(parent.mImpl->createSubBuffer(buffer, flags, size, &mImpl));
}

Memory::Memory(Context &context,
               PropArray &&properties,
               MemFlags flags,
               Memory *parent,
               void *hostPtr)
    : mContext(&context),
      mProperties(std::move(properties)),
      mFlags(InheritMemFlags(flags, parent)),
      mHostPtr(flags.intersects(CL_MEM_USE_HOST_PTR) ? hostPtr : nullptr),
      mParent(parent),
      mImpl(nullptr),
      mSize(0u),
      mMapCount(0u)
{}

}  // namespace cl
