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

#include <cutils/log.h>

#include <optional>

#include "drm_fourcc.h"

namespace gfxstream {
namespace {

static constexpr int numFds = 0;
static constexpr int numInts = 1;

std::optional<uint32_t> GlFormatToDrmFormat(uint32_t glFormat) {
    switch (glFormat) {
        case kGlRGB:
            return DRM_FORMAT_BGR888;
        case kGlRGB565:
            return DRM_FORMAT_BGR565;
        case kGlRGBA:
            return DRM_FORMAT_ABGR8888;
    }
    return std::nullopt;
}

std::optional<uint32_t> DrmToVirglFormat(uint32_t drmFormat) {
    switch (drmFormat) {
        case DRM_FORMAT_ABGR8888:
            return VIRGL_FORMAT_B8G8R8A8_UNORM;
        case DRM_FORMAT_BGR888:
            return VIRGL_FORMAT_R8G8B8_UNORM;
        case DRM_FORMAT_BGR565:
            return VIRGL_FORMAT_B5G6R5_UNORM;
    }
    return std::nullopt;
}

}  // namespace

EmulatedAHardwareBuffer::EmulatedAHardwareBuffer(uint32_t width, uint32_t height,
                                                 VirtGpuBlobPtr resource)
    : mRefCount(1), mWidth(width), mHeight(height), mResource(resource) {}

EmulatedAHardwareBuffer::~EmulatedAHardwareBuffer() {}

uint32_t EmulatedAHardwareBuffer::getResourceId() const { return mResource->getResourceHandle(); }

uint32_t EmulatedAHardwareBuffer::getWidth() const { return mWidth; }

uint32_t EmulatedAHardwareBuffer::getHeight() const { return mHeight; }

int EmulatedAHardwareBuffer::getAndroidFormat() const {
    return /*AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM=*/1;
}

uint32_t EmulatedAHardwareBuffer::getDrmFormat() const { return DRM_FORMAT_ABGR8888; }

AHardwareBuffer* EmulatedAHardwareBuffer::asAHardwareBuffer() {
    return reinterpret_cast<AHardwareBuffer*>(this);
}

buffer_handle_t EmulatedAHardwareBuffer::asBufferHandle() {
    return reinterpret_cast<buffer_handle_t>(this);
}

EGLClientBuffer EmulatedAHardwareBuffer::asEglClientBuffer() {
    return reinterpret_cast<EGLClientBuffer>(this);
}

void EmulatedAHardwareBuffer::acquire() { ++mRefCount; }

void EmulatedAHardwareBuffer::release() {
    --mRefCount;
    if (mRefCount == 0) {
        delete this;
    }
}

EmulatedGralloc::EmulatedGralloc() {}

uint32_t EmulatedGralloc::createColorBuffer(void*, int width, int height, uint32_t glFormat) {
    auto drmFormat = GlFormatToDrmFormat(glFormat);
    if (!drmFormat) {
        ALOGE("Unhandled format");
    }

    auto ahb = allocate(width, height, *drmFormat);

    EmulatedAHardwareBuffer* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);

    mOwned.emplace_back(rahb);

    return rahb->getResourceId();
}

int EmulatedGralloc::allocate(uint32_t width, uint32_t height, uint32_t format, uint64_t usage,
                              AHardwareBuffer** outputAhb) {
    (void)usage;
    *outputAhb = allocate(width, height, format);
    return 0;
}

AHardwareBuffer* EmulatedGralloc::allocate(uint32_t width, uint32_t height, uint32_t format) {
    ALOGE("Allocating AHB w:%u, h:%u, format %u", width, height, format);

    auto device = VirtGpuDevice::getInstance();
    if (!device) {
        ALOGE("Failed to allocate: no virtio gpu device.");
        return nullptr;
    }

    auto virglFormat = DrmToVirglFormat(format);
    if (!virglFormat) {
        ALOGE("Unhandled DRM format:%u", format);
        return nullptr;
    }

    auto resource = device->createVirglBlob(width, height, *virglFormat);
    if (!resource) {
        ALOGE("Failed to allocate: failed to create virtio resource.");
        return nullptr;
    }

    resource->wait();

    return reinterpret_cast<AHardwareBuffer*>(
        new EmulatedAHardwareBuffer(width, height, std::move(resource)));
}

void EmulatedGralloc::acquire(AHardwareBuffer* ahb) {
    auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
    rahb->acquire();
}

void EmulatedGralloc::release(AHardwareBuffer* ahb) {
    auto* rahb = reinterpret_cast<EmulatedAHardwareBuffer*>(ahb);
    rahb->release();
}

uint32_t EmulatedGralloc::getHostHandle(const native_handle_t* handle) {
    const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
    return ahb->getResourceId();
}

uint32_t EmulatedGralloc::getHostHandle(const AHardwareBuffer* handle) {
    const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
    return ahb->getResourceId();
}

const native_handle_t* EmulatedGralloc::getNativeHandle(const AHardwareBuffer* ahb) {
    return reinterpret_cast<const native_handle_t*>(ahb);
}

int EmulatedGralloc::getFormat(const native_handle_t* handle) {
    const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
    return ahb->getAndroidFormat();
}

int EmulatedGralloc::getFormat(const AHardwareBuffer* handle) {
    const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
    return ahb->getAndroidFormat();
}

uint32_t EmulatedGralloc::getFormatDrmFourcc(const AHardwareBuffer* handle) {
    const auto* ahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(handle);
    return ahb->getDrmFormat();
}

size_t EmulatedGralloc::getAllocatedSize(const native_handle_t*) {
    ALOGE("Unimplemented.");
    return 0;
}

size_t EmulatedGralloc::getAllocatedSize(const AHardwareBuffer*) {
    ALOGE("Unimplemented.");
    return 0;
}

int EmulatedGralloc::getId(const AHardwareBuffer* ahb, uint64_t* id) {
    const auto* rahb = reinterpret_cast<const EmulatedAHardwareBuffer*>(ahb);
    *id = rahb->getResourceId();
    return 0;
}

Gralloc* createPlatformGralloc(int /*deviceFd*/) {
    return new EmulatedGralloc();
}

}  // namespace gfxstream
