1 /*
2  * XML DRI client-side driver configuration
3  * Copyright (C) 2003 Felix Kuehling
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  *
23  */
24 /**
25  * \file xmlconfig.h
26  * \brief Driver-independent client-side part of the XML configuration
27  * \author Felix Kuehling
28  */
29 
30 #ifndef __XMLCONFIG_H
31 #define __XMLCONFIG_H
32 
33 #include "util/mesa-sha1.h"
34 #include "util/ralloc.h"
35 #include <stdint.h>
36 #include <string.h>
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #if defined(ANDROID) || defined(_WIN32)
43 #define WITH_XMLCONFIG 0
44 #else
45 #define WITH_XMLCONFIG 1
46 #endif
47 
48 #define STRING_CONF_MAXLEN 1024
49 
50 /** \brief Option data types */
51 typedef enum driOptionType {
52    DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT, DRI_STRING, DRI_SECTION
53 } driOptionType;
54 
55 /** \brief Option value */
56 typedef union driOptionValue {
57    unsigned char _bool; /**< \brief Boolean */
58    int _int;      /**< \brief Integer or Enum */
59    float _float;  /**< \brief Floating-point */
60    char *_string;   /**< \brief String */
61 } driOptionValue;
62 
63 /** \brief Single range of valid values
64  *
65  * For empty ranges (a single value) start == end */
66 typedef struct driOptionRange {
67    driOptionValue start; /**< \brief Start */
68    driOptionValue end;   /**< \brief End */
69 } driOptionRange;
70 
71 /** \brief Information about an option */
72 typedef struct driOptionInfo {
73    char *name;             /**< \brief Name */
74    driOptionType type;     /**< \brief Type */
75    driOptionRange range;   /**< \brief Valid range of the option (or 0:0) */
76 } driOptionInfo;
77 
78 /** \brief Option cache
79  *
80  * \li One in <driver>Screen caching option info and the default values
81  * \li One in each <driver>Context with the actual values for that context */
82 typedef struct driOptionCache {
83    driOptionInfo *info;
84    /**< \brief Array of option infos
85     *
86     * Points to the same array in the screen and all contexts */
87    driOptionValue *values;
88    /**< \brief Array of option values
89     *
90     * \li Default values in screen
91     * \li Actual values in contexts
92     */
93    unsigned int tableSize;
94    /**< \brief Size of the arrays
95     *
96     * In the current implementation it's not actually a size but log2(size).
97     * The value is the same in the screen and all contexts. */
98 } driOptionCache;
99 
100 typedef struct driEnumDescription {
101    int value;
102    const char *desc;
103 } driEnumDescription;
104 
105 /**
106  * Struct for a driver's definition of an option, its default value, and the
107  * text documenting it.
108  */
109 typedef struct driOptionDescription {
110    const char *desc;
111 
112    driOptionInfo info;
113    driOptionValue value;
114    driEnumDescription enums[4];
115 } driOptionDescription;
116 
117 /** Returns an XML string describing the options for the driver. */
118 char *
119 driGetOptionsXml(const driOptionDescription *configOptions, unsigned numOptions);
120 
121 /** \brief Parse driconf option array from configOptions
122  *
123  * To be called in <driver>CreateScreen
124  *
125  * \param info    pointer to a driOptionCache that will store the option info
126  * \param configOptions   Array of XML document describing available configuration opts
127  *
128  * For the option information to be available to external configuration tools
129  * it must be a public symbol __driConfigOptions. It is also passed as a
130  * parameter to driParseOptionInfo in order to avoid driver-independent code
131  * depending on symbols in driver-specific code. */
132 void driParseOptionInfo(driOptionCache *info,
133                         const driOptionDescription *configOptions,
134                         unsigned numOptions);
135 /** \brief Initialize option cache from info and parse configuration files
136  *
137  * To be called in <driver>CreateContext. screenNum, driverName,
138  * kernelDriverName, applicationName and engineName select device sections. */
139 void driParseConfigFiles(driOptionCache *cache, const driOptionCache *info,
140                          int screenNum, const char *driverName,
141                          const char *kernelDriverName,
142                          const char *deviceName,
143                          const char *applicationName, uint32_t applicationVersion,
144                          const char *engineName, uint32_t engineVersion);
145 /** \brief Destroy option info
146  *
147  * To be called in <driver>DestroyScreen */
148 void driDestroyOptionInfo(driOptionCache *info);
149 /** \brief Destroy option cache
150  *
151  * To be called in <driver>DestroyContext */
152 void driDestroyOptionCache(driOptionCache *cache);
153 
154 /** \brief Check if there exists a certain option */
155 unsigned char driCheckOption(const driOptionCache *cache, const char *name,
156                              driOptionType type);
157 
158 /** \brief Query a boolean option value */
159 unsigned char driQueryOptionb(const driOptionCache *cache, const char *name);
160 /** \brief Query an integer option value */
161 int driQueryOptioni(const driOptionCache *cache, const char *name);
162 /** \brief Query a floating-point option value */
163 float driQueryOptionf(const driOptionCache *cache, const char *name);
164 /** \brief Query a string option value */
165 char *driQueryOptionstr(const driOptionCache *cache, const char *name);
166 
167 /* Overrides for the unit tests to control drirc parsing. */
168 void driInjectDataDir(const char *dir);
169 void driInjectExecName(const char *exec);
170 
171 /**
172  * Returns a hash of the options for this application.
173  */
174 static inline void
driComputeOptionsSha1(const driOptionCache * cache,unsigned char * sha1)175 driComputeOptionsSha1(const driOptionCache *cache, unsigned char *sha1)
176 {
177    void *ctx = ralloc_context(NULL);
178    char *dri_options = ralloc_strdup(ctx, "");
179 
180    for (int i = 0; i < 1 << cache->tableSize; i++) {
181       if (cache->info[i].name == NULL)
182          continue;
183 
184       bool ret = false;
185       switch (cache->info[i].type) {
186       case DRI_BOOL:
187          ret = ralloc_asprintf_append(&dri_options, "%s:%u,",
188                                       cache->info[i].name,
189                                       cache->values[i]._bool);
190          break;
191       case DRI_INT:
192       case DRI_ENUM:
193          ret = ralloc_asprintf_append(&dri_options, "%s:%d,",
194                                       cache->info[i].name,
195                                       cache->values[i]._int);
196          break;
197       case DRI_FLOAT:
198          ret = ralloc_asprintf_append(&dri_options, "%s:%f,",
199                                       cache->info[i].name,
200                                       cache->values[i]._float);
201          break;
202       case DRI_STRING:
203          ret = ralloc_asprintf_append(&dri_options, "%s:%s,",
204                                       cache->info[i].name,
205                                       cache->values[i]._string);
206          break;
207       default:
208          unreachable("unsupported dri config type!");
209       }
210 
211       if (!ret) {
212          break;
213       }
214    }
215 
216    _mesa_sha1_compute(dri_options, strlen(dri_options), sha1);
217    ralloc_free(ctx);
218 }
219 
220 #ifdef __cplusplus
221 } /* extern C */
222 #endif
223 
224 #endif
225