// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_wire/client/Buffer.h"

#include "dawn_wire/BufferConsumer_impl.h"
#include "dawn_wire/WireCmd_autogen.h"
#include "dawn_wire/client/Client.h"
#include "dawn_wire/client/Device.h"

namespace dawn_wire { namespace client {

    // static
    WGPUBuffer Buffer::Create(Device* device, const WGPUBufferDescriptor* descriptor) {
        Client* wireClient = device->client;

        bool mappable =
            (descriptor->usage & (WGPUBufferUsage_MapRead | WGPUBufferUsage_MapWrite)) != 0 ||
            descriptor->mappedAtCreation;
        if (mappable && descriptor->size >= std::numeric_limits<size_t>::max()) {
            device->InjectError(WGPUErrorType_OutOfMemory, "Buffer is too large for map usage");
            return device->CreateErrorBuffer();
        }

        std::unique_ptr<MemoryTransferService::ReadHandle> readHandle = nullptr;
        std::unique_ptr<MemoryTransferService::WriteHandle> writeHandle = nullptr;

        DeviceCreateBufferCmd cmd;
        cmd.deviceId = device->id;
        cmd.descriptor = descriptor;
        cmd.readHandleCreateInfoLength = 0;
        cmd.readHandleCreateInfo = nullptr;
        cmd.writeHandleCreateInfoLength = 0;
        cmd.writeHandleCreateInfo = nullptr;

        if (mappable) {
            if ((descriptor->usage & WGPUBufferUsage_MapRead) != 0) {
                // Create the read handle on buffer creation.
                readHandle.reset(
                    wireClient->GetMemoryTransferService()->CreateReadHandle(descriptor->size));
                if (readHandle == nullptr) {
                    device->InjectError(WGPUErrorType_OutOfMemory,
                                        "Failed to create buffer mapping");
                    return device->CreateErrorBuffer();
                }
                cmd.readHandleCreateInfoLength = readHandle->SerializeCreateSize();
            }

            if ((descriptor->usage & WGPUBufferUsage_MapWrite) != 0 ||
                descriptor->mappedAtCreation) {
                // Create the write handle on buffer creation.
                writeHandle.reset(
                    wireClient->GetMemoryTransferService()->CreateWriteHandle(descriptor->size));
                if (writeHandle == nullptr) {
                    device->InjectError(WGPUErrorType_OutOfMemory,
                                        "Failed to create buffer mapping");
                    return device->CreateErrorBuffer();
                }
                cmd.writeHandleCreateInfoLength = writeHandle->SerializeCreateSize();
            }
        }

        // Create the buffer and send the creation command.
        // This must happen after any potential device->CreateErrorBuffer()
        // as server expects allocating ids to be monotonically increasing
        auto* bufferObjectAndSerial = wireClient->BufferAllocator().New(wireClient);
        Buffer* buffer = bufferObjectAndSerial->object.get();
        buffer->mDevice = device;
        buffer->mDeviceIsAlive = device->GetAliveWeakPtr();
        buffer->mSize = descriptor->size;
        buffer->mDestructWriteHandleOnUnmap = false;

        if (descriptor->mappedAtCreation) {
            // If the buffer is mapped at creation, a write handle is created and will be
            // destructed on unmap if the buffer doesn't have MapWrite usage
            // The buffer is mapped right now.
            buffer->mMapState = MapState::MappedAtCreation;

            // This flag is for write handle created by mappedAtCreation
            // instead of MapWrite usage. We don't have such a case for read handle
            buffer->mDestructWriteHandleOnUnmap =
                (descriptor->usage & WGPUBufferUsage_MapWrite) == 0;

            buffer->mMapOffset = 0;
            buffer->mMapSize = buffer->mSize;
            ASSERT(writeHandle != nullptr);
            buffer->mMappedData = writeHandle->GetData();
        }

        cmd.result = ObjectHandle{buffer->id, bufferObjectAndSerial->generation};

        wireClient->SerializeCommand(
            cmd, cmd.readHandleCreateInfoLength + cmd.writeHandleCreateInfoLength,
            [&](SerializeBuffer* serializeBuffer) {
                if (readHandle != nullptr) {
                    char* readHandleBuffer;
                    WIRE_TRY(
                        serializeBuffer->NextN(cmd.readHandleCreateInfoLength, &readHandleBuffer));
                    // Serialize the ReadHandle into the space after the command.
                    readHandle->SerializeCreate(readHandleBuffer);
                    buffer->mReadHandle = std::move(readHandle);
                }
                if (writeHandle != nullptr) {
                    char* writeHandleBuffer;
                    WIRE_TRY(serializeBuffer->NextN(cmd.writeHandleCreateInfoLength,
                                                    &writeHandleBuffer));
                    // Serialize the WriteHandle into the space after the command.
                    writeHandle->SerializeCreate(writeHandleBuffer);
                    buffer->mWriteHandle = std::move(writeHandle);
                }

                return WireResult::Success;
            });
        return ToAPI(buffer);
    }

    // static
    WGPUBuffer Buffer::CreateError(Device* device) {
        auto* allocation = device->client->BufferAllocator().New(device->client);
        allocation->object->mDevice = device;
        allocation->object->mDeviceIsAlive = device->GetAliveWeakPtr();

        DeviceCreateErrorBufferCmd cmd;
        cmd.self = ToAPI(device);
        cmd.result = ObjectHandle{allocation->object->id, allocation->generation};
        device->client->SerializeCommand(cmd);

        return ToAPI(allocation->object.get());
    }

    Buffer::~Buffer() {
        ClearAllCallbacks(WGPUBufferMapAsyncStatus_DestroyedBeforeCallback);
        FreeMappedData();
    }

    void Buffer::CancelCallbacksForDisconnect() {
        ClearAllCallbacks(WGPUBufferMapAsyncStatus_DeviceLost);
    }

    void Buffer::ClearAllCallbacks(WGPUBufferMapAsyncStatus status) {
        mRequests.CloseAll([status](MapRequestData* request) {
            if (request->callback != nullptr) {
                request->callback(status, request->userdata);
            }
        });
    }

    void Buffer::MapAsync(WGPUMapModeFlags mode,
                          size_t offset,
                          size_t size,
                          WGPUBufferMapCallback callback,
                          void* userdata) {
        if (client->IsDisconnected()) {
            return callback(WGPUBufferMapAsyncStatus_DeviceLost, userdata);
        }

        // Handle the defaulting of size required by WebGPU.
        if (size == 0 && offset < mSize) {
            size = mSize - offset;
        }

        // Create the request structure that will hold information while this mapping is
        // in flight.
        MapRequestData request = {};
        request.callback = callback;
        request.userdata = userdata;
        request.offset = offset;
        request.size = size;
        if (mode & WGPUMapMode_Read) {
            request.type = MapRequestType::Read;
        } else if (mode & WGPUMapMode_Write) {
            request.type = MapRequestType::Write;
        }

        uint64_t serial = mRequests.Add(std::move(request));

        // Serialize the command to send to the server.
        BufferMapAsyncCmd cmd;
        cmd.bufferId = this->id;
        cmd.requestSerial = serial;
        cmd.mode = mode;
        cmd.offset = offset;
        cmd.size = size;

        client->SerializeCommand(cmd);
    }

    bool Buffer::OnMapAsyncCallback(uint64_t requestSerial,
                                    uint32_t status,
                                    uint64_t readDataUpdateInfoLength,
                                    const uint8_t* readDataUpdateInfo) {
        MapRequestData request;
        if (!mRequests.Acquire(requestSerial, &request)) {
            return false;
        }

        auto FailRequest = [&request]() -> bool {
            if (request.callback != nullptr) {
                request.callback(WGPUBufferMapAsyncStatus_DeviceLost, request.userdata);
            }
            return false;
        };

        // Take into account the client-side status of the request if the server says it is a success.
        if (status == WGPUBufferMapAsyncStatus_Success) {
            status = request.clientStatus;
        }

        if (status == WGPUBufferMapAsyncStatus_Success) {
            switch (request.type) {
                case MapRequestType::Read: {
                    if (readDataUpdateInfoLength > std::numeric_limits<size_t>::max()) {
                        // This is the size of data deserialized from the command stream, which must
                        // be CPU-addressable.
                        return FailRequest();
                    }

                    // Validate to prevent bad map request; buffer destroyed during map request
                    if (mReadHandle == nullptr) {
                        return FailRequest();
                    }
                    // Update user map data with server returned data
                    if (!mReadHandle->DeserializeDataUpdate(
                            readDataUpdateInfo, static_cast<size_t>(readDataUpdateInfoLength),
                            request.offset, request.size)) {
                        return FailRequest();
                    }
                    mMapState = MapState::MappedForRead;
                    mMappedData = const_cast<void*>(mReadHandle->GetData());
                    break;
                }
                case MapRequestType::Write: {
                    if (mWriteHandle == nullptr) {
                        return FailRequest();
                    }
                    mMapState = MapState::MappedForWrite;
                    mMappedData = mWriteHandle->GetData();
                    break;
                }
                default:
                    UNREACHABLE();
            }

            mMapOffset = request.offset;
            mMapSize = request.size;
        }

        if (request.callback) {
            request.callback(static_cast<WGPUBufferMapAsyncStatus>(status), request.userdata);
        }

        return true;
    }

    void* Buffer::GetMappedRange(size_t offset, size_t size) {
        if (!IsMappedForWriting() || !CheckGetMappedRangeOffsetSize(offset, size)) {
            return nullptr;
        }
        return static_cast<uint8_t*>(mMappedData) + offset;
    }

    const void* Buffer::GetConstMappedRange(size_t offset, size_t size) {
        if (!(IsMappedForWriting() || IsMappedForReading()) ||
            !CheckGetMappedRangeOffsetSize(offset, size)) {
            return nullptr;
        }
        return static_cast<uint8_t*>(mMappedData) + offset;
    }

    void Buffer::Unmap() {
        // Invalidate the local pointer, and cancel all other in-flight requests that would
        // turn into errors anyway (you can't double map). This prevents race when the following
        // happens, where the application code would have unmapped a buffer but still receive a
        // callback:
        //   - Client -> Server: MapRequest1, Unmap, MapRequest2
        //   - Server -> Client: Result of MapRequest1
        //   - Unmap locally on the client
        //   - Server -> Client: Result of MapRequest2

        // mWriteHandle can still be nullptr if buffer has been destroyed before unmap
        if ((mMapState == MapState::MappedForWrite || mMapState == MapState::MappedAtCreation) &&
            mWriteHandle != nullptr) {
            // Writes need to be flushed before Unmap is sent. Unmap calls all associated
            // in-flight callbacks which may read the updated data.

            // Get the serialization size of data update writes.
            size_t writeDataUpdateInfoLength =
                mWriteHandle->SizeOfSerializeDataUpdate(mMapOffset, mMapSize);

            BufferUpdateMappedDataCmd cmd;
            cmd.bufferId = id;
            cmd.writeDataUpdateInfoLength = writeDataUpdateInfoLength;
            cmd.writeDataUpdateInfo = nullptr;
            cmd.offset = mMapOffset;
            cmd.size = mMapSize;

            client->SerializeCommand(
                cmd, writeDataUpdateInfoLength, [&](SerializeBuffer* serializeBuffer) {
                    char* writeHandleBuffer;
                    WIRE_TRY(serializeBuffer->NextN(writeDataUpdateInfoLength, &writeHandleBuffer));

                    // Serialize flush metadata into the space after the command.
                    // This closes the handle for writing.
                    mWriteHandle->SerializeDataUpdate(writeHandleBuffer, cmd.offset, cmd.size);

                    return WireResult::Success;
                });

            // If mDestructWriteHandleOnUnmap is true, that means the write handle is merely
            // for mappedAtCreation usage. It is destroyed on unmap after flush to server
            // instead of at buffer destruction.
            if (mMapState == MapState::MappedAtCreation && mDestructWriteHandleOnUnmap) {
                mWriteHandle = nullptr;
                if (mReadHandle) {
                    // If it's both mappedAtCreation and MapRead we need to reset
                    // mMappedData to readHandle's GetData(). This could be changed to
                    // merging read/write handle in future
                    mMappedData = const_cast<void*>(mReadHandle->GetData());
                }
            }
        }

        // Free map access tokens
        mMapState = MapState::Unmapped;
        mMapOffset = 0;
        mMapSize = 0;

        // Tag all mapping requests still in flight as unmapped before callback.
        mRequests.ForAll([](MapRequestData* request) {
            if (request->clientStatus == WGPUBufferMapAsyncStatus_Success) {
                request->clientStatus = WGPUBufferMapAsyncStatus_UnmappedBeforeCallback;
            }
        });

        BufferUnmapCmd cmd;
        cmd.self = ToAPI(this);
        client->SerializeCommand(cmd);
    }

    void Buffer::Destroy() {
        // Remove the current mapping and destroy Read/WriteHandles.
        FreeMappedData();

        // Tag all mapping requests still in flight as destroyed before callback.
        mRequests.ForAll([](MapRequestData* request) {
            if (request->clientStatus == WGPUBufferMapAsyncStatus_Success) {
                request->clientStatus = WGPUBufferMapAsyncStatus_DestroyedBeforeCallback;
            }
        });

        BufferDestroyCmd cmd;
        cmd.self = ToAPI(this);
        client->SerializeCommand(cmd);
    }

    bool Buffer::IsMappedForReading() const {
        return mMapState == MapState::MappedForRead;
    }

    bool Buffer::IsMappedForWriting() const {
        return mMapState == MapState::MappedForWrite || mMapState == MapState::MappedAtCreation;
    }

    bool Buffer::CheckGetMappedRangeOffsetSize(size_t offset, size_t size) const {
        if (offset % 8 != 0 || size % 4 != 0) {
            return false;
        }

        if (size > mMapSize || offset < mMapOffset) {
            return false;
        }

        size_t offsetInMappedRange = offset - mMapOffset;
        return offsetInMappedRange <= mMapSize - size;
    }

    void Buffer::FreeMappedData() {
#if defined(DAWN_ENABLE_ASSERTS)
        // When in "debug" mode, 0xCA-out the mapped data when we free it so that in we can detect
        // use-after-free of the mapped data. This is particularly useful for WebGPU test about the
        // interaction of mapping and GC.
        if (mMappedData) {
            memset(static_cast<uint8_t*>(mMappedData) + mMapOffset, 0xCA, mMapSize);
        }
#endif  // defined(DAWN_ENABLE_ASSERTS)

        mMapOffset = 0;
        mMapSize = 0;
        mReadHandle = nullptr;
        mWriteHandle = nullptr;
        mMappedData = nullptr;
    }

}}  // namespace dawn_wire::client
