Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2008 Red Hat, Inc | |
3 | * | |
4 | * Permission to use, copy, modify, distribute, and sell this software | |
5 | * and its documentation for any purpose is hereby granted without | |
6 | * fee, provided that the above copyright notice appear in all copies | |
7 | * and that both that copyright notice and this permission notice | |
8 | * appear in supporting documentation, and that the name of the | |
9 | * copyright holders not be used in advertising or publicity | |
10 | * pertaining to distribution of the software without specific, | |
11 | * written prior permission. The copyright holders make no | |
12 | * representations about the suitability of this software for any | |
13 | * purpose. It is provided "as is" without express or implied | |
14 | * warranty. | |
15 | * | |
16 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | |
17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
18 | * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
19 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
20 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | |
21 | * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | |
22 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
23 | * SOFTWARE. | |
24 | */ | |
25 | ||
26 | #ifdef HAVE_DIX_CONFIG_H | |
27 | #include <dix-config.h> | |
28 | #endif | |
29 | ||
30 | #include <stdint.h> | |
31 | #include <errno.h> | |
32 | #include <dlfcn.h> | |
33 | #include <sys/time.h> | |
34 | #include <GL/gl.h> | |
35 | #include <GL/glxtokens.h> | |
36 | #include <GL/internal/dri_interface.h> | |
37 | #include <os.h> | |
38 | #include "glxserver.h" | |
39 | #include "glxext.h" | |
40 | #include "glxcontext.h" | |
41 | #include "glxscreens.h" | |
42 | #include "glxdricommon.h" | |
43 | ||
44 | static int | |
45 | getUST(int64_t * ust) | |
46 | { | |
47 | struct timeval tv; | |
48 | ||
49 | if (ust == NULL) | |
50 | return -EFAULT; | |
51 | ||
52 | if (gettimeofday(&tv, NULL) == 0) { | |
53 | ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; | |
54 | return 0; | |
55 | } | |
56 | else { | |
57 | return -errno; | |
58 | } | |
59 | } | |
60 | ||
61 | const __DRIsystemTimeExtension systemTimeExtension = { | |
62 | {__DRI_SYSTEM_TIME, 1}, | |
63 | getUST, | |
64 | NULL, | |
65 | }; | |
66 | ||
67 | #define __ATTRIB(attrib, field) \ | |
68 | { attrib, offsetof(__GLXconfig, field) } | |
69 | ||
70 | static const struct { | |
71 | unsigned int attrib, offset; | |
72 | } attribMap[] = { | |
73 | __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), | |
74 | __ATTRIB(__DRI_ATTRIB_LEVEL, level), | |
75 | __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), | |
76 | __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), | |
77 | __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), | |
78 | __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), | |
79 | __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), | |
80 | __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), | |
81 | __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), | |
82 | __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), | |
83 | __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), | |
84 | __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), | |
85 | __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), | |
86 | __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), | |
87 | __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), | |
88 | __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), | |
89 | __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), | |
90 | __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), | |
91 | __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), | |
92 | __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), | |
93 | __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), | |
94 | __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), | |
95 | __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), | |
96 | __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), | |
97 | __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), | |
98 | __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), | |
99 | __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), | |
100 | __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), | |
101 | __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), | |
102 | __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), | |
103 | __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), | |
104 | __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), | |
105 | __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), | |
106 | __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), | |
107 | __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), | |
108 | __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), | |
109 | __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), | |
110 | __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE, sRGBCapable), | |
111 | }; | |
112 | ||
113 | static void | |
114 | setScalar(__GLXconfig * config, unsigned int attrib, unsigned int value) | |
115 | { | |
116 | int i; | |
117 | ||
118 | for (i = 0; i < ARRAY_SIZE(attribMap); i++) | |
119 | if (attribMap[i].attrib == attrib) { | |
120 | *(unsigned int *) ((char *) config + attribMap[i].offset) = value; | |
121 | return; | |
122 | } | |
123 | } | |
124 | ||
125 | static __GLXconfig * | |
126 | createModeFromConfig(const __DRIcoreExtension * core, | |
127 | const __DRIconfig * driConfig, | |
128 | unsigned int visualType, unsigned int drawableType) | |
129 | { | |
130 | __GLXDRIconfig *config; | |
131 | GLint renderType = 0; | |
132 | unsigned int attrib, value; | |
133 | int i; | |
134 | ||
135 | config = calloc(1, sizeof *config); | |
136 | ||
137 | config->driConfig = driConfig; | |
138 | ||
139 | i = 0; | |
140 | while (core->indexConfigAttrib(driConfig, i++, &attrib, &value)) { | |
141 | switch (attrib) { | |
142 | case __DRI_ATTRIB_RENDER_TYPE: | |
143 | if (value & __DRI_ATTRIB_RGBA_BIT) | |
144 | renderType |= GLX_RGBA_BIT; | |
145 | if (value & __DRI_ATTRIB_COLOR_INDEX_BIT) | |
146 | renderType |= GLX_COLOR_INDEX_BIT; | |
147 | if (value & __DRI_ATTRIB_FLOAT_BIT) | |
148 | renderType |= GLX_RGBA_FLOAT_BIT_ARB; | |
149 | if (value & __DRI_ATTRIB_UNSIGNED_FLOAT_BIT) | |
150 | renderType |= GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT; | |
151 | break; | |
152 | case __DRI_ATTRIB_CONFIG_CAVEAT: | |
153 | if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) | |
154 | config->config.visualRating = GLX_NON_CONFORMANT_CONFIG; | |
155 | else if (value & __DRI_ATTRIB_SLOW_BIT) | |
156 | config->config.visualRating = GLX_SLOW_CONFIG; | |
157 | else | |
158 | config->config.visualRating = GLX_NONE; | |
159 | break; | |
160 | case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS: | |
161 | config->config.bindToTextureTargets = 0; | |
162 | if (value & __DRI_ATTRIB_TEXTURE_1D_BIT) | |
163 | config->config.bindToTextureTargets |= GLX_TEXTURE_1D_BIT_EXT; | |
164 | if (value & __DRI_ATTRIB_TEXTURE_2D_BIT) | |
165 | config->config.bindToTextureTargets |= GLX_TEXTURE_2D_BIT_EXT; | |
166 | if (value & __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT) | |
167 | config->config.bindToTextureTargets |= | |
168 | GLX_TEXTURE_RECTANGLE_BIT_EXT; | |
169 | break; | |
170 | default: | |
171 | setScalar(&config->config, attrib, value); | |
172 | break; | |
173 | } | |
174 | } | |
175 | ||
176 | config->config.next = NULL; | |
177 | config->config.xRenderable = GL_TRUE; | |
178 | config->config.visualType = visualType; | |
179 | config->config.renderType = renderType; | |
180 | config->config.drawableType = drawableType; | |
181 | config->config.yInverted = GL_TRUE; | |
182 | ||
183 | return &config->config; | |
184 | } | |
185 | ||
186 | static Bool | |
187 | render_type_is_pbuffer_only(unsigned renderType) | |
188 | { | |
189 | /* The GL_ARB_color_buffer_float spec says: | |
190 | * | |
191 | * "Note that floating point rendering is only supported for | |
192 | * GLXPbuffer drawables. The GLX_DRAWABLE_TYPE attribute of the | |
193 | * GLXFBConfig must have the GLX_PBUFFER_BIT bit set and the | |
194 | * GLX_RENDER_TYPE attribute must have the GLX_RGBA_FLOAT_BIT set." | |
195 | */ | |
196 | return !!(renderType & (__DRI_ATTRIB_UNSIGNED_FLOAT_BIT | |
197 | | __DRI_ATTRIB_FLOAT_BIT)); | |
198 | } | |
199 | ||
200 | __GLXconfig * | |
201 | glxConvertConfigs(const __DRIcoreExtension * core, | |
202 | const __DRIconfig ** configs, unsigned int drawableType) | |
203 | { | |
204 | __GLXconfig head, *tail; | |
205 | int i; | |
206 | ||
207 | tail = &head; | |
208 | head.next = NULL; | |
209 | ||
210 | for (i = 0; configs[i]; i++) { | |
211 | unsigned renderType = 0; | |
212 | if (core->getConfigAttrib(configs[i], __DRI_ATTRIB_RENDER_TYPE, | |
213 | &renderType)) { | |
214 | if (render_type_is_pbuffer_only(renderType) && | |
215 | !(drawableType & GLX_PBUFFER_BIT)) | |
216 | continue; | |
217 | } | |
218 | /* Add all the others */ | |
219 | tail->next = createModeFromConfig(core, | |
220 | configs[i], GLX_TRUE_COLOR, | |
221 | drawableType); | |
222 | if (tail->next == NULL) | |
223 | break; | |
224 | ||
225 | tail = tail->next; | |
226 | } | |
227 | ||
228 | for (i = 0; configs[i]; i++) { | |
229 | int renderType = 0; | |
230 | if (core->getConfigAttrib(configs[i], __DRI_ATTRIB_RENDER_TYPE, | |
231 | &renderType)) { | |
232 | if (render_type_is_pbuffer_only(renderType) && | |
233 | !(drawableType & GLX_PBUFFER_BIT)) | |
234 | continue; | |
235 | } | |
236 | /* Add all the others */ | |
237 | tail->next = createModeFromConfig(core, | |
238 | configs[i], GLX_DIRECT_COLOR, | |
239 | drawableType); | |
240 | if (tail->next == NULL) | |
241 | break; | |
242 | ||
243 | tail = tail->next; | |
244 | } | |
245 | ||
246 | return head.next; | |
247 | } | |
248 | ||
249 | static const char dri_driver_path[] = DRI_DRIVER_PATH; | |
250 | ||
251 | /* Temporary define to allow building without a dri_interface.h from | |
252 | * updated Mesa. Some day when we don't care about Mesa that old any | |
253 | * more this can be removed. | |
254 | */ | |
255 | #ifndef __DRI_DRIVER_GET_EXTENSIONS | |
256 | #define __DRI_DRIVER_GET_EXTENSIONS "__driDriverGetExtensions" | |
257 | #endif | |
258 | ||
259 | void * | |
260 | glxProbeDriver(const char *driverName, | |
261 | void **coreExt, const char *coreName, int coreVersion, | |
262 | void **renderExt, const char *renderName, int renderVersion) | |
263 | { | |
264 | int i; | |
265 | void *driver; | |
266 | char filename[PATH_MAX]; | |
267 | char *get_extensions_name; | |
268 | const __DRIextension **extensions = NULL; | |
269 | ||
270 | snprintf(filename, sizeof filename, "%s/%s_dri.so", | |
271 | dri_driver_path, driverName); | |
272 | ||
273 | driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); | |
274 | if (driver == NULL) { | |
275 | LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n", | |
276 | filename, dlerror()); | |
277 | goto cleanup_failure; | |
278 | } | |
279 | ||
280 | if (asprintf(&get_extensions_name, "%s_%s", | |
281 | __DRI_DRIVER_GET_EXTENSIONS, driverName) != -1) { | |
282 | const __DRIextension **(*get_extensions)(void); | |
283 | ||
284 | get_extensions = dlsym(driver, get_extensions_name); | |
285 | if (get_extensions) | |
286 | extensions = get_extensions(); | |
287 | free(get_extensions_name); | |
288 | } | |
289 | ||
290 | if (!extensions) | |
291 | extensions = dlsym(driver, __DRI_DRIVER_EXTENSIONS); | |
292 | if (extensions == NULL) { | |
293 | LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n", | |
294 | driverName, dlerror()); | |
295 | goto cleanup_failure; | |
296 | } | |
297 | ||
298 | for (i = 0; extensions[i]; i++) { | |
299 | if (strcmp(extensions[i]->name, coreName) == 0 && | |
300 | extensions[i]->version >= coreVersion) { | |
301 | *coreExt = (void *) extensions[i]; | |
302 | } | |
303 | ||
304 | if (strcmp(extensions[i]->name, renderName) == 0 && | |
305 | extensions[i]->version >= renderVersion) { | |
306 | *renderExt = (void *) extensions[i]; | |
307 | } | |
308 | } | |
309 | ||
310 | if (*coreExt == NULL || *renderExt == NULL) { | |
311 | LogMessage(X_ERROR, | |
312 | "AIGLX error: %s does not export required DRI extension\n", | |
313 | driverName); | |
314 | goto cleanup_failure; | |
315 | } | |
316 | return driver; | |
317 | ||
318 | cleanup_failure: | |
319 | if (driver) | |
320 | dlclose(driver); | |
321 | *coreExt = *renderExt = NULL; | |
322 | return NULL; | |
323 | } |