driconf: Make the driver's declarations be structs instead of XML.

We can generate the XML if anybody actually queries it, but this reduces
the amount of work in driver setup and means that we'll be able to support
driconf option queries on Android without libexpat.

This updates the driconf interface struct version for i965, i915, and
radeon to use the new getXml entrypoint to call the on-demand xml
generation.  Note that our loaders (egl, glx) implement the v2 function
interface and don't use .xml when that's set, and the X server doesn't use
this interface at all.

XML generation tested on iris and i965 using adriconf

Acked-by: Eric Engestrom <eric@engestrom.ch>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6916>
This commit is contained in:
Eric Anholt
2020-09-25 12:56:22 -07:00
committed by Marge Bot
parent 9fbf206a13
commit 8a05d6ffc6
22 changed files with 511 additions and 534 deletions

View File

@@ -606,8 +606,7 @@ radv_handle_per_app_options(struct radv_instance *instance,
instance->debug_flags |= RADV_DEBUG_NO_DYNAMIC_BOUNDS;
}
static const char radv_dri_options_xml[] =
DRI_CONF_BEGIN
static const driOptionDescription radv_dri_options[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_ADAPTIVE_SYNC("true")
DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
@@ -623,11 +622,11 @@ DRI_CONF_BEGIN
DRI_CONF_OVERRIDE_VRAM_SIZE()
DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
DRI_CONF_SECTION_END
DRI_CONF_END;
};
static void radv_init_dri_options(struct radv_instance *instance)
{
driParseOptionInfo(&instance->available_dri_options, radv_dri_options_xml);
driParseOptionInfo(&instance->available_dri_options, radv_dri_options, ARRAY_SIZE(radv_dri_options));
driParseConfigFiles(&instance->dri_options,
&instance->available_dri_options,
0, "radv", NULL,

View File

@@ -51,9 +51,9 @@ static int (*backends[])(struct pipe_loader_device **, int) = {
&pipe_loader_sw_probe
};
const char gallium_driinfo_xml[] =
const driOptionDescription gallium_driconf[] = {
#include "driinfo_gallium.h"
;
};
int
pipe_loader_probe(struct pipe_loader_device **devs, int ndev)
@@ -85,45 +85,62 @@ pipe_loader_base_release(struct pipe_loader_device **dev)
*dev = NULL;
}
static driOptionDescription *
merge_driconf(const driOptionDescription *driver_driconf, unsigned driver_count,
unsigned *merged_count)
{
unsigned gallium_count = ARRAY_SIZE(gallium_driconf);
driOptionDescription *merged = malloc((driver_count + gallium_count) *
sizeof(*merged));
if (!merged) {
*merged_count = 0;
return NULL;
}
memcpy(merged, gallium_driconf, sizeof(*merged) * gallium_count);
memcpy(&merged[gallium_count], driver_driconf, sizeof(*merged) * driver_count);
*merged_count = driver_count + gallium_count;
return merged;
}
void
pipe_loader_load_options(struct pipe_loader_device *dev)
{
if (dev->option_info.info)
return;
const char *driver_xml = dev->ops->get_driconf_xml(dev);
unsigned driver_count, merged_count;
const driOptionDescription *driver_driconf =
dev->ops->get_driconf(dev, &driver_count);
char *xml_options;
int ret = asprintf(&xml_options, "%s%s%s%s",
DRI_CONF_BEGIN,
gallium_driinfo_xml,
driver_xml ? driver_xml : "",
DRI_CONF_END);
if (ret >= 0) {
driParseOptionInfo(&dev->option_info, xml_options);
driParseConfigFiles(&dev->option_cache, &dev->option_info, 0,
dev->driver_name, NULL, NULL, 0, NULL, 0);
free(xml_options);
}
const driOptionDescription *merged_driconf =
merge_driconf(driver_driconf, driver_count, &merged_count);
driParseOptionInfo(&dev->option_info, merged_driconf, merged_count);
driParseConfigFiles(&dev->option_cache, &dev->option_info, 0,
dev->driver_name, NULL, NULL, 0, NULL, 0);
}
char *
pipe_loader_get_driinfo_xml(const char *driver_name)
{
unsigned driver_count = 0;
const driOptionDescription *driver_driconf = NULL;
#ifdef HAVE_LIBDRM
char *driver_xml = pipe_loader_drm_get_driinfo_xml(driver_name);
#else
char *driver_xml = NULL;
driver_driconf = pipe_loader_drm_get_driconf_by_name(driver_name,
&driver_count);
#endif
char *xml;
int ret = asprintf(&xml, "%s%s%s%s",
DRI_CONF_BEGIN,
gallium_driinfo_xml,
driver_xml ? driver_xml : "",
DRI_CONF_END);
if (ret < 0)
xml = NULL;
unsigned merged_count;
const driOptionDescription *merged_driconf =
merge_driconf(driver_driconf, driver_count, &merged_count);
free((void *)driver_driconf);
char *xml = driGetOptionsXml(merged_driconf, merged_count);
free((void *)merged_driconf);
return xml;
}

View File

@@ -199,14 +199,12 @@ bool
pipe_loader_drm_probe_fd(struct pipe_loader_device **dev, int fd);
/**
* Get the driinfo XML used for the DRM driver of the given name, if any.
* Get the dri options used for the DRM driver of the given name, if any.
*
* The returned string is heap-allocated.
* The returned array is heap-allocated.
*/
char *
pipe_loader_drm_get_driinfo_xml(const char *driver_name);
extern const char gallium_driinfo_xml[];
const struct driOptionDescription *
pipe_loader_drm_get_driconf_by_name(const char *driver_name, unsigned *count);
#ifdef __cplusplus
}

View File

@@ -46,6 +46,7 @@
#include "util/u_memory.h"
#include "util/u_dl.h"
#include "util/u_debug.h"
#include "util/xmlconfig.h"
#define DRM_RENDER_NODE_DEV_NAME_FORMAT "%s/renderD%d"
#define DRM_RENDER_NODE_MAX_NODES 63
@@ -241,15 +242,13 @@ pipe_loader_drm_release(struct pipe_loader_device **dev)
pipe_loader_base_release(dev);
}
static const char *
pipe_loader_drm_get_driconf_xml(struct pipe_loader_device *dev)
static const struct driOptionDescription *
pipe_loader_drm_get_driconf(struct pipe_loader_device *dev, unsigned *count)
{
struct pipe_loader_drm_device *ddev = pipe_loader_drm_device(dev);
if (!ddev->dd->driconf_xml)
return NULL;
return *ddev->dd->driconf_xml;
*count = ddev->dd->driconf_count;
return ddev->dd->driconf;
}
static struct pipe_screen *
@@ -261,24 +260,30 @@ pipe_loader_drm_create_screen(struct pipe_loader_device *dev,
return ddev->dd->create_screen(ddev->fd, config);
}
char *
pipe_loader_drm_get_driinfo_xml(const char *driver_name)
const struct driOptionDescription *
pipe_loader_drm_get_driconf_by_name(const char *driver_name, unsigned *count)
{
char *xml = NULL;
driOptionDescription *driconf = NULL;
struct util_dl_library *lib = NULL;
const struct drm_driver_descriptor *dd =
get_driver_descriptor(driver_name, &lib);
if (dd && dd->driconf_xml && *dd->driconf_xml)
xml = strdup(*dd->driconf_xml);
if (!dd) {
*count = 0;
} else {
*count = dd->driconf_count;
size_t size = sizeof(*driconf) * *count;
driconf = malloc(size);
memcpy(driconf, dd->driconf, size);
}
if (lib)
util_dl_close(lib);
return xml;
return driconf;
}
static const struct pipe_loader_ops pipe_loader_drm_ops = {
.create_screen = pipe_loader_drm_create_screen,
.get_driconf_xml = pipe_loader_drm_get_driconf_xml,
.get_driconf = pipe_loader_drm_get_driconf,
.release = pipe_loader_drm_release
};

View File

@@ -34,7 +34,8 @@ struct pipe_loader_ops {
struct pipe_screen *(*create_screen)(struct pipe_loader_device *dev,
const struct pipe_screen_config *config);
const char *(*get_driconf_xml)(struct pipe_loader_device *dev);
const struct driOptionDescription *(*get_driconf)(struct pipe_loader_device *dev,
unsigned *count);
void (*release)(struct pipe_loader_device **dev);
};

View File

@@ -294,9 +294,10 @@ pipe_loader_sw_release(struct pipe_loader_device **dev)
pipe_loader_base_release(dev);
}
static const char *
pipe_loader_sw_get_driconf_xml(struct pipe_loader_device *dev)
static const struct driOptionDescription *
pipe_loader_sw_get_driconf(struct pipe_loader_device *dev, unsigned *count)
{
*count = 0;
return NULL;
}
@@ -316,6 +317,6 @@ pipe_loader_sw_create_screen(struct pipe_loader_device *dev,
static const struct pipe_loader_ops pipe_loader_sw_ops = {
.create_screen = pipe_loader_sw_create_screen,
.get_driconf_xml = pipe_loader_sw_get_driconf_xml,
.get_driconf = pipe_loader_sw_get_driconf,
.release = pipe_loader_sw_release
};

View File

@@ -10,10 +10,11 @@
/**
* Instantiate a drm_driver_descriptor struct.
*/
#define DEFINE_DRM_DRIVER_DESCRIPTOR(descriptor_name, driver, driconf, func) \
#define DEFINE_DRM_DRIVER_DESCRIPTOR(descriptor_name, driver, _driconf, _driconf_count, func) \
const struct drm_driver_descriptor descriptor_name = { \
.driver_name = #driver, \
.driconf_xml = driconf, \
.driconf = _driconf, \
.driconf_count = _driconf_count, \
.create_screen = func, \
};
@@ -32,17 +33,17 @@ const struct drm_driver_descriptor descriptor_name = { \
#ifdef PIPE_LOADER_DYNAMIC
#define DRM_DRIVER_DESCRIPTOR(driver, driconf) \
PUBLIC DEFINE_DRM_DRIVER_DESCRIPTOR(driver_descriptor, driver, driconf, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR(driver, driconf, driconf_count) \
PUBLIC DEFINE_DRM_DRIVER_DESCRIPTOR(driver_descriptor, driver, driconf, driconf_count, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR_STUB(driver)
#define DRM_DRIVER_DESCRIPTOR_ALIAS(driver, alias, driconf)
#define DRM_DRIVER_DESCRIPTOR_ALIAS(driver, alias, driconf, driconf_count)
#else
#define DRM_DRIVER_DESCRIPTOR(driver, driconf) \
DEFINE_DRM_DRIVER_DESCRIPTOR(driver##_driver_descriptor, driver, driconf, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR(driver, driconf, driconf_count) \
DEFINE_DRM_DRIVER_DESCRIPTOR(driver##_driver_descriptor, driver, driconf, driconf_count, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR_STUB(driver) \
static struct pipe_screen * \
@@ -51,10 +52,11 @@ const struct drm_driver_descriptor descriptor_name = { \
fprintf(stderr, #driver ": driver missing\n"); \
return NULL; \
} \
DRM_DRIVER_DESCRIPTOR(driver, NULL)
DRM_DRIVER_DESCRIPTOR(driver, NULL, 0)
#define DRM_DRIVER_DESCRIPTOR_ALIAS(driver, alias, driconf) \
DEFINE_DRM_DRIVER_DESCRIPTOR(alias##_driver_descriptor, alias, driconf, pipe_##driver##_create_screen)
#define DRM_DRIVER_DESCRIPTOR_ALIAS(driver, alias, driconf, driconf_count) \
DEFINE_DRM_DRIVER_DESCRIPTOR(alias##_driver_descriptor, alias, driconf, \
driconf_count, pipe_##driver##_create_screen)
#endif
@@ -75,7 +77,7 @@ pipe_i915_create_screen(int fd, const struct pipe_screen_config *config)
screen = i915_screen_create(iws);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(i915, NULL)
DRM_DRIVER_DESCRIPTOR(i915, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(i915)
#endif
@@ -92,10 +94,10 @@ pipe_iris_create_screen(int fd, const struct pipe_screen_config *config)
return screen ? debug_screen_wrap(screen) : NULL;
}
const char *iris_driconf_xml =
const driOptionDescription iris_driconf[] = {
#include "iris/driinfo_iris.h"
;
DRM_DRIVER_DESCRIPTOR(iris, &iris_driconf_xml)
};
DRM_DRIVER_DESCRIPTOR(iris, iris_driconf, ARRAY_SIZE(iris_driconf))
#else
DRM_DRIVER_DESCRIPTOR_STUB(iris)
@@ -112,16 +114,16 @@ pipe_nouveau_create_screen(int fd, const struct pipe_screen_config *config)
screen = nouveau_drm_screen_create(fd);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(nouveau, NULL)
DRM_DRIVER_DESCRIPTOR(nouveau, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(nouveau)
#endif
#if defined(GALLIUM_VC4) || defined(GALLIUM_V3D)
const char *v3d_driconf_xml =
const driOptionDescription v3d_driconf[] = {
#include "v3d/driinfo_v3d.h"
;
};
#endif
#ifdef GALLIUM_KMSRO
@@ -136,9 +138,9 @@ pipe_kmsro_create_screen(int fd, const struct pipe_screen_config *config)
return screen ? debug_screen_wrap(screen) : NULL;
}
#if defined(GALLIUM_VC4) || defined(GALLIUM_V3D)
DRM_DRIVER_DESCRIPTOR(kmsro, &v3d_driconf_xml)
DRM_DRIVER_DESCRIPTOR(kmsro, v3d_driconf, ARRAY_SIZE(v3d_driconf))
#else
DRM_DRIVER_DESCRIPTOR(kmsro, NULL)
DRM_DRIVER_DESCRIPTOR(kmsro, NULL, 0)
#endif
#else
@@ -158,7 +160,7 @@ pipe_r300_create_screen(int fd, const struct pipe_screen_config *config)
rw = radeon_drm_winsys_create(fd, config, r300_screen_create);
return rw ? debug_screen_wrap(rw->screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(r300, NULL)
DRM_DRIVER_DESCRIPTOR(r300, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(r300)
@@ -177,7 +179,7 @@ pipe_r600_create_screen(int fd, const struct pipe_screen_config *config)
rw = radeon_drm_winsys_create(fd, config, r600_screen_create);
return rw ? debug_screen_wrap(rw->screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(r600, NULL)
DRM_DRIVER_DESCRIPTOR(r600, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(r600)
@@ -194,10 +196,10 @@ pipe_radeonsi_create_screen(int fd, const struct pipe_screen_config *config)
return screen ? debug_screen_wrap(screen) : NULL;
}
const char *radeonsi_driconf_xml =
const driOptionDescription radeonsi_driconf[] = {
#include "radeonsi/driinfo_radeonsi.h"
;
DRM_DRIVER_DESCRIPTOR(radeonsi, &radeonsi_driconf_xml)
};
DRM_DRIVER_DESCRIPTOR(radeonsi, radeonsi_driconf, ARRAY_SIZE(radeonsi_driconf))
#else
DRM_DRIVER_DESCRIPTOR_STUB(radeonsi)
@@ -220,7 +222,7 @@ pipe_vmwgfx_create_screen(int fd, const struct pipe_screen_config *config)
screen = svga_screen_create(sws);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(vmwgfx, NULL)
DRM_DRIVER_DESCRIPTOR(vmwgfx, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(vmwgfx)
@@ -237,11 +239,11 @@ pipe_msm_create_screen(int fd, const struct pipe_screen_config *config)
screen = fd_drm_screen_create(fd, NULL);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(msm, NULL)
DRM_DRIVER_DESCRIPTOR(msm, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(msm)
#endif
DRM_DRIVER_DESCRIPTOR_ALIAS(msm, kgsl, NULL)
DRM_DRIVER_DESCRIPTOR_ALIAS(msm, kgsl, NULL, 0)
#ifdef GALLIUM_VIRGL
#include "virgl/drm/virgl_drm_public.h"
@@ -256,10 +258,10 @@ pipe_virtio_gpu_create_screen(int fd, const struct pipe_screen_config *config)
return screen ? debug_screen_wrap(screen) : NULL;
}
const char *virgl_driconf_xml =
const driOptionDescription virgl_driconf[] = {
#include "virgl/virgl_driinfo.h.in"
;
DRM_DRIVER_DESCRIPTOR(virtio_gpu, &virgl_driconf_xml)
};
DRM_DRIVER_DESCRIPTOR(virtio_gpu, virgl_driconf, ARRAY_SIZE(virgl_driconf))
#else
DRM_DRIVER_DESCRIPTOR_STUB(virtio_gpu)
@@ -276,7 +278,7 @@ pipe_vc4_create_screen(int fd, const struct pipe_screen_config *config)
screen = vc4_drm_screen_create(fd, config);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(vc4, &v3d_driconf_xml)
DRM_DRIVER_DESCRIPTOR(vc4, v3d_driconf, ARRAY_SIZE(v3d_driconf))
#else
DRM_DRIVER_DESCRIPTOR_STUB(vc4)
#endif
@@ -293,7 +295,7 @@ pipe_v3d_create_screen(int fd, const struct pipe_screen_config *config)
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(v3d, &v3d_driconf_xml)
DRM_DRIVER_DESCRIPTOR(v3d, v3d_driconf, ARRAY_SIZE(v3d_driconf))
#else
DRM_DRIVER_DESCRIPTOR_STUB(v3d)
@@ -310,7 +312,7 @@ pipe_panfrost_create_screen(int fd, const struct pipe_screen_config *config)
screen = panfrost_drm_screen_create(fd);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(panfrost, NULL)
DRM_DRIVER_DESCRIPTOR(panfrost, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(panfrost)
@@ -327,7 +329,7 @@ pipe_etnaviv_create_screen(int fd, const struct pipe_screen_config *config)
screen = etna_drm_screen_create(fd);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(etnaviv, NULL)
DRM_DRIVER_DESCRIPTOR(etnaviv, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(etnaviv)
@@ -345,7 +347,7 @@ pipe_tegra_create_screen(int fd, const struct pipe_screen_config *config)
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(tegra, NULL)
DRM_DRIVER_DESCRIPTOR(tegra, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(tegra)
@@ -362,7 +364,7 @@ pipe_lima_create_screen(int fd, const struct pipe_screen_config *config)
screen = lima_drm_screen_create(fd);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(lima, NULL)
DRM_DRIVER_DESCRIPTOR(lima, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(lima)
@@ -378,7 +380,7 @@ pipe_zink_create_screen(int fd, const struct pipe_screen_config *config)
screen = zink_drm_create_screen(fd);
return screen ? debug_screen_wrap(screen) : NULL;
}
DRM_DRIVER_DESCRIPTOR(zink, NULL)
DRM_DRIVER_DESCRIPTOR(zink, NULL, 0)
#else
DRM_DRIVER_DESCRIPTOR_STUB(zink)

View File

@@ -7,5 +7,5 @@ DRI_CONF_SECTION_DEBUG
DRI_CONF_SECTION_END
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_OPT_E(bo_reuse, 1, 0, 1, "Buffer object reuse", "")
DRI_CONF_OPT_E(bo_reuse, 1, 0, 1, "Buffer object reuse",)
DRI_CONF_SECTION_END

View File

@@ -51,7 +51,6 @@
const __DRIconfigOptionsExtension gallium_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 2 },
.xml = gallium_driinfo_xml,
.getXml = pipe_loader_get_driinfo_xml
};

View File

@@ -19,11 +19,13 @@ struct drm_driver_descriptor
const char *driver_name;
/**
* Pointer to the XML string fragment describing driver-specific driconf
* options. Use DRI_CONF_* macros to create the string, do not wrap in
* DRI_CONF_BEGIN/END.
* Optional pointer to the array of driOptionDescription describing
* driver-specific driconf options.
*/
const char **driconf_xml;
const struct driOptionDescription *driconf;
/* Number of entries in the driconf array. */
unsigned driconf_count;
/**
* Create a pipe srcreen.

View File

@@ -47,8 +47,7 @@
#define DBG_CHANNEL DBG_ADAPTER
const char __driConfigOptionsNine[] =
DRI_CONF_BEGIN
const driOptionDescription __driConfigOptionsNine[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
DRI_CONF_SECTION_END
@@ -62,7 +61,7 @@ DRI_CONF_BEGIN
DRI_CONF_NINE_DYNAMICTEXTUREWORKAROUND("false")
DRI_CONF_NINE_SHADERINLINECONSTANTS("false")
DRI_CONF_SECTION_END
DRI_CONF_END;
};
struct fallback_card_config {
const char *name;
@@ -249,7 +248,8 @@ drm_create_adapter( int fd,
ctx->base.throttling_value = 2;
ctx->base.throttling = ctx->base.throttling_value > 0;
driParseOptionInfo(&defaultInitOptions, __driConfigOptionsNine);
driParseOptionInfo(&defaultInitOptions, __driConfigOptionsNine,
ARRAY_SIZE(__driConfigOptionsNine));
driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0,
"nine", NULL, NULL, 0, NULL, 0);
if (driCheckOption(&userInitOptions, "throttle_value", DRI_INT)) {

View File

@@ -49,8 +49,7 @@
#include "genxml/gen7_pack.h"
static const char anv_dri_options_xml[] =
DRI_CONF_BEGIN
static const driOptionDescription anv_dri_options[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
DRI_CONF_VK_X11_STRICT_IMAGE_COUNT("false")
@@ -60,7 +59,7 @@ DRI_CONF_BEGIN
DRI_CONF_ALWAYS_FLUSH_CACHE("false")
DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
DRI_CONF_SECTION_END
DRI_CONF_END;
};
/* This is probably far to big but it reflects the max size used for messages
* in OpenGLs KHR_debug.
@@ -768,7 +767,8 @@ VkResult anv_CreateInstance(
VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
driParseOptionInfo(&instance->available_dri_options, anv_dri_options_xml);
driParseOptionInfo(&instance->available_dri_options, anv_dri_options,
ARRAY_SIZE(anv_dri_options));
driParseConfigFiles(&instance->dri_options, &instance->available_dri_options,
0, "anv", NULL,
instance->app_info.app_name,

View File

@@ -178,13 +178,12 @@ loader_open_render_node(const char *name)
}
#ifdef USE_DRICONF
static const char __driConfigOptionsLoader[] =
DRI_CONF_BEGIN
static const driOptionDescription __driConfigOptionsLoader[] = {
DRI_CONF_SECTION_INITIALIZATION
DRI_CONF_DEVICE_ID_PATH_TAG()
DRI_CONF_DRI_DRIVER()
DRI_CONF_SECTION_END
DRI_CONF_END;
};
static char *loader_get_dri_config_driver(int fd)
{
@@ -193,7 +192,8 @@ static char *loader_get_dri_config_driver(int fd)
char *dri_driver = NULL;
char *kernel_driver = loader_get_kernel_driver_name(fd);
driParseOptionInfo(&defaultInitOptions, __driConfigOptionsLoader);
driParseOptionInfo(&defaultInitOptions, __driConfigOptionsLoader,
ARRAY_SIZE(__driConfigOptionsLoader));
driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0,
"loader", kernel_driver, NULL, 0, NULL, 0);
if (driCheckOption(&userInitOptions, "dri_driver", DRI_STRING)) {
@@ -215,7 +215,8 @@ static char *loader_get_dri_config_device_id(void)
driOptionCache userInitOptions;
char *prime = NULL;
driParseOptionInfo(&defaultInitOptions, __driConfigOptionsLoader);
driParseOptionInfo(&defaultInitOptions, __driConfigOptionsLoader,
ARRAY_SIZE(__driConfigOptionsLoader));
driParseConfigFiles(&userInitOptions, &defaultInitOptions, 0,
"loader", NULL, NULL, 0, NULL, 0);
if (driCheckOption(&userInitOptions, "device_id", DRI_STRING))

View File

@@ -51,12 +51,11 @@
#include "main/errors.h"
#include "main/macros.h"
const char __dri2ConfigOptions[] =
DRI_CONF_BEGIN
driOptionDescription __dri2ConfigOptions[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
DRI_CONF_SECTION_END
DRI_CONF_END;
};
/*****************************************************************/
/** \name Screen handling functions */
@@ -148,7 +147,8 @@ driCreateNewScreen2(int scrn, int fd,
psp->myNum = scrn;
/* Option parsing before ->InitScreen(), as some options apply there. */
driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions);
driParseOptionInfo(&psp->optionInfo,
__dri2ConfigOptions, ARRAY_SIZE(__dri2ConfigOptions));
driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum,
"dri2", NULL, NULL, 0, NULL, 0);

View File

@@ -43,11 +43,7 @@
#include "util/driconf.h"
#include "util/u_memory.h"
static const __DRIconfigOptionsExtension i915_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 1 },
.xml =
DRI_CONF_BEGIN
static const driOptionDescription i915_driconf[] = {
DRI_CONF_SECTION_PERFORMANCE
/* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
* DRI_CONF_BO_REUSE_ALL
@@ -75,7 +71,18 @@ DRI_CONF_BEGIN
DRI_CONF_OPT_B(shader_precompile, "true", "Perform code generation at shader link time.")
DRI_CONF_SECTION_END
DRI_CONF_END
};
static char *
i915_driconf_get_xml(const char *driver_name)
{
return driGetOptionsXml(i915_driconf, ARRAY_SIZE(i915_driconf));
}
static const __DRIconfigOptionsExtension i915_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 2 },
.xml = NULL,
.getXml = i915_driconf_get_xml,
};
#include "intel_batchbuffer.h"
@@ -1155,7 +1162,8 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp)
return false;
}
/* parse information in __driConfigOptions */
driParseOptionInfo(&intelScreen->optionCache, i915_config_options.xml);
driParseOptionInfo(&intelScreen->optionCache, i915_driconf,
ARRAY_SIZE(i915_driconf));
intelScreen->driScrnPriv = psp;
psp->driverPrivate = (void *) intelScreen;

View File

@@ -49,10 +49,7 @@
#include "common/gen_defines.h"
static const __DRIconfigOptionsExtension brw_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 1 },
.xml =
DRI_CONF_BEGIN
static const driOptionDescription brw_driconf[] = {
DRI_CONF_SECTION_PERFORMANCE
/* Options correspond to DRI_CONF_BO_REUSE_DISABLED,
* DRI_CONF_BO_REUSE_ALL
@@ -100,7 +97,18 @@ DRI_CONF_BEGIN
DRI_CONF_ALLOW_RGB565_CONFIGS("true")
DRI_CONF_ALLOW_FP16_CONFIGS("false")
DRI_CONF_SECTION_END
DRI_CONF_END
};
static char *
brw_driconf_get_xml(const char *driver_name)
{
return driGetOptionsXml(brw_driconf, ARRAY_SIZE(brw_driconf));
}
static const __DRIconfigOptionsExtension brw_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 2 },
.xml = NULL,
.getXml = brw_driconf_get_xml,
};
#include "intel_batchbuffer.h"
@@ -2538,7 +2546,7 @@ __DRIconfig **intelInitScreen2(__DRIscreen *dri_screen)
driOptionCache options;
memset(&options, 0, sizeof(options));
driParseOptionInfo(&options, brw_config_options.xml);
driParseOptionInfo(&options, brw_driconf, ARRAY_SIZE(brw_driconf));
driParseConfigFiles(&screen->optionCache, &options, dri_screen->myNum,
"i965", NULL, NULL, 0, NULL, 0);
driDestroyOptionCache(&options);

View File

@@ -91,10 +91,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"Initial maximum value for anisotropic texture filtering")
#if defined(RADEON_R100) /* R100 */
static const __DRIconfigOptionsExtension radeon_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 1 },
.xml =
DRI_CONF_BEGIN
static const driOptionDescription radeon_driconf[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
@@ -110,15 +107,10 @@ DRI_CONF_BEGIN
DRI_CONF_ROUND_MODE(DRI_CONF_ROUND_TRUNC)
DRI_CONF_DITHER_MODE(DRI_CONF_DITHER_XERRORDIFF)
DRI_CONF_SECTION_END
DRI_CONF_END
};
#elif defined(RADEON_R200)
static const __DRIconfigOptionsExtension radeon_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 1 },
.xml =
DRI_CONF_BEGIN
static const driOptionDescription radeon_driconf[] = {
DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_TCL_MODE(DRI_CONF_TCL_CODEGEN)
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
@@ -136,10 +128,21 @@ DRI_CONF_BEGIN
DRI_CONF_OPT_F(texture_blend_quality, 1.0, 0.0, 1.0,
"Texture filtering quality vs. speed, AKA “brilinear” texture filtering")
DRI_CONF_SECTION_END
DRI_CONF_END
};
#endif
static char *
radeon_driconf_get_xml(const char *driver_name)
{
return driGetOptionsXml(radeon_driconf, ARRAY_SIZE(radeon_driconf));
}
static const __DRIconfigOptionsExtension radeon_config_options = {
.base = { __DRI_CONFIG_OPTIONS, 2 },
.xml = NULL,
.getXml = radeon_driconf_get_xml,
};
static int
radeonGetParam(__DRIscreen *sPriv, int param, void *value)
{
@@ -578,7 +581,8 @@ radeonCreateScreen2(__DRIscreen *sPriv)
radeon_init_debug();
/* parse information in __driConfigOptions */
driParseOptionInfo (&screen->optionCache, radeon_config_options.xml);
driParseOptionInfo (&screen->optionCache, radeon_driconf,
ARRAY_SIZE(radeon_driconf));
screen->chip_flags = 0;

View File

@@ -33,119 +33,95 @@
#ifndef __DRICONF_H
#define __DRICONF_H
#include "xmlconfig.h"
/*
* generic macros
*/
/** \brief Begin __driConfigOptions */
#define DRI_CONF_BEGIN \
"<?xml version=\"1.0\" standalone=\"yes\"?>" \
"<!DOCTYPE driinfo [" \
" <!ELEMENT driinfo (section*)>" \
" <!ELEMENT section (description+, option+)>" \
" <!ELEMENT description (enum*)>" \
" <!ATTLIST description lang CDATA #FIXED \"en\"" \
" text CDATA #REQUIRED>" \
" <!ELEMENT option (description+)>" \
" <!ATTLIST option name CDATA #REQUIRED" \
" type (bool|enum|int|float) #REQUIRED" \
" default CDATA #REQUIRED" \
" valid CDATA #IMPLIED>" \
" <!ELEMENT enum EMPTY>" \
" <!ATTLIST enum value CDATA #REQUIRED" \
" text CDATA #REQUIRED>" \
"]>" \
"<driinfo>\n"
/** \brief End __driConfigOptions */
#define DRI_CONF_END \
"</driinfo>\n"
/** \brief Begin a section of related options */
#define DRI_CONF_SECTION_BEGIN \
"<section>\n"
/** \brief End a section of related options */
#define DRI_CONF_SECTION_END \
"</section>\n"
/** \brief Begin an option definition */
#define DRI_CONF_OPT_BEGIN(name,type,def) \
"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n"
/** \brief Begin an option definition with restrictions on valid values */
#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \
"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\"" valid "\">\n"
/** \brief Names a section of related options to follow */
#define DRI_CONF_SECTION(text) { .desc = text, .info = { .type = DRI_SECTION } },
#define DRI_CONF_SECTION_END
/** \brief End an option description */
#define DRI_CONF_OPT_END \
"</option>\n"
#define DRI_CONF_OPT_END },
/** \brief A verbal description (empty version) */
#define DRI_CONF_DESC(text) \
"<description lang=\"en\" text=\"" text "\"/>\n"
/** \brief Begining of a verbal description */
#define DRI_CONF_DESC_BEGIN(text) \
"<description lang=\"en\" text=\"" text "\">\n"
/** \brief End a description */
#define DRI_CONF_DESC_END \
"</description>\n"
#define DRI_CONF_DESC(text) .desc = text,
/** \brief A verbal description of an enum value */
#define DRI_CONF_ENUM(value,text) \
"<enum value=\""#value"\" text=\"" text "\"/>\n"
#define DRI_CONF_ENUM(_value,text) { .value = _value, .desc = text },
#define DRI_CONF(sections) \
DRI_CONF_BEGIN \
sections \
DRI_CONF_END
#define DRI_CONF_RANGE_I(min, max) \
.range = { \
.start = { ._int = min }, \
.end = { ._int = max }, \
} \
#define DRI_CONF_SECTION(desc, options) \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC(desc) \
options \
DRI_CONF_SECTION_END
#define DRI_CONF_RANGE_F(min, max) \
.range = { \
.start = { ._float = min }, \
.end = { ._float = max }, \
} \
/**
* \brief A boolean option definition, with the default value passed in as a
* string
*/
#define DRI_CONF_OPT_B(name, def, desc) \
"<option name=\""#name"\" type=\"bool\" default="#def">\n" \
DRI_CONF_DESC(desc) \
DRI_CONF_OPT_END
#define DRI_CONF_OPT_I(name, def, min, max, desc) \
DRI_CONF_OPT_BEGIN_V(name, int, def, #min ":" #max) \
DRI_CONF_DESC(desc) \
DRI_CONF_OPT_END
#define DRI_CONF_OPT_B(_name, def, _desc) { \
.desc = _desc, \
.info = { \
.name = #_name, \
.type = DRI_BOOL, \
}, \
.value = { ._string = (char *)def }, \
},
#define DRI_CONF_OPT_F(name, def, min, max, desc) \
DRI_CONF_OPT_BEGIN_V(name, float, def, #min ":" #max) \
DRI_CONF_DESC(desc) \
DRI_CONF_OPT_END
#define DRI_CONF_OPT_I(_name, def, min, max, _desc) { \
.desc = _desc, \
.info = { \
.name = #_name, \
.type = DRI_INT, \
DRI_CONF_RANGE_I(min, max), \
}, \
.value = { ._int = def }, \
},
/* Note that def should not be quoted in the caller! */
#define DRI_CONF_OPT_S(name, def, desc) \
DRI_CONF_OPT_BEGIN(name, string, def) \
DRI_CONF_DESC(desc) \
DRI_CONF_OPT_END
#define DRI_CONF_OPT_F(_name, def, min, max, _desc) { \
.desc = _desc, \
.info = { \
.name = #_name, \
.type = DRI_FLOAT, \
DRI_CONF_RANGE_F(min, max), \
}, \
.value = { ._float = def }, \
},
#define DRI_CONF_OPT_E(name, def, min, max, desc, values) \
DRI_CONF_OPT_BEGIN_V(name, enum, def, #min ":" #max) \
DRI_CONF_DESC_BEGIN(desc) \
values \
DRI_CONF_DESC_END \
DRI_CONF_OPT_END
#define DRI_CONF_OPT_E(_name, def, min, max, _desc, values) { \
.desc = _desc, \
.info = { \
.name = #_name, \
.type = DRI_ENUM, \
DRI_CONF_RANGE_I(min, max), \
}, \
.value = { ._int = def }, \
.enums = { values }, \
},
#define DRI_CONF_OPT_S(_name, def, _desc) { \
.desc = _desc, \
.info = { \
.name = #_name, \
.type = DRI_STRING, \
}, \
.value = { ._string = #def }, \
},
/**
* \brief Debugging options
*/
#define DRI_CONF_SECTION_DEBUG \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC("Debugging")
#define DRI_CONF_SECTION_DEBUG DRI_CONF_SECTION("Debugging")
#define DRI_CONF_ALWAYS_FLUSH_BATCH(def) \
DRI_CONF_OPT_B(always_flush_batch, def, \
@@ -244,9 +220,7 @@ DRI_CONF_SECTION_BEGIN \
/**
* \brief Image quality-related options
*/
#define DRI_CONF_SECTION_QUALITY \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC("Image Quality")
#define DRI_CONF_SECTION_QUALITY DRI_CONF_SECTION("Image Quality")
#define DRI_CONF_PRECISE_TRIG(def) \
DRI_CONF_OPT_B(precise_trig, def, \
@@ -255,22 +229,22 @@ DRI_CONF_SECTION_BEGIN \
#define DRI_CONF_PP_CELSHADE(def) \
DRI_CONF_OPT_E(pp_celshade, def, 0, 1, \
"A post-processing filter to cel-shade the output", \
"")
)
#define DRI_CONF_PP_NORED(def) \
DRI_CONF_OPT_E(pp_nored, def, 0, 1, \
"A post-processing filter to remove the red channel", \
"")
)
#define DRI_CONF_PP_NOGREEN(def) \
DRI_CONF_OPT_E(pp_nogreen, def, 0, 1, \
"A post-processing filter to remove the green channel", \
"")
)
#define DRI_CONF_PP_NOBLUE(def) \
DRI_CONF_OPT_E(pp_noblue, def, 0, 1, \
"A post-processing filter to remove the blue channel", \
"")
)
#define DRI_CONF_PP_JIMENEZMLAA(def,min,max) \
DRI_CONF_OPT_I(pp_jimenezmlaa, def, min, max, \
@@ -283,9 +257,7 @@ DRI_CONF_SECTION_BEGIN \
/**
* \brief Performance-related options
*/
#define DRI_CONF_SECTION_PERFORMANCE \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC("Performance")
#define DRI_CONF_SECTION_PERFORMANCE DRI_CONF_SECTION("Performance")
#define DRI_CONF_VBLANK_NEVER 0
#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
@@ -344,9 +316,7 @@ DRI_CONF_SECTION_BEGIN \
/**
* \brief Miscellaneous configuration options
*/
#define DRI_CONF_SECTION_MISCELLANEOUS \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC("Miscellaneous")
#define DRI_CONF_SECTION_MISCELLANEOUS DRI_CONF_SECTION("Miscellaneous")
#define DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER(def) \
DRI_CONF_OPT_B(always_have_depth_buffer, def, \
@@ -379,9 +349,7 @@ DRI_CONF_SECTION_BEGIN \
/**
* \brief Initialization configuration options
*/
#define DRI_CONF_SECTION_INITIALIZATION \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC("Initialization")
#define DRI_CONF_SECTION_INITIALIZATION DRI_CONF_SECTION("Initialization")
#define DRI_CONF_DEVICE_ID_PATH_TAG(def) \
DRI_CONF_OPT_S(device_id, def, "Define the graphic device to use if possible")
@@ -393,9 +361,7 @@ DRI_CONF_SECTION_BEGIN \
* \brief Gallium-Nine specific configuration options
*/
#define DRI_CONF_SECTION_NINE \
DRI_CONF_SECTION_BEGIN \
DRI_CONF_DESC("Gallium Nine")
#define DRI_CONF_SECTION_NINE DRI_CONF_SECTION("Gallium Nine")
#define DRI_CONF_NINE_THROTTLE(def) \
DRI_CONF_OPT_I(throttle_value, def, 0, 0, \

View File

@@ -220,12 +220,16 @@ idep_xmlconfig = declare_dependency(
)
if with_tests
if host_machine.system() != 'windows'
# DRI_CONF macros use designated initializers (required for union
# initializaiton), so we need c++2a since gtest forces us to use c++
if host_machine.system() != 'windows' and cpp.has_argument('--std=c++2a')
test('xmlconfig',
executable('xmlconfig_test',
files('tests/xmlconfig.cpp'),
include_directories : [inc_include, inc_src],
dependencies : [idep_mesautil, idep_xmlconfig, idep_gtest],
override_options : ['cpp_std=c++2a'],
cpp_args: ['-Wno-write-strings']
),
suite : ['util'],
)

View File

@@ -31,8 +31,6 @@ protected:
~xmlconfig_test();
driOptionCache options;
void driconf(const char *driconf);
};
xmlconfig_test::xmlconfig_test()
@@ -45,23 +43,16 @@ xmlconfig_test::~xmlconfig_test()
}
/* wraps a DRI_CONF_OPT_* in the required xml bits */
#define DRI_CONF_TEST_OPT(x) \
DRI_CONF(DRI_CONF_SECTION("section", x))
void
xmlconfig_test::driconf(const char *driconf)
{
/* If your XML fails to parse, printing it here can help. */
/* printf("%s", driconf); */
driParseOptionInfo(&options, driconf);
}
#define DRI_CONF_TEST_OPT(x) x
TEST_F(xmlconfig_test, bools)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_GLSL_ZERO_INIT("false")
DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER("true")));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_GLSL_ZERO_INIT("false")
DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER("true")
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
EXPECT_EQ(driQueryOptionb(&options, "glsl_zero_init"), false);
EXPECT_EQ(driQueryOptionb(&options, "always_have_depth_buffer"), true);
@@ -69,41 +60,56 @@ TEST_F(xmlconfig_test, bools)
TEST_F(xmlconfig_test, ints)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_OPT_I(opt, 2, 0, 999, "option")));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_OPT_I(opt, 2, 0, 999, "option")
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
EXPECT_EQ(driQueryOptioni(&options, "opt"), 2);
}
TEST_F(xmlconfig_test, floats)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_OPT_F(opt, 2.0, 1.0, 2.0, "option")));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_OPT_F(opt, 2.0, 1.0, 2.0, "option")
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
EXPECT_EQ(driQueryOptionf(&options, "opt"), 2.0);
}
TEST_F(xmlconfig_test, enums)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1)
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
EXPECT_EQ(driQueryOptioni(&options, "vblank_mode"), DRI_CONF_VBLANK_DEF_INTERVAL_1);
}
TEST_F(xmlconfig_test, string)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_OPT_S(opt, value, "option")));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_OPT_S(opt, value, "option")
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
EXPECT_STREQ(driQueryOptionstr(&options, "opt"), "value");
}
TEST_F(xmlconfig_test, check_option)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_GLSL_ZERO_INIT("true")
DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER("true")));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_GLSL_ZERO_INIT("true")
DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER("true")
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
EXPECT_EQ(driCheckOption(&options, "glsl_zero_init", DRI_BOOL), true);
@@ -117,9 +123,12 @@ TEST_F(xmlconfig_test, check_option)
TEST_F(xmlconfig_test, copy_cache)
{
driconf(DRI_CONF_TEST_OPT(
DRI_CONF_OPT_B(mesa_b_option, "true", "description")
DRI_CONF_OPT_S(mesa_s_option, value, "description")));
driOptionDescription driconf[] = {
DRI_CONF_SECTION_MISCELLANEOUS
DRI_CONF_OPT_B(mesa_b_option, "true", "description")
DRI_CONF_OPT_S(mesa_s_option, value, "description")
};
driParseOptionInfo(&options, driconf, ARRAY_SIZE(driconf));
driOptionCache cache;

View File

@@ -279,6 +279,8 @@ parseValue(driOptionValue *v, driOptionType type, const XML_Char *string)
free(v->_string);
v->_string = strndup(string, STRING_CONF_MAXLEN);
return true;
case DRI_SECTION:
unreachable("shouldn't be parsing values in section declarations");
}
if (tail == string)
@@ -323,7 +325,7 @@ parseRange(driOptionInfo *info, const XML_Char *string)
}
/** \brief Check if a value is in info->range. */
static bool
UNUSED static bool
checkValue(const driOptionValue *v, const driOptionInfo *info)
{
switch (info->type) {
@@ -391,245 +393,12 @@ __driUtilMessage(const char *f, ...)
(int) XML_GetCurrentColumnNumber(data->parser), \
##__VA_ARGS__); \
} while (0)
/** \brief Output a fatal error message and abort. */
#define XML_FATAL1(msg) do { \
fprintf(stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
data->name, \
(int) XML_GetCurrentLineNumber(data->parser), \
(int) XML_GetCurrentColumnNumber(data->parser)); \
abort(); \
} while (0)
#define XML_FATAL(msg, ...) do { \
fprintf(stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
data->name, \
(int) XML_GetCurrentLineNumber(data->parser), \
(int) XML_GetCurrentColumnNumber(data->parser), \
##__VA_ARGS__); \
abort(); \
} while (0)
/** \brief Parser context for __driConfigOptions. */
struct OptInfoData {
const char *name;
XML_Parser parser;
driOptionCache *cache;
bool inDriInfo;
bool inSection;
bool inDesc;
bool inOption;
bool inEnum;
int curOption;
};
/** \brief Elements in __driConfigOptions. */
enum OptInfoElem {
OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT
};
static const XML_Char *OptInfoElems[] = {
"description", "driinfo", "enum", "option", "section"
};
/** \brief Parse attributes of an enum element.
*
* We're not actually interested in the data. Just make sure this is ok
* for external configuration tools.
*/
static void
parseEnumAttr(struct OptInfoData *data, const XML_Char **attr)
{
uint32_t i;
const XML_Char *value = NULL, *text = NULL;
driOptionValue v;
uint32_t opt = data->curOption;
for (i = 0; attr[i]; i += 2) {
if (!strcmp(attr[i], "value")) value = attr[i+1];
else if (!strcmp(attr[i], "text")) text = attr[i+1];
else XML_FATAL("illegal enum attribute: %s.", attr[i]);
}
if (!value) XML_FATAL1("value attribute missing in enum.");
if (!text) XML_FATAL1("text attribute missing in enum.");
if (!parseValue(&v, data->cache->info[opt].type, value))
XML_FATAL("illegal enum value: %s.", value);
if (!checkValue(&v, &data->cache->info[opt]))
XML_FATAL("enum value out of valid range: %s.", value);
}
/** \brief Parse attributes of a description element.
*
* We're not actually interested in the data. Just make sure this is ok
* for external configuration tools.
*/
static void
parseDescAttr(struct OptInfoData *data, const XML_Char **attr)
{
uint32_t i;
const XML_Char *lang = NULL, *text = NULL;
for (i = 0; attr[i]; i += 2) {
if (!strcmp(attr[i], "lang")) lang = attr[i+1];
else if (!strcmp(attr[i], "text")) text = attr[i+1];
else XML_FATAL("illegal description attribute: %s.", attr[i]);
}
if (!lang) XML_FATAL1("lang attribute missing in description.");
if (!text) XML_FATAL1("text attribute missing in description.");
}
/** \brief Parse attributes of an option element. */
static void
parseOptInfoAttr(struct OptInfoData *data, const XML_Char **attr)
{
enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT};
static const XML_Char *optAttr[] = {"default", "name", "type", "valid"};
const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
const char *defaultVal;
driOptionCache *cache = data->cache;
uint32_t opt, i;
for (i = 0; attr[i]; i += 2) {
uint32_t attrName = bsearchStr(attr[i], optAttr, OA_COUNT);
if (attrName >= OA_COUNT)
XML_FATAL("illegal option attribute: %s", attr[i]);
attrVal[attrName] = attr[i+1];
}
if (!attrVal[OA_NAME]) XML_FATAL1("name attribute missing in option.");
if (!attrVal[OA_TYPE]) XML_FATAL1("type attribute missing in option.");
if (!attrVal[OA_DEFAULT]) XML_FATAL1("default attribute missing in option.");
opt = findOption(cache, attrVal[OA_NAME]);
if (cache->info[opt].name)
XML_FATAL("option %s redefined.", attrVal[OA_NAME]);
data->curOption = opt;
XSTRDUP(cache->info[opt].name, attrVal[OA_NAME]);
if (!strcmp(attrVal[OA_TYPE], "bool"))
cache->info[opt].type = DRI_BOOL;
else if (!strcmp(attrVal[OA_TYPE], "enum"))
cache->info[opt].type = DRI_ENUM;
else if (!strcmp(attrVal[OA_TYPE], "int"))
cache->info[opt].type = DRI_INT;
else if (!strcmp(attrVal[OA_TYPE], "float"))
cache->info[opt].type = DRI_FLOAT;
else if (!strcmp(attrVal[OA_TYPE], "string"))
cache->info[opt].type = DRI_STRING;
else
XML_FATAL("illegal type in option: %s.", attrVal[OA_TYPE]);
defaultVal = getenv(cache->info[opt].name);
if (defaultVal != NULL) {
/* don't use XML_WARNING, we want the user to see this! */
if (be_verbose()) {
fprintf(stderr,
"ATTENTION: default value of option %s overridden by environment.\n",
cache->info[opt].name);
}
} else
defaultVal = attrVal[OA_DEFAULT];
if (!parseValue(&cache->values[opt], cache->info[opt].type, defaultVal))
XML_FATAL("illegal default value for %s: %s.", cache->info[opt].name, defaultVal);
if (attrVal[OA_VALID]) {
if (cache->info[opt].type == DRI_BOOL)
XML_FATAL1("boolean option with valid attribute.");
if (!parseRange(&cache->info[opt], attrVal[OA_VALID]))
XML_FATAL("illegal valid attribute: %s.", attrVal[OA_VALID]);
if (!checkValue(&cache->values[opt], &cache->info[opt]))
XML_FATAL("default value out of valid range '%s': %s.",
attrVal[OA_VALID], defaultVal);
} else if (cache->info[opt].type == DRI_ENUM) {
XML_FATAL1("valid attribute missing in option (mandatory for enums).");
} else {
memset(&cache->info[opt].range, 0, sizeof(cache->info[opt].range));
}
}
/** \brief Handler for start element events. */
static void
optInfoStartElem(void *userData, const XML_Char *name, const XML_Char **attr)
{
struct OptInfoData *data = (struct OptInfoData *)userData;
enum OptInfoElem elem = bsearchStr(name, OptInfoElems, OI_COUNT);
switch (elem) {
case OI_DRIINFO:
if (data->inDriInfo)
XML_FATAL1("nested <driinfo> elements.");
if (attr[0])
XML_FATAL1("attributes specified on <driinfo> element.");
data->inDriInfo = true;
break;
case OI_SECTION:
if (!data->inDriInfo)
XML_FATAL1("<section> must be inside <driinfo>.");
if (data->inSection)
XML_FATAL1("nested <section> elements.");
if (attr[0])
XML_FATAL1("attributes specified on <section> element.");
data->inSection = true;
break;
case OI_DESCRIPTION:
if (!data->inSection && !data->inOption)
XML_FATAL1("<description> must be inside <description> or <option.");
if (data->inDesc)
XML_FATAL1("nested <description> elements.");
data->inDesc = true;
parseDescAttr(data, attr);
break;
case OI_OPTION:
if (!data->inSection)
XML_FATAL1("<option> must be inside <section>.");
if (data->inDesc)
XML_FATAL1("<option> nested in <description> element.");
if (data->inOption)
XML_FATAL1("nested <option> elements.");
data->inOption = true;
parseOptInfoAttr(data, attr);
break;
case OI_ENUM:
if (!(data->inOption && data->inDesc))
XML_FATAL1("<enum> must be inside <option> and <description>.");
if (data->inEnum)
XML_FATAL1("nested <enum> elements.");
data->inEnum = true;
parseEnumAttr(data, attr);
break;
default:
XML_FATAL("unknown element: %s.", name);
}
}
/** \brief Handler for end element events. */
static void
optInfoEndElem(void *userData, const XML_Char *name)
{
struct OptInfoData *data = (struct OptInfoData *)userData;
enum OptInfoElem elem = bsearchStr(name, OptInfoElems, OI_COUNT);
switch (elem) {
case OI_DRIINFO:
data->inDriInfo = false;
break;
case OI_SECTION:
data->inSection = false;
break;
case OI_DESCRIPTION:
data->inDesc = false;
break;
case OI_OPTION:
data->inOption = false;
break;
case OI_ENUM:
data->inEnum = false;
break;
default:
assert(0); /* should have been caught by StartElem */
}
}
void
driParseOptionInfo(driOptionCache *info, const char *configOptions)
driParseOptionInfo(driOptionCache *info,
const driOptionDescription *configOptions,
unsigned numOptions)
{
XML_Parser p;
int status;
struct OptInfoData userData;
struct OptInfoData *data = &userData;
/* Make the hash table big enough to fit more than the maximum number of
* config options we've ever seen in a driver.
*/
@@ -641,25 +410,187 @@ driParseOptionInfo(driOptionCache *info, const char *configOptions)
abort();
}
p = XML_ParserCreate("UTF-8"); /* always UTF-8 */
XML_SetElementHandler(p, optInfoStartElem, optInfoEndElem);
XML_SetUserData(p, data);
UNUSED bool in_section = false;
for (int o = 0; o < numOptions; o++) {
const driOptionDescription *opt = &configOptions[o];
userData.name = "__driConfigOptions";
userData.parser = p;
userData.cache = info;
userData.inDriInfo = false;
userData.inSection = false;
userData.inDesc = false;
userData.inOption = false;
userData.inEnum = false;
userData.curOption = -1;
if (opt->info.type == DRI_SECTION) {
in_section = true;
continue;
}
status = XML_Parse(p, configOptions, strlen(configOptions), 1);
if (!status)
XML_FATAL("%s.", XML_ErrorString(XML_GetErrorCode(p)));
/* for driconf xml generation, options must always be preceded by a
* DRI_CONF_SECTION
*/
assert(in_section);
XML_ParserFree(p);
const char *name = opt->info.name;
int i = findOption(info, name);
driOptionInfo *optinfo = &info->info[i];
driOptionValue *optval = &info->values[i];
assert(!optinfo->name); /* No duplicate options in your list. */
optinfo->type = opt->info.type;
XSTRDUP(optinfo->name, name);
switch (opt->info.type) {
case DRI_BOOL:
if (strcmp(opt->value._string, "true") == 0)
optval->_bool = true;
else {
assert(strcmp(opt->value._string, "false") == 0);
optval->_bool = false;
}
break;
case DRI_INT:
case DRI_ENUM:
optval->_int = opt->value._int;
break;
case DRI_FLOAT:
optval->_float = opt->value._float;
break;
case DRI_STRING:
XSTRDUP(optval->_string, opt->value._string);
break;
case DRI_SECTION:
unreachable("handled above");
}
assert(checkValue(optval, optinfo));
}
}
char *
driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions)
{
char *str = ralloc_strdup(NULL,
"<?xml version=\"1.0\" standalone=\"yes\"?>\n" \
"<!DOCTYPE driinfo [\n" \
" <!ELEMENT driinfo (section*)>\n" \
" <!ELEMENT section (description+, option+)>\n" \
" <!ELEMENT description (enum*)>\n" \
" <!ATTLIST description lang CDATA #FIXED \"en\"\n" \
" text CDATA #REQUIRED>\n" \
" <!ELEMENT option (description+)>\n" \
" <!ATTLIST option name CDATA #REQUIRED\n" \
" type (bool|enum|int|float) #REQUIRED\n" \
" default CDATA #REQUIRED\n" \
" valid CDATA #IMPLIED>\n" \
" <!ELEMENT enum EMPTY>\n" \
" <!ATTLIST enum value CDATA #REQUIRED\n" \
" text CDATA #REQUIRED>\n" \
"]>" \
"<driinfo>\n");
bool in_section = false;
for (int o = 0; o < numOptions; o++) {
const driOptionDescription *opt = &configOptions[o];
const char *name = opt->info.name;
const char *types[] = {
[DRI_BOOL] = "bool",
[DRI_INT] = "int",
[DRI_FLOAT] = "float",
[DRI_ENUM] = "enum",
[DRI_STRING] = "string",
};
if (opt->info.type == DRI_SECTION) {
if (in_section)
ralloc_asprintf_append(&str, " </section>\n");
ralloc_asprintf_append(&str,
" <section>\n"
" <description lang=\"en\" text=\"%s\"/>\n",
opt->desc);
in_section = true;
continue;
}
ralloc_asprintf_append(&str,
" <option name=\"%s\" type=\"%s\" default=\"",
name,
types[opt->info.type]);
switch (opt->info.type) {
case DRI_BOOL:
ralloc_asprintf_append(&str, opt->value._bool ? "true" : "false");
break;
case DRI_INT:
case DRI_ENUM:
ralloc_asprintf_append(&str, "%d", opt->value._int);
break;
case DRI_FLOAT:
ralloc_asprintf_append(&str, "%f", opt->value._float);
break;
case DRI_STRING:
ralloc_asprintf_append(&str, "%s", opt->value._string);
break;
case DRI_SECTION:
unreachable("handled above");
break;
}
ralloc_asprintf_append(&str, "\"");
switch (opt->info.type) {
case DRI_INT:
case DRI_ENUM:
if (opt->info.range.start._int < opt->info.range.end._int) {
ralloc_asprintf_append(&str, " valid=\"%d:%d\"",
opt->info.range.start._int,
opt->info.range.end._int);
}
break;
case DRI_FLOAT:
if (opt->info.range.start._float < opt->info.range.end._float) {
ralloc_asprintf_append(&str, " valid=\"%f:%f\"",
opt->info.range.start._float,
opt->info.range.end._float);
}
break;
default:
break;
}
ralloc_asprintf_append(&str, ">\n"); /* end of <option> */
ralloc_asprintf_append(&str, " <description lang=\"en\" text=\"%s\"%s>\n",
opt->desc, opt->info.type != DRI_ENUM ? "/" : "");
if (opt->info.type == DRI_ENUM) {
for (int i = 0; i < ARRAY_SIZE(opt->enums) && opt->enums[i].desc; i++) {
ralloc_asprintf_append(&str, " <enum value=\"%d\" text=\"%s\"/>\n",
opt->enums[i].value, opt->enums[i].desc);
}
ralloc_asprintf_append(&str, " </description>\n");
}
ralloc_asprintf_append(&str, " </option>\n");
}
assert(in_section);
ralloc_asprintf_append(&str, " </section>\n");
ralloc_asprintf_append(&str, "</driinfo>\n");
char *output = strdup(str);
ralloc_free(str);
return output;
}
/** \brief Parser context for configuration files. */

View File

@@ -43,7 +43,7 @@ extern "C" {
/** \brief Option data types */
typedef enum driOptionType {
DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT, DRI_STRING
DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT, DRI_STRING, DRI_SECTION
} driOptionType;
/** \brief Option value */
@@ -91,19 +91,41 @@ typedef struct driOptionCache {
* The value is the same in the screen and all contexts. */
} driOptionCache;
/** \brief Parse XML option info from configOptions
typedef struct driEnumDescription {
int value;
const char *desc;
} driEnumDescription;
/**
* Struct for a driver's definition of an option, its default value, and the
* text documenting it.
*/
typedef struct driOptionDescription {
const char *desc;
driOptionInfo info;
driOptionValue value;
driEnumDescription enums[4];
} driOptionDescription;
/** Returns an XML string describing the options for the driver. */
char *
driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions);
/** \brief Parse driconf option array from configOptions
*
* To be called in <driver>CreateScreen
*
* \param info pointer to a driOptionCache that will store the option info
* \param configOptions XML document describing available configuration opts
* \param configOptions Array of XML document describing available configuration opts
*
* For the option information to be available to external configuration tools
* it must be a public symbol __driConfigOptions. It is also passed as a
* parameter to driParseOptionInfo in order to avoid driver-independent code
* depending on symbols in driver-specific code. */
void driParseOptionInfo(driOptionCache *info,
const char *configOptions);
const driOptionDescription *configOptions,
unsigned numOptions);
/** \brief Initialize option cache from info and parse configuration files
*
* To be called in <driver>CreateContext. screenNum, driverName,