From 8a178ebe55507112c834ac3d7edb4626c9a8cfc1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 9 Jun 2020 21:59:25 +0530 Subject: [PATCH] Wayland: Apply the same framebuffer selection optimisation Not as much of a win, since EGL only causes approx 1K getpid() calls of which this optimization eliminates only half --- glfw/context.c | 168 --------------------------------------------- glfw/egl_context.c | 98 ++++++++++---------------- glfw/egl_context.h | 3 + glfw/internal.h | 3 - 4 files changed, 38 insertions(+), 234 deletions(-) diff --git a/glfw/context.c b/glfw/context.c index dec0b141d..b2d9199af 100644 --- a/glfw/context.c +++ b/glfw/context.c @@ -173,174 +173,6 @@ bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) return true; } -// Chooses the framebuffer config that best matches the desired one -// -const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, - const _GLFWfbconfig* alternatives, - unsigned int count) -{ - unsigned int i; - unsigned int missing, leastMissing = UINT_MAX; - unsigned int colorDiff, leastColorDiff = UINT_MAX; - unsigned int extraDiff, leastExtraDiff = UINT_MAX; - const _GLFWfbconfig* current; - const _GLFWfbconfig* closest = NULL; - - for (i = 0; i < count; i++) - { - current = alternatives + i; - - if (desired->stereo > 0 && current->stereo == 0) - { - // Stereo is a hard constraint - continue; - } - - if (desired->doublebuffer != current->doublebuffer) - { - // Double buffering is a hard constraint - continue; - } - - // Count number of missing buffers - { - missing = 0; - - if (desired->alphaBits > 0 && current->alphaBits == 0) - missing++; - - if (desired->depthBits > 0 && current->depthBits == 0) - missing++; - - if (desired->stencilBits > 0 && current->stencilBits == 0) - missing++; - - if (desired->auxBuffers > 0 && - current->auxBuffers < desired->auxBuffers) - { - missing += desired->auxBuffers - current->auxBuffers; - } - - if (desired->samples > 0 && current->samples == 0) - { - // Technically, several multisampling buffers could be - // involved, but that's a lower level implementation detail and - // not important to us here, so we count them as one - missing++; - } - - if (desired->transparent != current->transparent) - missing++; - } - - // These polynomials make many small channel size differences matter - // less than one large channel size difference - - // Calculate color channel size difference value - { - colorDiff = 0; - - if (desired->redBits != GLFW_DONT_CARE) - { - colorDiff += (desired->redBits - current->redBits) * - (desired->redBits - current->redBits); - } - - if (desired->greenBits != GLFW_DONT_CARE) - { - colorDiff += (desired->greenBits - current->greenBits) * - (desired->greenBits - current->greenBits); - } - - if (desired->blueBits != GLFW_DONT_CARE) - { - colorDiff += (desired->blueBits - current->blueBits) * - (desired->blueBits - current->blueBits); - } - } - - // Calculate non-color channel size difference value - { - extraDiff = 0; - - if (desired->alphaBits != GLFW_DONT_CARE) - { - extraDiff += (desired->alphaBits - current->alphaBits) * - (desired->alphaBits - current->alphaBits); - } - - if (desired->depthBits != GLFW_DONT_CARE) - { - extraDiff += (desired->depthBits - current->depthBits) * - (desired->depthBits - current->depthBits); - } - - if (desired->stencilBits != GLFW_DONT_CARE) - { - extraDiff += (desired->stencilBits - current->stencilBits) * - (desired->stencilBits - current->stencilBits); - } - - if (desired->accumRedBits != GLFW_DONT_CARE) - { - extraDiff += (desired->accumRedBits - current->accumRedBits) * - (desired->accumRedBits - current->accumRedBits); - } - - if (desired->accumGreenBits != GLFW_DONT_CARE) - { - extraDiff += (desired->accumGreenBits - current->accumGreenBits) * - (desired->accumGreenBits - current->accumGreenBits); - } - - if (desired->accumBlueBits != GLFW_DONT_CARE) - { - extraDiff += (desired->accumBlueBits - current->accumBlueBits) * - (desired->accumBlueBits - current->accumBlueBits); - } - - if (desired->accumAlphaBits != GLFW_DONT_CARE) - { - extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) * - (desired->accumAlphaBits - current->accumAlphaBits); - } - - if (desired->samples != GLFW_DONT_CARE) - { - extraDiff += (desired->samples - current->samples) * - (desired->samples - current->samples); - } - - if (desired->sRGB && !current->sRGB) - extraDiff++; - } - - // Figure out if the current one is better than the best one found so far - // Least number of missing buffers is the most important heuristic, - // then color buffer size match and lastly size match for other buffers - - if (missing < leastMissing) - closest = current; - else if (missing == leastMissing) - { - if ((colorDiff < leastColorDiff) || - (colorDiff == leastColorDiff && extraDiff < leastExtraDiff)) - { - closest = current; - } - } - - if (current == closest) - { - leastMissing = missing; - leastColorDiff = colorDiff; - leastExtraDiff = extraDiff; - } - } - - return closest; -} - // Retrieves the attributes of the current context // bool _glfwRefreshContextAttribs(_GLFWwindow* window, diff --git a/glfw/egl_context.c b/glfw/egl_context.c index 39786760a..82333db5c 100644 --- a/glfw/egl_context.c +++ b/glfw/egl_context.c @@ -76,6 +76,7 @@ static const char* getEGLErrorString(EGLint error) } } +#ifdef _GLFW_X11 // Returns the specified attribute of the specified EGLConfig // static int getEGLConfigAttrib(EGLConfig config, int attrib) @@ -84,6 +85,7 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib) eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value); return value; } +#endif // Return the EGLConfig most closely matching the specified hints // @@ -91,39 +93,44 @@ static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* desired, EGLConfig* result) { - EGLConfig* nativeConfigs; - _GLFWfbconfig* usableConfigs; - const _GLFWfbconfig* closest; - int i, nativeCount, usableCount; + EGLConfig configs[512]; + int i = 0, nativeCount = 0, ans_idx = 0; + EGLint attributes[64]; +#define ATTR(k, v) { attributes[i++] = k; attributes[i++] = v; } + ATTR(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); + ATTR(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + if (ctxconfig->client == GLFW_OPENGL_ES_API) { + if (ctxconfig->major == 1) ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT) + else ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT); + } + else if (ctxconfig->client == GLFW_OPENGL_API) ATTR(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT); + if (desired->samples > 0) ATTR(EGL_SAMPLES, desired->samples); + if (desired->depthBits > 0) ATTR(EGL_DEPTH_SIZE, desired->depthBits); + if (desired->stencilBits > 0) ATTR(EGL_STENCIL_SIZE, desired->stencilBits); + if (desired->redBits > 0) ATTR(EGL_RED_SIZE, desired->redBits); + if (desired->greenBits > 0) ATTR(EGL_GREEN_SIZE, desired->greenBits); + if (desired->blueBits > 0) ATTR(EGL_BLUE_SIZE, desired->blueBits); + if (desired->alphaBits > 0) ATTR(EGL_ALPHA_SIZE, desired->alphaBits); + ATTR(EGL_NONE, EGL_NONE); +#undef ATTR + if (!eglChooseConfig(_glfw.egl.display, attributes, configs, sizeof(configs)/sizeof(configs[0]), &nativeCount)) { + _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: eglChooseConfig failed"); + return false; + } - eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); if (!nativeCount) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned"); return false; } - nativeConfigs = calloc(nativeCount, sizeof(EGLConfig)); - eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); - - usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); - usableCount = 0; for (i = 0; i < nativeCount; i++) { - const EGLConfig n = nativeConfigs[i]; - _GLFWfbconfig* u = usableConfigs + usableCount; - - // Only consider RGB(A) EGLConfigs - if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) - continue; - - // Only consider window EGLConfigs - if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) - continue; #if defined(_GLFW_X11) { + const EGLConfig n = configs[i]; XVisualInfo vi = {0}; // Only consider EGLConfigs with associated Visuals @@ -138,55 +145,18 @@ static bool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count); if (vis) { - u->transparent = _glfwIsVisualTransparentX11(vis[0].visual); + bool transparent = _glfwIsVisualTransparentX11(vis[0].visual); XFree(vis); + if (!transparent) continue; } } } #endif // _GLFW_X11 - - if (ctxconfig->client == GLFW_OPENGL_ES_API) - { - if (ctxconfig->major == 1) - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) - continue; - } - else - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) - continue; - } - } - else if (ctxconfig->client == GLFW_OPENGL_API) - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) - continue; - } - - u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE); - u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE); - u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE); - - u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE); - u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE); - u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); - - u->samples = getEGLConfigAttrib(n, EGL_SAMPLES); - u->doublebuffer = true; - - u->handle = (uintptr_t) n; - usableCount++; + ans_idx = i; + break; } - - closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); - if (closest) - *result = (EGLConfig) closest->handle; - - free(nativeConfigs); - free(usableConfigs); - - return closest != NULL; + *result = configs[ans_idx]; + return true; } static void makeContextCurrentEGL(_GLFWwindow* window) @@ -340,6 +310,7 @@ bool _glfwInitEGL(void) glfw_dlsym(_glfw.egl.GetConfigAttrib, _glfw.egl.handle, "eglGetConfigAttrib"); glfw_dlsym(_glfw.egl.GetConfigs, _glfw.egl.handle, "eglGetConfigs"); + glfw_dlsym(_glfw.egl.ChooseConfig, _glfw.egl.handle, "eglChooseConfig"); glfw_dlsym(_glfw.egl.GetDisplay, _glfw.egl.handle, "eglGetDisplay"); glfw_dlsym(_glfw.egl.GetError, _glfw.egl.handle, "eglGetError"); glfw_dlsym(_glfw.egl.Initialize, _glfw.egl.handle, "eglInitialize"); @@ -357,6 +328,7 @@ bool _glfwInitEGL(void) if (!_glfw.egl.GetConfigAttrib || !_glfw.egl.GetConfigs || + !_glfw.egl.ChooseConfig || !_glfw.egl.GetDisplay || !_glfw.egl.GetError || !_glfw.egl.Initialize || diff --git a/glfw/egl_context.h b/glfw/egl_context.h index baae5d160..362de2fe0 100644 --- a/glfw/egl_context.h +++ b/glfw/egl_context.h @@ -120,6 +120,7 @@ typedef void* EGLSurface; // EGL function pointer typedefs typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*); typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*); +typedef EGLBoolean (EGLAPIENTRY * PFN_eglChooseConfig)(EGLDisplay,EGLint const*,EGLConfig*,EGLint,EGLint*); typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType); typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void); typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*); @@ -136,6 +137,7 @@ typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint); typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(const char*); #define eglGetConfigAttrib _glfw.egl.GetConfigAttrib #define eglGetConfigs _glfw.egl.GetConfigs +#define eglChooseConfig _glfw.egl.ChooseConfig #define eglGetDisplay _glfw.egl.GetDisplay #define eglGetError _glfw.egl.GetError #define eglInitialize _glfw.egl.Initialize @@ -185,6 +187,7 @@ typedef struct _GLFWlibraryEGL PFN_eglGetConfigAttrib GetConfigAttrib; PFN_eglGetConfigs GetConfigs; + PFN_eglChooseConfig ChooseConfig; PFN_eglGetDisplay GetDisplay; PFN_eglGetError GetError; PFN_eglInitialize Initialize; diff --git a/glfw/internal.h b/glfw/internal.h index 98d08fad1..b6ff86f62 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -794,9 +794,6 @@ void _glfwDebug(const char* format, ...); ////////////////////////////////////////////////////////////////////////// bool _glfwStringInExtensionString(const char* string, const char* extensions); -const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, - const _GLFWfbconfig* alternatives, - unsigned int count); bool _glfwRefreshContextAttribs(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig); bool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);