1b877906bSopenharmony_ci//========================================================================
2b877906bSopenharmony_ci// GLFW 3.5 GLX - www.glfw.org
3b877906bSopenharmony_ci//------------------------------------------------------------------------
4b877906bSopenharmony_ci// Copyright (c) 2002-2006 Marcus Geelnard
5b877906bSopenharmony_ci// Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
6b877906bSopenharmony_ci//
7b877906bSopenharmony_ci// This software is provided 'as-is', without any express or implied
8b877906bSopenharmony_ci// warranty. In no event will the authors be held liable for any damages
9b877906bSopenharmony_ci// arising from the use of this software.
10b877906bSopenharmony_ci//
11b877906bSopenharmony_ci// Permission is granted to anyone to use this software for any purpose,
12b877906bSopenharmony_ci// including commercial applications, and to alter it and redistribute it
13b877906bSopenharmony_ci// freely, subject to the following restrictions:
14b877906bSopenharmony_ci//
15b877906bSopenharmony_ci// 1. The origin of this software must not be misrepresented; you must not
16b877906bSopenharmony_ci//    claim that you wrote the original software. If you use this software
17b877906bSopenharmony_ci//    in a product, an acknowledgment in the product documentation would
18b877906bSopenharmony_ci//    be appreciated but is not required.
19b877906bSopenharmony_ci//
20b877906bSopenharmony_ci// 2. Altered source versions must be plainly marked as such, and must not
21b877906bSopenharmony_ci//    be misrepresented as being the original software.
22b877906bSopenharmony_ci//
23b877906bSopenharmony_ci// 3. This notice may not be removed or altered from any source
24b877906bSopenharmony_ci//    distribution.
25b877906bSopenharmony_ci//
26b877906bSopenharmony_ci//========================================================================
27b877906bSopenharmony_ci
28b877906bSopenharmony_ci#include "internal.h"
29b877906bSopenharmony_ci
30b877906bSopenharmony_ci#if defined(_GLFW_X11)
31b877906bSopenharmony_ci
32b877906bSopenharmony_ci#include <string.h>
33b877906bSopenharmony_ci#include <stdlib.h>
34b877906bSopenharmony_ci#include <assert.h>
35b877906bSopenharmony_ci
36b877906bSopenharmony_ci#ifndef GLXBadProfileARB
37b877906bSopenharmony_ci #define GLXBadProfileARB 13
38b877906bSopenharmony_ci#endif
39b877906bSopenharmony_ci
40b877906bSopenharmony_ci
41b877906bSopenharmony_ci// Returns the specified attribute of the specified GLXFBConfig
42b877906bSopenharmony_ci//
43b877906bSopenharmony_cistatic int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
44b877906bSopenharmony_ci{
45b877906bSopenharmony_ci    int value;
46b877906bSopenharmony_ci    glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
47b877906bSopenharmony_ci    return value;
48b877906bSopenharmony_ci}
49b877906bSopenharmony_ci
50b877906bSopenharmony_ci// Return the GLXFBConfig most closely matching the specified hints
51b877906bSopenharmony_ci//
52b877906bSopenharmony_cistatic GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
53b877906bSopenharmony_ci                                  GLXFBConfig* result)
54b877906bSopenharmony_ci{
55b877906bSopenharmony_ci    GLXFBConfig* nativeConfigs;
56b877906bSopenharmony_ci    _GLFWfbconfig* usableConfigs;
57b877906bSopenharmony_ci    const _GLFWfbconfig* closest;
58b877906bSopenharmony_ci    int nativeCount, usableCount;
59b877906bSopenharmony_ci    const char* vendor;
60b877906bSopenharmony_ci    GLFWbool trustWindowBit = GLFW_TRUE;
61b877906bSopenharmony_ci
62b877906bSopenharmony_ci    // HACK: This is a (hopefully temporary) workaround for Chromium
63b877906bSopenharmony_ci    //       (VirtualBox GL) not setting the window bit on any GLXFBConfigs
64b877906bSopenharmony_ci    vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
65b877906bSopenharmony_ci    if (vendor && strcmp(vendor, "Chromium") == 0)
66b877906bSopenharmony_ci        trustWindowBit = GLFW_FALSE;
67b877906bSopenharmony_ci
68b877906bSopenharmony_ci    nativeConfigs =
69b877906bSopenharmony_ci        glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
70b877906bSopenharmony_ci    if (!nativeConfigs || !nativeCount)
71b877906bSopenharmony_ci    {
72b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
73b877906bSopenharmony_ci        return GLFW_FALSE;
74b877906bSopenharmony_ci    }
75b877906bSopenharmony_ci
76b877906bSopenharmony_ci    usableConfigs = _glfw_calloc(nativeCount, sizeof(_GLFWfbconfig));
77b877906bSopenharmony_ci    usableCount = 0;
78b877906bSopenharmony_ci
79b877906bSopenharmony_ci    for (int i = 0;  i < nativeCount;  i++)
80b877906bSopenharmony_ci    {
81b877906bSopenharmony_ci        const GLXFBConfig n = nativeConfigs[i];
82b877906bSopenharmony_ci        _GLFWfbconfig* u = usableConfigs + usableCount;
83b877906bSopenharmony_ci
84b877906bSopenharmony_ci        // Only consider RGBA GLXFBConfigs
85b877906bSopenharmony_ci        if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
86b877906bSopenharmony_ci            continue;
87b877906bSopenharmony_ci
88b877906bSopenharmony_ci        // Only consider window GLXFBConfigs
89b877906bSopenharmony_ci        if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
90b877906bSopenharmony_ci        {
91b877906bSopenharmony_ci            if (trustWindowBit)
92b877906bSopenharmony_ci                continue;
93b877906bSopenharmony_ci        }
94b877906bSopenharmony_ci
95b877906bSopenharmony_ci        if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER) != desired->doublebuffer)
96b877906bSopenharmony_ci            continue;
97b877906bSopenharmony_ci
98b877906bSopenharmony_ci        if (desired->transparent)
99b877906bSopenharmony_ci        {
100b877906bSopenharmony_ci            XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
101b877906bSopenharmony_ci            if (vi)
102b877906bSopenharmony_ci            {
103b877906bSopenharmony_ci                u->transparent = _glfwIsVisualTransparentX11(vi->visual);
104b877906bSopenharmony_ci                XFree(vi);
105b877906bSopenharmony_ci            }
106b877906bSopenharmony_ci        }
107b877906bSopenharmony_ci
108b877906bSopenharmony_ci        u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
109b877906bSopenharmony_ci        u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
110b877906bSopenharmony_ci        u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
111b877906bSopenharmony_ci
112b877906bSopenharmony_ci        u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
113b877906bSopenharmony_ci        u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
114b877906bSopenharmony_ci        u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE);
115b877906bSopenharmony_ci
116b877906bSopenharmony_ci        u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
117b877906bSopenharmony_ci        u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
118b877906bSopenharmony_ci        u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
119b877906bSopenharmony_ci        u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
120b877906bSopenharmony_ci
121b877906bSopenharmony_ci        u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
122b877906bSopenharmony_ci
123b877906bSopenharmony_ci        if (getGLXFBConfigAttrib(n, GLX_STEREO))
124b877906bSopenharmony_ci            u->stereo = GLFW_TRUE;
125b877906bSopenharmony_ci
126b877906bSopenharmony_ci        if (_glfw.glx.ARB_multisample)
127b877906bSopenharmony_ci            u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
128b877906bSopenharmony_ci
129b877906bSopenharmony_ci        if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
130b877906bSopenharmony_ci            u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
131b877906bSopenharmony_ci
132b877906bSopenharmony_ci        u->handle = (uintptr_t) n;
133b877906bSopenharmony_ci        usableCount++;
134b877906bSopenharmony_ci    }
135b877906bSopenharmony_ci
136b877906bSopenharmony_ci    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
137b877906bSopenharmony_ci    if (closest)
138b877906bSopenharmony_ci        *result = (GLXFBConfig) closest->handle;
139b877906bSopenharmony_ci
140b877906bSopenharmony_ci    XFree(nativeConfigs);
141b877906bSopenharmony_ci    _glfw_free(usableConfigs);
142b877906bSopenharmony_ci
143b877906bSopenharmony_ci    return closest != NULL;
144b877906bSopenharmony_ci}
145b877906bSopenharmony_ci
146b877906bSopenharmony_ci// Create the OpenGL context using legacy API
147b877906bSopenharmony_ci//
148b877906bSopenharmony_cistatic GLXContext createLegacyContextGLX(_GLFWwindow* window,
149b877906bSopenharmony_ci                                         GLXFBConfig fbconfig,
150b877906bSopenharmony_ci                                         GLXContext share)
151b877906bSopenharmony_ci{
152b877906bSopenharmony_ci    return glXCreateNewContext(_glfw.x11.display,
153b877906bSopenharmony_ci                               fbconfig,
154b877906bSopenharmony_ci                               GLX_RGBA_TYPE,
155b877906bSopenharmony_ci                               share,
156b877906bSopenharmony_ci                               True);
157b877906bSopenharmony_ci}
158b877906bSopenharmony_ci
159b877906bSopenharmony_cistatic void makeContextCurrentGLX(_GLFWwindow* window)
160b877906bSopenharmony_ci{
161b877906bSopenharmony_ci    if (window)
162b877906bSopenharmony_ci    {
163b877906bSopenharmony_ci        if (!glXMakeCurrent(_glfw.x11.display,
164b877906bSopenharmony_ci                            window->context.glx.window,
165b877906bSopenharmony_ci                            window->context.glx.handle))
166b877906bSopenharmony_ci        {
167b877906bSopenharmony_ci            _glfwInputError(GLFW_PLATFORM_ERROR,
168b877906bSopenharmony_ci                            "GLX: Failed to make context current");
169b877906bSopenharmony_ci            return;
170b877906bSopenharmony_ci        }
171b877906bSopenharmony_ci    }
172b877906bSopenharmony_ci    else
173b877906bSopenharmony_ci    {
174b877906bSopenharmony_ci        if (!glXMakeCurrent(_glfw.x11.display, None, NULL))
175b877906bSopenharmony_ci        {
176b877906bSopenharmony_ci            _glfwInputError(GLFW_PLATFORM_ERROR,
177b877906bSopenharmony_ci                            "GLX: Failed to clear current context");
178b877906bSopenharmony_ci            return;
179b877906bSopenharmony_ci        }
180b877906bSopenharmony_ci    }
181b877906bSopenharmony_ci
182b877906bSopenharmony_ci    _glfwPlatformSetTls(&_glfw.contextSlot, window);
183b877906bSopenharmony_ci}
184b877906bSopenharmony_ci
185b877906bSopenharmony_cistatic void swapBuffersGLX(_GLFWwindow* window)
186b877906bSopenharmony_ci{
187b877906bSopenharmony_ci    glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
188b877906bSopenharmony_ci}
189b877906bSopenharmony_ci
190b877906bSopenharmony_cistatic void swapIntervalGLX(int interval)
191b877906bSopenharmony_ci{
192b877906bSopenharmony_ci    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
193b877906bSopenharmony_ci    assert(window != NULL);
194b877906bSopenharmony_ci
195b877906bSopenharmony_ci    if (_glfw.glx.EXT_swap_control)
196b877906bSopenharmony_ci    {
197b877906bSopenharmony_ci        _glfw.glx.SwapIntervalEXT(_glfw.x11.display,
198b877906bSopenharmony_ci                                  window->context.glx.window,
199b877906bSopenharmony_ci                                  interval);
200b877906bSopenharmony_ci    }
201b877906bSopenharmony_ci    else if (_glfw.glx.MESA_swap_control)
202b877906bSopenharmony_ci        _glfw.glx.SwapIntervalMESA(interval);
203b877906bSopenharmony_ci    else if (_glfw.glx.SGI_swap_control)
204b877906bSopenharmony_ci    {
205b877906bSopenharmony_ci        if (interval > 0)
206b877906bSopenharmony_ci            _glfw.glx.SwapIntervalSGI(interval);
207b877906bSopenharmony_ci    }
208b877906bSopenharmony_ci}
209b877906bSopenharmony_ci
210b877906bSopenharmony_cistatic int extensionSupportedGLX(const char* extension)
211b877906bSopenharmony_ci{
212b877906bSopenharmony_ci    const char* extensions =
213b877906bSopenharmony_ci        glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
214b877906bSopenharmony_ci    if (extensions)
215b877906bSopenharmony_ci    {
216b877906bSopenharmony_ci        if (_glfwStringInExtensionString(extension, extensions))
217b877906bSopenharmony_ci            return GLFW_TRUE;
218b877906bSopenharmony_ci    }
219b877906bSopenharmony_ci
220b877906bSopenharmony_ci    return GLFW_FALSE;
221b877906bSopenharmony_ci}
222b877906bSopenharmony_ci
223b877906bSopenharmony_cistatic GLFWglproc getProcAddressGLX(const char* procname)
224b877906bSopenharmony_ci{
225b877906bSopenharmony_ci    if (_glfw.glx.GetProcAddress)
226b877906bSopenharmony_ci        return _glfw.glx.GetProcAddress((const GLubyte*) procname);
227b877906bSopenharmony_ci    else if (_glfw.glx.GetProcAddressARB)
228b877906bSopenharmony_ci        return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
229b877906bSopenharmony_ci    else
230b877906bSopenharmony_ci    {
231b877906bSopenharmony_ci        // NOTE: glvnd provides GLX 1.4, so this can only happen with libGL
232b877906bSopenharmony_ci        return _glfwPlatformGetModuleSymbol(_glfw.glx.handle, procname);
233b877906bSopenharmony_ci    }
234b877906bSopenharmony_ci}
235b877906bSopenharmony_ci
236b877906bSopenharmony_cistatic void destroyContextGLX(_GLFWwindow* window)
237b877906bSopenharmony_ci{
238b877906bSopenharmony_ci    if (window->context.glx.window)
239b877906bSopenharmony_ci    {
240b877906bSopenharmony_ci        glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
241b877906bSopenharmony_ci        window->context.glx.window = None;
242b877906bSopenharmony_ci    }
243b877906bSopenharmony_ci
244b877906bSopenharmony_ci    if (window->context.glx.handle)
245b877906bSopenharmony_ci    {
246b877906bSopenharmony_ci        glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
247b877906bSopenharmony_ci        window->context.glx.handle = NULL;
248b877906bSopenharmony_ci    }
249b877906bSopenharmony_ci}
250b877906bSopenharmony_ci
251b877906bSopenharmony_ci
252b877906bSopenharmony_ci//////////////////////////////////////////////////////////////////////////
253b877906bSopenharmony_ci//////                       GLFW internal API                      //////
254b877906bSopenharmony_ci//////////////////////////////////////////////////////////////////////////
255b877906bSopenharmony_ci
256b877906bSopenharmony_ci// Initialize GLX
257b877906bSopenharmony_ci//
258b877906bSopenharmony_ciGLFWbool _glfwInitGLX(void)
259b877906bSopenharmony_ci{
260b877906bSopenharmony_ci    const char* sonames[] =
261b877906bSopenharmony_ci    {
262b877906bSopenharmony_ci#if defined(_GLFW_GLX_LIBRARY)
263b877906bSopenharmony_ci        _GLFW_GLX_LIBRARY,
264b877906bSopenharmony_ci#elif defined(__CYGWIN__)
265b877906bSopenharmony_ci        "libGL-1.so",
266b877906bSopenharmony_ci#elif defined(__OpenBSD__) || defined(__NetBSD__)
267b877906bSopenharmony_ci        "libGL.so",
268b877906bSopenharmony_ci#else
269b877906bSopenharmony_ci        "libGLX.so.0",
270b877906bSopenharmony_ci        "libGL.so.1",
271b877906bSopenharmony_ci        "libGL.so",
272b877906bSopenharmony_ci#endif
273b877906bSopenharmony_ci        NULL
274b877906bSopenharmony_ci    };
275b877906bSopenharmony_ci
276b877906bSopenharmony_ci    if (_glfw.glx.handle)
277b877906bSopenharmony_ci        return GLFW_TRUE;
278b877906bSopenharmony_ci
279b877906bSopenharmony_ci    for (int i = 0;  sonames[i];  i++)
280b877906bSopenharmony_ci    {
281b877906bSopenharmony_ci        _glfw.glx.handle = _glfwPlatformLoadModule(sonames[i]);
282b877906bSopenharmony_ci        if (_glfw.glx.handle)
283b877906bSopenharmony_ci            break;
284b877906bSopenharmony_ci    }
285b877906bSopenharmony_ci
286b877906bSopenharmony_ci    if (!_glfw.glx.handle)
287b877906bSopenharmony_ci    {
288b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
289b877906bSopenharmony_ci        return GLFW_FALSE;
290b877906bSopenharmony_ci    }
291b877906bSopenharmony_ci
292b877906bSopenharmony_ci    _glfw.glx.GetFBConfigs = (PFNGLXGETFBCONFIGSPROC)
293b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetFBConfigs");
294b877906bSopenharmony_ci    _glfw.glx.GetFBConfigAttrib = (PFNGLXGETFBCONFIGATTRIBPROC)
295b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetFBConfigAttrib");
296b877906bSopenharmony_ci    _glfw.glx.GetClientString = (PFNGLXGETCLIENTSTRINGPROC)
297b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetClientString");
298b877906bSopenharmony_ci    _glfw.glx.QueryExtension = (PFNGLXQUERYEXTENSIONPROC)
299b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXQueryExtension");
300b877906bSopenharmony_ci    _glfw.glx.QueryVersion = (PFNGLXQUERYVERSIONPROC)
301b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXQueryVersion");
302b877906bSopenharmony_ci    _glfw.glx.DestroyContext = (PFNGLXDESTROYCONTEXTPROC)
303b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXDestroyContext");
304b877906bSopenharmony_ci    _glfw.glx.MakeCurrent = (PFNGLXMAKECURRENTPROC)
305b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXMakeCurrent");
306b877906bSopenharmony_ci    _glfw.glx.SwapBuffers = (PFNGLXSWAPBUFFERSPROC)
307b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXSwapBuffers");
308b877906bSopenharmony_ci    _glfw.glx.QueryExtensionsString = (PFNGLXQUERYEXTENSIONSSTRINGPROC)
309b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXQueryExtensionsString");
310b877906bSopenharmony_ci    _glfw.glx.CreateNewContext = (PFNGLXCREATENEWCONTEXTPROC)
311b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXCreateNewContext");
312b877906bSopenharmony_ci    _glfw.glx.CreateWindow = (PFNGLXCREATEWINDOWPROC)
313b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXCreateWindow");
314b877906bSopenharmony_ci    _glfw.glx.DestroyWindow = (PFNGLXDESTROYWINDOWPROC)
315b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXDestroyWindow");
316b877906bSopenharmony_ci    _glfw.glx.GetVisualFromFBConfig = (PFNGLXGETVISUALFROMFBCONFIGPROC)
317b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetVisualFromFBConfig");
318b877906bSopenharmony_ci
319b877906bSopenharmony_ci    if (!_glfw.glx.GetFBConfigs ||
320b877906bSopenharmony_ci        !_glfw.glx.GetFBConfigAttrib ||
321b877906bSopenharmony_ci        !_glfw.glx.GetClientString ||
322b877906bSopenharmony_ci        !_glfw.glx.QueryExtension ||
323b877906bSopenharmony_ci        !_glfw.glx.QueryVersion ||
324b877906bSopenharmony_ci        !_glfw.glx.DestroyContext ||
325b877906bSopenharmony_ci        !_glfw.glx.MakeCurrent ||
326b877906bSopenharmony_ci        !_glfw.glx.SwapBuffers ||
327b877906bSopenharmony_ci        !_glfw.glx.QueryExtensionsString ||
328b877906bSopenharmony_ci        !_glfw.glx.CreateNewContext ||
329b877906bSopenharmony_ci        !_glfw.glx.CreateWindow ||
330b877906bSopenharmony_ci        !_glfw.glx.DestroyWindow ||
331b877906bSopenharmony_ci        !_glfw.glx.GetVisualFromFBConfig)
332b877906bSopenharmony_ci    {
333b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_ERROR,
334b877906bSopenharmony_ci                        "GLX: Failed to load required entry points");
335b877906bSopenharmony_ci        return GLFW_FALSE;
336b877906bSopenharmony_ci    }
337b877906bSopenharmony_ci
338b877906bSopenharmony_ci    // NOTE: Unlike GLX 1.3 entry points these are not required to be present
339b877906bSopenharmony_ci    _glfw.glx.GetProcAddress = (PFNGLXGETPROCADDRESSPROC)
340b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddress");
341b877906bSopenharmony_ci    _glfw.glx.GetProcAddressARB = (PFNGLXGETPROCADDRESSPROC)
342b877906bSopenharmony_ci        _glfwPlatformGetModuleSymbol(_glfw.glx.handle, "glXGetProcAddressARB");
343b877906bSopenharmony_ci
344b877906bSopenharmony_ci    if (!glXQueryExtension(_glfw.x11.display,
345b877906bSopenharmony_ci                           &_glfw.glx.errorBase,
346b877906bSopenharmony_ci                           &_glfw.glx.eventBase))
347b877906bSopenharmony_ci    {
348b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
349b877906bSopenharmony_ci        return GLFW_FALSE;
350b877906bSopenharmony_ci    }
351b877906bSopenharmony_ci
352b877906bSopenharmony_ci    if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
353b877906bSopenharmony_ci    {
354b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE,
355b877906bSopenharmony_ci                        "GLX: Failed to query GLX version");
356b877906bSopenharmony_ci        return GLFW_FALSE;
357b877906bSopenharmony_ci    }
358b877906bSopenharmony_ci
359b877906bSopenharmony_ci    if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
360b877906bSopenharmony_ci    {
361b877906bSopenharmony_ci        _glfwInputError(GLFW_API_UNAVAILABLE,
362b877906bSopenharmony_ci                        "GLX: GLX version 1.3 is required");
363b877906bSopenharmony_ci        return GLFW_FALSE;
364b877906bSopenharmony_ci    }
365b877906bSopenharmony_ci
366b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_EXT_swap_control"))
367b877906bSopenharmony_ci    {
368b877906bSopenharmony_ci        _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
369b877906bSopenharmony_ci            getProcAddressGLX("glXSwapIntervalEXT");
370b877906bSopenharmony_ci
371b877906bSopenharmony_ci        if (_glfw.glx.SwapIntervalEXT)
372b877906bSopenharmony_ci            _glfw.glx.EXT_swap_control = GLFW_TRUE;
373b877906bSopenharmony_ci    }
374b877906bSopenharmony_ci
375b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_SGI_swap_control"))
376b877906bSopenharmony_ci    {
377b877906bSopenharmony_ci        _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
378b877906bSopenharmony_ci            getProcAddressGLX("glXSwapIntervalSGI");
379b877906bSopenharmony_ci
380b877906bSopenharmony_ci        if (_glfw.glx.SwapIntervalSGI)
381b877906bSopenharmony_ci            _glfw.glx.SGI_swap_control = GLFW_TRUE;
382b877906bSopenharmony_ci    }
383b877906bSopenharmony_ci
384b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_MESA_swap_control"))
385b877906bSopenharmony_ci    {
386b877906bSopenharmony_ci        _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
387b877906bSopenharmony_ci            getProcAddressGLX("glXSwapIntervalMESA");
388b877906bSopenharmony_ci
389b877906bSopenharmony_ci        if (_glfw.glx.SwapIntervalMESA)
390b877906bSopenharmony_ci            _glfw.glx.MESA_swap_control = GLFW_TRUE;
391b877906bSopenharmony_ci    }
392b877906bSopenharmony_ci
393b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_multisample"))
394b877906bSopenharmony_ci        _glfw.glx.ARB_multisample = GLFW_TRUE;
395b877906bSopenharmony_ci
396b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
397b877906bSopenharmony_ci        _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
398b877906bSopenharmony_ci
399b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
400b877906bSopenharmony_ci        _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
401b877906bSopenharmony_ci
402b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_create_context"))
403b877906bSopenharmony_ci    {
404b877906bSopenharmony_ci        _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
405b877906bSopenharmony_ci            getProcAddressGLX("glXCreateContextAttribsARB");
406b877906bSopenharmony_ci
407b877906bSopenharmony_ci        if (_glfw.glx.CreateContextAttribsARB)
408b877906bSopenharmony_ci            _glfw.glx.ARB_create_context = GLFW_TRUE;
409b877906bSopenharmony_ci    }
410b877906bSopenharmony_ci
411b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
412b877906bSopenharmony_ci        _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
413b877906bSopenharmony_ci
414b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
415b877906bSopenharmony_ci        _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
416b877906bSopenharmony_ci
417b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
418b877906bSopenharmony_ci        _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
419b877906bSopenharmony_ci
420b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
421b877906bSopenharmony_ci        _glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
422b877906bSopenharmony_ci
423b877906bSopenharmony_ci    if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
424b877906bSopenharmony_ci        _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
425b877906bSopenharmony_ci
426b877906bSopenharmony_ci    return GLFW_TRUE;
427b877906bSopenharmony_ci}
428b877906bSopenharmony_ci
429b877906bSopenharmony_ci// Terminate GLX
430b877906bSopenharmony_ci//
431b877906bSopenharmony_civoid _glfwTerminateGLX(void)
432b877906bSopenharmony_ci{
433b877906bSopenharmony_ci    // NOTE: This function must not call any X11 functions, as it is called
434b877906bSopenharmony_ci    //       after XCloseDisplay (see _glfwTerminateX11 for details)
435b877906bSopenharmony_ci
436b877906bSopenharmony_ci    if (_glfw.glx.handle)
437b877906bSopenharmony_ci    {
438b877906bSopenharmony_ci        _glfwPlatformFreeModule(_glfw.glx.handle);
439b877906bSopenharmony_ci        _glfw.glx.handle = NULL;
440b877906bSopenharmony_ci    }
441b877906bSopenharmony_ci}
442b877906bSopenharmony_ci
443b877906bSopenharmony_ci#define SET_ATTRIB(a, v) \
444b877906bSopenharmony_ci{ \
445b877906bSopenharmony_ci    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
446b877906bSopenharmony_ci    attribs[index++] = a; \
447b877906bSopenharmony_ci    attribs[index++] = v; \
448b877906bSopenharmony_ci}
449b877906bSopenharmony_ci
450b877906bSopenharmony_ci// Create the OpenGL or OpenGL ES context
451b877906bSopenharmony_ci//
452b877906bSopenharmony_ciGLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
453b877906bSopenharmony_ci                               const _GLFWctxconfig* ctxconfig,
454b877906bSopenharmony_ci                               const _GLFWfbconfig* fbconfig)
455b877906bSopenharmony_ci{
456b877906bSopenharmony_ci    int attribs[40];
457b877906bSopenharmony_ci    GLXFBConfig native = NULL;
458b877906bSopenharmony_ci    GLXContext share = NULL;
459b877906bSopenharmony_ci
460b877906bSopenharmony_ci    if (ctxconfig->share)
461b877906bSopenharmony_ci        share = ctxconfig->share->context.glx.handle;
462b877906bSopenharmony_ci
463b877906bSopenharmony_ci    if (!chooseGLXFBConfig(fbconfig, &native))
464b877906bSopenharmony_ci    {
465b877906bSopenharmony_ci        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
466b877906bSopenharmony_ci                        "GLX: Failed to find a suitable GLXFBConfig");
467b877906bSopenharmony_ci        return GLFW_FALSE;
468b877906bSopenharmony_ci    }
469b877906bSopenharmony_ci
470b877906bSopenharmony_ci    if (ctxconfig->client == GLFW_OPENGL_ES_API)
471b877906bSopenharmony_ci    {
472b877906bSopenharmony_ci        if (!_glfw.glx.ARB_create_context ||
473b877906bSopenharmony_ci            !_glfw.glx.ARB_create_context_profile ||
474b877906bSopenharmony_ci            !_glfw.glx.EXT_create_context_es2_profile)
475b877906bSopenharmony_ci        {
476b877906bSopenharmony_ci            _glfwInputError(GLFW_API_UNAVAILABLE,
477b877906bSopenharmony_ci                            "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");
478b877906bSopenharmony_ci            return GLFW_FALSE;
479b877906bSopenharmony_ci        }
480b877906bSopenharmony_ci    }
481b877906bSopenharmony_ci
482b877906bSopenharmony_ci    if (ctxconfig->forward)
483b877906bSopenharmony_ci    {
484b877906bSopenharmony_ci        if (!_glfw.glx.ARB_create_context)
485b877906bSopenharmony_ci        {
486b877906bSopenharmony_ci            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
487b877906bSopenharmony_ci                            "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
488b877906bSopenharmony_ci            return GLFW_FALSE;
489b877906bSopenharmony_ci        }
490b877906bSopenharmony_ci    }
491b877906bSopenharmony_ci
492b877906bSopenharmony_ci    if (ctxconfig->profile)
493b877906bSopenharmony_ci    {
494b877906bSopenharmony_ci        if (!_glfw.glx.ARB_create_context ||
495b877906bSopenharmony_ci            !_glfw.glx.ARB_create_context_profile)
496b877906bSopenharmony_ci        {
497b877906bSopenharmony_ci            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
498b877906bSopenharmony_ci                            "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
499b877906bSopenharmony_ci            return GLFW_FALSE;
500b877906bSopenharmony_ci        }
501b877906bSopenharmony_ci    }
502b877906bSopenharmony_ci
503b877906bSopenharmony_ci    _glfwGrabErrorHandlerX11();
504b877906bSopenharmony_ci
505b877906bSopenharmony_ci    if (_glfw.glx.ARB_create_context)
506b877906bSopenharmony_ci    {
507b877906bSopenharmony_ci        int index = 0, mask = 0, flags = 0;
508b877906bSopenharmony_ci
509b877906bSopenharmony_ci        if (ctxconfig->client == GLFW_OPENGL_API)
510b877906bSopenharmony_ci        {
511b877906bSopenharmony_ci            if (ctxconfig->forward)
512b877906bSopenharmony_ci                flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
513b877906bSopenharmony_ci
514b877906bSopenharmony_ci            if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
515b877906bSopenharmony_ci                mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
516b877906bSopenharmony_ci            else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
517b877906bSopenharmony_ci                mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
518b877906bSopenharmony_ci        }
519b877906bSopenharmony_ci        else
520b877906bSopenharmony_ci            mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
521b877906bSopenharmony_ci
522b877906bSopenharmony_ci        if (ctxconfig->debug)
523b877906bSopenharmony_ci            flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
524b877906bSopenharmony_ci
525b877906bSopenharmony_ci        if (ctxconfig->robustness)
526b877906bSopenharmony_ci        {
527b877906bSopenharmony_ci            if (_glfw.glx.ARB_create_context_robustness)
528b877906bSopenharmony_ci            {
529b877906bSopenharmony_ci                if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
530b877906bSopenharmony_ci                {
531b877906bSopenharmony_ci                    SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
532b877906bSopenharmony_ci                               GLX_NO_RESET_NOTIFICATION_ARB);
533b877906bSopenharmony_ci                }
534b877906bSopenharmony_ci                else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
535b877906bSopenharmony_ci                {
536b877906bSopenharmony_ci                    SET_ATTRIB(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
537b877906bSopenharmony_ci                               GLX_LOSE_CONTEXT_ON_RESET_ARB);
538b877906bSopenharmony_ci                }
539b877906bSopenharmony_ci
540b877906bSopenharmony_ci                flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
541b877906bSopenharmony_ci            }
542b877906bSopenharmony_ci        }
543b877906bSopenharmony_ci
544b877906bSopenharmony_ci        if (ctxconfig->release)
545b877906bSopenharmony_ci        {
546b877906bSopenharmony_ci            if (_glfw.glx.ARB_context_flush_control)
547b877906bSopenharmony_ci            {
548b877906bSopenharmony_ci                if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
549b877906bSopenharmony_ci                {
550b877906bSopenharmony_ci                    SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
551b877906bSopenharmony_ci                               GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
552b877906bSopenharmony_ci                }
553b877906bSopenharmony_ci                else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
554b877906bSopenharmony_ci                {
555b877906bSopenharmony_ci                    SET_ATTRIB(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
556b877906bSopenharmony_ci                               GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
557b877906bSopenharmony_ci                }
558b877906bSopenharmony_ci            }
559b877906bSopenharmony_ci        }
560b877906bSopenharmony_ci
561b877906bSopenharmony_ci        if (ctxconfig->noerror)
562b877906bSopenharmony_ci        {
563b877906bSopenharmony_ci            if (_glfw.glx.ARB_create_context_no_error)
564b877906bSopenharmony_ci                SET_ATTRIB(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
565b877906bSopenharmony_ci        }
566b877906bSopenharmony_ci
567b877906bSopenharmony_ci        // NOTE: Only request an explicitly versioned context when necessary, as
568b877906bSopenharmony_ci        //       explicitly requesting version 1.0 does not always return the
569b877906bSopenharmony_ci        //       highest version supported by the driver
570b877906bSopenharmony_ci        if (ctxconfig->major != 1 || ctxconfig->minor != 0)
571b877906bSopenharmony_ci        {
572b877906bSopenharmony_ci            SET_ATTRIB(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
573b877906bSopenharmony_ci            SET_ATTRIB(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
574b877906bSopenharmony_ci        }
575b877906bSopenharmony_ci
576b877906bSopenharmony_ci        if (mask)
577b877906bSopenharmony_ci            SET_ATTRIB(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
578b877906bSopenharmony_ci
579b877906bSopenharmony_ci        if (flags)
580b877906bSopenharmony_ci            SET_ATTRIB(GLX_CONTEXT_FLAGS_ARB, flags);
581b877906bSopenharmony_ci
582b877906bSopenharmony_ci        SET_ATTRIB(None, None);
583b877906bSopenharmony_ci
584b877906bSopenharmony_ci        window->context.glx.handle =
585b877906bSopenharmony_ci            _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
586b877906bSopenharmony_ci                                              native,
587b877906bSopenharmony_ci                                              share,
588b877906bSopenharmony_ci                                              True,
589b877906bSopenharmony_ci                                              attribs);
590b877906bSopenharmony_ci
591b877906bSopenharmony_ci        // HACK: This is a fallback for broken versions of the Mesa
592b877906bSopenharmony_ci        //       implementation of GLX_ARB_create_context_profile that fail
593b877906bSopenharmony_ci        //       default 1.0 context creation with a GLXBadProfileARB error in
594b877906bSopenharmony_ci        //       violation of the extension spec
595b877906bSopenharmony_ci        if (!window->context.glx.handle)
596b877906bSopenharmony_ci        {
597b877906bSopenharmony_ci            if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
598b877906bSopenharmony_ci                ctxconfig->client == GLFW_OPENGL_API &&
599b877906bSopenharmony_ci                ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
600b877906bSopenharmony_ci                ctxconfig->forward == GLFW_FALSE)
601b877906bSopenharmony_ci            {
602b877906bSopenharmony_ci                window->context.glx.handle =
603b877906bSopenharmony_ci                    createLegacyContextGLX(window, native, share);
604b877906bSopenharmony_ci            }
605b877906bSopenharmony_ci        }
606b877906bSopenharmony_ci    }
607b877906bSopenharmony_ci    else
608b877906bSopenharmony_ci    {
609b877906bSopenharmony_ci        window->context.glx.handle =
610b877906bSopenharmony_ci            createLegacyContextGLX(window, native, share);
611b877906bSopenharmony_ci    }
612b877906bSopenharmony_ci
613b877906bSopenharmony_ci    _glfwReleaseErrorHandlerX11();
614b877906bSopenharmony_ci
615b877906bSopenharmony_ci    if (!window->context.glx.handle)
616b877906bSopenharmony_ci    {
617b877906bSopenharmony_ci        _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
618b877906bSopenharmony_ci        return GLFW_FALSE;
619b877906bSopenharmony_ci    }
620b877906bSopenharmony_ci
621b877906bSopenharmony_ci    window->context.glx.window =
622b877906bSopenharmony_ci        glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
623b877906bSopenharmony_ci    if (!window->context.glx.window)
624b877906bSopenharmony_ci    {
625b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
626b877906bSopenharmony_ci        return GLFW_FALSE;
627b877906bSopenharmony_ci    }
628b877906bSopenharmony_ci
629b877906bSopenharmony_ci    window->context.makeCurrent = makeContextCurrentGLX;
630b877906bSopenharmony_ci    window->context.swapBuffers = swapBuffersGLX;
631b877906bSopenharmony_ci    window->context.swapInterval = swapIntervalGLX;
632b877906bSopenharmony_ci    window->context.extensionSupported = extensionSupportedGLX;
633b877906bSopenharmony_ci    window->context.getProcAddress = getProcAddressGLX;
634b877906bSopenharmony_ci    window->context.destroy = destroyContextGLX;
635b877906bSopenharmony_ci
636b877906bSopenharmony_ci    return GLFW_TRUE;
637b877906bSopenharmony_ci}
638b877906bSopenharmony_ci
639b877906bSopenharmony_ci#undef SET_ATTRIB
640b877906bSopenharmony_ci
641b877906bSopenharmony_ci// Returns the Visual and depth of the chosen GLXFBConfig
642b877906bSopenharmony_ci//
643b877906bSopenharmony_ciGLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
644b877906bSopenharmony_ci                              const _GLFWctxconfig* ctxconfig,
645b877906bSopenharmony_ci                              const _GLFWfbconfig* fbconfig,
646b877906bSopenharmony_ci                              Visual** visual, int* depth)
647b877906bSopenharmony_ci{
648b877906bSopenharmony_ci    GLXFBConfig native;
649b877906bSopenharmony_ci    XVisualInfo* result;
650b877906bSopenharmony_ci
651b877906bSopenharmony_ci    if (!chooseGLXFBConfig(fbconfig, &native))
652b877906bSopenharmony_ci    {
653b877906bSopenharmony_ci        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
654b877906bSopenharmony_ci                        "GLX: Failed to find a suitable GLXFBConfig");
655b877906bSopenharmony_ci        return GLFW_FALSE;
656b877906bSopenharmony_ci    }
657b877906bSopenharmony_ci
658b877906bSopenharmony_ci    result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
659b877906bSopenharmony_ci    if (!result)
660b877906bSopenharmony_ci    {
661b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_ERROR,
662b877906bSopenharmony_ci                        "GLX: Failed to retrieve Visual for GLXFBConfig");
663b877906bSopenharmony_ci        return GLFW_FALSE;
664b877906bSopenharmony_ci    }
665b877906bSopenharmony_ci
666b877906bSopenharmony_ci    *visual = result->visual;
667b877906bSopenharmony_ci    *depth  = result->depth;
668b877906bSopenharmony_ci
669b877906bSopenharmony_ci    XFree(result);
670b877906bSopenharmony_ci    return GLFW_TRUE;
671b877906bSopenharmony_ci}
672b877906bSopenharmony_ci
673b877906bSopenharmony_ci
674b877906bSopenharmony_ci//////////////////////////////////////////////////////////////////////////
675b877906bSopenharmony_ci//////                        GLFW native API                       //////
676b877906bSopenharmony_ci//////////////////////////////////////////////////////////////////////////
677b877906bSopenharmony_ci
678b877906bSopenharmony_ciGLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
679b877906bSopenharmony_ci{
680b877906bSopenharmony_ci    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
681b877906bSopenharmony_ci
682b877906bSopenharmony_ci    if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
683b877906bSopenharmony_ci    {
684b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "GLX: Platform not initialized");
685b877906bSopenharmony_ci        return NULL;
686b877906bSopenharmony_ci    }
687b877906bSopenharmony_ci
688b877906bSopenharmony_ci    _GLFWwindow* window = (_GLFWwindow*) handle;
689b877906bSopenharmony_ci    assert(window != NULL);
690b877906bSopenharmony_ci
691b877906bSopenharmony_ci    if (window->context.source != GLFW_NATIVE_CONTEXT_API)
692b877906bSopenharmony_ci    {
693b877906bSopenharmony_ci        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
694b877906bSopenharmony_ci        return NULL;
695b877906bSopenharmony_ci    }
696b877906bSopenharmony_ci
697b877906bSopenharmony_ci    return window->context.glx.handle;
698b877906bSopenharmony_ci}
699b877906bSopenharmony_ci
700b877906bSopenharmony_ciGLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)
701b877906bSopenharmony_ci{
702b877906bSopenharmony_ci    _GLFW_REQUIRE_INIT_OR_RETURN(None);
703b877906bSopenharmony_ci
704b877906bSopenharmony_ci    if (_glfw.platform.platformID != GLFW_PLATFORM_X11)
705b877906bSopenharmony_ci    {
706b877906bSopenharmony_ci        _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "GLX: Platform not initialized");
707b877906bSopenharmony_ci        return None;
708b877906bSopenharmony_ci    }
709b877906bSopenharmony_ci
710b877906bSopenharmony_ci    _GLFWwindow* window = (_GLFWwindow*) handle;
711b877906bSopenharmony_ci    assert(window != NULL);
712b877906bSopenharmony_ci
713b877906bSopenharmony_ci    if (window->context.source != GLFW_NATIVE_CONTEXT_API)
714b877906bSopenharmony_ci    {
715b877906bSopenharmony_ci        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
716b877906bSopenharmony_ci        return None;
717b877906bSopenharmony_ci    }
718b877906bSopenharmony_ci
719b877906bSopenharmony_ci    return window->context.glx.window;
720b877906bSopenharmony_ci}
721b877906bSopenharmony_ci
722b877906bSopenharmony_ci#endif // _GLFW_X11
723b877906bSopenharmony_ci
724