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

// DisplayGL.h: GL implementation of egl::Display

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

#include "libANGLE/AttributeMap.h"
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/gl/ContextGL.h"
#include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/SurfaceGL.h"

#include <EGL/eglext.h>

namespace rx
{

// On Linux with the amdgpu driver, the renderer string looks like:
//
// AMD Radeon (TM) <GPU model> Graphics (<GPUgeneration>, DRM <DRMversion>, <kernelversion>,
// LLVM <LLVMversion>) eg. AMD Radeon (TM) RX 460 Graphics (POLARIS11,
// DRM 3.35.0, 5.4.0-65-generic, LLVM 11.0.0)
//
// We also want to handle the case without GPUGeneration:
// AMD Radeon GPU model (DRM DRMversion, kernelversion, LLVM LLVMversion)
//
// Thanks to Jeff Gilbert of Mozilla for this example
// https://phabricator.services.mozilla.com/D105636
std::string SanitizeRendererString(std::string rendererString)
{
    size_t pos = rendererString.find(", DRM ");
    if (pos != std::string::npos)
    {
        rendererString.resize(pos);
        rendererString.push_back(')');
        return rendererString;
    }
    pos = rendererString.find(" (DRM ");
    if (pos != std::string::npos)
    {
        rendererString.resize(pos);
        return rendererString;
    }
    return rendererString;
}

// OpenGL ES requires a prefix of "OpenGL ES" for the GL_VERSION string.
// We can also add the prefix to desktop OpenGL for consistency.
std::string SanitizeVersionString(std::string versionString, bool isES)
{
    if (versionString.find("OpenGL") == std::string::npos)
    {
        std::string prefix = "OpenGL ";
        if (isES)
        {
            prefix += "ES ";
        }
        versionString = prefix + versionString;
    }
    return versionString;
}

DisplayGL::DisplayGL(const egl::DisplayState &state) : DisplayImpl(state) {}

DisplayGL::~DisplayGL() {}

egl::Error DisplayGL::initialize(egl::Display *display)
{
    return egl::NoError();
}

void DisplayGL::terminate() {}

ImageImpl *DisplayGL::createImage(const egl::ImageState &state,
                                  const gl::Context *context,
                                  EGLenum target,
                                  const egl::AttributeMap &attribs)
{
    UNIMPLEMENTED();
    return nullptr;
}

SurfaceImpl *DisplayGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
                                                      EGLenum buftype,
                                                      EGLClientBuffer clientBuffer,
                                                      const egl::AttributeMap &attribs)
{
    UNIMPLEMENTED();
    return nullptr;
}

StreamProducerImpl *DisplayGL::createStreamProducerD3DTexture(
    egl::Stream::ConsumerType consumerType,
    const egl::AttributeMap &attribs)
{
    UNIMPLEMENTED();
    return nullptr;
}

ShareGroupImpl *DisplayGL::createShareGroup()
{
    return new ShareGroupGL();
}

egl::Error DisplayGL::makeCurrent(egl::Display *display,
                                  egl::Surface *drawSurface,
                                  egl::Surface *readSurface,
                                  gl::Context *context)
{
    // Ensure that the correct global DebugAnnotator is installed when the end2end tests change
    // the ANGLE back-end (done frequently).
    display->setGlobalDebugAnnotator();

    if (!context)
    {
        return egl::NoError();
    }

    // Pause transform feedback before making a new surface current, to workaround anglebug.com/1426
    ContextGL *glContext = GetImplAs<ContextGL>(context);
    glContext->getStateManager()->pauseTransformFeedback();

    if (drawSurface == nullptr)
    {
        ANGLE_TRY(makeCurrentSurfaceless(context));
    }

    return egl::NoError();
}

gl::Version DisplayGL::getMaxConformantESVersion() const
{
    // 3.1 support is in progress.
    return std::min(getMaxSupportedESVersion(), gl::Version(3, 0));
}

void DisplayGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
    // Advertise robust resource initialization on all OpenGL backends for testing even though it is
    // not fully implemented.
    outExtensions->robustResourceInitializationANGLE = true;
}

egl::Error DisplayGL::makeCurrentSurfaceless(gl::Context *context)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

std::string DisplayGL::getRendererDescription()
{
    std::string rendererString        = GetRendererString(getRenderer()->getFunctions());
    const angle::FeaturesGL &features = getRenderer()->getFeatures();

    if (features.sanitizeAmdGpuRendererString.enabled)
    {
        return SanitizeRendererString(rendererString);
    }
    return rendererString;
}

std::string DisplayGL::getVendorString()
{
    return GetVendorString(getRenderer()->getFunctions());
}

std::string DisplayGL::getVersionString()
{
    std::string versionString = GetVersionString(getRenderer()->getFunctions());
    return SanitizeVersionString(versionString,
                                 getRenderer()->getFunctions()->standard == STANDARD_GL_ES);
}

}  // namespace rx
