/*
 * Copyright 2016 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 "driver.h"

namespace vulkan {
namespace driver {

DebugReportCallbackList::Node* DebugReportCallbackList::AddCallback(
    const VkDebugReportCallbackCreateInfoEXT& info,
    VkDebugReportCallbackEXT driver_handle,
    const VkAllocationCallbacks& allocator) {
    void* mem = allocator.pfnAllocation(allocator.pUserData, sizeof(Node),
                                        alignof(Node),
                                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
    if (!mem)
        return nullptr;

    // initialize and prepend node to the list
    std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
    head_.next = new (mem) Node{head_.next, info.flags, info.pfnCallback,
                                info.pUserData, driver_handle};

    return head_.next;
}

void DebugReportCallbackList::RemoveCallback(
    Node* node,
    const VkAllocationCallbacks& allocator) {
    // remove node from the list
    {
        std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
        Node* prev = &head_;
        while (prev && prev->next != node)
            prev = prev->next;
        prev->next = node->next;
    }

    allocator.pfnFree(allocator.pUserData, node);
}

void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
                                      VkDebugReportObjectTypeEXT object_type,
                                      uint64_t object,
                                      size_t location,
                                      int32_t message_code,
                                      const char* layer_prefix,
                                      const char* message) const {
    std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
    const Node* node = &head_;
    while ((node = node->next)) {
        if ((node->flags & flags) != 0) {
            node->callback(flags, object_type, object, location, message_code,
                           layer_prefix, message, node->user_data);
        }
    }
}

void DebugReportLogger::Message(VkDebugReportFlagsEXT flags,
                                VkDebugReportObjectTypeEXT object_type,
                                uint64_t object,
                                size_t location,
                                int32_t message_code,
                                const char* layer_prefix,
                                const char* message) const {
    const VkDebugReportCallbackCreateInfoEXT* info =
        reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
            instance_pnext_);
    while (info) {
        if (info->sType ==
                VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT &&
            (info->flags & flags) != 0) {
            info->pfnCallback(flags, object_type, object, location,
                              message_code, layer_prefix, message,
                              info->pUserData);
        }

        info = reinterpret_cast<const VkDebugReportCallbackCreateInfoEXT*>(
            info->pNext);
    }

    if (callbacks_) {
        callbacks_->Message(flags, object_type, object, location, message_code,
                            layer_prefix, message);
    }
}

void DebugReportLogger::PrintV(VkDebugReportFlagsEXT flags,
                               VkDebugReportObjectTypeEXT object_type,
                               uint64_t object,
                               const char* format,
                               va_list ap) const {
    char buf[1024];
    int len = vsnprintf(buf, sizeof(buf), format, ap);

    // message truncated
    if (len >= static_cast<int>(sizeof(buf)))
        memcpy(buf + sizeof(buf) - 4, "...", 4);

    Message(flags, object_type, object, 0, 0, LOG_TAG, buf);
}

VkResult CreateDebugReportCallbackEXT(
    VkInstance instance,
    const VkDebugReportCallbackCreateInfoEXT* create_info,
    const VkAllocationCallbacks* allocator,
    VkDebugReportCallbackEXT* callback) {
    const auto& driver = GetData(instance).driver;
    VkDebugReportCallbackEXT driver_handle = VK_NULL_HANDLE;
    if (driver.CreateDebugReportCallbackEXT) {
        VkResult result = driver.CreateDebugReportCallbackEXT(
            instance, create_info, allocator, &driver_handle);
        if (result != VK_SUCCESS)
            return result;
    }

    auto& callbacks = GetData(instance).debug_report_callbacks;
    auto node = callbacks.AddCallback(
        *create_info, driver_handle,
        (allocator) ? *allocator : GetData(instance).allocator);
    if (!node) {
        if (driver_handle != VK_NULL_HANDLE) {
            driver.DestroyDebugReportCallbackEXT(instance, driver_handle,
                                                 allocator);
        }

        return VK_ERROR_OUT_OF_HOST_MEMORY;
    }

    *callback = callbacks.GetHandle(node);

    return VK_SUCCESS;
}

void DestroyDebugReportCallbackEXT(VkInstance instance,
                                   VkDebugReportCallbackEXT callback,
                                   const VkAllocationCallbacks* allocator) {
    if (callback == VK_NULL_HANDLE)
        return;

    auto& callbacks = GetData(instance).debug_report_callbacks;
    auto node = callbacks.FromHandle(callback);
    auto driver_handle = callbacks.GetDriverHandle(node);

    callbacks.RemoveCallback(
        node, (allocator) ? *allocator : GetData(instance).allocator);

    if (driver_handle != VK_NULL_HANDLE) {
        GetData(instance).driver.DestroyDebugReportCallbackEXT(
            instance, driver_handle, allocator);
    }
}

void DebugReportMessageEXT(VkInstance instance,
                           VkDebugReportFlagsEXT flags,
                           VkDebugReportObjectTypeEXT object_type,
                           uint64_t object,
                           size_t location,
                           int32_t message_code,
                           const char* layer_prefix,
                           const char* message) {
    if (GetData(instance).driver.DebugReportMessageEXT) {
        GetData(instance).driver.DebugReportMessageEXT(
            instance, flags, object_type, object, location, message_code,
            layer_prefix, message);
    } else {
        GetData(instance).debug_report_callbacks.Message(
            flags, object_type, object, location, message_code, layer_prefix,
            message);
    }
}

}  // namespace driver
}  // namespace vulkan
