Hello, attached is an updated dri configuration design. Most of the changes are based on the feedback on the list and some things that became clearer after reading the XML 1.0 recommendation. There are still enough of open issues, so don't hesitate to comment on these. The most important one that should be decided before the implementation starts is 3.3 (about character encodings and gcc).
Best regards, Felix ------------ __\|/__ ___ ___ ------------------------- Felix ___\_e -_/___/ __\___/ __\_____ You can do anything, Kühling (_____\Ä/____/ /_____/ /________) just not everything [EMAIL PROTECTED] \___/ \___/ U at the same time.
DRI Configuration Infrastructure (Draft) Revision 1 Felix Kühling <[EMAIL PROTECTED]>, D. Hageman <[EMAIL PROTECTED]> 05 March 2003 1. Introduction --------------- Many proprietary OpenGL implementations come with configuration tools which allow the customization of a large number of parameters. DRI lacks such a configuration so far. The only way to modify the behavior of the driver is through environment variables. The growing number of environment variables and the demand for more configuration options called for a consistent, flexible, robust and last but not least user-friendly configuration infrastructure for DRI. In an ongoing discussion in the last months a number of systems were discussed. I'll summarize them here shortly (without any intention of starting another discussion about the same topic ;-). 1. Keep the old system with environment variables. If you want to save the configuration for your favorite game write a wrapper script which sets the necessary environment variables and then runs the program. 2. Make an OpenGL wrapper library which is loaded via LD_PRELOAD and modifies the behavior of OpenGL transparently to the application. Thus no changes to the drivers are required. 3. The drivers read configuration options from a configuration file. The discussion converged to the third option. A number of demands were brought up which are listed here in no particular order. - It should be possible to change the configuration with a text editor. - It should be easy to implement GUI tools to edit the configuration. - The drivers themselves provide information about available configuration options to external programs. - Internationalized descriptions of driver options - Support for multi-headed setups - Configuration per application, per screen and/or driver - Keep indirect accelerated rendering in mind. - It should be possible for other driver vendors to adopt the same configuration scheme so that their drivers can be configured with the same configuration file and GUI. 2. Design --------- This is a very early stage of a design. Often several options are proposed with a personal preference or argument for one of them. The frequent use of subjunctive will hopefully soon change to more definite statements. 2.1 Configuration file format For the configuration file and for advertising available options we came to a general agreement (or at least the lack of disagreement) to use XML. Advantages are that it is already used in the XFree86 font configuration and a version of expat is included in the XFree86 distribution. It allows the creation of a structured format which can accommodate configuration on a per application, per screen and per driver basis. Furthermore there are XML bindings for a number of scripting languages which will ease the creation of GUI configuration tools. As a disadvantage the bad readability was commonly stated. The W3C XML 1.0 Recommendation specifies the syntax of a well formed XML document. DTDs (document type definitions) are used to define element types and their attributes. The DTD used for the configuration file is shown in an example of a configuration file: <dri> <device> <!-- device independent configuration without a screen or driver attribute --> <application name="Default"> <!-- Default application configuration has no executable attribute. The name can be chosen arbitrarily --> </application> </device> <device screen="0"> <!-- device specification in terms of a X screen number --> <application name="Wolfenstein 3D (Multiplayer)" executable="wolfmp"> <!-- Name attribute is a nice human readable name of an application. The executable attribute is most likely what a driver would have to key off to determine a configuration --> <option name="debug_dma" value="true"/> <option name="preferred_bpt" value="16"/> </application> </device> <device driver="radeon"> <!-- device specification in terms of the DRI driver --> </device> </dri> 2.2 Advertising available options All information about available configuration options, including their data type, valid range and verbal descriptions will be advertised by the drivers. No knowledge about the drivers is required in an external configuration GUI. This way the GUI always presents an up-to-date view of all available options of the drivers currently installed. Furthermore it would be possible for third party binary-only drivers, which adopt this configuration scheme, to be configured by the same GUI without modifications. Available options will be described by an XML document which is contained in a constant character array in the driver. An option is defined by four attributes: - option name - data type (int, float, bool, ...) - range or set of valid values (if applicable) - default value Furthermore internationalized verbal descriptions are associated with each option. Options will be grouped according to their purpose. This extra information is not necessary for parsing or validating the configuration file but it enables the GUI to present options in comprehensible chunks. An example shows how this can be expressed in XML: <section> <description lang="en" text="Debugging"/> <description lang="de" text="Fehlersuche"/> <option name="debug_dma" type="bool" default="false"> <description lang="en" text="Debug DMA buffers"/> <description lang="de" text="DMA Puffer debuggen"/> </option> </section> <section> <description lang="en" text="Texture"/> <description lang="de" text="Textur"/> <option name="preferred_bpt" type="int" valid="0,16,32" default="0"> <description lang="en" text="Preferred texture color depth, 0 means 'same as frame buffer'"/> <description lang="de" text="Bevorzugte Textur Farbtiefe, 0 bedeutet 'so wie Framebuffer'"/> </option> <option name="stupid_example" type="float" valid="0.5-1.0,2.0-3.0" default="0.75"> </option> </section> 2.2.1 Proposed naming conventions Options should be named in a consistent way. We propose to use only lower case letters with words separated by underscores. Clearly driver-specific options should start with a driver name prefix. Other options don't have any prefix at all. 2.2.2 Pools of options Many common options will be duplicated in several drivers, as for instance the "preferred_bpt" example above. This makes maintaining the description translations difficult and leads almost inevitably to diverging translations of similar options in different drivers. Therefore common options and their translations as well as the section descriptions should be maintained in a central place. However, it must still be possible to change the valid value ranges and the default values in a driver-specific way. A set of generic macros would help avoid quoting mistakes and make it easier to change the format in early stages of development. Example: #define DRI_OPT_BEGIN(name,type,def) \ "<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n" #define DRI_OPT_BEGIN_V(name,type,valid,def) \ "<option name=\""#name"\" type=\""#type"\" valid=\""valid" default=\""#def"\">\n" #define DRI_OPT_DESC(lang,text) \ " <description lang=\""#lang"\" text=\""text"\"/>\n" #define DRI_OPT_END \ "</option>\n" #define DRI_OPT_SECTION_BEGIN \ "<section>\n" #define DRI_OPT_SECTION_END \ "</section>\n" Note that only the 'valid' and 'text' arguments have to be specified as string literals and can contain punctuations which would otherwise confuse the preprocessor. The option pool is a header file that uses the generic macros in order to define one parametrized macro for each option and one macro for each type of section: #define DRI_OPT_SECTION_DEBUG \ DRI_OPT_SECTION_BEGIN \ DRI_OPT_DESC(en,"Debugging") \ DRI_OPT_DESC(de,"Fehlersuche") #define DRI_OPT_SECTION_TEXTURE \ DRI_OPT_SECTION_BEGIN \ DRI_OPT_DESC(en,"Texture") \ DRI_OPT_DESC(de,"Textur") #define DRI_OPT_DEBUG_DMA(def) \ DRI_OPT_BEGIN(debug_dma,bool,def) \ DRI_OPT_DESC(en,"Debug DMA buffers") \ DRI_OPT_DESC(de,"DMA Puffer debuggen") \ DRI_OPT_END #define DRI_OPT_PREFERRED_BPT(valid,def) \ DRI_OPT_BEGIN_V(preferred_bpt,int,valid,def) \ DRI_OPT_DESC(en,"Preferred texture color depth, 0 means 'same as frame buffer'") \ DRI_OPT_DESC(de,"Bevorzugte Textur Farbtiefe, 0 bedeutet 'so wie Framebuffer'") \ DRI_OPT_END Driver specific options will be maintained in the same way but in a header file in the driver's own directory. Eventually the drivers construct their list of available options from the macros defined in the central option pool and the driver specific one. const char driConfigurationOptions[] = DRI_OPT_SECTION_DEBUG DRI_OPT_DEBUG_DMA(false) DRI_OPT_SECTION_END DRI_OPT_SECTION_TEXTURE DRI_OPT_PREFERRED_BPT("0,16,32",0) DRI_OPT_END; 2.2.3 Character encoding The XML 1.0 recommendation requires XML processors to support at least the UTF-8 and UTF-16 encodings. UTF-8 is an ASCII compatible multi-byte encoding which supports the entire Unicode character set. Thus it is ideal as a single encoding for internationalized descriptions including languages as different at English, Russian, Greek, Korean, Chinese or Japanese. As the source files containing the option definitions and their descriptions are processed by the C compiler, the compiler would either have to understand input files in UTF-8 encoding or a preprocessor has to translate a UTF-8 encoded option library converting non-ASCII and multi-byte characters in string literals to series of C string escape sequences. The goal is to make sure that the resulting object file contains the available options and descriptions in UTF-8 encoding. So far I haven't been able to find much information about encoding support in gcc. However, for the sake of portability the second options seems preferable. 2.2.4 Obtaining option descriptions from a driver The basic functionality for acquiring descriptions of configuration options will be implemented in libGL. Applications can use glXGetProcAddress to obtain the addresses of the new functions: char *libglGetScreenDriver (Display *dpy, int screen); char *libglGetDriverConfiguration (const char *drivername); libglGetScreenDriver requires a local X connection in order to determine the client side driver associated with screen. libglGetDriverConfiguration can be called without an X connection. The functions will be implemented in xc/lib/GL/dri/dri_glx.c, the same file in which the loading of client side drivers is implemented. Most of the necessary code is already there. libglGetScreenDriver uses the DRI Xserver extension to obtain the name of the client side driver for screen. libglGetDriverConfiguration dlopens the driver and locates the XML document that describes available configuration options using dlsym. The document is copied into a newly allocated buffer before the driver is dlclosed. The address of the buffer is returned to the application. In case of failure NULL is returned. The application has to take care of freeing the memory when it is no longer needed. 2.2.5 Command line tool for dumping XML option descriptions A small command line program will make the functionality of libglGetScreenDriver and libglGetDriverConfiguration available to command line users and to GUIs written in a scripting language that cannot use libGL directly. The command line tool must be able to work with and without a local X connection. The following operations must be supported: 1. get the number of screens on the current display 2. get the driver name for a given screen 3. dump the configuration of the driver on a given screen 4. dump the configuration of a driver given a driver name Without a local X connection only (4) will be available. (3) is redundant but a convenience that is easy enough to implement. Synopsis: xdriinfo [ nscreens | driver <screen> | options <screen or driver> ] If called without an argument it lists the direct rendering capability and, if it is dri capable, the driver name for each screen. 2.3 Validation XML distinguishes between well-formed and valid XML documents. All XML processors verify that a document is well-formed. Only validating XML processors verify the validity of a document with respect to a DTD. Expat, the XML processor included in XFree86, is non-validating. Therefore the correct order and nesting of elements and the use of valid attributes has to be checked by the driver or the GUI that reads a configuration file or an XML document describing available options. There are three choices how to handle unknown elements or attributes and character data: 1) ignore, 2) warning, 3) error. Unknown data in the configuration file should probably cause a warning. If the driver finds unknown data in the XML document describing the driver's options it should indicate a fatal error. Data type and range checking of option values has to be implemented based on the information provided by the drivers. 2.4 Where and when to read the configuration There are two options when to read the configuration file. It could be done right after libGL loaded the DRI driver. Alternatively it could be read when a context is created. As the best place for caching the configuration options seems to be the OpenGL context I prefer reading the configuration on context creation. This would also allow an external utility to test a new configuration online. It would save the configuration, destroy its OpenGL context and create a new one which would automatically use the new configuration. In either case any behavior before the driver is loaded cannot be influenced by configuration options. This includes the environment variables LIBGL_ALWAYS_INDIRECT and LIBGL_DEBUG in the current implementation. Reading and verifying the configuration can be done driver independently. All necessary information is contained in the driver-specific option list. The necessary source files could live in xc/lib/GL/mesa/src/drv/common. The configuration reading routine could be invoked by the driver's context creation function. A configuration cache would be contained in the driver context. All this can be done without touching the Mesa source code. 2.5 Selecting the correct sections from configuration files There should be a system wide configuration in /etc and user-specific configuration files in the users' home directories. The configuration files themselves will be structured in nested sections which contain options specific to a particular device or a set of applications. When the configuration is parsed options from all sections matching the current situation would be read. All other ones are skipped including all their subsections. If the same option is specified and read more than once then the one read last will apply. Options read from a user-specific configuration file override the system wide configuration. Technically there is no limit to the order or depth of nesting of device and application sections from the driver's point of view. It may however be a good idea to enforce limitations in order to allow configuration GUIs to present the configuration in a simple way. The most sensible ordering for systems which have generally only few pieces of graphics hardware but many applications installed would be to have device sections on the top level with nested application specific sections. Allowing the opposite order of nesting would not add more power to the configuration files. It would only be a matter convenience for very rare setups with many different graphics devices. The conventions used in the example configuration file in section 2.1 can be summarized like this: - On the top level there are only device sections. - A device section without a screen or driver attribute applies to all devices. - Device sections contain only application sections. - Application sections without an executable attribute apply to all applications. - Only application sections can contain options. 2.6 How to query configuration options inside the driver The configuration is cached in an opaque data type driConfigCache. A set of functions for querying options of different types will be exported to the drivers with naming conventions similar to OpenGL functions: GLint driQueryOptioni (const driConfigCache *config, const char *name); GLfloat driQueryOptionf (const driConfigCache *config, const char *name); ... If a configuration option was not specified in the configuration file then these functions would return the default value given in driConfigurationOptions. If an option's type and the function used don't match or if a queried option is not defined at all an assertion should fail in order to enforce consistency as to how options are advertised and used. The driQueryOption* calls would obviously be rather expensive as they have to find an option given a string as a key, even if some intelligent hashing algorithm is used. Therefore they should not be used in inner loops. If an option has to be accessed very frequently it is better to query the option once during context creation and store the value in a variable in the driver context in the same way as environment variables are handled now. 3. Issues --------- 3.1 Are there better keys for device sections in the config file than "screen" and "driver"? How would the driver and the GUI associate the key with a driver name? One idea was to use the device identifier from XF86Config-4. However, with the current DRI extension there is no way to find the driver name associated with a device identifier. 3.2 Do we need more data types than int, float and bool? 3.3 Someone with experience in internationalization should comment on section 2.2.3. What about gcc and character encodings? 3.4 Nesting of device and application sections. Flexibility vs. Simplicity See section 2.5. 3.5 Where would the DTDs be stored so that they are available to the driver and the GUI? Closed. Expat is non-validating, so we don't need DTDs. 3.6 Common options We should decide on an initial pool of common options which should be implemented in all driver if supported by the respective hardware. Having an initial pool of common options would also avoid uncontrolled growth of driver-specific option pools in early stages. 3.7 Internals of the parser and the option cache This is really an implementation issue with low priority for now. Just pointing out that we haven't thought about it yet. 4. Revision History ------------------ 2003/02/19 First public version 2003/03/05 Revision 1 - Reading drivers' XML option description in libGL - Command line tool xdriinfo - XML terminology - Expat instead of libxml - Less subjunctive References ---------- Larry Mongin An XML primer (http://www.bloomington.in.us/~mongin/xml-tutorial/index.htm) The Expat XML Parser (http://expat.sourceforge.net) LibXML Website (http://www.libxml.org) W3C Recommendation Extensible Markup Language (XML) 1.0 (Second Edition) (http://www.w3.org/TR/2000/REC-xml-20001006) DRI Website (http://dri.sourceforge.net) ARB_get_proc_address (http://oss.sgi.com/projects/ogl-sample/registry/ARB/get_proc_address.txt)