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

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

#include "libANGLE/Debug.h"
#include "common/unsafe_buffers.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(),
                      ANGLE_UNSAFE_TODO(messageLog + messageStringIndex));
            messageStringIndex += m.message.length();

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

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

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

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

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

        if (lengths != nullptr)
        {
            ANGLE_UNSAFE_TODO(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
