//
// 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/Data.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/FenceNVGL.h"
#include "libANGLE/renderer/gl/FenceSyncGL.h"
#include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.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"

#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;
    }

    ERR("\n\tSource: %s\n\tType: %s\n\tID: %d\n\tSeverity: %s\n\tMessage: %s", sourceText.c_str(), typeText.c_str(), id,
        severityText.c_str(), message);
}
#endif

namespace rx
{

RendererGL::RendererGL(const FunctionsGL *functions, const egl::AttributeMap &attribMap)
    : Renderer(),
      mMaxSupportedESVersion(0, 0),
      mFunctions(functions),
      mStateManager(nullptr),
      mBlitter(nullptr),
      mHasDebugOutput(false),
      mSkipDrawCalls(false)
{
    ASSERT(mFunctions);
    mStateManager = new StateManagerGL(mFunctions, getRendererCaps());
    nativegl_gl::GenerateWorkarounds(mFunctions, &mWorkarounds);
    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_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;
    }
}

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

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

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::Error(GL_NO_ERROR);
}

gl::Error RendererGL::drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count)
{
    gl::Error error = mStateManager->setDrawArraysState(data, first, count, 0);
    if (error.isError())
    {
        return error;
    }

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

    return gl::Error(GL_NO_ERROR);
}

gl::Error RendererGL::drawArraysInstanced(const gl::Data &data,
                                          GLenum mode,
                                          GLint first,
                                          GLsizei count,
                                          GLsizei instanceCount)
{
    gl::Error error = mStateManager->setDrawArraysState(data, first, count, instanceCount);
    if (error.isError())
    {
        return error;
    }

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

    return gl::Error(GL_NO_ERROR);
}

gl::Error RendererGL::drawElements(const gl::Data &data,
                                   GLenum mode,
                                   GLsizei count,
                                   GLenum type,
                                   const GLvoid *indices,
                                   const gl::IndexRange &indexRange)
{
    const GLvoid *drawIndexPointer = nullptr;
    gl::Error error =
        mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer);
    if (error.isError())
    {
        return error;
    }

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

    return gl::Error(GL_NO_ERROR);
}

gl::Error RendererGL::drawElementsInstanced(const gl::Data &data,
                                            GLenum mode,
                                            GLsizei count,
                                            GLenum type,
                                            const GLvoid *indices,
                                            GLsizei instances,
                                            const gl::IndexRange &indexRange)
{
    const GLvoid *drawIndexPointer = nullptr;
    gl::Error error = mStateManager->setDrawElementsState(data, count, type, indices, instances,
                                                          &drawIndexPointer);
    if (error.isError())
    {
        return error;
    }

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

    return gl::Error(GL_NO_ERROR);
}

gl::Error RendererGL::drawRangeElements(const gl::Data &data,
                                        GLenum mode,
                                        GLuint start,
                                        GLuint end,
                                        GLsizei count,
                                        GLenum type,
                                        const GLvoid *indices,
                                        const gl::IndexRange &indexRange)
{
    const GLvoid *drawIndexPointer = nullptr;
    gl::Error error =
        mStateManager->setDrawElementsState(data, count, type, indices, 0, &drawIndexPointer);
    if (error.isError())
    {
        return error;
    }

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

    return gl::Error(GL_NO_ERROR);
}

CompilerImpl *RendererGL::createCompiler()
{
    return new CompilerGL(mFunctions);
}

ShaderImpl *RendererGL::createShader(const gl::Shader::Data &data)
{
    return new ShaderGL(data, mFunctions, mWorkarounds);
}

ProgramImpl *RendererGL::createProgram(const gl::Program::Data &data)
{
    return new ProgramGL(data, mFunctions, mWorkarounds, mStateManager);
}

FramebufferImpl *RendererGL::createFramebuffer(const gl::Framebuffer::Data &data)
{
    return new FramebufferGL(data, mFunctions, mStateManager, mWorkarounds, false);
}

TextureImpl *RendererGL::createTexture(GLenum target)
{
    return new TextureGL(target, mFunctions, mWorkarounds, mStateManager, mBlitter);
}

RenderbufferImpl *RendererGL::createRenderbuffer()
{
    return new RenderbufferGL(mFunctions, mWorkarounds, mStateManager, getRendererTextureCaps());
}

BufferImpl *RendererGL::createBuffer()
{
    return new BufferGL(mFunctions, mStateManager);
}

VertexArrayImpl *RendererGL::createVertexArray(const gl::VertexArray::Data &data)
{
    return new VertexArrayGL(data, mFunctions, mStateManager);
}

QueryImpl *RendererGL::createQuery(GLenum type)
{
    return new QueryGL(type, mFunctions, mStateManager);
}

FenceNVImpl *RendererGL::createFenceNV()
{
    return new FenceNVGL(mFunctions);
}

FenceSyncImpl *RendererGL::createFenceSync()
{
    return new FenceSyncGL(mFunctions);
}

TransformFeedbackImpl *RendererGL::createTransformFeedback()
{
    return new TransformFeedbackGL(mFunctions, mStateManager,
                                   getRendererCaps().maxTransformFeedbackSeparateComponents);
}

SamplerImpl *RendererGL::createSampler()
{
    return new SamplerGL(mFunctions, mStateManager);
}

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();
}

void RendererGL::notifyDeviceLost()
{
    UNIMPLEMENTED();
}

bool RendererGL::isDeviceLost() const
{
    UNIMPLEMENTED();
    return bool();
}

bool RendererGL::testDeviceLost()
{
    UNIMPLEMENTED();
    return bool();
}

bool RendererGL::testDeviceResettable()
{
    UNIMPLEMENTED();
    return bool();
}

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
    getRendererCaps();

    return mMaxSupportedESVersion;
}

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

void RendererGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
{
    mStateManager->syncState(state, dirtyBits);
}

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::onMakeCurrent(const gl::Data &data)
{
    // Queries need to be paused/resumed on context switches
    mStateManager->onMakeCurrent(data);
}
}
