X11: Further reduce startup time

Use the GLX 1.3 API function to choose the best framebuffer config
instead of doing it ourselves. Reduces the number fo getpid() calls by
a further ~15K
This commit is contained in:
Kovid Goyal 2020-06-09 20:18:07 +05:30
parent 5c7471910d
commit 9a97f0bced
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 48 additions and 65 deletions

110
glfw/glx_context.c vendored
View File

@ -47,21 +47,46 @@ static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
return value; return value;
} }
static GLXFBConfig*
choose_fb_config(const _GLFWfbconfig* desired, bool trust_window_bit, int *nelements) {
int attrib_list[64];
int pos = 0;
#define ATTR(x, y) { attrib_list[pos++] = x; attrib_list[pos++] = y; }
ATTR(GLX_DOUBLEBUFFER, desired->doublebuffer ? True : False);
if (desired->stereo > 0) ATTR(GLX_STEREO, desired->stereo ? True : False);
if (desired->auxBuffers > 0) ATTR(GLX_AUX_BUFFERS, desired->auxBuffers);
if (_glfw.glx.ARB_multisample && desired->samples > 0) ATTR(GLX_SAMPLES, desired->samples);
if (desired->depthBits != GLFW_DONT_CARE) ATTR(GLX_DEPTH_SIZE, desired->depthBits);
if (desired->stencilBits != GLFW_DONT_CARE) ATTR(GLX_STENCIL_SIZE, desired->stencilBits);
if (desired->redBits != GLFW_DONT_CARE) ATTR(GLX_RED_SIZE, desired->redBits);
if (desired->greenBits != GLFW_DONT_CARE) ATTR(GLX_GREEN_SIZE, desired->greenBits);
if (desired->blueBits != GLFW_DONT_CARE) ATTR(GLX_BLUE_SIZE, desired->blueBits);
if (desired->alphaBits != GLFW_DONT_CARE) ATTR(GLX_ALPHA_SIZE, desired->alphaBits);
if (desired->accumRedBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_RED_SIZE, desired->accumRedBits);
if (desired->accumGreenBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_GREEN_SIZE, desired->accumGreenBits);
if (desired->accumBlueBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_BLUE_SIZE, desired->accumBlueBits);
if (desired->accumAlphaBits != GLFW_DONT_CARE) ATTR(GLX_ACCUM_ALPHA_SIZE, desired->accumAlphaBits);
if (!trust_window_bit) ATTR(GLX_DRAWABLE_TYPE, 0);
ATTR(None, None);
return glXChooseFBConfig(_glfw.x11.display, _glfw.x11.screen, attrib_list, nelements);
#undef ATTR
}
// Return the GLXFBConfig most closely matching the specified hints // Return the GLXFBConfig most closely matching the specified hints
// //
static bool chooseGLXFBConfig(const _GLFWfbconfig* desired, static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
GLXFBConfig* result) GLXFBConfig* result)
{ {
GLXFBConfig* nativeConfigs; GLXFBConfig* nativeConfigs;
_GLFWfbconfig* usableConfigs; int i, nativeCount, ans_idx = 0;
const _GLFWfbconfig* closest;
int i, nativeCount, usableCount;
const char* vendor; const char* vendor;
bool trustWindowBit = true; bool trustWindowBit = true;
static _GLFWfbconfig prev_desired = {0}; static _GLFWfbconfig prev_desired = {0};
static uintptr_t prev_result = 0; static GLXFBConfig prev_result = 0;
if (prev_result != 0 && memcmp(&prev_desired, desired, sizeof(_GLFWfbconfig)) == 0) { if (prev_result != 0 && memcmp(&prev_desired, desired, sizeof(_GLFWfbconfig)) == 0) {
*result = (GLXFBConfig)prev_result; *result = prev_result;
return true; return true;
} }
prev_desired = *desired; prev_desired = *desired;
@ -71,84 +96,38 @@ static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR);
if (vendor && strcmp(vendor, "Chromium") == 0) if (vendor && strcmp(vendor, "Chromium") == 0)
trustWindowBit = false; trustWindowBit = false;
nativeConfigs = choose_fb_config(desired, trustWindowBit, &nativeCount);
nativeConfigs =
glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
if (!nativeConfigs || !nativeCount) if (!nativeConfigs || !nativeCount)
{ {
_glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned"); _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
return false; return false;
} }
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0;
for (i = 0; i < nativeCount; i++) for (i = 0; i < nativeCount; i++)
{ {
const GLXFBConfig n = nativeConfigs[i]; const GLXFBConfig n = nativeConfigs[i];
_GLFWfbconfig* u = usableConfigs + usableCount; bool transparency_matches = true, srgb_matches = true;
if (desired->transparent) {
// Only consider RGBA GLXFBConfigs transparency_matches = false;
if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
continue;
// Only consider window GLXFBConfigs
if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
{
if (trustWindowBit)
continue;
}
if (desired->transparent)
{
XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n); XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
if (vi) if (vi && _glfwIsVisualTransparentX11(vi->visual)) transparency_matches = true;
{
u->transparent = _glfwIsVisualTransparentX11(vi->visual);
XFree(vi);
}
} }
u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE); if (desired->sRGB && (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)) {
u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE); srgb_matches = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB) ? true : false;
u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE); }
u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE); if (transparency_matches && srgb_matches) {
u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE); ans_idx = i; break;
u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE); }
u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);
u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);
u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);
u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);
u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
if (getGLXFBConfigAttrib(n, GLX_STEREO))
u->stereo = true;
if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))
u->doublebuffer = true;
if (_glfw.glx.ARB_multisample)
u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES);
if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
u->handle = (uintptr_t) n;
usableCount++;
} }
closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); *result = nativeConfigs[ans_idx];
if (closest) { prev_result = nativeConfigs[ans_idx];
*result = (GLXFBConfig) closest->handle;
prev_result = (uintptr_t) closest->handle;
}
XFree(nativeConfigs); XFree(nativeConfigs);
free(usableConfigs);
return closest != NULL; return true;
} }
// Create the OpenGL context using legacy API // Create the OpenGL context using legacy API
@ -296,6 +275,7 @@ bool _glfwInitGLX(void)
glfw_dlsym(_glfw.glx.GetFBConfigs, _glfw.glx.handle, "glXGetFBConfigs"); glfw_dlsym(_glfw.glx.GetFBConfigs, _glfw.glx.handle, "glXGetFBConfigs");
glfw_dlsym(_glfw.glx.GetFBConfigAttrib, _glfw.glx.handle, "glXGetFBConfigAttrib"); glfw_dlsym(_glfw.glx.GetFBConfigAttrib, _glfw.glx.handle, "glXGetFBConfigAttrib");
glfw_dlsym(_glfw.glx.ChooseFBConfig, _glfw.glx.handle, "glXChooseFBConfig");
glfw_dlsym(_glfw.glx.GetClientString, _glfw.glx.handle, "glXGetClientString"); glfw_dlsym(_glfw.glx.GetClientString, _glfw.glx.handle, "glXGetClientString");
glfw_dlsym(_glfw.glx.QueryExtension, _glfw.glx.handle, "glXQueryExtension"); glfw_dlsym(_glfw.glx.QueryExtension, _glfw.glx.handle, "glXQueryExtension");
glfw_dlsym(_glfw.glx.QueryVersion, _glfw.glx.handle, "glXQueryVersion"); glfw_dlsym(_glfw.glx.QueryVersion, _glfw.glx.handle, "glXQueryVersion");

3
glfw/glx_context.h vendored
View File

@ -73,6 +73,7 @@ typedef struct __GLXcontext* GLXContext;
typedef void (*__GLXextproc)(void); typedef void (*__GLXextproc)(void);
typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*); typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);
typedef GLXFBConfig* (*PFNGLXCHOOSEFBCONFIGPROC)(Display*,int,const int*,int*);
typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int); typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);
typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*); typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);
typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*); typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);
@ -95,6 +96,7 @@ typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLX
// libGL.so function pointer typedefs // libGL.so function pointer typedefs
#define glXGetFBConfigs _glfw.glx.GetFBConfigs #define glXGetFBConfigs _glfw.glx.GetFBConfigs
#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib #define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib
#define glXChooseFBConfig _glfw.glx.ChooseFBConfig
#define glXGetClientString _glfw.glx.GetClientString #define glXGetClientString _glfw.glx.GetClientString
#define glXQueryExtension _glfw.glx.QueryExtension #define glXQueryExtension _glfw.glx.QueryExtension
#define glXQueryVersion _glfw.glx.QueryVersion #define glXQueryVersion _glfw.glx.QueryVersion
@ -134,6 +136,7 @@ typedef struct _GLFWlibraryGLX
// GLX 1.3 functions // GLX 1.3 functions
PFNGLXGETFBCONFIGSPROC GetFBConfigs; PFNGLXGETFBCONFIGSPROC GetFBConfigs;
PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib; PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;
PFNGLXCHOOSEFBCONFIGPROC ChooseFBConfig;
PFNGLXGETCLIENTSTRINGPROC GetClientString; PFNGLXGETCLIENTSTRINGPROC GetClientString;
PFNGLXQUERYEXTENSIONPROC QueryExtension; PFNGLXQUERYEXTENSIONPROC QueryExtension;
PFNGLXQUERYVERSIONPROC QueryVersion; PFNGLXQUERYVERSIONPROC QueryVersion;