Imported Upstream version 1.15.1
[deb_xorg-server.git] / glx / glxdricommon.c
CommitLineData
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
44static int
45getUST(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
61const __DRIsystemTimeExtension systemTimeExtension = {
62 {__DRI_SYSTEM_TIME, 1},
63 getUST,
64 NULL,
65};
66
67#define __ATTRIB(attrib, field) \
68 { attrib, offsetof(__GLXconfig, field) }
69
70static 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
113static void
114setScalar(__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
125static __GLXconfig *
126createModeFromConfig(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
186static Bool
187render_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 *
201glxConvertConfigs(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
249static 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
259void *
260glxProbeDriver(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}