//
// Copyright 2015 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.
//

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

// Debug.cpp: Defines debug state used for GL_KHR_debug

#include "libANGLE/Debug.h"

#include "common/debug.h"

#include <algorithm>
#include <tuple>

namespace
{
const char *GLSeverityToString(GLenum severity)
{
    switch (severity)
    {
        case GL_DEBUG_SEVERITY_HIGH:
            return "HIGH";
        case GL_DEBUG_SEVERITY_MEDIUM:
            return "MEDIUM";
        case GL_DEBUG_SEVERITY_LOW:
            return "LOW";
        case GL_DEBUG_SEVERITY_NOTIFICATION:
        default:
            return "NOTIFICATION";
    }
}

const char *EGLMessageTypeToString(egl::MessageType messageType)
{
    switch (messageType)
    {
        case egl::MessageType::Critical:
            return "CRITICAL";
        case egl::MessageType::Error:
            return "ERROR";
        case egl::MessageType::Warn:
            return "WARNING";
        case egl::MessageType::Info:
        default:
            return "INFO";
    }
}

const char *GLMessageTypeToString(GLenum type)
{
    switch (type)
    {
        case GL_DEBUG_TYPE_ERROR:
            return "error";
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
            return "deprecated behavior";
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
            return "undefined behavior";
        case GL_DEBUG_TYPE_PORTABILITY:
            return "portability";
        case GL_DEBUG_TYPE_PERFORMANCE:
            return "performance";
        case GL_DEBUG_TYPE_MARKER:
            return "marker";
        case GL_DEBUG_TYPE_PUSH_GROUP:
            return "start of group";
        case GL_DEBUG_TYPE_POP_GROUP:
            return "end of group";
        case GL_DEBUG_TYPE_OTHER:
        default:
            return "other message";
    }
}
}  // namespace

namespace gl
{

Debug::Control::Control() {}

Debug::Control::~Control() {}

Debug::Control::Control(const Control &other) = default;

Debug::Group::Group() {}

Debug::Group::~Group() {}

Debug::Group::Group(const Group &other) = default;

Debug::Debug(bool initialDebugState)
    : mOutputEnabled(initialDebugState),
      mCallbackFunction(nullptr),
      mCallbackUserParam(nullptr),
      mMessages(),
      mMaxLoggedMessages(0),
      mOutputSynchronous(false),
      mGroups()
{
    pushDefaultGroup();
}

Debug::~Debug() {}

void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages)
{
    mMaxLoggedMessages = maxLoggedMessages;
}

void Debug::setOutputEnabled(bool enabled)
{
    mOutputEnabled = enabled;
}

bool Debug::isOutputEnabled() const
{
    return mOutputEnabled;
}

void Debug::setOutputSynchronous(bool synchronous)
{
    mOutputSynchronous = synchronous;
}

bool Debug::isOutputSynchronous() const
{
    return mOutputSynchronous;
}

void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam)
{
    mCallbackFunction  = callback;
    mCallbackUserParam = userParam;
}

GLDEBUGPROCKHR Debug::getCallback() const
{
    return mCallbackFunction;
}

const void *Debug::getUserParam() const
{
    return mCallbackUserParam;
}

void Debug::insertMessage(GLenum source,
                          GLenum type,
                          GLuint id,
                          GLenum severity,
                          const std::string &message,
                          gl::LogSeverity logSeverity) const
{
    std::string messageCopy(message);
    insertMessage(source, type, id, severity, std::move(messageCopy), logSeverity);
}

void Debug::insertMessage(GLenum source,
                          GLenum type,
                          GLuint id,
                          GLenum severity,
                          std::string &&message,
                          gl::LogSeverity logSeverity) const
{
    {
        // output all messages to the debug log
        const char *messageTypeString = GLMessageTypeToString(type);
        const char *severityString    = GLSeverityToString(severity);
        std::ostringstream messageStream;
        messageStream << "GL " << messageTypeString << ": " << severityString << ": " << message;
        switch (logSeverity)
        {
            case gl::LOG_FATAL:
                FATAL() << messageStream.str();
                break;
            case gl::LOG_ERR:
                ERR() << messageStream.str();
                break;
            case gl::LOG_WARN:
                WARN() << messageStream.str();
                break;
            case gl::LOG_INFO:
                INFO() << messageStream.str();
                break;
            case gl::LOG_EVENT:
                ANGLE_LOG(EVENT) << messageStream.str();
                break;
        }
    }

    if (!isMessageEnabled(source, type, id, severity))
    {
        return;
    }

    // TODO(geofflang) Check the synchronous flag and potentially flush messages from another
    // thread.
    // If isOutputSynchronous(), mMutex does not need to be held, but instead the message should be
    // dropped/queued if it doesn't originate from the current context.  If !isOutputSynchronous(),
    // the callback is expected to be thread-safe per spec, so there is no need for locking.
    if (mCallbackFunction != nullptr)
    {
        mCallbackFunction(source, type, id, severity, static_cast<GLsizei>(message.length()),
                          message.c_str(), mCallbackUserParam);
    }
    else
    {
        std::lock_guard<angle::SimpleMutex> lock(mMutex);

        if (mMessages.size() >= mMaxLoggedMessages)
        {
            // Drop messages over the limit
            return;
        }

        Message m;
        m.source   = source;
        m.type     = type;
        m.id       = id;
        m.severity = severity;
        m.message  = std::move(message);

        mMessages.push_back(std::move(m));
    }
}

size_t Debug::getMessages(GLuint count,
                          GLsizei bufSize,
                          GLenum *sources,
                          GLenum *types,
                          GLuint *ids,
                          GLenum *severities,
                          GLsizei *lengths,
                          GLchar *messageLog)
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);

    size_t messageCount       = 0;
    size_t messageStringIndex = 0;
    while (messageCount <= count && !mMessages.empty())
    {
        const Message &m = mMessages.front();

        if (messageLog != nullptr)
        {
            // Check that this message can fit in the message buffer
            if (messageStringIndex + m.message.length() + 1 > static_cast<size_t>(bufSize))
            {
                break;
            }

            std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex);
            messageStringIndex += m.message.length();

            messageLog[messageStringIndex] = '\0';
            messageStringIndex += 1;
        }

        if (sources != nullptr)
        {
            sources[messageCount] = m.source;
        }

        if (types != nullptr)
        {
            types[messageCount] = m.type;
        }

        if (ids != nullptr)
        {
            ids[messageCount] = m.id;
        }

        if (severities != nullptr)
        {
            severities[messageCount] = m.severity;
        }

        if (lengths != nullptr)
        {
            lengths[messageCount] = static_cast<GLsizei>(m.message.length()) + 1;
        }

        mMessages.pop_front();

        messageCount++;
    }

    return messageCount;
}

size_t Debug::getNextMessageLength() const
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);
    return mMessages.empty() ? 0 : mMessages.front().message.length() + 1;
}

size_t Debug::getMessageCount() const
{
    std::lock_guard<angle::SimpleMutex> lock(mMutex);
    return mMessages.size();
}

void Debug::setMessageControl(GLenum source,
                              GLenum type,
                              GLenum severity,
                              std::vector<GLuint> &&ids,
                              bool enabled)
{
    Control c;
    c.source   = source;
    c.type     = type;
    c.severity = severity;
    c.ids      = std::move(ids);
    c.enabled  = enabled;

    auto &controls = mGroups.back().controls;
    controls.push_back(std::move(c));
}

void Debug::pushGroup(GLenum source, GLuint id, std::string &&message)
{
    insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION,
                  std::string(message), gl::LOG_INFO);

    Group g;
    g.source  = source;
    g.id      = id;
    g.message = std::move(message);
    mGroups.push_back(std::move(g));
}

void Debug::popGroup()
{
    // Make sure the default group is not about to be popped
    ASSERT(mGroups.size() > 1);

    Group g = mGroups.back();
    mGroups.pop_back();

    insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION,
                  g.message, gl::LOG_INFO);
}

size_t Debug::getGroupStackDepth() const
{
    return mGroups.size();
}

void Debug::insertPerfWarning(GLenum severity, bool isLastRepeat, const char *message) const
{
    std::string msg = message;
    if (isLastRepeat)
    {
        msg += " (this message will no longer repeat)";
    }

    // Note: insertMessage will acquire GetDebugMutex(), so it must be released before this call.
    insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_PERFORMANCE, 0, severity, std::move(msg),
                  gl::LOG_INFO);
}

bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const
{
    if (!mOutputEnabled)
    {
        return false;
    }

    for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++)
    {
        const auto &controls = groupIter->controls;
        for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++)
        {
            const auto &control = *controlIter;

            if (control.source != GL_DONT_CARE && control.source != source)
            {
                continue;
            }

            if (control.type != GL_DONT_CARE && control.type != type)
            {
                continue;
            }

            if (control.severity != GL_DONT_CARE && control.severity != severity)
            {
                continue;
            }

            if (!control.ids.empty() &&
                std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end())
            {
                continue;
            }

            return control.enabled;
        }
    }

    return true;
}

void Debug::pushDefaultGroup()
{
    Group g;
    g.source  = GL_NONE;
    g.id      = 0;
    g.message = "";

    Control c0;
    c0.source   = GL_DONT_CARE;
    c0.type     = GL_DONT_CARE;
    c0.severity = GL_DONT_CARE;
    c0.enabled  = true;
    g.controls.push_back(std::move(c0));

    Control c1;
    c1.source   = GL_DONT_CARE;
    c1.type     = GL_DONT_CARE;
    c1.severity = GL_DEBUG_SEVERITY_LOW;
    c1.enabled  = false;
    g.controls.push_back(std::move(c1));

    mGroups.push_back(std::move(g));
}
}  // namespace gl

namespace egl
{

namespace
{
angle::PackedEnumBitSet<MessageType> GetDefaultMessageTypeBits()
{
    angle::PackedEnumBitSet<MessageType> result;
    result.set(MessageType::Critical);
    result.set(MessageType::Error);
    return result;
}
}  // anonymous namespace

Debug::Debug() : mCallback(nullptr), mEnabledMessageTypes(GetDefaultMessageTypeBits()) {}

void Debug::setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
{
    mCallback = callback;

    const angle::PackedEnumBitSet<MessageType> defaultMessageTypes = GetDefaultMessageTypeBits();
    if (mCallback != nullptr)
    {
        for (MessageType messageType : angle::AllEnums<MessageType>())
        {
            mEnabledMessageTypes[messageType] =
                (attribs.getAsInt(egl::ToEGLenum(messageType), defaultMessageTypes[messageType]) ==
                 EGL_TRUE);
        }
    }
}

EGLDEBUGPROCKHR Debug::getCallback() const
{
    return mCallback;
}

bool Debug::isMessageTypeEnabled(MessageType type) const
{
    return mEnabledMessageTypes[type];
}

void Debug::insertMessage(EGLenum error,
                          const char *command,
                          MessageType messageType,
                          EGLLabelKHR threadLabel,
                          EGLLabelKHR objectLabel,
                          const std::string &message) const
{
    {
        // output all messages to the debug log
        const char *messageTypeString = EGLMessageTypeToString(messageType);
        std::ostringstream messageStream;
        messageStream << "EGL " << messageTypeString << ": " << command << ": " << message;
        INFO() << messageStream.str();
    }

    // TODO(geofflang): Lock before checking the callback. http://anglebug.com/40096492
    if (mCallback && isMessageTypeEnabled(messageType))
    {
        mCallback(error, command, egl::ToEGLenum(messageType), threadLabel, objectLabel,
                  message.c_str());
    }
}

}  // namespace egl
