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

// FunctionsGLX.cpp: Implements the FunctionsGLX class.

#define ANGLE_SKIP_GLX_DEFINES 1
#include "libANGLE/renderer/gl/glx/FunctionsGLX.h"
#undef ANGLE_SKIP_GLX_DEFINES

// We can only include glx.h in files which do not include ANGLE's GLES
// headers, to avoid doubly-defined GLenum macros, typedefs, etc.
#include <GL/glx.h>

#include <dlfcn.h>
#include <algorithm>

#include "common/string_utils.h"
#include "libANGLE/renderer/gl/glx/functionsglx_typedefs.h"

namespace rx
{

void *FunctionsGLX::sLibHandle = nullptr;

template <typename T>
static bool GetProc(PFNGETPROCPROC getProc, T *member, const char *name)
{
    *member = reinterpret_cast<T>(getProc(name));
    return *member != nullptr;
}

struct FunctionsGLX::GLXFunctionTable
{
    GLXFunctionTable()
        : createContextPtr(nullptr),
          destroyContextPtr(nullptr),
          makeCurrentPtr(nullptr),
          swapBuffersPtr(nullptr),
          queryExtensionPtr(nullptr),
          queryVersionPtr(nullptr),
          getCurrentContextPtr(nullptr),
          getCurrentDrawablePtr(nullptr),
          waitXPtr(nullptr),
          waitGLPtr(nullptr),
          getClientStringPtr(nullptr),
          queryExtensionsStringPtr(nullptr),
          getFBConfigsPtr(nullptr),
          chooseFBConfigPtr(nullptr),
          getFBConfigAttribPtr(nullptr),
          getVisualFromFBConfigPtr(nullptr),
          createWindowPtr(nullptr),
          destroyWindowPtr(nullptr),
          createPbufferPtr(nullptr),
          destroyPbufferPtr(nullptr),
          queryDrawablePtr(nullptr),
          createContextAttribsARBPtr(nullptr),
          swapIntervalEXTPtr(nullptr),
          swapIntervalMESAPtr(nullptr),
          swapIntervalSGIPtr(nullptr),
          getSyncValuesOMLPtr(nullptr)
    {}

    // GLX 1.0
    PFNGLXCREATECONTEXTPROC createContextPtr;
    PFNGLXDESTROYCONTEXTPROC destroyContextPtr;
    PFNGLXMAKECURRENTPROC makeCurrentPtr;
    PFNGLXSWAPBUFFERSPROC swapBuffersPtr;
    PFNGLXQUERYEXTENSIONPROC queryExtensionPtr;
    PFNGLXQUERYVERSIONPROC queryVersionPtr;
    PFNGLXGETCURRENTCONTEXTPROC getCurrentContextPtr;
    PFNGLXGETCURRENTDRAWABLEPROC getCurrentDrawablePtr;
    PFNGLXWAITXPROC waitXPtr;
    PFNGLXWAITGLPROC waitGLPtr;

    // GLX 1.1
    PFNGLXGETCLIENTSTRINGPROC getClientStringPtr;
    PFNGLXQUERYEXTENSIONSSTRINGPROC queryExtensionsStringPtr;

    // GLX 1.3
    PFNGLXGETFBCONFIGSPROC getFBConfigsPtr;
    PFNGLXCHOOSEFBCONFIGPROC chooseFBConfigPtr;
    PFNGLXGETFBCONFIGATTRIBPROC getFBConfigAttribPtr;
    PFNGLXGETVISUALFROMFBCONFIGPROC getVisualFromFBConfigPtr;
    PFNGLXCREATEWINDOWPROC createWindowPtr;
    PFNGLXDESTROYWINDOWPROC destroyWindowPtr;
    PFNGLXCREATEPBUFFERPROC createPbufferPtr;
    PFNGLXDESTROYPBUFFERPROC destroyPbufferPtr;
    PFNGLXQUERYDRAWABLEPROC queryDrawablePtr;

    // GLX_ARB_create_context
    PFNGLXCREATECONTEXTATTRIBSARBPROC createContextAttribsARBPtr;

    // GLX_EXT_swap_control
    PFNGLXSWAPINTERVALEXTPROC swapIntervalEXTPtr;

    // GLX_MESA_swap_control
    PFNGLXSWAPINTERVALMESAPROC swapIntervalMESAPtr;

    // GLX_SGI_swap_control
    PFNGLXSWAPINTERVALSGIPROC swapIntervalSGIPtr;

    // GLX_OML_sync_control
    PFNGLXGETSYNCVALUESOMLPROC getSyncValuesOMLPtr;
};

FunctionsGLX::FunctionsGLX()
    : majorVersion(0),
      minorVersion(0),
      mXDisplay(nullptr),
      mXScreen(-1),
      mFnPtrs(new GLXFunctionTable())
{}

FunctionsGLX::~FunctionsGLX()
{
    delete mFnPtrs;
    terminate();
}

bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorString)
{
    terminate();
    mXDisplay = xDisplay;
    mXScreen  = screen;

#if !defined(ANGLE_LINK_GLX)
    // Some OpenGL implementations can't handle having this library
    // handle closed while there's any X window still open against
    // which a GLXWindow was ever created.
    if (!sLibHandle)
    {
        sLibHandle = dlopen("libGL.so.1", RTLD_NOW);
        if (!sLibHandle)
        {
            *errorString = std::string("Could not dlopen libGL.so.1: ") + dlerror();
            return false;
        }
    }

    getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddress"));
    if (!getProc)
    {
        getProc = reinterpret_cast<PFNGETPROCPROC>(dlsym(sLibHandle, "glXGetProcAddressARB"));
    }
    if (!getProc)
    {
        *errorString = "Could not retrieve glXGetProcAddress";
        return false;
    }
#else
    getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
#endif

#define GET_PROC_OR_ERROR(MEMBER, NAME)                             \
    do                                                              \
    {                                                               \
        if (!GetProc(getProc, MEMBER, #NAME))                       \
        {                                                           \
            *errorString = "Could not load GLX entry point " #NAME; \
            return false;                                           \
        }                                                           \
    } while (0)
#if !defined(ANGLE_LINK_GLX)
#    define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
#else
#    define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME
#endif

    // GLX 1.0
    GET_FNPTR_OR_ERROR(&mFnPtrs->createContextPtr, glXCreateContext);
    GET_FNPTR_OR_ERROR(&mFnPtrs->destroyContextPtr, glXDestroyContext);
    GET_FNPTR_OR_ERROR(&mFnPtrs->makeCurrentPtr, glXMakeCurrent);
    GET_FNPTR_OR_ERROR(&mFnPtrs->swapBuffersPtr, glXSwapBuffers);
    GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionPtr, glXQueryExtension);
    GET_FNPTR_OR_ERROR(&mFnPtrs->queryVersionPtr, glXQueryVersion);
    GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentContextPtr, glXGetCurrentContext);
    GET_FNPTR_OR_ERROR(&mFnPtrs->getCurrentDrawablePtr, glXGetCurrentDrawable);
    GET_FNPTR_OR_ERROR(&mFnPtrs->waitXPtr, glXWaitX);
    GET_FNPTR_OR_ERROR(&mFnPtrs->waitGLPtr, glXWaitGL);

    // GLX 1.1
    GET_FNPTR_OR_ERROR(&mFnPtrs->getClientStringPtr, glXGetClientString);
    GET_FNPTR_OR_ERROR(&mFnPtrs->queryExtensionsStringPtr, glXQueryExtensionsString);

    // Check we have a working GLX
    {
        int errorBase;
        int eventBase;
        if (!queryExtension(&errorBase, &eventBase))
        {
            *errorString = "GLX is not present.";
            return false;
        }
    }

    // Check we have a supported version of GLX
    if (!queryVersion(&majorVersion, &minorVersion))
    {
        *errorString = "Could not query the GLX version.";
        return false;
    }
    if (majorVersion != 1 || minorVersion < 3)
    {
        *errorString = "Unsupported GLX version (requires at least 1.3).";
        return false;
    }

    const char *extensions = queryExtensionsString();
    if (!extensions)
    {
        *errorString = "glXQueryExtensionsString returned NULL";
        return false;
    }
    angle::SplitStringAlongWhitespace(extensions, &mExtensions);

    // GLX 1.3
    GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigsPtr, glXGetFBConfigs);
    GET_FNPTR_OR_ERROR(&mFnPtrs->chooseFBConfigPtr, glXChooseFBConfig);
    GET_FNPTR_OR_ERROR(&mFnPtrs->getFBConfigAttribPtr, glXGetFBConfigAttrib);
    GET_FNPTR_OR_ERROR(&mFnPtrs->getVisualFromFBConfigPtr, glXGetVisualFromFBConfig);
    GET_FNPTR_OR_ERROR(&mFnPtrs->createWindowPtr, glXCreateWindow);
    GET_FNPTR_OR_ERROR(&mFnPtrs->destroyWindowPtr, glXDestroyWindow);
    GET_FNPTR_OR_ERROR(&mFnPtrs->createPbufferPtr, glXCreatePbuffer);
    GET_FNPTR_OR_ERROR(&mFnPtrs->destroyPbufferPtr, glXDestroyPbuffer);
    GET_FNPTR_OR_ERROR(&mFnPtrs->queryDrawablePtr, glXQueryDrawable);

    // Extensions
    if (hasExtension("GLX_ARB_create_context"))
    {
        GET_PROC_OR_ERROR(&mFnPtrs->createContextAttribsARBPtr, glXCreateContextAttribsARB);
    }
    if (hasExtension("GLX_EXT_swap_control"))
    {
        GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalEXTPtr, glXSwapIntervalEXT);
    }
    if (hasExtension("GLX_MESA_swap_control"))
    {
        GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalMESAPtr, glXSwapIntervalMESA);
    }
    if (hasExtension("GLX_SGI_swap_control"))
    {
        GET_PROC_OR_ERROR(&mFnPtrs->swapIntervalSGIPtr, glXSwapIntervalSGI);
    }
    if (hasExtension("GLX_OML_sync_control"))
    {
        GET_PROC_OR_ERROR(&mFnPtrs->getSyncValuesOMLPtr, glXGetSyncValuesOML);
    }

#undef GET_FNPTR_OR_ERROR
#undef GET_PROC_OR_ERROR

    *errorString = "";
    return true;
}

void FunctionsGLX::terminate() {}

bool FunctionsGLX::hasExtension(const char *extension) const
{
    return std::find(mExtensions.begin(), mExtensions.end(), extension) != mExtensions.end();
}

Display *FunctionsGLX::getDisplay() const
{
    return mXDisplay;
}

int FunctionsGLX::getScreen() const
{
    return mXScreen;
}

// GLX functions

// GLX 1.0
glx::Context FunctionsGLX::createContext(XVisualInfo *visual, glx::Context share, bool direct) const
{
    GLXContext shareCtx = reinterpret_cast<GLXContext>(share);
    GLXContext context  = mFnPtrs->createContextPtr(mXDisplay, visual, shareCtx, direct);
    return reinterpret_cast<glx::Context>(context);
}
void FunctionsGLX::destroyContext(glx::Context context) const
{
    GLXContext ctx = reinterpret_cast<GLXContext>(context);
    mFnPtrs->destroyContextPtr(mXDisplay, ctx);
}
Bool FunctionsGLX::makeCurrent(glx::Drawable drawable, glx::Context context) const
{
    GLXContext ctx = reinterpret_cast<GLXContext>(context);
    return mFnPtrs->makeCurrentPtr(mXDisplay, drawable, ctx);
}
void FunctionsGLX::swapBuffers(glx::Drawable drawable) const
{
    mFnPtrs->swapBuffersPtr(mXDisplay, drawable);
}
Bool FunctionsGLX::queryExtension(int *errorBase, int *event) const
{
    return mFnPtrs->queryExtensionPtr(mXDisplay, errorBase, event);
}
Bool FunctionsGLX::queryVersion(int *major, int *minor) const
{
    return mFnPtrs->queryVersionPtr(mXDisplay, major, minor);
}
glx::Context FunctionsGLX::getCurrentContext() const
{
    GLXContext context = mFnPtrs->getCurrentContextPtr();
    return reinterpret_cast<glx::Context>(context);
}
glx::Drawable FunctionsGLX::getCurrentDrawable() const
{
    GLXDrawable drawable = mFnPtrs->getCurrentDrawablePtr();
    return reinterpret_cast<glx::Drawable>(drawable);
}
void FunctionsGLX::waitX() const
{
    mFnPtrs->waitXPtr();
}
void FunctionsGLX::waitGL() const
{
    mFnPtrs->waitGLPtr();
}

// GLX 1.1
const char *FunctionsGLX::getClientString(int name) const
{
    return mFnPtrs->getClientStringPtr(mXDisplay, name);
}

const char *FunctionsGLX::queryExtensionsString() const
{
    return mFnPtrs->queryExtensionsStringPtr(mXDisplay, mXScreen);
}

// GLX 1.4
glx::FBConfig *FunctionsGLX::getFBConfigs(int *nElements) const
{
    GLXFBConfig *configs = mFnPtrs->getFBConfigsPtr(mXDisplay, mXScreen, nElements);
    return reinterpret_cast<glx::FBConfig *>(configs);
}
glx::FBConfig *FunctionsGLX::chooseFBConfig(const int *attribList, int *nElements) const
{
    GLXFBConfig *configs = mFnPtrs->chooseFBConfigPtr(mXDisplay, mXScreen, attribList, nElements);
    return reinterpret_cast<glx::FBConfig *>(configs);
}
int FunctionsGLX::getFBConfigAttrib(glx::FBConfig config, int attribute, int *value) const
{
    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
    return mFnPtrs->getFBConfigAttribPtr(mXDisplay, cfg, attribute, value);
}
XVisualInfo *FunctionsGLX::getVisualFromFBConfig(glx::FBConfig config) const
{
    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
    return mFnPtrs->getVisualFromFBConfigPtr(mXDisplay, cfg);
}
GLXWindow FunctionsGLX::createWindow(glx::FBConfig config,
                                     Window window,
                                     const int *attribList) const
{
    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
    return mFnPtrs->createWindowPtr(mXDisplay, cfg, window, attribList);
}
void FunctionsGLX::destroyWindow(glx::Window window) const
{
    mFnPtrs->destroyWindowPtr(mXDisplay, window);
}
glx::Pbuffer FunctionsGLX::createPbuffer(glx::FBConfig config, const int *attribList) const
{
    GLXFBConfig cfg = reinterpret_cast<GLXFBConfig>(config);
    return mFnPtrs->createPbufferPtr(mXDisplay, cfg, attribList);
}
void FunctionsGLX::destroyPbuffer(glx::Pbuffer pbuffer) const
{
    mFnPtrs->destroyPbufferPtr(mXDisplay, pbuffer);
}
void FunctionsGLX::queryDrawable(glx::Drawable drawable, int attribute, unsigned int *value) const
{
    mFnPtrs->queryDrawablePtr(mXDisplay, drawable, attribute, value);
}

// GLX_ARB_create_context
glx::Context FunctionsGLX::createContextAttribsARB(glx::FBConfig config,
                                                   glx::Context shareContext,
                                                   Bool direct,
                                                   const int *attribList) const
{
    GLXContext shareCtx = reinterpret_cast<GLXContext>(shareContext);
    GLXFBConfig cfg     = reinterpret_cast<GLXFBConfig>(config);
    GLXContext ctx =
        mFnPtrs->createContextAttribsARBPtr(mXDisplay, cfg, shareCtx, direct, attribList);
    return reinterpret_cast<glx::Context>(ctx);
}

void FunctionsGLX::swapIntervalEXT(glx::Drawable drawable, int intervals) const
{
    mFnPtrs->swapIntervalEXTPtr(mXDisplay, drawable, intervals);
}

int FunctionsGLX::swapIntervalMESA(int intervals) const
{
    return mFnPtrs->swapIntervalMESAPtr(intervals);
}

int FunctionsGLX::swapIntervalSGI(int intervals) const
{
    return mFnPtrs->swapIntervalSGIPtr(intervals);
}

bool FunctionsGLX::getSyncValuesOML(glx::Drawable drawable,
                                    int64_t *ust,
                                    int64_t *msc,
                                    int64_t *sbc) const
{
    return mFnPtrs->getSyncValuesOMLPtr(mXDisplay, drawable, ust, msc, sbc);
}

}  // namespace rx
