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: 3de62b2f9a ("gallium/dril: Compatibility stub for the legacy DRI loader interface")

Acked-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30311>
This commit is contained in:
Mike Blumenkrantz
2024-07-22 19:18:00 -04:00
committed by Marge Bot
parent dd5362c78a
commit ec7afd2c24

View File

@@ -26,6 +26,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#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]));