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

// RendererGL.cpp: Implements the class methods for RendererGL.

#include "libANGLE/renderer/gl/RendererGL.h"

#include <EGL/eglext.h>

#include "common/debug.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/ContextState.h"
#include "libANGLE/Path.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/BlitGL.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/CompilerGL.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/FenceNVGL.h"
#include "libANGLE/renderer/gl/FenceSyncGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
#include "libANGLE/renderer/gl/PathGL.h"
#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/QueryGL.h"
#include "libANGLE/renderer/gl/RenderbufferGL.h"
#include "libANGLE/renderer/gl/SamplerGL.h"
#include "libANGLE/renderer/gl/ShaderGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/SurfaceGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "libANGLE/renderer/gl/VertexArrayGL.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"

namespace
{

std::vector<GLuint> GatherPaths(const std::vector<gl::Path *> &paths)
{
    std::vector<GLuint> ret;
    ret.reserve(paths.size());

    for (const auto *p : paths)
    {
        const auto *pathObj = rx::GetImplAs<rx::PathGL>(p);
        ret.push_back(pathObj->getPathID());
    }
    return ret;
}

}  // namespace

#ifndef NDEBUG
static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source,
                                                   GLenum type,
                                                   GLuint id,
                                                   GLenum severity,
                                                   GLsizei length,
                                                   const GLchar *message,
                                                   const void *userParam)
{
    std::string sourceText;
    switch (source)
    {
        case GL_DEBUG_SOURCE_API:
            sourceText = "OpenGL";
            break;
        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
            sourceText = "Windows";
            break;
        case GL_DEBUG_SOURCE_SHADER_COMPILER:
            sourceText = "Shader Compiler";
            break;
        case GL_DEBUG_SOURCE_THIRD_PARTY:
            sourceText = "Third Party";
            break;
        case GL_DEBUG_SOURCE_APPLICATION:
            sourceText = "Application";
            break;
        case GL_DEBUG_SOURCE_OTHER:
            sourceText = "Other";
            break;
        default:
            sourceText = "UNKNOWN";
            break;
    }

    std::string typeText;
    switch (type)
    {
        case GL_DEBUG_TYPE_ERROR:
            typeText = "Error";
            break;
        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
            typeText = "Deprecated behavior";
            break;
        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
            typeText = "Undefined behavior";
            break;
        case GL_DEBUG_TYPE_PORTABILITY:
            typeText = "Portability";
            break;
        case GL_DEBUG_TYPE_PERFORMANCE:
            typeText = "Performance";
            break;
        case GL_DEBUG_TYPE_OTHER:
            typeText = "Other";
            break;
        case GL_DEBUG_TYPE_MARKER:
            typeText = "Marker";
            break;
        default:
            typeText = "UNKNOWN";
            break;
    }

    std::string severityText;
    switch (severity)
    {
        case GL_DEBUG_SEVERITY_HIGH:
            severityText = "High";
            break;
        case GL_DEBUG_SEVERITY_MEDIUM:
            severityText = "Medium";
            break;
        case GL_DEBUG_SEVERITY_LOW:
            severityText = "Low";
            break;
        case GL_DEBUG_SEVERITY_NOTIFICATION:
            severityText = "Notification";
            break;
        default:
            severityText = "UNKNOWN";
            break;
    }

    if (type == GL_DEBUG_TYPE_ERROR)
    {
        ERR() << std::endl
              << "\tSource: " << sourceText << std::endl
              << "\tType: " << typeText << std::endl
              << "\tID: " << gl::Error(id) << std::endl
              << "\tSeverity: " << severityText << std::endl
              << "\tMessage: " << message;
    }
    else
    {
        // TODO(ynovikov): filter into WARN and INFO if INFO is ever implemented
        WARN() << std::endl
               << "\tSource: " << sourceText << std::endl
               << "\tType: " << typeText << std::endl
               << "\tID: " << gl::Error(id) << std::endl
               << "\tSeverity: " << severityText << std::endl
               << "\tMessage: " << message;
    }
}
#endif

namespace rx
{

RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap)
    : mMaxSupportedESVersion(0, 0),
      mFunctions(functions),
      mStateManager(nullptr),
      mBlitter(nullptr),
      mHasDebugOutput(false),
      mSkipDrawCalls(false),
      mCapsInitialized(false)
{
    ASSERT(mFunctions);
    nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
    mStateManager = new StateManagerGL(mFunctions, getNativeCaps());
    mBlitter      = new BlitGL(functions, mWorkarounds, mStateManager);

    mHasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
                      mFunctions->hasGLExtension("GL_KHR_debug") ||
                      mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
                      mFunctions->hasGLESExtension("GL_KHR_debug");
#ifndef NDEBUG
    if (mHasDebugOutput)
    {
        mFunctions->enable(GL_DEBUG_OUTPUT);
        mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
                                        nullptr, GL_TRUE);
        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0,
                                        nullptr, GL_TRUE);
        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
                                        nullptr, GL_FALSE);
        mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION,
                                        0, nullptr, GL_FALSE);
        mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr);
    }
#endif

    EGLint deviceType =
        static_cast<EGLint>(attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_NONE));
    if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE)
    {
        mSkipDrawCalls = true;
    }

    if (mWorkarounds.initializeCurrentVertexAttributes)
    {
        GLint maxVertexAttribs = 0;
        mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);

        for (GLint i = 0; i < maxVertexAttribs; ++i)
        {
            mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f);
        }
    }
}

RendererGL::~RendererGL()
{
    SafeDelete(mBlitter);
    SafeDelete(mStateManager);
}

gl::Error RendererGL::flush()
{
    mFunctions->flush();
    return gl::NoError();
}

gl::Error RendererGL::finish()
{
#ifdef NDEBUG
    if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
    {
        mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    }
#endif

    mFunctions->finish();

#ifdef NDEBUG
    if (mWorkarounds.finishDoesNotCauseQueriesToBeAvailable && mHasDebugOutput)
    {
        mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
    }
#endif

    return gl::NoError();
}

gl::Error RendererGL::drawArrays(const gl::ContextState &data,
                                 GLenum mode,
                                 GLint first,
                                 GLsizei count)
{
    ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, 0));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawArrays(mode, first, count);
    }

    return gl::NoError();
}

gl::Error RendererGL::drawArraysInstanced(const gl::ContextState &data,
                                          GLenum mode,
                                          GLint first,
                                          GLsizei count,
                                          GLsizei instanceCount)
{
    ANGLE_TRY(mStateManager->setDrawArraysState(data, first, count, instanceCount));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawArraysInstanced(mode, first, count, instanceCount);
    }

    return gl::NoError();
}

gl::Error RendererGL::drawElements(const gl::ContextState &data,
                                   GLenum mode,
                                   GLsizei count,
                                   GLenum type,
                                   const void *indices,
                                   const gl::IndexRange &indexRange)
{
    const void *drawIndexPtr = nullptr;
    ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPtr));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawElements(mode, count, type, drawIndexPtr);
    }

    return gl::NoError();
}

gl::Error RendererGL::drawElementsInstanced(const gl::ContextState &data,
                                            GLenum mode,
                                            GLsizei count,
                                            GLenum type,
                                            const void *indices,
                                            GLsizei instances,
                                            const gl::IndexRange &indexRange)
{
    const void *drawIndexPointer = nullptr;
    ANGLE_TRY(mStateManager->setDrawElementsState(data, count, type, indices, instances,
                                                  &drawIndexPointer));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawElementsInstanced(mode, count, type, drawIndexPointer, instances);
    }

    return gl::NoError();
}

gl::Error RendererGL::drawRangeElements(const gl::ContextState &data,
                                        GLenum mode,
                                        GLuint start,
                                        GLuint end,
                                        GLsizei count,
                                        GLenum type,
                                        const void *indices,
                                        const gl::IndexRange &indexRange)
{
    const void *drawIndexPointer = nullptr;
    ANGLE_TRY(
        mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawRangeElements(mode, start, end, count, type, drawIndexPointer);
    }

    return gl::NoError();
}

gl::Error RendererGL::drawArraysIndirect(const gl::ContextState &data,
                                         GLenum mode,
                                         const void *indirect)
{
    ANGLE_TRY(mStateManager->setDrawIndirectState(data, GL_NONE));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawArraysIndirect(mode, indirect);
    }
    return gl::NoError();
}

gl::Error RendererGL::drawElementsIndirect(const gl::ContextState &data,
                                           GLenum mode,
                                           GLenum type,
                                           const void *indirect)
{
    ANGLE_TRY(mStateManager->setDrawIndirectState(data, type));

    if (!mSkipDrawCalls)
    {
        mFunctions->drawElementsIndirect(mode, type, indirect);
    }
    return gl::NoError();
}

void RendererGL::stencilFillPath(const gl::ContextState &state,
                                 const gl::Path *path,
                                 GLenum fillMode,
                                 GLuint mask)
{
    const auto *pathObj = GetImplAs<PathGL>(path);

    mFunctions->stencilFillPathNV(pathObj->getPathID(), fillMode, mask);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::stencilStrokePath(const gl::ContextState &state,
                                   const gl::Path *path,
                                   GLint reference,
                                   GLuint mask)
{
    const auto *pathObj = GetImplAs<PathGL>(path);

    mFunctions->stencilStrokePathNV(pathObj->getPathID(), reference, mask);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::coverFillPath(const gl::ContextState &state,
                               const gl::Path *path,
                               GLenum coverMode)
{

    const auto *pathObj = GetImplAs<PathGL>(path);
    mFunctions->coverFillPathNV(pathObj->getPathID(), coverMode);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::coverStrokePath(const gl::ContextState &state,
                                 const gl::Path *path,
                                 GLenum coverMode)
{
    const auto *pathObj = GetImplAs<PathGL>(path);
    mFunctions->coverStrokePathNV(pathObj->getPathID(), coverMode);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::stencilThenCoverFillPath(const gl::ContextState &state,
                                          const gl::Path *path,
                                          GLenum fillMode,
                                          GLuint mask,
                                          GLenum coverMode)
{

    const auto *pathObj = GetImplAs<PathGL>(path);
    mFunctions->stencilThenCoverFillPathNV(pathObj->getPathID(), fillMode, mask, coverMode);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::stencilThenCoverStrokePath(const gl::ContextState &state,
                                            const gl::Path *path,
                                            GLint reference,
                                            GLuint mask,
                                            GLenum coverMode)
{

    const auto *pathObj = GetImplAs<PathGL>(path);
    mFunctions->stencilThenCoverStrokePathNV(pathObj->getPathID(), reference, mask, coverMode);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::coverFillPathInstanced(const gl::ContextState &state,
                                        const std::vector<gl::Path *> &paths,
                                        GLenum coverMode,
                                        GLenum transformType,
                                        const GLfloat *transformValues)
{
    const auto &pathObjs = GatherPaths(paths);

    mFunctions->coverFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
                                         &pathObjs[0], 0, coverMode, transformType,
                                         transformValues);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::coverStrokePathInstanced(const gl::ContextState &state,
                                          const std::vector<gl::Path *> &paths,
                                          GLenum coverMode,
                                          GLenum transformType,
                                          const GLfloat *transformValues)
{
    const auto &pathObjs = GatherPaths(paths);

    mFunctions->coverStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
                                           &pathObjs[0], 0, coverMode, transformType,
                                           transformValues);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::stencilFillPathInstanced(const gl::ContextState &state,
                                          const std::vector<gl::Path *> &paths,
                                          GLenum fillMode,
                                          GLuint mask,
                                          GLenum transformType,
                                          const GLfloat *transformValues)
{
    const auto &pathObjs = GatherPaths(paths);

    mFunctions->stencilFillPathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
                                           &pathObjs[0], 0, fillMode, mask, transformType,
                                           transformValues);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::stencilStrokePathInstanced(const gl::ContextState &state,
                                            const std::vector<gl::Path *> &paths,
                                            GLint reference,
                                            GLuint mask,
                                            GLenum transformType,
                                            const GLfloat *transformValues)
{
    const auto &pathObjs = GatherPaths(paths);

    mFunctions->stencilStrokePathInstancedNV(static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT,
                                             &pathObjs[0], 0, reference, mask, transformType,
                                             transformValues);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

void RendererGL::stencilThenCoverFillPathInstanced(const gl::ContextState &state,
                                                   const std::vector<gl::Path *> &paths,
                                                   GLenum coverMode,
                                                   GLenum fillMode,
                                                   GLuint mask,
                                                   GLenum transformType,
                                                   const GLfloat *transformValues)
{
    const auto &pathObjs = GatherPaths(paths);

    mFunctions->stencilThenCoverFillPathInstancedNV(
        static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, fillMode, mask,
        coverMode, transformType, transformValues);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}
void RendererGL::stencilThenCoverStrokePathInstanced(const gl::ContextState &state,
                                                     const std::vector<gl::Path *> &paths,
                                                     GLenum coverMode,
                                                     GLint reference,
                                                     GLuint mask,
                                                     GLenum transformType,
                                                     const GLfloat *transformValues)
{
    const auto &pathObjs = GatherPaths(paths);

    mFunctions->stencilThenCoverStrokePathInstancedNV(
        static_cast<GLsizei>(pathObjs.size()), GL_UNSIGNED_INT, &pathObjs[0], 0, reference, mask,
        coverMode, transformType, transformValues);

    ASSERT(mFunctions->getError() == GL_NO_ERROR);
}

GLenum RendererGL::getResetStatus()
{
    return mFunctions->getGraphicsResetStatus();
}

ContextImpl *RendererGL::createContext(const gl::ContextState &state)
{
    return new ContextGL(state, this);
}

void RendererGL::insertEventMarker(GLsizei length, const char *marker)
{
    mFunctions->debugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0,
                                   GL_DEBUG_SEVERITY_NOTIFICATION, length, marker);
}

void RendererGL::pushGroupMarker(GLsizei length, const char *marker)
{
    mFunctions->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, length, marker);
}

void RendererGL::popGroupMarker()
{
    mFunctions->popDebugGroup();
}

std::string RendererGL::getVendorString() const
{
    return std::string(reinterpret_cast<const char *>(mFunctions->getString(GL_VENDOR)));
}

std::string RendererGL::getRendererDescription() const
{
    std::string nativeVendorString(
        reinterpret_cast<const char *>(mFunctions->getString(GL_VENDOR)));
    std::string nativeRendererString(
        reinterpret_cast<const char *>(mFunctions->getString(GL_RENDERER)));

    std::ostringstream rendererString;
    rendererString << nativeVendorString << " " << nativeRendererString << " OpenGL";
    if (mFunctions->standard == STANDARD_GL_ES)
    {
        rendererString << " ES";
    }
    rendererString << " " << mFunctions->version.major << "." << mFunctions->version.minor;
    if (mFunctions->standard == STANDARD_GL_DESKTOP)
    {
        // Some drivers (NVIDIA) use a profile mask of 0 when in compatibility profile.
        if ((mFunctions->profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) != 0 ||
            (mFunctions->isAtLeastGL(gl::Version(3, 2)) && mFunctions->profile == 0))
        {
            rendererString << " compatibility";
        }
        else if ((mFunctions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
        {
            rendererString << " core";
        }
    }

    return rendererString.str();
}

const gl::Version &RendererGL::getMaxSupportedESVersion() const
{
    // Force generation of caps
    getNativeCaps();

    return mMaxSupportedESVersion;
}

void RendererGL::generateCaps(gl::Caps *outCaps,
                              gl::TextureCapsMap *outTextureCaps,
                              gl::Extensions *outExtensions,
                              gl::Limitations * /* outLimitations */) const
{
    nativegl_gl::GenerateCaps(mFunctions, mWorkarounds, outCaps, outTextureCaps, outExtensions,
                              &mMaxSupportedESVersion);
}

GLint RendererGL::getGPUDisjoint()
{
    // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
    return 0;
}

GLint64 RendererGL::getTimestamp()
{
    GLint64 result = 0;
    mFunctions->getInteger64v(GL_TIMESTAMP, &result);
    return result;
}

void RendererGL::ensureCapsInitialized() const
{
    if (!mCapsInitialized)
    {
        generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
        mCapsInitialized = true;
    }
}

const gl::Caps &RendererGL::getNativeCaps() const
{
    ensureCapsInitialized();
    return mNativeCaps;
}

const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
{
    ensureCapsInitialized();
    return mNativeTextureCaps;
}

const gl::Extensions &RendererGL::getNativeExtensions() const
{
    ensureCapsInitialized();
    return mNativeExtensions;
}

const gl::Limitations &RendererGL::getNativeLimitations() const
{
    ensureCapsInitialized();
    return mNativeLimitations;
}

gl::Error RendererGL::dispatchCompute(const gl::ContextState &data,
                                      GLuint numGroupsX,
                                      GLuint numGroupsY,
                                      GLuint numGroupsZ)
{
    ANGLE_TRY(mStateManager->setDispatchComputeState(data));
    mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
    return gl::NoError();
}

}  // namespace rx
