// Copyright 2023 The Android Open Source Project
//
// 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 "VirtioGpuAddressSpaceStream.h"

#include "util.h"

static bool GetRingParamsFromCapset(enum VirtGpuCapset capset, const VirtGpuCaps& caps,
                                    uint32_t& ringSize, uint32_t& bufferSize,
                                    uint32_t& blobAlignment) {
    switch (capset) {
        case kCapsetGfxStreamVulkan:
            ringSize = caps.vulkanCapset.ringSize;
            bufferSize = caps.vulkanCapset.bufferSize;
            blobAlignment = caps.vulkanCapset.blobAlignment;
            break;
        case kCapsetGfxStreamMagma:
            ringSize = caps.magmaCapset.ringSize;
            bufferSize = caps.magmaCapset.bufferSize;
            blobAlignment = caps.magmaCapset.blobAlignment;
            break;
        case kCapsetGfxStreamGles:
            ringSize = caps.glesCapset.ringSize;
            bufferSize = caps.glesCapset.bufferSize;
            blobAlignment = caps.glesCapset.blobAlignment;
            break;
        case kCapsetGfxStreamComposer:
            ringSize = caps.composerCapset.ringSize;
            bufferSize = caps.composerCapset.bufferSize;
            blobAlignment = caps.composerCapset.blobAlignment;
            break;
        default:
            return false;
    }

    return true;
}

address_space_handle_t virtgpu_address_space_open() {
    return (address_space_handle_t)(-EINVAL);
}

void virtgpu_address_space_close(address_space_handle_t) {
    // Handle opened by VirtioGpuDevice wrapper
}

bool virtgpu_address_space_ping(address_space_handle_t, struct address_space_ping* info) {
    int ret;
    struct VirtGpuExecBuffer exec = {};
    VirtGpuDevice* instance = VirtGpuDevice::getInstance();
    struct gfxstreamContextPing ping = {};

    ping.hdr.opCode = GFXSTREAM_CONTEXT_PING;
    ping.resourceId = info->resourceId;

    exec.command = static_cast<void*>(&ping);
    exec.command_size = sizeof(ping);

    ret = instance->execBuffer(exec, nullptr);
    if (ret)
        return false;

    return true;
}

AddressSpaceStream* createVirtioGpuAddressSpaceStream(enum VirtGpuCapset capset,
                                                      HealthMonitor<>* healthMonitor) {
    VirtGpuResourcePtr pipe, blob;
    VirtGpuResourceMappingPtr pipeMapping, blobMapping;
    struct VirtGpuExecBuffer exec = {};
    struct VirtGpuCreateBlob blobCreate = {};
    struct gfxstreamContextCreate contextCreate = {};

    uint32_t ringSize = 0;
    uint32_t bufferSize = 0;
    uint32_t blobAlignment = 0;

    char* blobAddr, *bufferPtr;
    int ret;

    VirtGpuDevice* instance = VirtGpuDevice::getInstance();
    auto caps = instance->getCaps();

    if (!GetRingParamsFromCapset(capset, caps, ringSize, bufferSize, blobAlignment)) {
        ALOGE("Failed to get ring parameters");
        return nullptr;
    }

    blobCreate.blobId = 0;
    blobCreate.blobMem = kBlobMemHost3d;
    blobCreate.flags = kBlobFlagMappable;
    blobCreate.size = ALIGN(ringSize + bufferSize, blobAlignment);
    blob = instance->createBlob(blobCreate);
    if (!blob)
        return nullptr;

    // Context creation command
    contextCreate.hdr.opCode = GFXSTREAM_CONTEXT_CREATE;
    contextCreate.resourceId = blob->getResourceHandle();

    exec.command = static_cast<void*>(&contextCreate);
    exec.command_size = sizeof(contextCreate);

    ret = instance->execBuffer(exec, blob.get());
    if (ret)
        return nullptr;

    // Wait occurs on global timeline -- should we use context specific one?
    ret = blob->wait();
    if (ret)
        return nullptr;

    blobMapping = blob->createMapping();
    if (!blobMapping)
        return nullptr;

    blobAddr = reinterpret_cast<char*>(blobMapping->asRawPtr());

    bufferPtr = blobAddr + sizeof(struct asg_ring_storage);
    struct asg_context context = asg_context_create(blobAddr, bufferPtr, bufferSize);

    context.ring_config->transfer_mode = 1;
    context.ring_config->host_consumed_pos = 0;
    context.ring_config->guest_write_pos = 0;

    struct address_space_ops ops = {
        .open = virtgpu_address_space_open,
        .close = virtgpu_address_space_close,
        .ping = virtgpu_address_space_ping,
    };

    AddressSpaceStream* res =
            new AddressSpaceStream((address_space_handle_t)(-1), 1, context, 0, 0, ops, healthMonitor);

    res->setMapping(blobMapping);
    res->setResourceId(contextCreate.resourceId);
    return res;
}
