From ec7afd2c24c6afa6a5c80da4f80e0b799580e12a Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Mon, 22 Jul 2024 19:18:00 -0400 Subject: [PATCH] dril: rework config creation the original implementation of config selection had a number of flaws: * using eglChooseConfigs with lots of loops, which was okay for filtering but also added considerable complexity and made it difficult to correctly get all the configs * not adding enough configs; there were a lot more color and zs formats which weren't in the base config list * double buffer configs were never created * srgb configs were also never created there will now be fewer configs than there were pre-DRIL, but this is only because accum buffers are now gone and not because anything of value is missing Fixes: 3de62b2f9a6 ("gallium/dril: Compatibility stub for the legacy DRI loader interface") Acked-by: Daniel Stone Part-of: --- src/gallium/targets/dril/dril_target.c | 195 +++++++++++++++++-------- 1 file changed, 137 insertions(+), 58 deletions(-) diff --git a/src/gallium/targets/dril/dril_target.c b/src/gallium/targets/dril/dril_target.c index 3b854396c8d..98306c7665d 100644 --- a/src/gallium/targets/dril/dril_target.c +++ b/src/gallium/targets/dril/dril_target.c @@ -26,6 +26,7 @@ #include #include #include "gbm/main/gbm.h" +#include "drm-uapi/drm_fourcc.h" #define EGL_PLATFORM_GBM_MESA 0x31D7 @@ -33,33 +34,38 @@ #define GLX_NONE 0x8000 #define GLX_DONT_CARE 0xFFFFFFFF -#define CONFIG_DB(color, zs, doublebuffer) \ +#define CONFIG_ZS(color, zs) \ { \ .color_format = color, \ .zs_format = zs, \ - .doubleBufferMode = doublebuffer, \ } -#define CONFIG(color, zs) \ - CONFIG_DB(color, zs, GL_TRUE), \ - CONFIG_DB(color, zs, GL_FALSE) + +#define CONFIG(color) \ + CONFIG_ZS(color, PIPE_FORMAT_S8_UINT), \ + CONFIG_ZS(color, PIPE_FORMAT_Z24_UNORM_S8_UINT), \ + CONFIG_ZS(color, PIPE_FORMAT_Z24X8_UNORM), \ + CONFIG_ZS(color, PIPE_FORMAT_Z16_UNORM), \ + CONFIG_ZS(color, PIPE_FORMAT_NONE) \ static const struct gl_config drilConfigs[] = { - CONFIG(PIPE_FORMAT_R8G8B8A8_UNORM, PIPE_FORMAT_S8_UINT), - CONFIG(PIPE_FORMAT_R8G8B8A8_UNORM, PIPE_FORMAT_Z24_UNORM_S8_UINT), - CONFIG(PIPE_FORMAT_R8G8B8A8_UNORM, PIPE_FORMAT_NONE), - CONFIG(PIPE_FORMAT_R8G8B8X8_UNORM, PIPE_FORMAT_S8_UINT), - CONFIG(PIPE_FORMAT_R8G8B8X8_UNORM, PIPE_FORMAT_Z24_UNORM_S8_UINT), - CONFIG(PIPE_FORMAT_R8G8B8X8_UNORM, PIPE_FORMAT_NONE), - CONFIG(PIPE_FORMAT_R10G10B10A2_UNORM, PIPE_FORMAT_S8_UINT), - CONFIG(PIPE_FORMAT_R10G10B10A2_UNORM, PIPE_FORMAT_Z24_UNORM_S8_UINT), - CONFIG(PIPE_FORMAT_R10G10B10A2_UNORM, PIPE_FORMAT_NONE), - CONFIG(PIPE_FORMAT_R10G10B10X2_UNORM, PIPE_FORMAT_S8_UINT), - CONFIG(PIPE_FORMAT_R10G10B10X2_UNORM, PIPE_FORMAT_Z24_UNORM_S8_UINT), - CONFIG(PIPE_FORMAT_R10G10B10X2_UNORM, PIPE_FORMAT_NONE), - CONFIG(PIPE_FORMAT_R5G6B5_UNORM, PIPE_FORMAT_S8_UINT), - CONFIG(PIPE_FORMAT_R5G6B5_UNORM, PIPE_FORMAT_Z16_UNORM), - CONFIG(PIPE_FORMAT_R5G6B5_UNORM, PIPE_FORMAT_NONE), - // etc... + CONFIG(PIPE_FORMAT_R8G8B8A8_UNORM), + CONFIG(PIPE_FORMAT_R8G8B8X8_UNORM), + CONFIG(PIPE_FORMAT_B8G8R8A8_UNORM), + CONFIG(PIPE_FORMAT_B8G8R8X8_UNORM), + CONFIG(PIPE_FORMAT_R10G10B10A2_UNORM), + CONFIG(PIPE_FORMAT_R10G10B10X2_UNORM), + CONFIG(PIPE_FORMAT_B10G10R10A2_UNORM), + CONFIG(PIPE_FORMAT_B10G10R10X2_UNORM), + CONFIG(PIPE_FORMAT_R5G6B5_UNORM), + CONFIG(PIPE_FORMAT_R5G5B5A1_UNORM), + CONFIG(PIPE_FORMAT_R5G5B5X1_UNORM), + CONFIG(PIPE_FORMAT_R4G4B4A4_UNORM), + CONFIG(PIPE_FORMAT_R4G4B4X4_UNORM), + CONFIG(PIPE_FORMAT_B5G6R5_UNORM), + CONFIG(PIPE_FORMAT_B5G5R5A1_UNORM), + CONFIG(PIPE_FORMAT_B5G5R5X1_UNORM), + CONFIG(PIPE_FORMAT_B4G4R4A4_UNORM), + CONFIG(PIPE_FORMAT_B4G4R4X4_UNORM), }; #define RGB UTIL_FORMAT_COLORSPACE_RGB @@ -123,6 +129,7 @@ drilIndexConfigAttrib(const __DRIconfig *_config, int index, CASE(CONFORMANT, GL_TRUE); CASE(DOUBLE_BUFFER, config->doubleBufferMode); CASE(SAMPLES, config->samples); + CASE(FRAMEBUFFER_SRGB_CAPABLE, config->sRGBCapable); CASE(TRANSPARENT_TYPE, GLX_NONE); CASE(TRANSPARENT_INDEX_VALUE, GLX_NONE); @@ -272,14 +279,56 @@ drilCreateNewDrawable(__DRIscreen *psp, return NULL; } -#define NUM_SAMPLE_COUNTS 7 + +static enum pipe_format +fourcc_to_pipe_format(int fourcc) +{ + switch (fourcc) { + case DRM_FORMAT_RGB565: return PIPE_FORMAT_B5G6R5_UNORM; + case DRM_FORMAT_XRGB8888: return PIPE_FORMAT_BGRX8888_UNORM; + case DRM_FORMAT_ARGB8888: return PIPE_FORMAT_BGRA8888_UNORM; + case DRM_FORMAT_ABGR8888: return PIPE_FORMAT_RGBA8888_UNORM; + case DRM_FORMAT_XBGR8888: return PIPE_FORMAT_RGBX8888_UNORM; + case DRM_FORMAT_XRGB2101010: return PIPE_FORMAT_B10G10R10X2_UNORM; + case DRM_FORMAT_ARGB2101010: return PIPE_FORMAT_B10G10R10A2_UNORM; + case DRM_FORMAT_XBGR2101010: return PIPE_FORMAT_R10G10B10X2_UNORM; + case DRM_FORMAT_ABGR2101010: return PIPE_FORMAT_R10G10B10A2_UNORM; + case DRM_FORMAT_XBGR16161616F: return PIPE_FORMAT_R16G16B16A16_FLOAT; + case DRM_FORMAT_ABGR16161616F: return PIPE_FORMAT_R16G16B16X16_FLOAT; + case DRM_FORMAT_ARGB1555: return PIPE_FORMAT_B5G5R5A1_UNORM; + case DRM_FORMAT_ABGR1555: return PIPE_FORMAT_R5G5B5A1_UNORM; + case DRM_FORMAT_ARGB4444: return PIPE_FORMAT_B4G4R4A4_UNORM; + case DRM_FORMAT_ABGR4444: return PIPE_FORMAT_R4G4B4A4_UNORM; + default: return PIPE_FORMAT_NONE; + } +} + +static unsigned +add_srgb_config(struct gl_config **configs, unsigned c, enum pipe_format last_pformat, unsigned last_start) +{ + enum pipe_format srgb = util_format_srgb(last_pformat); + if (!srgb) + return c; + unsigned end = c; + for (unsigned j = last_start; j < end; j++) { + configs[c] = mem_dup(configs[j], sizeof(drilConfigs[j])); + + struct gl_config *cfg = configs[c++]; + cfg->color_format = srgb; + cfg->sRGBCapable = 1; + } + return c; +} /* DRI2 awfulness */ -static bool -init_dri2_configs(int fd, const __DRIconfig **configs) +static const __DRIconfig ** +init_dri2_configs(int fd) { void *egl = NULL; - bool ret = false; + struct gl_config **configs = NULL; + unsigned c = 0; + enum pipe_format last_pformat = 0; + unsigned last_start = 0; /* dlopen/dlsym to avoid linkage */ egl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); @@ -290,7 +339,9 @@ init_dri2_configs(int fd, const __DRIconfig **configs) EGLDisplay (*peglGetPlatformDisplayEXT)(EGLenum, void *, const EGLint *) = peglGetProcAddress("eglGetPlatformDisplayEXT"); EGLDisplay (*peglInitialize)(EGLDisplay, int*, int*) = peglGetProcAddress("eglInitialize"); void (*peglTerminate)(EGLDisplay) = peglGetProcAddress("eglTerminate"); - EGLBoolean (*peglChooseConfig)(EGLDisplay, EGLint const *, EGLConfig *, EGLint, EGLint*) = peglGetProcAddress("eglChooseConfig"); + EGLBoolean (*peglGetConfigs)(EGLDisplay, EGLConfig*, EGLint, EGLint*) = peglGetProcAddress("eglGetConfigs"); + EGLBoolean (*peglGetConfigAttrib)(EGLDisplay, EGLConfig, EGLint, EGLint *) = peglGetProcAddress("eglGetConfigAttrib"); + const char *(*peglQueryString)(EGLDisplay, EGLint) = peglGetProcAddress("eglQueryString"); /* try opening GBM for hardware driver info */ struct gbm_device *gbm = gbm_create_device(fd); @@ -300,44 +351,66 @@ init_dri2_configs(int fd, const __DRIconfig **configs) EGLDisplay dpy = peglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA, gbm, NULL); if (!dpy) goto out_gbm; - int maj, min; if (!peglInitialize(dpy, &maj, &min)) goto out_gbm; - unsigned c = 0; + const char *egl_extension_list = peglQueryString(dpy, EGL_EXTENSIONS); + bool has_srgb = strstr(egl_extension_list, "EGL_KHR_gl_colorspace"); - /* iterate over base configs and check for multisample support */ - for (unsigned i = 0; i < ARRAY_SIZE(drilConfigs); i++) { - unsigned num_samples[] = { - 0, 2, 4, 6, 8, 16, 32 - }; - static_assert(ARRAY_SIZE(num_samples) == NUM_SAMPLE_COUNTS, "sample count define needs updating"); - for (unsigned j = 0; j < ARRAY_SIZE(num_samples); j++) { - const EGLint config_attribs[] = { - EGL_RED_SIZE, SIZE(drilConfigs[i].color_format, RGB, 0), - EGL_GREEN_SIZE, SIZE(drilConfigs[i].color_format, RGB, 1), - EGL_BLUE_SIZE, SIZE(drilConfigs[i].color_format, RGB, 2), - EGL_ALPHA_SIZE, SIZE(drilConfigs[i].color_format, RGB, 3), - EGL_DEPTH_SIZE, SIZE(drilConfigs[i].zs_format, ZS, 0), - EGL_STENCIL_SIZE, SIZE(drilConfigs[i].zs_format, ZS, 1), - EGL_SAMPLES, num_samples[j], - EGL_NONE - }; - int num_configs = 0; - if (peglChooseConfig(dpy, config_attribs, NULL, 0, &num_configs) && num_configs) { - /* only copy supported configs */ - configs[c] = mem_dup(&drilConfigs[i], sizeof(drilConfigs[i])); + int num_configs = 0; + EGLConfig *eglconfigs = NULL; + if (!peglGetConfigs(dpy, NULL, 0, &num_configs)) + goto out_egl; + eglconfigs = malloc(sizeof(EGLConfig) * num_configs); + /* overestimate: num_configs * doubleBuffer * sRGB + NULL */ + configs = calloc(num_configs * 2 * 2 + 1, sizeof(struct gl_config)); + if (!peglGetConfigs(dpy, eglconfigs, num_configs, &num_configs)) + goto out_egl; - /* hardcoded configs have samples=0, need to update */ - struct gl_config *cfg = (void*)configs[c]; - cfg->samples = num_samples[j]; - ret = true; - c++; + for (unsigned i = 0; i < num_configs; i++) { + /* verify that this is the right format */ + EGLint format, depth, stencil, samples; + + if (!peglGetConfigAttrib(dpy, eglconfigs[i], EGL_NATIVE_VISUAL_ID, &format) || + !peglGetConfigAttrib(dpy, eglconfigs[i], EGL_DEPTH_SIZE, &depth) || + !peglGetConfigAttrib(dpy, eglconfigs[i], EGL_STENCIL_SIZE, &stencil) || + !peglGetConfigAttrib(dpy, eglconfigs[i], EGL_SAMPLES, &samples)) + continue; + + enum pipe_format pformat = fourcc_to_pipe_format(format); + + /* srgb configs go after base configs */ + if (last_pformat && has_srgb && pformat != last_pformat) + c = add_srgb_config(configs, c, last_pformat, last_start); + /* tracking for the number of srgb configs to create */ + if (pformat != last_pformat) + last_start = c; + + for (unsigned j = 0; j < ARRAY_SIZE(drilConfigs); j++) { + unsigned depth_size = SIZE(drilConfigs[j].zs_format, ZS, 0); + unsigned stencil_size = SIZE(drilConfigs[j].zs_format, ZS, 1); + /* only copy supported configs */ + if (pformat != drilConfigs[j].color_format || depth != depth_size || stencil != stencil_size) + continue; + + /* always create single-buffered and double-buffered */ + for (unsigned k = 0; k < 2; k++) { + configs[c] = mem_dup(&drilConfigs[j], sizeof(drilConfigs[j])); + + struct gl_config *cfg = configs[c++]; + cfg->samples = samples; + cfg->doubleBufferMode = k; } + break; } + last_pformat = pformat; } - + /* check last format for srgbness too */ + if (c && has_srgb) + c = add_srgb_config(configs, c, last_pformat, last_start); +out_egl: + free(eglconfigs); /* don't forget cleanup */ peglTerminate(dpy); @@ -345,7 +418,10 @@ out_gbm: gbm_device_destroy(gbm); out: dlclose(egl); - return ret; + if (c) + return (void*)configs; + free(configs); + return NULL; } static __DRIscreen * @@ -356,9 +432,12 @@ drilCreateNewScreen(int scrn, int fd, { /* multiply for possible 1/2/4/8/16/32 MSAA configs */ // allocate an array of pointers - const __DRIconfig **configs = calloc(ARRAY_SIZE(drilConfigs) * NUM_SAMPLE_COUNTS + 1, sizeof(void *)); + const __DRIconfig **configs = NULL; /* try dri2 if fd is valid */ - if (fd < 0 || !init_dri2_configs(fd, configs)) { + if (fd >= 0) + configs = init_dri2_configs(fd); + if (!configs) { + configs = calloc(ARRAY_SIZE(drilConfigs) + 1, sizeof(void *)); // otherwise set configs to point to our config list for (int i = 0; i < ARRAY_SIZE(drilConfigs); i++) { configs[i] = mem_dup(&drilConfigs[i], sizeof(drilConfigs[i]));