<commit_before>#include <limits>

#include <Bull/Core/Exception/InternalError.hpp>
#include <Bull/Core/Exception/Throw.hpp>
#include <Bull/Core/Support/Xlib/ErrorHandler.hpp>
#include <Bull/Core/Utility/StringUtils.hpp>

#include <Bull/Render/Context/GlKhrNoError.hpp>
#include <Bull/Render/Context/Glx/GlxContext.hpp>
#include <Bull/Render/Context/Glx/GlxContextNoError.hpp>
#include <Bull/Render/Context/Glx/GlxCreateContextARB.hpp>
#include <Bull/Render/Context/Glx/GlxPBufferSGIX.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlEXT.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlMESA.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlSGI.hpp>

namespace Bull
{
    namespace prv
    {
        void* GlxContext::getFunction(const String& function)
        {
            return reinterpret_cast<void*>(
                    glXGetProcAddressARB(
                            reinterpret_cast<const unsigned char*>(function.getBuffer())
                    )
            );
        }

        void GlxContext::requireExtensions(ExtensionsLoader::Instance& loader)
        {
            loader->require(glxCreateContextARB);
            loader->require(glxPbuffer);
            loader->require(glxSwapControlEXT);
            loader->require(glxSwapControlMESA);
            loader->require(glxSwapControlSGI);
        }

        GLXFBConfig GlxContext::chooseBestConfig(Display::Instance display, const ContextSettings& settings, Uint8 bitsPerPixel)
        {
            int fbCounts = 0;
            GLXFBConfig config;
            ErrorHandler handler;
            GLXFBConfig* configs = nullptr;
            unsigned int antialiasing = settings.antialiasing;
            int bestConfig = 0, bestScore = std::numeric_limits<int>::max();

            do
            {
                int attributes[] = {
                    GLX_X_RENDERABLE  , True,
                    GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
                    GLX_RENDER_TYPE   , GLX_RGBA_BIT,
                    GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
                    GLX_BUFFER_SIZE   , static_cast<int>(bitsPerPixel),
                    GLX_ALPHA_SIZE    , bitsPerPixel == 32 ? 8 : 0,
                    GLX_DEPTH_SIZE    , settings.depths,
                    GLX_STENCIL_SIZE  , settings.stencil,
                    GLX_DOUBLEBUFFER  , True,
                    GLX_SAMPLE_BUFFERS, antialiasing > 0 ? True : False,
                    GLX_SAMPLES       , static_cast<int>(antialiasing),
                    0
                };

                configs = glXChooseFBConfig(display->getHandler(), display->getDefaultScreen(), attributes, &fbCounts);

                if(fbCounts == 0)
                {
                    antialiasing /= 2;
                }
            }while(fbCounts == 0);

            for(int i = 0; i < fbCounts; i++)
            {
                XVisualInfo* vi = glXGetVisualFromFBConfig(display->getHandler(), configs[i]);

                if(vi)
                {
                    int depths, stencil;
                    int sampleBuffers, samples;
                    int red, green, blue, alpha;

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_RED_SIZE,   &red);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_GREEN_SIZE, &green);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_BLUE_SIZE,  &blue);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_ALPHA_SIZE, &alpha);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLE_BUFFERS, &sampleBuffers);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLES,        &samples);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_DEPTH_SIZE,   &depths);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_STENCIL_SIZE, &stencil);

                    int currentBitsPerPixel = red + green + blue + alpha;
                    int score = evaluatePixelFormat(currentBitsPerPixel, depths, stencil, sampleBuffers ? samples : 0, bitsPerPixel, settings);

                    if(bestScore > score)
                    {
                        bestScore  = score;
                        bestConfig = i;
                    }
                }

                XFree(vi);
            }

            config = configs[bestConfig];

            XFree(configs);

            return config;
        }

        GlxContext::GlxContext(const GlxContext* shared) :
            GlxContext(shared, VideoMode(1, 1), ContextSettings::Worst)
        {
            /// Nothing
        }

        GlxContext::GlxContext(const GlxContext* shared, const VideoMode& mode, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(nullptr),
            m_config(nullptr),
            m_pbuffer(0),
            m_colormap(0),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, mode.bitsPerPixel);

            createSurface(shared, mode.width, mode.height);

            if(m_window || m_pbuffer)
            {
                createContext(shared);
            }
        }

        GlxContext::GlxContext(const GlxContext* shared, Uint8 bitsPerPixel, const ContextSettings& settings) :
                GlxContext(shared, VideoMode(1, 1, bitsPerPixel), settings)
        {
            /// Nothing
        }

        GlxContext::GlxContext(const GlxContext* shared, const WindowImpl& window, Uint8 bitsPerPixel, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(nullptr),
            m_config(nullptr),
            m_pbuffer(0),
            m_colormap(0),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, bitsPerPixel);

            createSurface(window);

            if(m_window)
            {
                createContext(shared);
            }
        }

        GlxContext::~GlxContext()
        {
            ErrorHandler handler;

            if(m_render)
            {
                if(glXGetCurrentContext() == m_render)
                {
                    if(glXMakeCurrent(m_display->getHandler(), XNone, nullptr) == False)
                    {
                        Throw(InternalError, "GlxContext::~GlxContext", "Failed to disable current context");
                    }
                }

                glXDestroyContext(m_display->getHandler(), m_render);
            }

            if(m_pbuffer)
            {
                glXDestroyPbuffer(m_display->getHandler(), m_pbuffer);
            }

            if(m_ownWindow && m_window)
            {
                XDestroyWindow(m_display->getHandler(), m_window);
                XFreeColormap(m_display->getHandler(), m_colormap);

                m_display->flush();
            }
        }

        void GlxContext::display()
        {
            ErrorHandler handler;

            if(m_window)
            {
                glXSwapBuffers(m_display->getHandler(), m_window);
            }
            else if(m_pbuffer)
            {
                glXSwapBuffers(m_display->getHandler(), m_pbuffer);
            }
        }

        void GlxContext::enableVsync(bool active)
        {
            ErrorHandler handler;

            if(glxSwapControlEXT.isLoaded())
            {
                ext::glXSwapInterval(m_display->getHandler(), glXGetCurrentDrawable(), active ? 1 : 0);
            }
            else if(glxSwapControlMESA.isLoaded())
            {
                mesa::glXSwapInterval(active ? 1 : 0);
            }
            else if(glxSwapControlSGI.isLoaded())
            {
                sgi::glXSwapInterval(active ? 1 : 0);
            }
            else
            {
                m_log->warning("VSync is not available on your system");
            }
        }

        SurfaceHandler GlxContext::getSurfaceHandler() const
        {
            return m_display->getDefaultScreen();
        }

        void GlxContext::makeCurrent()
        {
            ErrorHandler handler;

            if(m_window)
            {
                if(glXMakeCurrent(m_display->getHandler(), m_window, m_render) == False)
                {
                    Throw(InternalError, "GlxContext::makeCurrent", "Failed to make context current");
                }
            }
            else if(m_pbuffer)
            {
                if(glXMakeContextCurrent(m_display->getHandler(), m_pbuffer, m_pbuffer, m_render) == False)
                {
                    Throw(InternalError, "GlxContext::makeCurrent", "Failed to make context current");
                }
            }

        }

        void GlxContext::createSurface(const WindowImpl& window)
        {
            m_window = window.getSystemHandler();
        }

        void GlxContext::createSurface(const GlxContext* shared, unsigned int width, unsigned int height)
        {
            ErrorHandler handler;

            if(glxPbuffer.isLoaded() && shared)
            {
                int fbCounts         = 0;
                GLXFBConfig* configs = glXChooseFBConfig(m_display->getHandler(), m_display->getDefaultScreen(), nullptr, &fbCounts);

                if(fbCounts && configs)
                {
                    int attributes[] = {
                        GLX_PBUFFER_WIDTH,  static_cast<int>(width),
                        GLX_PBUFFER_HEIGHT, static_cast<int>(height),
                        0
                    };

                    m_config = configs[0];

                    m_pbuffer = glXCreatePbuffer(m_display->getHandler(), m_config, attributes);

                    XFree(configs);
                }<commit_msg>[Render/GlxContext] Fix style<commit_after>#include <limits>

#include <Bull/Core/Exception/InternalError.hpp>
#include <Bull/Core/Exception/Throw.hpp>
#include <Bull/Core/Support/Xlib/ErrorHandler.hpp>
#include <Bull/Core/Utility/StringUtils.hpp>

#include <Bull/Render/Context/GlKhrNoError.hpp>
#include <Bull/Render/Context/Glx/GlxContext.hpp>
#include <Bull/Render/Context/Glx/GlxContextNoError.hpp>
#include <Bull/Render/Context/Glx/GlxCreateContextARB.hpp>
#include <Bull/Render/Context/Glx/GlxPBufferSGIX.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlEXT.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlMESA.hpp>
#include <Bull/Render/Context/Glx/GlxSwapControlSGI.hpp>

namespace Bull
{
    namespace prv
    {
        void* GlxContext::getFunction(const String& function)
        {
            return reinterpret_cast<void*>(
                    glXGetProcAddressARB(
                            reinterpret_cast<const unsigned char*>(function.getBuffer())
                    )
            );
        }

        void GlxContext::requireExtensions(ExtensionsLoader::Instance& loader)
        {
            loader->require(glxCreateContextARB);
            loader->require(glxPbuffer);
            loader->require(glxSwapControlEXT);
            loader->require(glxSwapControlMESA);
            loader->require(glxSwapControlSGI);
        }

        GLXFBConfig GlxContext::chooseBestConfig(Display::Instance display, const ContextSettings& settings, Uint8 bitsPerPixel)
        {
            int fbCounts = 0;
            GLXFBConfig config;
            ErrorHandler handler;
            GLXFBConfig* configs = nullptr;
            unsigned int antialiasing = settings.antialiasing;
            int bestConfig = 0, bestScore = std::numeric_limits<int>::max();

            do
            {
                int attributes[] = {
                    GLX_X_RENDERABLE  , True,
                    GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
                    GLX_RENDER_TYPE   , GLX_RGBA_BIT,
                    GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
                    GLX_BUFFER_SIZE   , static_cast<int>(bitsPerPixel),
                    GLX_ALPHA_SIZE    , bitsPerPixel == 32 ? 8 : 0,
                    GLX_DEPTH_SIZE    , settings.depths,
                    GLX_STENCIL_SIZE  , settings.stencil,
                    GLX_DOUBLEBUFFER  , True,
                    GLX_SAMPLE_BUFFERS, antialiasing > 0 ? True : False,
                    GLX_SAMPLES       , static_cast<int>(antialiasing),
                    0
                };

                configs = glXChooseFBConfig(display->getHandler(), display->getDefaultScreen(), attributes, &fbCounts);

                if(fbCounts == 0)
                {
                    antialiasing /= 2;
                }
            }while(fbCounts == 0);

            for(int i = 0; i < fbCounts; i++)
            {
                XVisualInfo* vi = glXGetVisualFromFBConfig(display->getHandler(), configs[i]);

                if(vi)
                {
                    int depths, stencil;
                    int sampleBuffers, samples;
                    int red, green, blue, alpha;

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_RED_SIZE,   &red);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_GREEN_SIZE, &green);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_BLUE_SIZE,  &blue);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_ALPHA_SIZE, &alpha);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLE_BUFFERS, &sampleBuffers);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_SAMPLES,        &samples);

                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_DEPTH_SIZE,   &depths);
                    glXGetFBConfigAttrib(display->getHandler(), configs[i], GLX_STENCIL_SIZE, &stencil);

                    int currentBitsPerPixel = red + green + blue + alpha;
                    int score = evaluatePixelFormat(currentBitsPerPixel, depths, stencil, sampleBuffers ? samples : 0, bitsPerPixel, settings);

                    if(bestScore > score)
                    {
                        bestScore  = score;
                        bestConfig = i;
                    }
                }

                XFree(vi);
            }

            config = configs[bestConfig];

            XFree(configs);

            return config;
        }

        GlxContext::GlxContext(const GlxContext* shared) :
            GlxContext(shared, VideoMode(1, 1), ContextSettings::Worst)
        {
            /// Nothing
        }

        GlxContext::GlxContext(const GlxContext* shared, const VideoMode& mode, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(nullptr),
            m_config(nullptr),
            m_pbuffer(0),
            m_colormap(0),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, mode.bitsPerPixel);

            createSurface(shared, mode.width, mode.height);

            if(m_window || m_pbuffer)
            {
                createContext(shared);
            }
        }

        GlxContext::GlxContext(const GlxContext* shared, Uint8 bitsPerPixel, const ContextSettings& settings) :
            GlxContext(shared, VideoMode(1, 1, bitsPerPixel), settings)
        {
            /// Nothing
        }

        GlxContext::GlxContext(const GlxContext* shared, const WindowImpl& window, Uint8 bitsPerPixel, const ContextSettings& settings) :
            GlContext(settings),
            m_window(0),
            m_render(nullptr),
            m_config(nullptr),
            m_pbuffer(0),
            m_colormap(0),
            m_ownWindow(false)
        {
            m_config = chooseBestConfig(m_display, m_settings, bitsPerPixel);

            createSurface(window);

            if(m_window)
            {
                createContext(shared);
            }
        }

        GlxContext::~GlxContext()
        {
            ErrorHandler handler;

            if(m_render)
            {
                if(glXGetCurrentContext() == m_render)
                {
                    if(glXMakeCurrent(m_display->getHandler(), XNone, nullptr) == False)
                    {
                        Throw(InternalError, "GlxContext::~GlxContext", "Failed to disable current context");
                    }
                }

                glXDestroyContext(m_display->getHandler(), m_render);
            }

            if(m_pbuffer)
            {
                glXDestroyPbuffer(m_display->getHandler(), m_pbuffer);
            }

            if(m_ownWindow && m_window)
            {
                XDestroyWindow(m_display->getHandler(), m_window);
                XFreeColormap(m_display->getHandler(), m_colormap);

                m_display->flush();
            }
        }

        void GlxContext::display()
        {
            ErrorHandler handler;

            if(m_window)
            {
                glXSwapBuffers(m_display->getHandler(), m_window);
            }
            else if(m_pbuffer)
            {
                glXSwapBuffers(m_display->getHandler(), m_pbuffer);
            }
        }

        void GlxContext::enableVsync(bool active)
        {
            ErrorHandler handler;

            if(glxSwapControlEXT.isLoaded())
            {
                ext::glXSwapInterval(m_display->getHandler(), glXGetCurrentDrawable(), active ? 1 : 0);
            }
            else if(glxSwapControlMESA.isLoaded())
            {
                mesa::glXSwapInterval(active ? 1 : 0);
            }
            else if(glxSwapControlSGI.isLoaded())
            {
                sgi::glXSwapInterval(active ? 1 : 0);
            }
            else
            {
                m_log->warning("VSync is not available on your system");
            }
        }

        SurfaceHandler GlxContext::getSurfaceHandler() const
        {
            return m_display->getDefaultScreen();
        }

        void GlxContext::makeCurrent()
        {
            ErrorHandler handler;

            if(m_window)
            {
                if(glXMakeCurrent(m_display->getHandler(), m_window, m_render) == False)
                {
                    Throw(InternalError, "GlxContext::makeCurrent", "Failed to make context current");
                }
            }
            else if(m_pbuffer)
            {
                if(glXMakeContextCurrent(m_display->getHandler(), m_pbuffer, m_pbuffer, m_render) == False)
                {
                    Throw(InternalError, "GlxContext::makeCurrent", "Failed to make context current");
                }
            }
        }

        void GlxContext::createSurface(const WindowImpl& window)
        {
            m_window = window.getSystemHandler();
        }

        void GlxContext::createSurface(const GlxContext* shared, unsigned int width, unsigned int height)
        {
            ErrorHandler handler;

            if(glxPbuffer.isLoaded() && shared)
            {
                int fbCounts         = 0;
                GLXFBConfig* configs = glXChooseFBConfig(m_display->getHandler(), m_display->getDefaultScreen(), nullptr, &fbCounts);

                if(fbCounts && configs)
                {
                    int attributes[] = {
                        GLX_PBUFFER_WIDTH,  static_cast<int>(width),
                        GLX_PBUFFER_HEIGHT, static_cast<int>(height),
                        0
                    };

                    m_config = configs[0];

                    m_pbuffer = glXCreatePbuffer(m_display->getHandler(), m_config, attributes);

                    XFree(configs);
                }
{'fraction_non_alphanumeric': 0.09603372098928445, 'fraction_numerical': 0.0035549235691432635, 'mean_word_length': 1.5845911536947106, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '401751', 'n_tokens_mistral': 5597, 'n_tokens_neox': 5324, 'n_words': 846}