Rev 4358 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) |
||
3 | * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. |
||
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 including the dates of first publication and |
||
13 | * either this permission notice or a reference to |
||
14 | * http://oss.sgi.com/projects/FreeB/ |
||
15 | * shall be included in all copies or substantial portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
||
21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF |
||
22 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||
23 | * SOFTWARE. |
||
24 | * |
||
25 | * Except as contained in this notice, the name of Silicon Graphics, Inc. |
||
26 | * shall not be used in advertising or otherwise to promote the sale, use or |
||
27 | * other dealings in this Software without prior written authorization from |
||
28 | * Silicon Graphics, Inc. |
||
29 | */ |
||
30 | |||
31 | /** |
||
32 | * \file glxcmds.c |
||
33 | * Client-side GLX interface. |
||
34 | */ |
||
35 | |||
36 | #include "glxclient.h" |
||
37 | #include "glapi.h" |
||
38 | #include "glxextensions.h" |
||
39 | #include "indirect.h" |
||
40 | #include "glx_error.h" |
||
41 | |||
42 | #ifdef GLX_DIRECT_RENDERING |
||
43 | #ifdef GLX_USE_APPLEGL |
||
44 | #include "apple_glx_context.h" |
||
45 | #include "apple_glx.h" |
||
46 | #else |
||
47 | #include |
||
48 | #ifdef XF86VIDMODE |
||
49 | #include |
||
50 | #endif |
||
51 | #include "xf86dri.h" |
||
52 | #endif |
||
53 | #else |
||
54 | #endif |
||
55 | |||
56 | #include |
||
57 | #include |
||
58 | #include |
||
59 | |||
60 | static const char __glXGLXClientVendorName[] = "Mesa Project and SGI"; |
||
61 | static const char __glXGLXClientVersion[] = "1.4"; |
||
62 | |||
63 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
64 | |||
65 | /** |
||
66 | * Get the __DRIdrawable for the drawable associated with a GLXContext |
||
67 | * |
||
68 | * \param dpy The display associated with \c drawable. |
||
69 | * \param drawable GLXDrawable whose __DRIdrawable part is to be retrieved. |
||
70 | * \param scrn_num If non-NULL, the drawables screen is stored there |
||
71 | * \returns A pointer to the context's __DRIdrawable on success, or NULL if |
||
72 | * the drawable is not associated with a direct-rendering context. |
||
73 | */ |
||
74 | _X_HIDDEN __GLXDRIdrawable * |
||
75 | GetGLXDRIDrawable(Display * dpy, GLXDrawable drawable) |
||
76 | { |
||
77 | struct glx_display *priv = __glXInitialize(dpy); |
||
78 | __GLXDRIdrawable *pdraw; |
||
79 | |||
80 | if (priv == NULL) |
||
81 | return NULL; |
||
82 | |||
83 | if (__glxHashLookup(priv->drawHash, drawable, (void *) &pdraw) == 0) |
||
84 | return pdraw; |
||
85 | |||
86 | return NULL; |
||
87 | } |
||
88 | |||
89 | #endif |
||
90 | |||
91 | _X_HIDDEN struct glx_drawable * |
||
92 | GetGLXDrawable(Display *dpy, GLXDrawable drawable) |
||
93 | { |
||
94 | struct glx_display *priv = __glXInitialize(dpy); |
||
95 | struct glx_drawable *glxDraw; |
||
96 | |||
97 | if (priv == NULL) |
||
98 | return NULL; |
||
99 | |||
100 | if (__glxHashLookup(priv->glXDrawHash, drawable, (void *) &glxDraw) == 0) |
||
101 | return glxDraw; |
||
102 | |||
103 | return NULL; |
||
104 | } |
||
105 | |||
106 | _X_HIDDEN int |
||
107 | InitGLXDrawable(Display *dpy, struct glx_drawable *glxDraw, XID xDrawable, |
||
108 | GLXDrawable drawable) |
||
109 | { |
||
110 | struct glx_display *priv = __glXInitialize(dpy); |
||
111 | |||
112 | if (!priv) |
||
113 | return -1; |
||
114 | |||
115 | glxDraw->xDrawable = xDrawable; |
||
116 | glxDraw->drawable = drawable; |
||
117 | glxDraw->lastEventSbc = 0; |
||
118 | glxDraw->eventSbcWrap = 0; |
||
119 | |||
120 | return __glxHashInsert(priv->glXDrawHash, drawable, glxDraw); |
||
121 | } |
||
122 | |||
123 | _X_HIDDEN void |
||
124 | DestroyGLXDrawable(Display *dpy, GLXDrawable drawable) |
||
125 | { |
||
126 | struct glx_display *priv = __glXInitialize(dpy); |
||
127 | struct glx_drawable *glxDraw; |
||
128 | |||
129 | if (!priv) |
||
130 | return; |
||
131 | |||
132 | glxDraw = GetGLXDrawable(dpy, drawable); |
||
133 | __glxHashDelete(priv->glXDrawHash, drawable); |
||
134 | free(glxDraw); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Get the GLX per-screen data structure associated with a GLX context. |
||
139 | * |
||
140 | * \param dpy Display for which the GLX per-screen information is to be |
||
141 | * retrieved. |
||
142 | * \param scrn Screen on \c dpy for which the GLX per-screen information is |
||
143 | * to be retrieved. |
||
144 | * \returns A pointer to the GLX per-screen data if \c dpy and \c scrn |
||
145 | * specify a valid GLX screen, or NULL otherwise. |
||
146 | * |
||
147 | * \todo Should this function validate that \c scrn is within the screen |
||
148 | * number range for \c dpy? |
||
149 | */ |
||
150 | |||
151 | _X_HIDDEN struct glx_screen * |
||
152 | GetGLXScreenConfigs(Display * dpy, int scrn) |
||
153 | { |
||
154 | struct glx_display *const priv = __glXInitialize(dpy); |
||
155 | |||
156 | return (priv |
||
157 | && priv->screens != |
||
158 | NULL) ? priv->screens[scrn] : NULL; |
||
159 | } |
||
160 | |||
161 | |||
162 | static int |
||
163 | GetGLXPrivScreenConfig(Display * dpy, int scrn, struct glx_display ** ppriv, |
||
164 | struct glx_screen ** ppsc) |
||
165 | { |
||
166 | /* Initialize the extension, if needed . This has the added value |
||
167 | * of initializing/allocating the display private |
||
168 | */ |
||
169 | |||
170 | if (dpy == NULL) { |
||
171 | return GLX_NO_EXTENSION; |
||
172 | } |
||
173 | |||
174 | *ppriv = __glXInitialize(dpy); |
||
175 | if (*ppriv == NULL) { |
||
176 | return GLX_NO_EXTENSION; |
||
177 | } |
||
178 | |||
179 | /* Check screen number to see if its valid */ |
||
180 | if ((scrn < 0) || (scrn >= ScreenCount(dpy))) { |
||
181 | return GLX_BAD_SCREEN; |
||
182 | } |
||
183 | |||
184 | /* Check to see if the GL is supported on this screen */ |
||
185 | *ppsc = (*ppriv)->screens[scrn]; |
||
4401 | Serge | 186 | if ((*ppsc)->configs == NULL && (*ppsc)->visuals == NULL) { |
4358 | Serge | 187 | /* No support for GL on this screen regardless of visual */ |
188 | return GLX_BAD_VISUAL; |
||
189 | } |
||
190 | |||
191 | return Success; |
||
192 | } |
||
193 | |||
194 | |||
195 | /** |
||
196 | * Determine if a \c GLXFBConfig supplied by the application is valid. |
||
197 | * |
||
198 | * \param dpy Application supplied \c Display pointer. |
||
199 | * \param config Application supplied \c GLXFBConfig. |
||
200 | * |
||
201 | * \returns If the \c GLXFBConfig is valid, the a pointer to the matching |
||
202 | * \c struct glx_config structure is returned. Otherwise, \c NULL |
||
203 | * is returned. |
||
204 | */ |
||
205 | static struct glx_config * |
||
206 | ValidateGLXFBConfig(Display * dpy, GLXFBConfig fbconfig) |
||
207 | { |
||
208 | struct glx_display *const priv = __glXInitialize(dpy); |
||
209 | int num_screens = ScreenCount(dpy); |
||
210 | unsigned i; |
||
211 | struct glx_config *config; |
||
212 | |||
213 | if (priv != NULL) { |
||
214 | for (i = 0; i < num_screens; i++) { |
||
215 | for (config = priv->screens[i]->configs; config != NULL; |
||
216 | config = config->next) { |
||
217 | if (config == (struct glx_config *) fbconfig) { |
||
218 | return config; |
||
219 | } |
||
220 | } |
||
221 | } |
||
222 | } |
||
223 | |||
224 | return NULL; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Verifies context's GLX_RENDER_TYPE value with config. |
||
229 | * |
||
230 | * \param config GLX FBConfig which will support the returned renderType. |
||
231 | * \param renderType The context render type to be verified. |
||
232 | * \return True if the value of context renderType was approved, or 0 if no |
||
233 | * valid value was found. |
||
234 | */ |
||
235 | Bool |
||
236 | validate_renderType_against_config(const struct glx_config *config, |
||
237 | int renderType) |
||
238 | { |
||
239 | switch (renderType) { |
||
240 | case GLX_RGBA_TYPE: |
||
241 | return (config->renderType & GLX_RGBA_BIT) != 0; |
||
242 | case GLX_COLOR_INDEX_TYPE: |
||
243 | return (config->renderType & GLX_COLOR_INDEX_BIT) != 0; |
||
244 | case GLX_RGBA_FLOAT_TYPE_ARB: |
||
245 | return (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) != 0; |
||
246 | case GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT: |
||
247 | return (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) != 0; |
||
248 | default: |
||
249 | break; |
||
250 | } |
||
251 | return 0; |
||
252 | } |
||
253 | |||
254 | _X_HIDDEN Bool |
||
255 | glx_context_init(struct glx_context *gc, |
||
256 | struct glx_screen *psc, struct glx_config *config) |
||
257 | { |
||
258 | gc->majorOpcode = __glXSetupForCommand(psc->display->dpy); |
||
259 | if (!gc->majorOpcode) |
||
260 | return False; |
||
261 | |||
262 | gc->screen = psc->scr; |
||
263 | gc->psc = psc; |
||
264 | gc->config = config; |
||
265 | gc->isDirect = GL_TRUE; |
||
266 | gc->currentContextTag = -1; |
||
267 | |||
268 | return True; |
||
269 | } |
||
270 | |||
271 | |||
272 | /** |
||
273 | * Create a new context. |
||
274 | * |
||
275 | * \param renderType For FBConfigs, what is the rendering type? |
||
276 | */ |
||
277 | |||
278 | static GLXContext |
||
279 | CreateContext(Display *dpy, int generic_id, struct glx_config *config, |
||
280 | GLXContext shareList_user, Bool allowDirect, |
||
281 | unsigned code, int renderType, int screen) |
||
282 | { |
||
283 | struct glx_context *gc; |
||
284 | struct glx_screen *psc; |
||
285 | struct glx_context *shareList = (struct glx_context *) shareList_user; |
||
286 | if (dpy == NULL) |
||
287 | return NULL; |
||
288 | |||
289 | psc = GetGLXScreenConfigs(dpy, screen); |
||
290 | if (psc == NULL) |
||
291 | return NULL; |
||
292 | |||
293 | if (generic_id == None) |
||
294 | return NULL; |
||
295 | |||
296 | gc = NULL; |
||
297 | #ifdef GLX_USE_APPLEGL |
||
298 | gc = applegl_create_context(psc, config, shareList, renderType); |
||
299 | #else |
||
300 | if (allowDirect && psc->vtable->create_context) |
||
301 | gc = psc->vtable->create_context(psc, config, shareList, renderType); |
||
302 | if (!gc) |
||
303 | gc = indirect_create_context(psc, config, shareList, renderType); |
||
304 | #endif |
||
305 | if (!gc) |
||
306 | return NULL; |
||
307 | |||
308 | LockDisplay(dpy); |
||
309 | switch (code) { |
||
310 | case X_GLXCreateContext: { |
||
311 | xGLXCreateContextReq *req; |
||
312 | |||
313 | /* Send the glXCreateContext request */ |
||
314 | GetReq(GLXCreateContext, req); |
||
315 | req->reqType = gc->majorOpcode; |
||
316 | req->glxCode = X_GLXCreateContext; |
||
317 | req->context = gc->xid = XAllocID(dpy); |
||
318 | req->visual = generic_id; |
||
319 | req->screen = screen; |
||
320 | req->shareList = shareList ? shareList->xid : None; |
||
321 | req->isDirect = gc->isDirect; |
||
322 | break; |
||
323 | } |
||
324 | |||
325 | case X_GLXCreateNewContext: { |
||
326 | xGLXCreateNewContextReq *req; |
||
327 | |||
328 | /* Send the glXCreateNewContext request */ |
||
329 | GetReq(GLXCreateNewContext, req); |
||
330 | req->reqType = gc->majorOpcode; |
||
331 | req->glxCode = X_GLXCreateNewContext; |
||
332 | req->context = gc->xid = XAllocID(dpy); |
||
333 | req->fbconfig = generic_id; |
||
334 | req->screen = screen; |
||
335 | req->renderType = renderType; |
||
336 | req->shareList = shareList ? shareList->xid : None; |
||
337 | req->isDirect = gc->isDirect; |
||
338 | break; |
||
339 | } |
||
340 | |||
341 | case X_GLXvop_CreateContextWithConfigSGIX: { |
||
342 | xGLXVendorPrivateWithReplyReq *vpreq; |
||
343 | xGLXCreateContextWithConfigSGIXReq *req; |
||
344 | |||
345 | /* Send the glXCreateNewContext request */ |
||
346 | GetReqExtra(GLXVendorPrivateWithReply, |
||
347 | sz_xGLXCreateContextWithConfigSGIXReq - |
||
348 | sz_xGLXVendorPrivateWithReplyReq, vpreq); |
||
349 | req = (xGLXCreateContextWithConfigSGIXReq *) vpreq; |
||
350 | req->reqType = gc->majorOpcode; |
||
351 | req->glxCode = X_GLXVendorPrivateWithReply; |
||
352 | req->vendorCode = X_GLXvop_CreateContextWithConfigSGIX; |
||
353 | req->context = gc->xid = XAllocID(dpy); |
||
354 | req->fbconfig = generic_id; |
||
355 | req->screen = screen; |
||
356 | req->renderType = renderType; |
||
357 | req->shareList = shareList ? shareList->xid : None; |
||
358 | req->isDirect = gc->isDirect; |
||
359 | break; |
||
360 | } |
||
361 | |||
362 | default: |
||
363 | /* What to do here? This case is the sign of an internal error. It |
||
364 | * should never be reachable. |
||
365 | */ |
||
366 | break; |
||
367 | } |
||
368 | |||
369 | UnlockDisplay(dpy); |
||
370 | SyncHandle(); |
||
371 | |||
372 | gc->share_xid = shareList ? shareList->xid : None; |
||
373 | gc->imported = GL_FALSE; |
||
374 | |||
375 | return (GLXContext) gc; |
||
376 | } |
||
377 | |||
378 | _X_EXPORT GLXContext |
||
379 | glXCreateContext(Display * dpy, XVisualInfo * vis, |
||
380 | GLXContext shareList, Bool allowDirect) |
||
381 | { |
||
382 | struct glx_config *config = NULL; |
||
383 | int renderType = GLX_RGBA_TYPE; |
||
384 | |||
385 | #if defined(GLX_DIRECT_RENDERING) || defined(GLX_USE_APPLEGL) |
||
386 | struct glx_screen *const psc = GetGLXScreenConfigs(dpy, vis->screen); |
||
387 | |||
388 | config = glx_config_find_visual(psc->visuals, vis->visualid); |
||
389 | if (config == NULL) { |
||
390 | xError error; |
||
391 | |||
392 | error.errorCode = BadValue; |
||
393 | error.resourceID = vis->visualid; |
||
394 | error.sequenceNumber = dpy->request; |
||
395 | error.type = X_Error; |
||
396 | error.majorCode = __glXSetupForCommand(dpy); |
||
397 | error.minorCode = X_GLXCreateContext; |
||
398 | _XError(dpy, &error); |
||
399 | return None; |
||
400 | } |
||
401 | |||
402 | /* Choose the context render type based on DRI config values. It is |
||
403 | * unusual to set this type from config, but we have no other choice, as |
||
404 | * this old API does not provide renderType parameter. |
||
405 | */ |
||
406 | if (config->renderType & GLX_RGBA_FLOAT_BIT_ARB) { |
||
407 | renderType = GLX_RGBA_FLOAT_TYPE_ARB; |
||
408 | } else if (config->renderType & GLX_RGBA_UNSIGNED_FLOAT_BIT_EXT) { |
||
409 | renderType = GLX_RGBA_UNSIGNED_FLOAT_TYPE_EXT; |
||
410 | } else if (config->renderType & GLX_RGBA_BIT) { |
||
411 | renderType = GLX_RGBA_TYPE; |
||
412 | } else if (config->renderType & GLX_COLOR_INDEX_BIT) { |
||
413 | renderType = GLX_COLOR_INDEX_TYPE; |
||
414 | } else if (config->rgbMode) { |
||
415 | /* If we're here, then renderType is not set correctly. Let's use a |
||
416 | * safeguard - any TrueColor or DirectColor mode is RGB mode. Such |
||
417 | * default value is needed by old DRI drivers, which didn't set |
||
418 | * renderType correctly as the value was just ignored. |
||
419 | */ |
||
420 | renderType = GLX_RGBA_TYPE; |
||
421 | } else { |
||
422 | /* Safeguard - only one option left, all non-RGB modes are indexed |
||
423 | * modes. Again, this allows drivers with invalid renderType to work |
||
424 | * properly. |
||
425 | */ |
||
426 | renderType = GLX_COLOR_INDEX_TYPE; |
||
427 | } |
||
428 | #endif |
||
429 | |||
430 | return CreateContext(dpy, vis->visualid, config, shareList, allowDirect, |
||
431 | X_GLXCreateContext, renderType, vis->screen); |
||
432 | } |
||
433 | |||
434 | static void |
||
435 | glx_send_destroy_context(Display *dpy, XID xid) |
||
436 | { |
||
437 | CARD8 opcode = __glXSetupForCommand(dpy); |
||
438 | xGLXDestroyContextReq *req; |
||
439 | |||
440 | LockDisplay(dpy); |
||
441 | GetReq(GLXDestroyContext, req); |
||
442 | req->reqType = opcode; |
||
443 | req->glxCode = X_GLXDestroyContext; |
||
444 | req->context = xid; |
||
445 | UnlockDisplay(dpy); |
||
446 | SyncHandle(); |
||
447 | } |
||
448 | |||
449 | /* |
||
450 | ** Destroy the named context |
||
451 | */ |
||
452 | |||
453 | _X_EXPORT void |
||
454 | glXDestroyContext(Display * dpy, GLXContext ctx) |
||
455 | { |
||
456 | struct glx_context *gc = (struct glx_context *) ctx; |
||
457 | |||
458 | if (gc == NULL || gc->xid == None) |
||
459 | return; |
||
460 | |||
461 | __glXLock(); |
||
462 | if (!gc->imported) |
||
463 | glx_send_destroy_context(dpy, gc->xid); |
||
464 | |||
465 | if (gc->currentDpy) { |
||
466 | /* This context is bound to some thread. According to the man page, |
||
467 | * we should not actually delete the context until it's unbound. |
||
468 | * Note that we set gc->xid = None above. In MakeContextCurrent() |
||
469 | * we check for that and delete the context there. |
||
470 | */ |
||
471 | gc->xid = None; |
||
472 | } else { |
||
473 | gc->vtable->destroy(gc); |
||
474 | } |
||
475 | __glXUnlock(); |
||
476 | } |
||
477 | |||
478 | /* |
||
479 | ** Return the major and minor version #s for the GLX extension |
||
480 | */ |
||
481 | _X_EXPORT Bool |
||
482 | glXQueryVersion(Display * dpy, int *major, int *minor) |
||
483 | { |
||
484 | struct glx_display *priv; |
||
485 | |||
486 | /* Init the extension. This fetches the major and minor version. */ |
||
487 | priv = __glXInitialize(dpy); |
||
488 | if (!priv) |
||
489 | return False; |
||
490 | |||
491 | if (major) |
||
492 | *major = priv->majorVersion; |
||
493 | if (minor) |
||
494 | *minor = priv->minorVersion; |
||
495 | return True; |
||
496 | } |
||
497 | |||
498 | /* |
||
499 | ** Query the existance of the GLX extension |
||
500 | */ |
||
501 | _X_EXPORT Bool |
||
502 | glXQueryExtension(Display * dpy, int *errorBase, int *eventBase) |
||
503 | { |
||
504 | int major_op, erb, evb; |
||
505 | Bool rv; |
||
506 | |||
507 | rv = XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_op, &evb, &erb); |
||
508 | if (rv) { |
||
509 | if (errorBase) |
||
510 | *errorBase = erb; |
||
511 | if (eventBase) |
||
512 | *eventBase = evb; |
||
513 | } |
||
514 | return rv; |
||
515 | } |
||
516 | |||
517 | /* |
||
518 | ** Put a barrier in the token stream that forces the GL to finish its |
||
519 | ** work before X can proceed. |
||
520 | */ |
||
521 | _X_EXPORT void |
||
522 | glXWaitGL(void) |
||
523 | { |
||
524 | struct glx_context *gc = __glXGetCurrentContext(); |
||
525 | |||
526 | if (gc && gc->vtable->wait_gl) |
||
527 | gc->vtable->wait_gl(gc); |
||
528 | } |
||
529 | |||
530 | /* |
||
531 | ** Put a barrier in the token stream that forces X to finish its |
||
532 | ** work before GL can proceed. |
||
533 | */ |
||
534 | _X_EXPORT void |
||
535 | glXWaitX(void) |
||
536 | { |
||
537 | struct glx_context *gc = __glXGetCurrentContext(); |
||
538 | |||
539 | if (gc && gc->vtable->wait_x) |
||
540 | gc->vtable->wait_x(gc); |
||
541 | } |
||
542 | |||
543 | _X_EXPORT void |
||
544 | glXUseXFont(Font font, int first, int count, int listBase) |
||
545 | { |
||
546 | struct glx_context *gc = __glXGetCurrentContext(); |
||
547 | |||
548 | if (gc && gc->vtable->use_x_font) |
||
549 | gc->vtable->use_x_font(gc, font, first, count, listBase); |
||
550 | } |
||
551 | |||
552 | /************************************************************************/ |
||
553 | |||
554 | /* |
||
555 | ** Copy the source context to the destination context using the |
||
556 | ** attribute "mask". |
||
557 | */ |
||
558 | _X_EXPORT void |
||
559 | glXCopyContext(Display * dpy, GLXContext source_user, |
||
560 | GLXContext dest_user, unsigned long mask) |
||
561 | { |
||
562 | struct glx_context *source = (struct glx_context *) source_user; |
||
563 | struct glx_context *dest = (struct glx_context *) dest_user; |
||
564 | #ifdef GLX_USE_APPLEGL |
||
565 | struct glx_context *gc = __glXGetCurrentContext(); |
||
566 | int errorcode; |
||
567 | bool x11error; |
||
568 | |||
569 | if(apple_glx_copy_context(gc->driContext, source->driContext, dest->driContext, |
||
570 | mask, &errorcode, &x11error)) { |
||
571 | __glXSendError(dpy, errorcode, 0, X_GLXCopyContext, x11error); |
||
572 | } |
||
573 | |||
574 | #else |
||
575 | xGLXCopyContextReq *req; |
||
576 | struct glx_context *gc = __glXGetCurrentContext(); |
||
577 | GLXContextTag tag; |
||
578 | CARD8 opcode; |
||
579 | |||
580 | opcode = __glXSetupForCommand(dpy); |
||
581 | if (!opcode) { |
||
582 | return; |
||
583 | } |
||
584 | |||
585 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
586 | if (gc->isDirect) { |
||
587 | /* NOT_DONE: This does not work yet */ |
||
588 | } |
||
589 | #endif |
||
590 | |||
591 | /* |
||
592 | ** If the source is the current context, send its tag so that the context |
||
593 | ** can be flushed before the copy. |
||
594 | */ |
||
595 | if (source == gc && dpy == gc->currentDpy) { |
||
596 | tag = gc->currentContextTag; |
||
597 | } |
||
598 | else { |
||
599 | tag = 0; |
||
600 | } |
||
601 | |||
602 | /* Send the glXCopyContext request */ |
||
603 | LockDisplay(dpy); |
||
604 | GetReq(GLXCopyContext, req); |
||
605 | req->reqType = opcode; |
||
606 | req->glxCode = X_GLXCopyContext; |
||
607 | req->source = source ? source->xid : None; |
||
608 | req->dest = dest ? dest->xid : None; |
||
609 | req->mask = mask; |
||
610 | req->contextTag = tag; |
||
611 | UnlockDisplay(dpy); |
||
612 | SyncHandle(); |
||
613 | #endif /* GLX_USE_APPLEGL */ |
||
614 | } |
||
615 | |||
616 | |||
617 | /** |
||
618 | * Determine if a context uses direct rendering. |
||
619 | * |
||
620 | * \param dpy Display where the context was created. |
||
621 | * \param contextID ID of the context to be tested. |
||
622 | * |
||
623 | * \returns \c True if the context is direct rendering or not. |
||
624 | */ |
||
625 | static Bool |
||
626 | __glXIsDirect(Display * dpy, GLXContextID contextID) |
||
627 | { |
||
628 | CARD8 opcode; |
||
629 | xcb_connection_t *c; |
||
630 | xcb_generic_error_t *err; |
||
631 | xcb_glx_is_direct_reply_t *reply; |
||
632 | Bool is_direct; |
||
633 | |||
634 | opcode = __glXSetupForCommand(dpy); |
||
635 | if (!opcode) { |
||
636 | return False; |
||
637 | } |
||
638 | |||
639 | c = XGetXCBConnection(dpy); |
||
640 | reply = xcb_glx_is_direct_reply(c, xcb_glx_is_direct(c, contextID), &err); |
||
641 | is_direct = (reply != NULL && reply->is_direct) ? True : False; |
||
642 | |||
643 | if (err != NULL) { |
||
644 | __glXSendErrorForXcb(dpy, err); |
||
645 | free(err); |
||
646 | } |
||
647 | |||
648 | free(reply); |
||
649 | |||
650 | return is_direct; |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * \todo |
||
655 | * Shouldn't this function \b always return \c False when |
||
656 | * \c GLX_DIRECT_RENDERING is not defined? Do we really need to bother with |
||
657 | * the GLX protocol here at all? |
||
658 | */ |
||
659 | _X_EXPORT Bool |
||
660 | glXIsDirect(Display * dpy, GLXContext gc_user) |
||
661 | { |
||
662 | struct glx_context *gc = (struct glx_context *) gc_user; |
||
663 | |||
664 | if (!gc) { |
||
665 | return False; |
||
666 | } |
||
667 | else if (gc->isDirect) { |
||
668 | return True; |
||
669 | } |
||
670 | #ifdef GLX_USE_APPLEGL /* TODO: indirect on darwin */ |
||
671 | return False; |
||
672 | #else |
||
673 | return __glXIsDirect(dpy, gc->xid); |
||
674 | #endif |
||
675 | } |
||
676 | |||
677 | _X_EXPORT GLXPixmap |
||
678 | glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap) |
||
679 | { |
||
680 | #ifdef GLX_USE_APPLEGL |
||
681 | int screen = vis->screen; |
||
682 | struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen); |
||
683 | const struct glx_config *config; |
||
684 | |||
685 | config = glx_config_find_visual(psc->visuals, vis->visualid); |
||
686 | |||
687 | if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config)) |
||
688 | return None; |
||
689 | |||
690 | return pixmap; |
||
691 | #else |
||
692 | xGLXCreateGLXPixmapReq *req; |
||
693 | struct glx_drawable *glxDraw; |
||
694 | GLXPixmap xid; |
||
695 | CARD8 opcode; |
||
696 | |||
697 | opcode = __glXSetupForCommand(dpy); |
||
698 | if (!opcode) { |
||
699 | return None; |
||
700 | } |
||
701 | |||
702 | glxDraw = malloc(sizeof(*glxDraw)); |
||
703 | if (!glxDraw) |
||
704 | return None; |
||
705 | |||
706 | /* Send the glXCreateGLXPixmap request */ |
||
707 | LockDisplay(dpy); |
||
708 | GetReq(GLXCreateGLXPixmap, req); |
||
709 | req->reqType = opcode; |
||
710 | req->glxCode = X_GLXCreateGLXPixmap; |
||
711 | req->screen = vis->screen; |
||
712 | req->visual = vis->visualid; |
||
713 | req->pixmap = pixmap; |
||
714 | req->glxpixmap = xid = XAllocID(dpy); |
||
715 | UnlockDisplay(dpy); |
||
716 | SyncHandle(); |
||
717 | |||
718 | if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) { |
||
719 | free(glxDraw); |
||
720 | return None; |
||
721 | } |
||
722 | |||
723 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
724 | do { |
||
725 | /* FIXME: Maybe delay __DRIdrawable creation until the drawable |
||
726 | * is actually bound to a context... */ |
||
727 | |||
728 | struct glx_display *const priv = __glXInitialize(dpy); |
||
729 | __GLXDRIdrawable *pdraw; |
||
730 | struct glx_screen *psc; |
||
731 | struct glx_config *config; |
||
732 | |||
733 | psc = priv->screens[vis->screen]; |
||
734 | if (psc->driScreen == NULL) |
||
735 | return xid; |
||
736 | |||
737 | config = glx_config_find_visual(psc->visuals, vis->visualid); |
||
738 | pdraw = psc->driScreen->createDrawable(psc, pixmap, xid, config); |
||
739 | if (pdraw == NULL) { |
||
740 | fprintf(stderr, "failed to create pixmap\n"); |
||
741 | xid = None; |
||
742 | break; |
||
743 | } |
||
744 | |||
745 | if (__glxHashInsert(priv->drawHash, xid, pdraw)) { |
||
746 | (*pdraw->destroyDrawable) (pdraw); |
||
747 | xid = None; |
||
748 | break; |
||
749 | } |
||
750 | } while (0); |
||
751 | |||
752 | if (xid == None) { |
||
753 | xGLXDestroyGLXPixmapReq *dreq; |
||
754 | LockDisplay(dpy); |
||
755 | GetReq(GLXDestroyGLXPixmap, dreq); |
||
756 | dreq->reqType = opcode; |
||
757 | dreq->glxCode = X_GLXDestroyGLXPixmap; |
||
758 | dreq->glxpixmap = xid; |
||
759 | UnlockDisplay(dpy); |
||
760 | SyncHandle(); |
||
761 | } |
||
762 | #endif |
||
763 | |||
764 | return xid; |
||
765 | #endif |
||
766 | } |
||
767 | |||
768 | /* |
||
769 | ** Destroy the named pixmap |
||
770 | */ |
||
771 | _X_EXPORT void |
||
772 | glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap) |
||
773 | { |
||
774 | #ifdef GLX_USE_APPLEGL |
||
775 | if(apple_glx_pixmap_destroy(dpy, glxpixmap)) |
||
776 | __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false); |
||
777 | #else |
||
778 | xGLXDestroyGLXPixmapReq *req; |
||
779 | CARD8 opcode; |
||
780 | |||
781 | opcode = __glXSetupForCommand(dpy); |
||
782 | if (!opcode) { |
||
783 | return; |
||
784 | } |
||
785 | |||
786 | /* Send the glXDestroyGLXPixmap request */ |
||
787 | LockDisplay(dpy); |
||
788 | GetReq(GLXDestroyGLXPixmap, req); |
||
789 | req->reqType = opcode; |
||
790 | req->glxCode = X_GLXDestroyGLXPixmap; |
||
791 | req->glxpixmap = glxpixmap; |
||
792 | UnlockDisplay(dpy); |
||
793 | SyncHandle(); |
||
794 | |||
795 | DestroyGLXDrawable(dpy, glxpixmap); |
||
796 | |||
797 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
798 | { |
||
799 | struct glx_display *const priv = __glXInitialize(dpy); |
||
800 | __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, glxpixmap); |
||
801 | |||
802 | if (pdraw != NULL) { |
||
803 | (*pdraw->destroyDrawable) (pdraw); |
||
804 | __glxHashDelete(priv->drawHash, glxpixmap); |
||
805 | } |
||
806 | } |
||
807 | #endif |
||
808 | #endif /* GLX_USE_APPLEGL */ |
||
809 | } |
||
810 | |||
811 | _X_EXPORT void |
||
812 | glXSwapBuffers(Display * dpy, GLXDrawable drawable) |
||
813 | { |
||
814 | #ifdef GLX_USE_APPLEGL |
||
815 | struct glx_context * gc = __glXGetCurrentContext(); |
||
816 | if(gc && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) { |
||
817 | apple_glx_swap_buffers(gc->driContext); |
||
818 | } else { |
||
819 | __glXSendError(dpy, GLXBadCurrentWindow, 0, X_GLXSwapBuffers, false); |
||
820 | } |
||
821 | #else |
||
822 | struct glx_context *gc; |
||
823 | GLXContextTag tag; |
||
824 | CARD8 opcode; |
||
825 | xcb_connection_t *c; |
||
826 | |||
827 | gc = __glXGetCurrentContext(); |
||
828 | |||
829 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
830 | { |
||
831 | __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); |
||
832 | |||
833 | if (pdraw != NULL) { |
||
834 | Bool flush = gc && drawable == gc->currentDrawable; |
||
835 | |||
836 | (*pdraw->psc->driScreen->swapBuffers)(pdraw, 0, 0, 0, flush); |
||
837 | return; |
||
838 | } |
||
839 | } |
||
840 | #endif |
||
841 | |||
842 | opcode = __glXSetupForCommand(dpy); |
||
843 | if (!opcode) { |
||
844 | return; |
||
845 | } |
||
846 | |||
847 | /* |
||
848 | ** The calling thread may or may not have a current context. If it |
||
849 | ** does, send the context tag so the server can do a flush. |
||
850 | */ |
||
851 | if ((gc != NULL) && (dpy == gc->currentDpy) && |
||
852 | ((drawable == gc->currentDrawable) |
||
853 | || (drawable == gc->currentReadable))) { |
||
854 | tag = gc->currentContextTag; |
||
855 | } |
||
856 | else { |
||
857 | tag = 0; |
||
858 | } |
||
859 | |||
860 | c = XGetXCBConnection(dpy); |
||
861 | xcb_glx_swap_buffers(c, tag, drawable); |
||
862 | xcb_flush(c); |
||
863 | #endif /* GLX_USE_APPLEGL */ |
||
864 | } |
||
865 | |||
866 | |||
867 | /* |
||
868 | ** Return configuration information for the given display, screen and |
||
869 | ** visual combination. |
||
870 | */ |
||
871 | _X_EXPORT int |
||
872 | glXGetConfig(Display * dpy, XVisualInfo * vis, int attribute, |
||
873 | int *value_return) |
||
874 | { |
||
875 | struct glx_display *priv; |
||
876 | struct glx_screen *psc; |
||
877 | struct glx_config *config; |
||
878 | int status; |
||
879 | |||
880 | status = GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc); |
||
881 | if (status == Success) { |
||
882 | config = glx_config_find_visual(psc->visuals, vis->visualid); |
||
883 | |||
884 | /* Lookup attribute after first finding a match on the visual */ |
||
885 | if (config != NULL) { |
||
886 | return glx_config_get(config, attribute, value_return); |
||
887 | } |
||
888 | |||
889 | status = GLX_BAD_VISUAL; |
||
890 | } |
||
891 | |||
892 | /* |
||
893 | ** If we can't find the config for this visual, this visual is not |
||
894 | ** supported by the OpenGL implementation on the server. |
||
895 | */ |
||
896 | if ((status == GLX_BAD_VISUAL) && (attribute == GLX_USE_GL)) { |
||
897 | *value_return = False; |
||
898 | status = Success; |
||
899 | } |
||
900 | |||
901 | return status; |
||
902 | } |
||
903 | |||
904 | /************************************************************************/ |
||
905 | |||
906 | static void |
||
907 | init_fbconfig_for_chooser(struct glx_config * config, |
||
908 | GLboolean fbconfig_style_tags) |
||
909 | { |
||
910 | memset(config, 0, sizeof(struct glx_config)); |
||
911 | config->visualID = (XID) GLX_DONT_CARE; |
||
912 | config->visualType = GLX_DONT_CARE; |
||
913 | |||
914 | /* glXChooseFBConfig specifies different defaults for these properties than |
||
915 | * glXChooseVisual. |
||
916 | */ |
||
917 | if (fbconfig_style_tags) { |
||
918 | config->rgbMode = GL_TRUE; |
||
919 | config->doubleBufferMode = GLX_DONT_CARE; |
||
920 | /* allow any kind of drawable, including those for off-screen buffers */ |
||
921 | config->drawableType = 0; |
||
922 | } else { |
||
923 | /* allow configs which support on-screen drawing */ |
||
924 | config->drawableType = GLX_WINDOW_BIT; |
||
925 | } |
||
926 | |||
927 | config->visualRating = GLX_DONT_CARE; |
||
928 | config->transparentPixel = GLX_NONE; |
||
929 | config->transparentRed = GLX_DONT_CARE; |
||
930 | config->transparentGreen = GLX_DONT_CARE; |
||
931 | config->transparentBlue = GLX_DONT_CARE; |
||
932 | config->transparentAlpha = GLX_DONT_CARE; |
||
933 | config->transparentIndex = GLX_DONT_CARE; |
||
934 | |||
935 | /* Set GLX_RENDER_TYPE property to not expect any flags by default. */ |
||
936 | config->renderType = 0; |
||
937 | config->xRenderable = GLX_DONT_CARE; |
||
938 | config->fbconfigID = (GLXFBConfigID) (GLX_DONT_CARE); |
||
939 | |||
940 | config->swapMethod = GLX_DONT_CARE; |
||
941 | } |
||
942 | |||
943 | #define MATCH_DONT_CARE( param ) \ |
||
944 | do { \ |
||
945 | if ( ((int) a-> param != (int) GLX_DONT_CARE) \ |
||
946 | && (a-> param != b-> param) ) { \ |
||
947 | return False; \ |
||
948 | } \ |
||
949 | } while ( 0 ) |
||
950 | |||
951 | #define MATCH_MINIMUM( param ) \ |
||
952 | do { \ |
||
953 | if ( ((int) a-> param != (int) GLX_DONT_CARE) \ |
||
954 | && (a-> param > b-> param) ) { \ |
||
955 | return False; \ |
||
956 | } \ |
||
957 | } while ( 0 ) |
||
958 | |||
959 | #define MATCH_EXACT( param ) \ |
||
960 | do { \ |
||
961 | if ( a-> param != b-> param) { \ |
||
962 | return False; \ |
||
963 | } \ |
||
964 | } while ( 0 ) |
||
965 | |||
966 | /* Test that all bits from a are contained in b */ |
||
967 | #define MATCH_MASK(param) \ |
||
968 | do { \ |
||
969 | if ( ((int) a-> param != (int) GLX_DONT_CARE) \ |
||
970 | && ((a->param & ~b->param) != 0) ) { \ |
||
971 | return False; \ |
||
972 | } \ |
||
973 | } while (0); |
||
974 | |||
975 | /** |
||
976 | * Determine if two GLXFBConfigs are compatible. |
||
977 | * |
||
978 | * \param a Application specified config to test. |
||
979 | * \param b Server specified config to test against \c a. |
||
980 | */ |
||
981 | static Bool |
||
982 | fbconfigs_compatible(const struct glx_config * const a, |
||
983 | const struct glx_config * const b) |
||
984 | { |
||
985 | MATCH_DONT_CARE(doubleBufferMode); |
||
986 | MATCH_DONT_CARE(visualType); |
||
987 | MATCH_DONT_CARE(visualRating); |
||
988 | MATCH_DONT_CARE(xRenderable); |
||
989 | MATCH_DONT_CARE(fbconfigID); |
||
990 | MATCH_DONT_CARE(swapMethod); |
||
991 | |||
992 | MATCH_MINIMUM(rgbBits); |
||
993 | MATCH_MINIMUM(numAuxBuffers); |
||
994 | MATCH_MINIMUM(redBits); |
||
995 | MATCH_MINIMUM(greenBits); |
||
996 | MATCH_MINIMUM(blueBits); |
||
997 | MATCH_MINIMUM(alphaBits); |
||
998 | MATCH_MINIMUM(depthBits); |
||
999 | MATCH_MINIMUM(stencilBits); |
||
1000 | MATCH_MINIMUM(accumRedBits); |
||
1001 | MATCH_MINIMUM(accumGreenBits); |
||
1002 | MATCH_MINIMUM(accumBlueBits); |
||
1003 | MATCH_MINIMUM(accumAlphaBits); |
||
1004 | MATCH_MINIMUM(sampleBuffers); |
||
1005 | MATCH_MINIMUM(maxPbufferWidth); |
||
1006 | MATCH_MINIMUM(maxPbufferHeight); |
||
1007 | MATCH_MINIMUM(maxPbufferPixels); |
||
1008 | MATCH_MINIMUM(samples); |
||
1009 | |||
1010 | MATCH_DONT_CARE(stereoMode); |
||
1011 | MATCH_EXACT(level); |
||
1012 | |||
1013 | MATCH_MASK(drawableType); |
||
1014 | MATCH_MASK(renderType); |
||
1015 | |||
1016 | /* There is a bug in a few of the XFree86 DDX drivers. They contain |
||
1017 | * visuals with a "transparent type" of 0 when they really mean GLX_NONE. |
||
1018 | * Technically speaking, it is a bug in the DDX driver, but there is |
||
1019 | * enough of an installed base to work around the problem here. In any |
||
1020 | * case, 0 is not a valid value of the transparent type, so we'll treat 0 |
||
1021 | * from the app as GLX_DONT_CARE. We'll consider GLX_NONE from the app and |
||
1022 | * 0 from the server to be a match to maintain backward compatibility with |
||
1023 | * the (broken) drivers. |
||
1024 | */ |
||
1025 | |||
1026 | if (a->transparentPixel != (int) GLX_DONT_CARE && a->transparentPixel != 0) { |
||
1027 | if (a->transparentPixel == GLX_NONE) { |
||
1028 | if (b->transparentPixel != GLX_NONE && b->transparentPixel != 0) |
||
1029 | return False; |
||
1030 | } |
||
1031 | else { |
||
1032 | MATCH_EXACT(transparentPixel); |
||
1033 | } |
||
1034 | |||
1035 | switch (a->transparentPixel) { |
||
1036 | case GLX_TRANSPARENT_RGB: |
||
1037 | MATCH_DONT_CARE(transparentRed); |
||
1038 | MATCH_DONT_CARE(transparentGreen); |
||
1039 | MATCH_DONT_CARE(transparentBlue); |
||
1040 | MATCH_DONT_CARE(transparentAlpha); |
||
1041 | break; |
||
1042 | |||
1043 | case GLX_TRANSPARENT_INDEX: |
||
1044 | MATCH_DONT_CARE(transparentIndex); |
||
1045 | break; |
||
1046 | |||
1047 | default: |
||
1048 | break; |
||
1049 | } |
||
1050 | } |
||
1051 | |||
1052 | return True; |
||
1053 | } |
||
1054 | |||
1055 | |||
1056 | /* There's some trickly language in the GLX spec about how this is supposed |
||
1057 | * to work. Basically, if a given component size is either not specified |
||
1058 | * or the requested size is zero, it is supposed to act like PERFER_SMALLER. |
||
1059 | * Well, that's really hard to do with the code as-is. This behavior is |
||
1060 | * closer to correct, but still not technically right. |
||
1061 | */ |
||
1062 | #define PREFER_LARGER_OR_ZERO(comp) \ |
||
1063 | do { \ |
||
1064 | if ( ((*a)-> comp) != ((*b)-> comp) ) { \ |
||
1065 | if ( ((*a)-> comp) == 0 ) { \ |
||
1066 | return -1; \ |
||
1067 | } \ |
||
1068 | else if ( ((*b)-> comp) == 0 ) { \ |
||
1069 | return 1; \ |
||
1070 | } \ |
||
1071 | else { \ |
||
1072 | return ((*b)-> comp) - ((*a)-> comp) ; \ |
||
1073 | } \ |
||
1074 | } \ |
||
1075 | } while( 0 ) |
||
1076 | |||
1077 | #define PREFER_LARGER(comp) \ |
||
1078 | do { \ |
||
1079 | if ( ((*a)-> comp) != ((*b)-> comp) ) { \ |
||
1080 | return ((*b)-> comp) - ((*a)-> comp) ; \ |
||
1081 | } \ |
||
1082 | } while( 0 ) |
||
1083 | |||
1084 | #define PREFER_SMALLER(comp) \ |
||
1085 | do { \ |
||
1086 | if ( ((*a)-> comp) != ((*b)-> comp) ) { \ |
||
1087 | return ((*a)-> comp) - ((*b)-> comp) ; \ |
||
1088 | } \ |
||
1089 | } while( 0 ) |
||
1090 | |||
1091 | /** |
||
1092 | * Compare two GLXFBConfigs. This function is intended to be used as the |
||
1093 | * compare function passed in to qsort. |
||
1094 | * |
||
1095 | * \returns If \c a is a "better" config, according to the specification of |
||
1096 | * SGIX_fbconfig, a number less than zero is returned. If \c b is |
||
1097 | * better, then a number greater than zero is return. If both are |
||
1098 | * equal, zero is returned. |
||
1099 | * \sa qsort, glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX |
||
1100 | */ |
||
1101 | static int |
||
1102 | fbconfig_compare(struct glx_config **a, struct glx_config **b) |
||
1103 | { |
||
1104 | /* The order of these comparisons must NOT change. It is defined by |
||
1105 | * the GLX 1.3 spec and ARB_multisample. |
||
1106 | */ |
||
1107 | |||
1108 | PREFER_SMALLER(visualSelectGroup); |
||
1109 | |||
1110 | /* The sort order for the visualRating is GLX_NONE, GLX_SLOW, and |
||
1111 | * GLX_NON_CONFORMANT_CONFIG. It just so happens that this is the |
||
1112 | * numerical sort order of the enums (0x8000, 0x8001, and 0x800D). |
||
1113 | */ |
||
1114 | PREFER_SMALLER(visualRating); |
||
1115 | |||
1116 | /* This isn't quite right. It is supposed to compare the sum of the |
||
1117 | * components the user specifically set minimums for. |
||
1118 | */ |
||
1119 | PREFER_LARGER_OR_ZERO(redBits); |
||
1120 | PREFER_LARGER_OR_ZERO(greenBits); |
||
1121 | PREFER_LARGER_OR_ZERO(blueBits); |
||
1122 | PREFER_LARGER_OR_ZERO(alphaBits); |
||
1123 | |||
1124 | PREFER_SMALLER(rgbBits); |
||
1125 | |||
1126 | if (((*a)->doubleBufferMode != (*b)->doubleBufferMode)) { |
||
1127 | /* Prefer single-buffer. |
||
1128 | */ |
||
1129 | return (!(*a)->doubleBufferMode) ? -1 : 1; |
||
1130 | } |
||
1131 | |||
1132 | PREFER_SMALLER(numAuxBuffers); |
||
1133 | |||
1134 | PREFER_LARGER_OR_ZERO(depthBits); |
||
1135 | PREFER_SMALLER(stencilBits); |
||
1136 | |||
1137 | /* This isn't quite right. It is supposed to compare the sum of the |
||
1138 | * components the user specifically set minimums for. |
||
1139 | */ |
||
1140 | PREFER_LARGER_OR_ZERO(accumRedBits); |
||
1141 | PREFER_LARGER_OR_ZERO(accumGreenBits); |
||
1142 | PREFER_LARGER_OR_ZERO(accumBlueBits); |
||
1143 | PREFER_LARGER_OR_ZERO(accumAlphaBits); |
||
1144 | |||
1145 | PREFER_SMALLER(visualType); |
||
1146 | |||
1147 | /* None of the multisample specs say where this comparison should happen, |
||
1148 | * so I put it near the end. |
||
1149 | */ |
||
1150 | PREFER_SMALLER(sampleBuffers); |
||
1151 | PREFER_SMALLER(samples); |
||
1152 | |||
1153 | /* None of the pbuffer or fbconfig specs say that this comparison needs |
||
1154 | * to happen at all, but it seems like it should. |
||
1155 | */ |
||
1156 | PREFER_LARGER(maxPbufferWidth); |
||
1157 | PREFER_LARGER(maxPbufferHeight); |
||
1158 | PREFER_LARGER(maxPbufferPixels); |
||
1159 | |||
1160 | return 0; |
||
1161 | } |
||
1162 | |||
1163 | |||
1164 | /** |
||
1165 | * Selects and sorts a subset of the supplied configs based on the attributes. |
||
1166 | * This function forms to basis of \c glXChooseVisual, \c glXChooseFBConfig, |
||
1167 | * and \c glXChooseFBConfigSGIX. |
||
1168 | * |
||
1169 | * \param configs Array of pointers to possible configs. The elements of |
||
1170 | * this array that do not meet the criteria will be set to |
||
1171 | * NULL. The remaining elements will be sorted according to |
||
1172 | * the various visual / FBConfig selection rules. |
||
1173 | * \param num_configs Number of elements in the \c configs array. |
||
1174 | * \param attribList Attributes used select from \c configs. This array is |
||
1175 | * terminated by a \c None tag. The array can either take |
||
1176 | * the form expected by \c glXChooseVisual (where boolean |
||
1177 | * tags do not have a value) or by \c glXChooseFBConfig |
||
1178 | * (where every tag has a value). |
||
1179 | * \param fbconfig_style_tags Selects whether \c attribList is in |
||
1180 | * \c glXChooseVisual style or |
||
1181 | * \c glXChooseFBConfig style. |
||
1182 | * \returns The number of valid elements left in \c configs. |
||
1183 | * |
||
1184 | * \sa glXChooseVisual, glXChooseFBConfig, glXChooseFBConfigSGIX |
||
1185 | */ |
||
1186 | static int |
||
1187 | choose_visual(struct glx_config ** configs, int num_configs, |
||
1188 | const int *attribList, GLboolean fbconfig_style_tags) |
||
1189 | { |
||
1190 | struct glx_config test_config; |
||
1191 | int base; |
||
1192 | int i; |
||
1193 | |||
1194 | /* This is a fairly direct implementation of the selection method |
||
1195 | * described by GLX_SGIX_fbconfig. Start by culling out all the |
||
1196 | * configs that are not compatible with the selected parameter |
||
1197 | * list. |
||
1198 | */ |
||
1199 | |||
1200 | init_fbconfig_for_chooser(&test_config, fbconfig_style_tags); |
||
1201 | __glXInitializeVisualConfigFromTags(&test_config, 512, |
||
1202 | (const INT32 *) attribList, |
||
1203 | GL_TRUE, fbconfig_style_tags); |
||
1204 | |||
1205 | base = 0; |
||
1206 | for (i = 0; i < num_configs; i++) { |
||
1207 | if (fbconfigs_compatible(&test_config, configs[i])) { |
||
1208 | configs[base] = configs[i]; |
||
1209 | base++; |
||
1210 | } |
||
1211 | } |
||
1212 | |||
1213 | if (base == 0) { |
||
1214 | return 0; |
||
1215 | } |
||
1216 | |||
1217 | if (base < num_configs) { |
||
1218 | (void) memset(&configs[base], 0, sizeof(void *) * (num_configs - base)); |
||
1219 | } |
||
1220 | |||
1221 | /* After the incompatible configs are removed, the resulting |
||
1222 | * list is sorted according to the rules set out in the various |
||
1223 | * specifications. |
||
1224 | */ |
||
1225 | |||
1226 | qsort(configs, base, sizeof(struct glx_config *), |
||
1227 | (int (*)(const void *, const void *)) fbconfig_compare); |
||
1228 | return base; |
||
1229 | } |
||
1230 | |||
1231 | |||
1232 | |||
1233 | |||
1234 | /* |
||
1235 | ** Return the visual that best matches the template. Return None if no |
||
1236 | ** visual matches the template. |
||
1237 | */ |
||
1238 | _X_EXPORT XVisualInfo * |
||
1239 | glXChooseVisual(Display * dpy, int screen, int *attribList) |
||
1240 | { |
||
1241 | XVisualInfo *visualList = NULL; |
||
1242 | struct glx_display *priv; |
||
1243 | struct glx_screen *psc; |
||
1244 | struct glx_config test_config; |
||
1245 | struct glx_config *config; |
||
1246 | struct glx_config *best_config = NULL; |
||
1247 | |||
1248 | /* |
||
1249 | ** Get a list of all visuals, return if list is empty |
||
1250 | */ |
||
1251 | if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { |
||
1252 | return None; |
||
1253 | } |
||
1254 | |||
1255 | |||
1256 | /* |
||
1257 | ** Build a template from the defaults and the attribute list |
||
1258 | ** Free visual list and return if an unexpected token is encountered |
||
1259 | */ |
||
1260 | init_fbconfig_for_chooser(&test_config, GL_FALSE); |
||
1261 | __glXInitializeVisualConfigFromTags(&test_config, 512, |
||
1262 | (const INT32 *) attribList, |
||
1263 | GL_TRUE, GL_FALSE); |
||
1264 | |||
1265 | /* |
||
1266 | ** Eliminate visuals that don't meet minimum requirements |
||
1267 | ** Compute a score for those that do |
||
1268 | ** Remember which visual, if any, got the highest score |
||
1269 | ** If no visual is acceptable, return None |
||
1270 | ** Otherwise, create an XVisualInfo list with just the selected X visual |
||
1271 | ** and return this. |
||
1272 | */ |
||
1273 | for (config = psc->visuals; config != NULL; config = config->next) { |
||
1274 | if (fbconfigs_compatible(&test_config, config) |
||
1275 | && ((best_config == NULL) || |
||
1276 | (fbconfig_compare (&config, &best_config) < 0))) { |
||
1277 | XVisualInfo visualTemplate; |
||
1278 | XVisualInfo *newList; |
||
1279 | int i; |
||
1280 | |||
1281 | visualTemplate.screen = screen; |
||
1282 | visualTemplate.visualid = config->visualID; |
||
1283 | newList = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, |
||
1284 | &visualTemplate, &i); |
||
1285 | |||
1286 | if (newList) { |
||
1287 | free(visualList); |
||
1288 | visualList = newList; |
||
1289 | best_config = config; |
||
1290 | } |
||
1291 | } |
||
1292 | } |
||
1293 | |||
1294 | #ifdef GLX_USE_APPLEGL |
||
1295 | if(visualList && getenv("LIBGL_DUMP_VISUALID")) { |
||
1296 | printf("visualid 0x%lx\n", visualList[0].visualid); |
||
1297 | } |
||
1298 | #endif |
||
1299 | |||
1300 | return visualList; |
||
1301 | } |
||
1302 | |||
1303 | |||
1304 | _X_EXPORT const char * |
||
1305 | glXQueryExtensionsString(Display * dpy, int screen) |
||
1306 | { |
||
1307 | struct glx_screen *psc; |
||
1308 | struct glx_display *priv; |
||
1309 | |||
1310 | if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { |
||
1311 | return NULL; |
||
1312 | } |
||
1313 | |||
1314 | if (!psc->effectiveGLXexts) { |
||
1315 | if (!psc->serverGLXexts) { |
||
1316 | psc->serverGLXexts = |
||
1317 | __glXQueryServerString(dpy, priv->majorOpcode, screen, |
||
1318 | GLX_EXTENSIONS); |
||
1319 | } |
||
1320 | |||
1321 | __glXCalculateUsableExtensions(psc, |
||
1322 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
1323 | (psc->driScreen != NULL), |
||
1324 | #else |
||
1325 | GL_FALSE, |
||
1326 | #endif |
||
1327 | priv->minorVersion); |
||
1328 | } |
||
1329 | |||
1330 | return psc->effectiveGLXexts; |
||
1331 | } |
||
1332 | |||
1333 | _X_EXPORT const char * |
||
1334 | glXGetClientString(Display * dpy, int name) |
||
1335 | { |
||
1336 | (void) dpy; |
||
1337 | |||
1338 | switch (name) { |
||
1339 | case GLX_VENDOR: |
||
1340 | return (__glXGLXClientVendorName); |
||
1341 | case GLX_VERSION: |
||
1342 | return (__glXGLXClientVersion); |
||
1343 | case GLX_EXTENSIONS: |
||
1344 | return (__glXGetClientExtensions()); |
||
1345 | default: |
||
1346 | return NULL; |
||
1347 | } |
||
1348 | } |
||
1349 | |||
1350 | _X_EXPORT const char * |
||
1351 | glXQueryServerString(Display * dpy, int screen, int name) |
||
1352 | { |
||
1353 | struct glx_screen *psc; |
||
1354 | struct glx_display *priv; |
||
1355 | const char **str; |
||
1356 | |||
1357 | |||
1358 | if (GetGLXPrivScreenConfig(dpy, screen, &priv, &psc) != Success) { |
||
1359 | return NULL; |
||
1360 | } |
||
1361 | |||
1362 | switch (name) { |
||
1363 | case GLX_VENDOR: |
||
1364 | str = &priv->serverGLXvendor; |
||
1365 | break; |
||
1366 | case GLX_VERSION: |
||
1367 | str = &priv->serverGLXversion; |
||
1368 | break; |
||
1369 | case GLX_EXTENSIONS: |
||
1370 | str = &psc->serverGLXexts; |
||
1371 | break; |
||
1372 | default: |
||
1373 | return NULL; |
||
1374 | } |
||
1375 | |||
1376 | if (*str == NULL) { |
||
1377 | *str = __glXQueryServerString(dpy, priv->majorOpcode, screen, name); |
||
1378 | } |
||
1379 | |||
1380 | return *str; |
||
1381 | } |
||
1382 | |||
1383 | void |
||
1384 | __glXClientInfo(Display * dpy, int opcode) |
||
1385 | { |
||
1386 | char *ext_str = __glXGetClientGLExtensionString(); |
||
1387 | int size = strlen(ext_str) + 1; |
||
1388 | |||
1389 | xcb_connection_t *c = XGetXCBConnection(dpy); |
||
1390 | xcb_glx_client_info(c, |
||
1391 | GLX_MAJOR_VERSION, GLX_MINOR_VERSION, size, ext_str); |
||
1392 | |||
1393 | free(ext_str); |
||
1394 | } |
||
1395 | |||
1396 | |||
1397 | /* |
||
1398 | ** EXT_import_context |
||
1399 | */ |
||
1400 | |||
1401 | _X_EXPORT Display * |
||
1402 | glXGetCurrentDisplay(void) |
||
1403 | { |
||
1404 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1405 | if (NULL == gc) |
||
1406 | return NULL; |
||
1407 | return gc->currentDpy; |
||
1408 | } |
||
1409 | |||
1410 | _X_EXPORT |
||
1411 | GLX_ALIAS(Display *, glXGetCurrentDisplayEXT, (void), (), |
||
1412 | glXGetCurrentDisplay) |
||
1413 | |||
1414 | #ifndef GLX_USE_APPLEGL |
||
1415 | _X_EXPORT GLXContext |
||
1416 | glXImportContextEXT(Display *dpy, GLXContextID contextID) |
||
1417 | { |
||
1418 | struct glx_display *priv = __glXInitialize(dpy); |
||
1419 | struct glx_screen *psc = NULL; |
||
1420 | xGLXQueryContextReply reply; |
||
1421 | CARD8 opcode; |
||
1422 | struct glx_context *ctx; |
||
1423 | |||
1424 | /* This GLX implementation knows about 5 different properties, so |
||
1425 | * allow the server to send us one of each. |
||
1426 | */ |
||
1427 | int propList[5 * 2], *pProp, nPropListBytes; |
||
1428 | int numProps; |
||
1429 | int i, renderType; |
||
1430 | XID share; |
||
1431 | struct glx_config *mode; |
||
1432 | uint32_t fbconfigID = 0; |
||
1433 | uint32_t visualID = 0; |
||
1434 | uint32_t screen = 0; |
||
1435 | Bool got_screen = False; |
||
1436 | |||
1437 | /* The GLX_EXT_import_context spec says: |
||
1438 | * |
||
1439 | * "If |
||
1440 | * error is generated; if |
||
1441 | * context then no error is generated but glXImportContextEXT returns |
||
1442 | * NULL." |
||
1443 | * |
||
1444 | * If contextID is None, generate BadContext on the client-side. Other |
||
1445 | * sorts of invalid contexts will be detected by the server in the |
||
1446 | * __glXIsDirect call. |
||
1447 | */ |
||
1448 | if (contextID == None) { |
||
1449 | __glXSendError(dpy, GLXBadContext, contextID, X_GLXIsDirect, false); |
||
1450 | return NULL; |
||
1451 | } |
||
1452 | |||
1453 | if (__glXIsDirect(dpy, contextID)) |
||
1454 | return NULL; |
||
1455 | |||
1456 | opcode = __glXSetupForCommand(dpy); |
||
1457 | if (!opcode) |
||
1458 | return 0; |
||
1459 | |||
1460 | /* Send the glXQueryContextInfoEXT request */ |
||
1461 | LockDisplay(dpy); |
||
1462 | |||
1463 | if (priv->majorVersion > 1 || priv->minorVersion >= 3) { |
||
1464 | xGLXQueryContextReq *req; |
||
1465 | |||
1466 | GetReq(GLXQueryContext, req); |
||
1467 | |||
1468 | req->reqType = opcode; |
||
1469 | req->glxCode = X_GLXQueryContext; |
||
1470 | req->context = contextID; |
||
1471 | } |
||
1472 | else { |
||
1473 | xGLXVendorPrivateReq *vpreq; |
||
1474 | xGLXQueryContextInfoEXTReq *req; |
||
1475 | |||
1476 | GetReqExtra(GLXVendorPrivate, |
||
1477 | sz_xGLXQueryContextInfoEXTReq - sz_xGLXVendorPrivateReq, |
||
1478 | vpreq); |
||
1479 | req = (xGLXQueryContextInfoEXTReq *) vpreq; |
||
1480 | req->reqType = opcode; |
||
1481 | req->glxCode = X_GLXVendorPrivateWithReply; |
||
1482 | req->vendorCode = X_GLXvop_QueryContextInfoEXT; |
||
1483 | req->context = contextID; |
||
1484 | } |
||
1485 | |||
1486 | _XReply(dpy, (xReply *) & reply, 0, False); |
||
1487 | |||
1488 | if (reply.n <= __GLX_MAX_CONTEXT_PROPS) |
||
1489 | nPropListBytes = reply.n * 2 * sizeof propList[0]; |
||
1490 | else |
||
1491 | nPropListBytes = 0; |
||
1492 | _XRead(dpy, (char *) propList, nPropListBytes); |
||
1493 | UnlockDisplay(dpy); |
||
1494 | SyncHandle(); |
||
1495 | |||
1496 | numProps = nPropListBytes / (2 * sizeof(propList[0])); |
||
1497 | share = None; |
||
1498 | mode = NULL; |
||
1499 | renderType = GLX_RGBA_TYPE; /* By default, assume RGBA context */ |
||
1500 | pProp = propList; |
||
1501 | |||
1502 | for (i = 0, pProp = propList; i < numProps; i++, pProp += 2) |
||
1503 | switch (pProp[0]) { |
||
1504 | case GLX_SCREEN: |
||
1505 | screen = pProp[1]; |
||
1506 | got_screen = True; |
||
1507 | break; |
||
1508 | case GLX_SHARE_CONTEXT_EXT: |
||
1509 | share = pProp[1]; |
||
1510 | break; |
||
1511 | case GLX_VISUAL_ID_EXT: |
||
1512 | visualID = pProp[1]; |
||
1513 | break; |
||
1514 | case GLX_FBCONFIG_ID: |
||
1515 | fbconfigID = pProp[1]; |
||
1516 | break; |
||
1517 | case GLX_RENDER_TYPE: |
||
1518 | renderType = pProp[1]; |
||
1519 | break; |
||
1520 | } |
||
1521 | |||
1522 | if (!got_screen) |
||
1523 | return NULL; |
||
1524 | |||
1525 | psc = GetGLXScreenConfigs(dpy, screen); |
||
1526 | if (psc == NULL) |
||
1527 | return NULL; |
||
1528 | |||
1529 | if (fbconfigID != 0) { |
||
1530 | mode = glx_config_find_fbconfig(psc->configs, fbconfigID); |
||
1531 | } else if (visualID != 0) { |
||
1532 | mode = glx_config_find_visual(psc->visuals, visualID); |
||
1533 | } |
||
1534 | |||
1535 | if (mode == NULL) |
||
1536 | return NULL; |
||
1537 | |||
1538 | ctx = indirect_create_context(psc, mode, NULL, renderType); |
||
1539 | if (ctx == NULL) |
||
1540 | return NULL; |
||
1541 | |||
1542 | ctx->xid = contextID; |
||
1543 | ctx->imported = GL_TRUE; |
||
1544 | ctx->share_xid = share; |
||
1545 | |||
1546 | return (GLXContext) ctx; |
||
1547 | } |
||
1548 | |||
1549 | #endif |
||
1550 | |||
1551 | _X_EXPORT int |
||
1552 | glXQueryContext(Display * dpy, GLXContext ctx_user, int attribute, int *value) |
||
1553 | { |
||
1554 | struct glx_context *ctx = (struct glx_context *) ctx_user; |
||
1555 | |||
1556 | switch (attribute) { |
||
1557 | case GLX_SHARE_CONTEXT_EXT: |
||
1558 | *value = ctx->share_xid; |
||
1559 | break; |
||
1560 | case GLX_VISUAL_ID_EXT: |
||
1561 | *value = ctx->config ? ctx->config->visualID : None; |
||
1562 | break; |
||
1563 | case GLX_SCREEN: |
||
1564 | *value = ctx->screen; |
||
1565 | break; |
||
1566 | case GLX_FBCONFIG_ID: |
||
1567 | *value = ctx->config ? ctx->config->fbconfigID : None; |
||
1568 | break; |
||
1569 | case GLX_RENDER_TYPE: |
||
1570 | *value = ctx->renderType; |
||
1571 | break; |
||
1572 | default: |
||
1573 | return GLX_BAD_ATTRIBUTE; |
||
1574 | } |
||
1575 | return Success; |
||
1576 | } |
||
1577 | |||
1578 | _X_EXPORT |
||
1579 | GLX_ALIAS(int, glXQueryContextInfoEXT, |
||
1580 | (Display * dpy, GLXContext ctx, int attribute, int *value), |
||
1581 | (dpy, ctx, attribute, value), glXQueryContext) |
||
1582 | |||
1583 | _X_EXPORT GLXContextID glXGetContextIDEXT(const GLXContext ctx_user) |
||
1584 | { |
||
1585 | struct glx_context *ctx = (struct glx_context *) ctx_user; |
||
1586 | |||
1587 | return (ctx == NULL) ? None : ctx->xid; |
||
1588 | } |
||
1589 | |||
1590 | _X_EXPORT void |
||
1591 | glXFreeContextEXT(Display *dpy, GLXContext ctx) |
||
1592 | { |
||
1593 | struct glx_context *gc = (struct glx_context *) ctx; |
||
1594 | |||
1595 | if (gc == NULL || gc->xid == None) |
||
1596 | return; |
||
1597 | |||
1598 | /* The GLX_EXT_import_context spec says: |
||
1599 | * |
||
1600 | * "glXFreeContext does not free the server-side context information or |
||
1601 | * the XID associated with the server-side context." |
||
1602 | * |
||
1603 | * Don't send any protocol. Just destroy the client-side tracking of the |
||
1604 | * context. Also, only release the context structure if it's not current. |
||
1605 | */ |
||
1606 | __glXLock(); |
||
1607 | if (gc->currentDpy) { |
||
1608 | gc->xid = None; |
||
1609 | } else { |
||
1610 | gc->vtable->destroy(gc); |
||
1611 | } |
||
1612 | __glXUnlock(); |
||
1613 | } |
||
1614 | |||
1615 | _X_EXPORT GLXFBConfig * |
||
1616 | glXChooseFBConfig(Display * dpy, int screen, |
||
1617 | const int *attribList, int *nitems) |
||
1618 | { |
||
1619 | struct glx_config **config_list; |
||
1620 | int list_size; |
||
1621 | |||
1622 | |||
1623 | config_list = (struct glx_config **) |
||
1624 | glXGetFBConfigs(dpy, screen, &list_size); |
||
1625 | |||
1626 | if ((config_list != NULL) && (list_size > 0) && (attribList != NULL)) { |
||
1627 | list_size = choose_visual(config_list, list_size, attribList, GL_TRUE); |
||
1628 | if (list_size == 0) { |
||
1629 | free(config_list); |
||
1630 | config_list = NULL; |
||
1631 | } |
||
1632 | } |
||
1633 | |||
1634 | *nitems = list_size; |
||
1635 | return (GLXFBConfig *) config_list; |
||
1636 | } |
||
1637 | |||
1638 | |||
1639 | _X_EXPORT GLXContext |
||
1640 | glXCreateNewContext(Display * dpy, GLXFBConfig fbconfig, |
||
1641 | int renderType, GLXContext shareList, Bool allowDirect) |
||
1642 | { |
||
1643 | struct glx_config *config = (struct glx_config *) fbconfig; |
||
1644 | |||
1645 | return CreateContext(dpy, config->fbconfigID, config, shareList, |
||
1646 | allowDirect, X_GLXCreateNewContext, renderType, |
||
1647 | config->screen); |
||
1648 | } |
||
1649 | |||
1650 | |||
1651 | _X_EXPORT GLXDrawable |
||
1652 | glXGetCurrentReadDrawable(void) |
||
1653 | { |
||
1654 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1655 | |||
1656 | return gc->currentReadable; |
||
1657 | } |
||
1658 | |||
1659 | |||
1660 | _X_EXPORT GLXFBConfig * |
||
1661 | glXGetFBConfigs(Display * dpy, int screen, int *nelements) |
||
1662 | { |
||
1663 | struct glx_display *priv = __glXInitialize(dpy); |
||
1664 | struct glx_config **config_list = NULL; |
||
1665 | struct glx_config *config; |
||
1666 | unsigned num_configs = 0; |
||
1667 | int i; |
||
1668 | |||
1669 | *nelements = 0; |
||
1670 | if (priv && (priv->screens != NULL) |
||
1671 | && (screen >= 0) && (screen <= ScreenCount(dpy)) |
||
1672 | && (priv->screens[screen]->configs != NULL) |
||
1673 | && (priv->screens[screen]->configs->fbconfigID |
||
1674 | != (int) GLX_DONT_CARE)) { |
||
1675 | |||
1676 | for (config = priv->screens[screen]->configs; config != NULL; |
||
1677 | config = config->next) { |
||
1678 | if (config->fbconfigID != (int) GLX_DONT_CARE) { |
||
1679 | num_configs++; |
||
1680 | } |
||
1681 | } |
||
1682 | |||
1683 | config_list = malloc(num_configs * sizeof *config_list); |
||
1684 | if (config_list != NULL) { |
||
1685 | *nelements = num_configs; |
||
1686 | i = 0; |
||
1687 | for (config = priv->screens[screen]->configs; config != NULL; |
||
1688 | config = config->next) { |
||
1689 | if (config->fbconfigID != (int) GLX_DONT_CARE) { |
||
1690 | config_list[i] = config; |
||
1691 | i++; |
||
1692 | } |
||
1693 | } |
||
1694 | } |
||
1695 | } |
||
1696 | |||
1697 | return (GLXFBConfig *) config_list; |
||
1698 | } |
||
1699 | |||
1700 | |||
1701 | _X_EXPORT int |
||
1702 | glXGetFBConfigAttrib(Display * dpy, GLXFBConfig fbconfig, |
||
1703 | int attribute, int *value) |
||
1704 | { |
||
1705 | struct glx_config *config = ValidateGLXFBConfig(dpy, fbconfig); |
||
1706 | |||
1707 | if (config == NULL) |
||
1708 | return GLXBadFBConfig; |
||
1709 | |||
1710 | return glx_config_get(config, attribute, value); |
||
1711 | } |
||
1712 | |||
1713 | |||
1714 | _X_EXPORT XVisualInfo * |
||
1715 | glXGetVisualFromFBConfig(Display * dpy, GLXFBConfig fbconfig) |
||
1716 | { |
||
1717 | XVisualInfo visualTemplate; |
||
1718 | struct glx_config *config = (struct glx_config *) fbconfig; |
||
1719 | int count; |
||
1720 | |||
1721 | /* |
||
1722 | ** Get a list of all visuals, return if list is empty |
||
1723 | */ |
||
1724 | visualTemplate.visualid = config->visualID; |
||
1725 | return XGetVisualInfo(dpy, VisualIDMask, &visualTemplate, &count); |
||
1726 | } |
||
1727 | |||
1728 | #ifndef GLX_USE_APPLEGL |
||
1729 | /* |
||
1730 | ** GLX_SGI_swap_control |
||
1731 | */ |
||
1732 | static int |
||
1733 | __glXSwapIntervalSGI(int interval) |
||
1734 | { |
||
1735 | xGLXVendorPrivateReq *req; |
||
1736 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1737 | struct glx_screen *psc; |
||
1738 | Display *dpy; |
||
1739 | CARD32 *interval_ptr; |
||
1740 | CARD8 opcode; |
||
1741 | |||
1742 | if (gc == NULL) { |
||
1743 | return GLX_BAD_CONTEXT; |
||
1744 | } |
||
1745 | |||
1746 | if (interval <= 0) { |
||
1747 | return GLX_BAD_VALUE; |
||
1748 | } |
||
1749 | |||
1750 | psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); |
||
1751 | |||
1752 | #ifdef GLX_DIRECT_RENDERING |
||
1753 | if (gc->isDirect && psc->driScreen && psc->driScreen->setSwapInterval) { |
||
1754 | __GLXDRIdrawable *pdraw = |
||
1755 | GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); |
||
1756 | psc->driScreen->setSwapInterval(pdraw, interval); |
||
1757 | return 0; |
||
1758 | } |
||
1759 | #endif |
||
1760 | |||
1761 | dpy = gc->currentDpy; |
||
1762 | opcode = __glXSetupForCommand(dpy); |
||
1763 | if (!opcode) { |
||
1764 | return 0; |
||
1765 | } |
||
1766 | |||
1767 | /* Send the glXSwapIntervalSGI request */ |
||
1768 | LockDisplay(dpy); |
||
1769 | GetReqExtra(GLXVendorPrivate, sizeof(CARD32), req); |
||
1770 | req->reqType = opcode; |
||
1771 | req->glxCode = X_GLXVendorPrivate; |
||
1772 | req->vendorCode = X_GLXvop_SwapIntervalSGI; |
||
1773 | req->contextTag = gc->currentContextTag; |
||
1774 | |||
1775 | interval_ptr = (CARD32 *) (req + 1); |
||
1776 | *interval_ptr = interval; |
||
1777 | |||
1778 | UnlockDisplay(dpy); |
||
1779 | SyncHandle(); |
||
1780 | XFlush(dpy); |
||
1781 | |||
1782 | return 0; |
||
1783 | } |
||
1784 | |||
1785 | |||
1786 | /* |
||
1787 | ** GLX_MESA_swap_control |
||
1788 | */ |
||
1789 | static int |
||
1790 | __glXSwapIntervalMESA(unsigned int interval) |
||
1791 | { |
||
1792 | #ifdef GLX_DIRECT_RENDERING |
||
1793 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1794 | |||
1795 | if (gc != NULL && gc->isDirect) { |
||
1796 | struct glx_screen *psc; |
||
1797 | |||
1798 | psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); |
||
1799 | if (psc->driScreen && psc->driScreen->setSwapInterval) { |
||
1800 | __GLXDRIdrawable *pdraw = |
||
1801 | GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); |
||
1802 | return psc->driScreen->setSwapInterval(pdraw, interval); |
||
1803 | } |
||
1804 | } |
||
1805 | #endif |
||
1806 | |||
1807 | return GLX_BAD_CONTEXT; |
||
1808 | } |
||
1809 | |||
1810 | |||
1811 | static int |
||
1812 | __glXGetSwapIntervalMESA(void) |
||
1813 | { |
||
1814 | #ifdef GLX_DIRECT_RENDERING |
||
1815 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1816 | |||
1817 | if (gc != NULL && gc->isDirect) { |
||
1818 | struct glx_screen *psc; |
||
1819 | |||
1820 | psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); |
||
1821 | if (psc->driScreen && psc->driScreen->getSwapInterval) { |
||
1822 | __GLXDRIdrawable *pdraw = |
||
1823 | GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); |
||
1824 | return psc->driScreen->getSwapInterval(pdraw); |
||
1825 | } |
||
1826 | } |
||
1827 | #endif |
||
1828 | |||
1829 | return 0; |
||
1830 | } |
||
1831 | |||
1832 | |||
1833 | /* |
||
1834 | ** GLX_SGI_video_sync |
||
1835 | */ |
||
1836 | static int |
||
1837 | __glXGetVideoSyncSGI(unsigned int *count) |
||
1838 | { |
||
1839 | int64_t ust, msc, sbc; |
||
1840 | int ret; |
||
1841 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1842 | struct glx_screen *psc; |
||
1843 | #ifdef GLX_DIRECT_RENDERING |
||
1844 | __GLXDRIdrawable *pdraw; |
||
1845 | #endif |
||
1846 | |||
1847 | if (!gc) |
||
1848 | return GLX_BAD_CONTEXT; |
||
1849 | |||
1850 | #ifdef GLX_DIRECT_RENDERING |
||
1851 | if (!gc->isDirect) |
||
1852 | return GLX_BAD_CONTEXT; |
||
1853 | #endif |
||
1854 | |||
1855 | psc = GetGLXScreenConfigs(gc->currentDpy, gc->screen); |
||
1856 | #ifdef GLX_DIRECT_RENDERING |
||
1857 | pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); |
||
1858 | #endif |
||
1859 | |||
1860 | /* FIXME: Looking at the GLX_SGI_video_sync spec in the extension registry, |
||
1861 | * FIXME: there should be a GLX encoding for this call. I can find no |
||
1862 | * FIXME: documentation for the GLX encoding. |
||
1863 | */ |
||
1864 | #ifdef GLX_DIRECT_RENDERING |
||
1865 | if (psc->driScreen && psc->driScreen->getDrawableMSC) { |
||
1866 | ret = psc->driScreen->getDrawableMSC(psc, pdraw, &ust, &msc, &sbc); |
||
1867 | *count = (unsigned) msc; |
||
1868 | return (ret == True) ? 0 : GLX_BAD_CONTEXT; |
||
1869 | } |
||
1870 | #endif |
||
1871 | |||
1872 | return GLX_BAD_CONTEXT; |
||
1873 | } |
||
1874 | |||
1875 | static int |
||
1876 | __glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) |
||
1877 | { |
||
1878 | struct glx_context *gc = __glXGetCurrentContext(); |
||
1879 | struct glx_screen *psc; |
||
1880 | #ifdef GLX_DIRECT_RENDERING |
||
1881 | __GLXDRIdrawable *pdraw; |
||
1882 | #endif |
||
1883 | int64_t ust, msc, sbc; |
||
1884 | int ret; |
||
1885 | |||
1886 | if (divisor <= 0 || remainder < 0) |
||
1887 | return GLX_BAD_VALUE; |
||
1888 | |||
1889 | if (!gc) |
||
1890 | return GLX_BAD_CONTEXT; |
||
1891 | |||
1892 | #ifdef GLX_DIRECT_RENDERING |
||
1893 | if (!gc->isDirect) |
||
1894 | return GLX_BAD_CONTEXT; |
||
1895 | #endif |
||
1896 | |||
1897 | psc = GetGLXScreenConfigs( gc->currentDpy, gc->screen); |
||
1898 | #ifdef GLX_DIRECT_RENDERING |
||
1899 | pdraw = GetGLXDRIDrawable(gc->currentDpy, gc->currentDrawable); |
||
1900 | #endif |
||
1901 | |||
1902 | #ifdef GLX_DIRECT_RENDERING |
||
1903 | if (psc->driScreen && psc->driScreen->waitForMSC) { |
||
1904 | ret = psc->driScreen->waitForMSC(pdraw, 0, divisor, remainder, &ust, &msc, |
||
1905 | &sbc); |
||
1906 | *count = (unsigned) msc; |
||
1907 | return (ret == True) ? 0 : GLX_BAD_CONTEXT; |
||
1908 | } |
||
1909 | #endif |
||
1910 | |||
1911 | return GLX_BAD_CONTEXT; |
||
1912 | } |
||
1913 | |||
1914 | #endif /* GLX_USE_APPLEGL */ |
||
1915 | |||
1916 | /* |
||
1917 | ** GLX_SGIX_fbconfig |
||
1918 | ** Many of these functions are aliased to GLX 1.3 entry points in the |
||
1919 | ** GLX_functions table. |
||
1920 | */ |
||
1921 | |||
1922 | _X_EXPORT |
||
1923 | GLX_ALIAS(int, glXGetFBConfigAttribSGIX, |
||
1924 | (Display * dpy, GLXFBConfigSGIX config, int attribute, int *value), |
||
1925 | (dpy, config, attribute, value), glXGetFBConfigAttrib) |
||
1926 | |||
1927 | _X_EXPORT GLX_ALIAS(GLXFBConfigSGIX *, glXChooseFBConfigSGIX, |
||
1928 | (Display * dpy, int screen, int *attrib_list, |
||
1929 | int *nelements), (dpy, screen, attrib_list, nelements), |
||
1930 | glXChooseFBConfig) |
||
1931 | |||
1932 | _X_EXPORT GLX_ALIAS(XVisualInfo *, glXGetVisualFromFBConfigSGIX, |
||
1933 | (Display * dpy, GLXFBConfigSGIX config), |
||
1934 | (dpy, config), glXGetVisualFromFBConfig) |
||
1935 | |||
1936 | _X_EXPORT GLXPixmap |
||
1937 | glXCreateGLXPixmapWithConfigSGIX(Display * dpy, |
||
1938 | GLXFBConfigSGIX fbconfig, |
||
1939 | Pixmap pixmap) |
||
1940 | { |
||
1941 | #ifndef GLX_USE_APPLEGL |
||
1942 | xGLXVendorPrivateWithReplyReq *vpreq; |
||
1943 | xGLXCreateGLXPixmapWithConfigSGIXReq *req; |
||
1944 | GLXPixmap xid = None; |
||
1945 | CARD8 opcode; |
||
1946 | struct glx_screen *psc; |
||
1947 | #endif |
||
1948 | struct glx_config *config = (struct glx_config *) fbconfig; |
||
1949 | |||
1950 | |||
1951 | if ((dpy == NULL) || (config == NULL)) { |
||
1952 | return None; |
||
1953 | } |
||
1954 | #ifdef GLX_USE_APPLEGL |
||
1955 | if(apple_glx_pixmap_create(dpy, config->screen, pixmap, config)) |
||
1956 | return None; |
||
1957 | return pixmap; |
||
1958 | #else |
||
1959 | |||
1960 | psc = GetGLXScreenConfigs(dpy, config->screen); |
||
1961 | if ((psc != NULL) |
||
1962 | && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { |
||
1963 | opcode = __glXSetupForCommand(dpy); |
||
1964 | if (!opcode) { |
||
1965 | return None; |
||
1966 | } |
||
1967 | |||
1968 | /* Send the glXCreateGLXPixmapWithConfigSGIX request */ |
||
1969 | LockDisplay(dpy); |
||
1970 | GetReqExtra(GLXVendorPrivateWithReply, |
||
1971 | sz_xGLXCreateGLXPixmapWithConfigSGIXReq - |
||
1972 | sz_xGLXVendorPrivateWithReplyReq, vpreq); |
||
1973 | req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) vpreq; |
||
1974 | req->reqType = opcode; |
||
1975 | req->glxCode = X_GLXVendorPrivateWithReply; |
||
1976 | req->vendorCode = X_GLXvop_CreateGLXPixmapWithConfigSGIX; |
||
1977 | req->screen = config->screen; |
||
1978 | req->fbconfig = config->fbconfigID; |
||
1979 | req->pixmap = pixmap; |
||
1980 | req->glxpixmap = xid = XAllocID(dpy); |
||
1981 | UnlockDisplay(dpy); |
||
1982 | SyncHandle(); |
||
1983 | } |
||
1984 | |||
1985 | return xid; |
||
1986 | #endif |
||
1987 | } |
||
1988 | |||
1989 | _X_EXPORT GLXContext |
||
1990 | glXCreateContextWithConfigSGIX(Display * dpy, |
||
1991 | GLXFBConfigSGIX fbconfig, int renderType, |
||
1992 | GLXContext shareList, Bool allowDirect) |
||
1993 | { |
||
1994 | GLXContext gc = NULL; |
||
1995 | struct glx_config *config = (struct glx_config *) fbconfig; |
||
1996 | struct glx_screen *psc; |
||
1997 | |||
1998 | |||
1999 | if ((dpy == NULL) || (config == NULL)) { |
||
2000 | return None; |
||
2001 | } |
||
2002 | |||
2003 | psc = GetGLXScreenConfigs(dpy, config->screen); |
||
2004 | if ((psc != NULL) |
||
2005 | && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit)) { |
||
2006 | gc = CreateContext(dpy, config->fbconfigID, config, shareList, |
||
2007 | allowDirect, |
||
2008 | X_GLXvop_CreateContextWithConfigSGIX, renderType, |
||
2009 | config->screen); |
||
2010 | } |
||
2011 | |||
2012 | return gc; |
||
2013 | } |
||
2014 | |||
2015 | |||
2016 | _X_EXPORT GLXFBConfigSGIX |
||
2017 | glXGetFBConfigFromVisualSGIX(Display * dpy, XVisualInfo * vis) |
||
2018 | { |
||
2019 | struct glx_display *priv; |
||
2020 | struct glx_screen *psc = NULL; |
||
2021 | |||
2022 | if ((GetGLXPrivScreenConfig(dpy, vis->screen, &priv, &psc) == Success) |
||
2023 | && __glXExtensionBitIsEnabled(psc, SGIX_fbconfig_bit) |
||
2024 | && (psc->configs->fbconfigID != (int) GLX_DONT_CARE)) { |
||
2025 | return (GLXFBConfigSGIX) glx_config_find_visual(psc->configs, |
||
2026 | vis->visualid); |
||
2027 | } |
||
2028 | |||
2029 | return NULL; |
||
2030 | } |
||
2031 | |||
2032 | #ifndef GLX_USE_APPLEGL |
||
2033 | /* |
||
2034 | ** GLX_SGIX_swap_group |
||
2035 | */ |
||
2036 | static void |
||
2037 | __glXJoinSwapGroupSGIX(Display * dpy, GLXDrawable drawable, |
||
2038 | GLXDrawable member) |
||
2039 | { |
||
2040 | (void) dpy; |
||
2041 | (void) drawable; |
||
2042 | (void) member; |
||
2043 | } |
||
2044 | |||
2045 | |||
2046 | /* |
||
2047 | ** GLX_SGIX_swap_barrier |
||
2048 | */ |
||
2049 | static void |
||
2050 | __glXBindSwapBarrierSGIX(Display * dpy, GLXDrawable drawable, int barrier) |
||
2051 | { |
||
2052 | (void) dpy; |
||
2053 | (void) drawable; |
||
2054 | (void) barrier; |
||
2055 | } |
||
2056 | |||
2057 | static Bool |
||
2058 | __glXQueryMaxSwapBarriersSGIX(Display * dpy, int screen, int *max) |
||
2059 | { |
||
2060 | (void) dpy; |
||
2061 | (void) screen; |
||
2062 | (void) max; |
||
2063 | return False; |
||
2064 | } |
||
2065 | |||
2066 | |||
2067 | /* |
||
2068 | ** GLX_OML_sync_control |
||
2069 | */ |
||
2070 | static Bool |
||
2071 | __glXGetSyncValuesOML(Display * dpy, GLXDrawable drawable, |
||
2072 | int64_t * ust, int64_t * msc, int64_t * sbc) |
||
2073 | { |
||
2074 | struct glx_display * const priv = __glXInitialize(dpy); |
||
2075 | int ret; |
||
2076 | #ifdef GLX_DIRECT_RENDERING |
||
2077 | __GLXDRIdrawable *pdraw; |
||
2078 | #endif |
||
2079 | struct glx_screen *psc; |
||
2080 | |||
2081 | if (!priv) |
||
2082 | return False; |
||
2083 | |||
2084 | #ifdef GLX_DIRECT_RENDERING |
||
2085 | pdraw = GetGLXDRIDrawable(dpy, drawable); |
||
2086 | psc = pdraw ? pdraw->psc : NULL; |
||
2087 | if (pdraw && psc->driScreen->getDrawableMSC) { |
||
2088 | ret = psc->driScreen->getDrawableMSC(psc, pdraw, ust, msc, sbc); |
||
2089 | return ret; |
||
2090 | } |
||
2091 | #endif |
||
2092 | |||
2093 | return False; |
||
2094 | } |
||
2095 | |||
2096 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
2097 | _X_HIDDEN GLboolean |
||
2098 | __glxGetMscRate(__GLXDRIdrawable *glxDraw, |
||
2099 | int32_t * numerator, int32_t * denominator) |
||
2100 | { |
||
2101 | #ifdef XF86VIDMODE |
||
2102 | struct glx_screen *psc; |
||
2103 | XF86VidModeModeLine mode_line; |
||
2104 | int dot_clock; |
||
2105 | int i; |
||
2106 | |||
2107 | psc = glxDraw->psc; |
||
2108 | if (XF86VidModeQueryVersion(psc->dpy, &i, &i) && |
||
2109 | XF86VidModeGetModeLine(psc->dpy, psc->scr, &dot_clock, &mode_line)) { |
||
2110 | unsigned n = dot_clock * 1000; |
||
2111 | unsigned d = mode_line.vtotal * mode_line.htotal; |
||
2112 | |||
2113 | # define V_INTERLACE 0x010 |
||
2114 | # define V_DBLSCAN 0x020 |
||
2115 | |||
2116 | if (mode_line.flags & V_INTERLACE) |
||
2117 | n *= 2; |
||
2118 | else if (mode_line.flags & V_DBLSCAN) |
||
2119 | d *= 2; |
||
2120 | |||
2121 | /* The OML_sync_control spec requires that if the refresh rate is a |
||
2122 | * whole number, that the returned numerator be equal to the refresh |
||
2123 | * rate and the denominator be 1. |
||
2124 | */ |
||
2125 | |||
2126 | if (n % d == 0) { |
||
2127 | n /= d; |
||
2128 | d = 1; |
||
2129 | } |
||
2130 | else { |
||
2131 | static const unsigned f[] = { 13, 11, 7, 5, 3, 2, 0 }; |
||
2132 | |||
2133 | /* This is a poor man's way to reduce a fraction. It's far from |
||
2134 | * perfect, but it will work well enough for this situation. |
||
2135 | */ |
||
2136 | |||
2137 | for (i = 0; f[i] != 0; i++) { |
||
2138 | while (n % f[i] == 0 && d % f[i] == 0) { |
||
2139 | d /= f[i]; |
||
2140 | n /= f[i]; |
||
2141 | } |
||
2142 | } |
||
2143 | } |
||
2144 | |||
2145 | *numerator = n; |
||
2146 | *denominator = d; |
||
2147 | |||
2148 | return True; |
||
2149 | } |
||
2150 | else |
||
2151 | #endif |
||
2152 | |||
2153 | return False; |
||
2154 | } |
||
2155 | #endif |
||
2156 | |||
2157 | /** |
||
2158 | * Determine the refresh rate of the specified drawable and display. |
||
2159 | * |
||
2160 | * \param dpy Display whose refresh rate is to be determined. |
||
2161 | * \param drawable Drawable whose refresh rate is to be determined. |
||
2162 | * \param numerator Numerator of the refresh rate. |
||
2163 | * \param demoninator Denominator of the refresh rate. |
||
2164 | * \return If the refresh rate for the specified display and drawable could |
||
2165 | * be calculated, True is returned. Otherwise False is returned. |
||
2166 | * |
||
2167 | * \note This function is implemented entirely client-side. A lot of other |
||
2168 | * functionality is required to export GLX_OML_sync_control, so on |
||
2169 | * XFree86 this function can be called for direct-rendering contexts |
||
2170 | * when GLX_OML_sync_control appears in the client extension string. |
||
2171 | */ |
||
2172 | |||
2173 | _X_HIDDEN GLboolean |
||
2174 | __glXGetMscRateOML(Display * dpy, GLXDrawable drawable, |
||
2175 | int32_t * numerator, int32_t * denominator) |
||
2176 | { |
||
2177 | #if defined( GLX_DIRECT_RENDERING ) && defined( XF86VIDMODE ) |
||
2178 | __GLXDRIdrawable *draw = GetGLXDRIDrawable(dpy, drawable); |
||
2179 | |||
2180 | if (draw == NULL) |
||
2181 | return False; |
||
2182 | |||
2183 | return __glxGetMscRate(draw, numerator, denominator); |
||
2184 | #else |
||
2185 | (void) dpy; |
||
2186 | (void) drawable; |
||
2187 | (void) numerator; |
||
2188 | (void) denominator; |
||
2189 | #endif |
||
2190 | return False; |
||
2191 | } |
||
2192 | |||
2193 | |||
2194 | static int64_t |
||
2195 | __glXSwapBuffersMscOML(Display * dpy, GLXDrawable drawable, |
||
2196 | int64_t target_msc, int64_t divisor, int64_t remainder) |
||
2197 | { |
||
2198 | struct glx_context *gc = __glXGetCurrentContext(); |
||
2199 | #ifdef GLX_DIRECT_RENDERING |
||
2200 | __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); |
||
2201 | struct glx_screen *psc = pdraw ? pdraw->psc : NULL; |
||
2202 | #endif |
||
2203 | |||
2204 | if (!gc) /* no GLX for this */ |
||
2205 | return -1; |
||
2206 | |||
2207 | #ifdef GLX_DIRECT_RENDERING |
||
2208 | if (!pdraw || !gc->isDirect) |
||
2209 | return -1; |
||
2210 | #endif |
||
2211 | |||
2212 | /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE |
||
2213 | * error", but it also says "It [glXSwapBuffersMscOML] will return a value |
||
2214 | * of -1 if the function failed because of errors detected in the input |
||
2215 | * parameters" |
||
2216 | */ |
||
2217 | if (divisor < 0 || remainder < 0 || target_msc < 0) |
||
2218 | return -1; |
||
2219 | if (divisor > 0 && remainder >= divisor) |
||
2220 | return -1; |
||
2221 | |||
2222 | if (target_msc == 0 && divisor == 0 && remainder == 0) |
||
2223 | remainder = 1; |
||
2224 | |||
2225 | #ifdef GLX_DIRECT_RENDERING |
||
2226 | if (psc->driScreen && psc->driScreen->swapBuffers) |
||
2227 | return (*psc->driScreen->swapBuffers)(pdraw, target_msc, divisor, |
||
2228 | remainder, False); |
||
2229 | #endif |
||
2230 | |||
2231 | return -1; |
||
2232 | } |
||
2233 | |||
2234 | |||
2235 | static Bool |
||
2236 | __glXWaitForMscOML(Display * dpy, GLXDrawable drawable, |
||
2237 | int64_t target_msc, int64_t divisor, |
||
2238 | int64_t remainder, int64_t * ust, |
||
2239 | int64_t * msc, int64_t * sbc) |
||
2240 | { |
||
2241 | #ifdef GLX_DIRECT_RENDERING |
||
2242 | __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); |
||
2243 | struct glx_screen *psc = pdraw ? pdraw->psc : NULL; |
||
2244 | int ret; |
||
2245 | #endif |
||
2246 | |||
2247 | |||
2248 | /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE |
||
2249 | * error", but the return type in the spec is Bool. |
||
2250 | */ |
||
2251 | if (divisor < 0 || remainder < 0 || target_msc < 0) |
||
2252 | return False; |
||
2253 | if (divisor > 0 && remainder >= divisor) |
||
2254 | return False; |
||
2255 | |||
2256 | #ifdef GLX_DIRECT_RENDERING |
||
2257 | if (pdraw && psc->driScreen && psc->driScreen->waitForMSC) { |
||
2258 | ret = psc->driScreen->waitForMSC(pdraw, target_msc, divisor, remainder, |
||
2259 | ust, msc, sbc); |
||
2260 | return ret; |
||
2261 | } |
||
2262 | #endif |
||
2263 | |||
2264 | return False; |
||
2265 | } |
||
2266 | |||
2267 | |||
2268 | static Bool |
||
2269 | __glXWaitForSbcOML(Display * dpy, GLXDrawable drawable, |
||
2270 | int64_t target_sbc, int64_t * ust, |
||
2271 | int64_t * msc, int64_t * sbc) |
||
2272 | { |
||
2273 | #ifdef GLX_DIRECT_RENDERING |
||
2274 | __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); |
||
2275 | struct glx_screen *psc = pdraw ? pdraw->psc : NULL; |
||
2276 | int ret; |
||
2277 | #endif |
||
2278 | |||
2279 | /* The OML_sync_control spec says this should "generate a GLX_BAD_VALUE |
||
2280 | * error", but the return type in the spec is Bool. |
||
2281 | */ |
||
2282 | if (target_sbc < 0) |
||
2283 | return False; |
||
2284 | |||
2285 | #ifdef GLX_DIRECT_RENDERING |
||
2286 | if (pdraw && psc->driScreen && psc->driScreen->waitForSBC) { |
||
2287 | ret = psc->driScreen->waitForSBC(pdraw, target_sbc, ust, msc, sbc); |
||
2288 | return ret; |
||
2289 | } |
||
2290 | #endif |
||
2291 | |||
2292 | return False; |
||
2293 | } |
||
2294 | |||
2295 | /*@}*/ |
||
2296 | |||
2297 | |||
2298 | /** |
||
2299 | * Mesa extension stubs. These will help reduce portability problems. |
||
2300 | */ |
||
2301 | /*@{*/ |
||
2302 | |||
2303 | /** |
||
2304 | * Release all buffers associated with the specified GLX drawable. |
||
2305 | * |
||
2306 | * \todo |
||
2307 | * This function was intended for stand-alone Mesa. The issue there is that |
||
2308 | * the library doesn't get any notification when a window is closed. In |
||
2309 | * DRI there is a similar but slightly different issue. When GLX 1.3 is |
||
2310 | * supported, there are 3 different functions to destroy a drawable. It |
||
2311 | * should be possible to create GLX protocol (or have it determine which |
||
2312 | * protocol to use based on the type of the drawable) to have one function |
||
2313 | * do the work of 3. For the direct-rendering case, this function could |
||
2314 | * just call the driver's \c __DRIdrawableRec::destroyDrawable function. |
||
2315 | * This would reduce the frequency with which \c __driGarbageCollectDrawables |
||
2316 | * would need to be used. This really should be done as part of the new DRI |
||
2317 | * interface work. |
||
2318 | * |
||
2319 | * \sa http://oss.sgi.com/projects/ogl-sample/registry/MESA/release_buffers.txt |
||
2320 | * __driGarbageCollectDrawables |
||
2321 | * glXDestroyGLXPixmap |
||
2322 | * glXDestroyPbuffer glXDestroyPixmap glXDestroyWindow |
||
2323 | * glXDestroyGLXPbufferSGIX glXDestroyGLXVideoSourceSGIX |
||
2324 | */ |
||
2325 | static Bool |
||
2326 | __glXReleaseBuffersMESA(Display * dpy, GLXDrawable d) |
||
2327 | { |
||
2328 | (void) dpy; |
||
2329 | (void) d; |
||
2330 | return False; |
||
2331 | } |
||
2332 | |||
2333 | |||
2334 | _X_EXPORT GLXPixmap |
||
2335 | glXCreateGLXPixmapMESA(Display * dpy, XVisualInfo * visual, |
||
2336 | Pixmap pixmap, Colormap cmap) |
||
2337 | { |
||
2338 | (void) dpy; |
||
2339 | (void) visual; |
||
2340 | (void) pixmap; |
||
2341 | (void) cmap; |
||
2342 | return 0; |
||
2343 | } |
||
2344 | |||
2345 | /*@}*/ |
||
2346 | |||
2347 | |||
2348 | /** |
||
2349 | * GLX_MESA_copy_sub_buffer |
||
2350 | */ |
||
2351 | #define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ |
||
2352 | static void |
||
2353 | __glXCopySubBufferMESA(Display * dpy, GLXDrawable drawable, |
||
2354 | int x, int y, int width, int height) |
||
2355 | { |
||
2356 | xGLXVendorPrivateReq *req; |
||
2357 | struct glx_context *gc; |
||
2358 | GLXContextTag tag; |
||
2359 | CARD32 *drawable_ptr; |
||
2360 | INT32 *x_ptr, *y_ptr, *w_ptr, *h_ptr; |
||
2361 | CARD8 opcode; |
||
2362 | |||
2363 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
2364 | __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); |
||
2365 | if (pdraw != NULL) { |
||
2366 | struct glx_screen *psc = pdraw->psc; |
||
2367 | if (psc->driScreen->copySubBuffer != NULL) { |
||
2368 | (*psc->driScreen->copySubBuffer) (pdraw, x, y, width, height, True); |
||
2369 | } |
||
2370 | |||
2371 | return; |
||
2372 | } |
||
2373 | #endif |
||
2374 | |||
2375 | opcode = __glXSetupForCommand(dpy); |
||
2376 | if (!opcode) |
||
2377 | return; |
||
2378 | |||
2379 | /* |
||
2380 | ** The calling thread may or may not have a current context. If it |
||
2381 | ** does, send the context tag so the server can do a flush. |
||
2382 | */ |
||
2383 | gc = __glXGetCurrentContext(); |
||
2384 | if ((gc != NULL) && (dpy == gc->currentDpy) && |
||
2385 | ((drawable == gc->currentDrawable) || |
||
2386 | (drawable == gc->currentReadable))) { |
||
2387 | tag = gc->currentContextTag; |
||
2388 | } |
||
2389 | else { |
||
2390 | tag = 0; |
||
2391 | } |
||
2392 | |||
2393 | LockDisplay(dpy); |
||
2394 | GetReqExtra(GLXVendorPrivate, sizeof(CARD32) + sizeof(INT32) * 4, req); |
||
2395 | req->reqType = opcode; |
||
2396 | req->glxCode = X_GLXVendorPrivate; |
||
2397 | req->vendorCode = X_GLXvop_CopySubBufferMESA; |
||
2398 | req->contextTag = tag; |
||
2399 | |||
2400 | drawable_ptr = (CARD32 *) (req + 1); |
||
2401 | x_ptr = (INT32 *) (drawable_ptr + 1); |
||
2402 | y_ptr = (INT32 *) (drawable_ptr + 2); |
||
2403 | w_ptr = (INT32 *) (drawable_ptr + 3); |
||
2404 | h_ptr = (INT32 *) (drawable_ptr + 4); |
||
2405 | |||
2406 | *drawable_ptr = drawable; |
||
2407 | *x_ptr = x; |
||
2408 | *y_ptr = y; |
||
2409 | *w_ptr = width; |
||
2410 | *h_ptr = height; |
||
2411 | |||
2412 | UnlockDisplay(dpy); |
||
2413 | SyncHandle(); |
||
2414 | } |
||
2415 | |||
2416 | /*@{*/ |
||
2417 | static void |
||
2418 | __glXBindTexImageEXT(Display * dpy, |
||
2419 | GLXDrawable drawable, int buffer, const int *attrib_list) |
||
2420 | { |
||
2421 | struct glx_context *gc = __glXGetCurrentContext(); |
||
2422 | |||
2423 | if (gc == NULL || gc->vtable->bind_tex_image == NULL) |
||
2424 | return; |
||
2425 | |||
2426 | gc->vtable->bind_tex_image(dpy, drawable, buffer, attrib_list); |
||
2427 | } |
||
2428 | |||
2429 | static void |
||
2430 | __glXReleaseTexImageEXT(Display * dpy, GLXDrawable drawable, int buffer) |
||
2431 | { |
||
2432 | struct glx_context *gc = __glXGetCurrentContext(); |
||
2433 | |||
2434 | if (gc == NULL || gc->vtable->release_tex_image == NULL) |
||
2435 | return; |
||
2436 | |||
2437 | gc->vtable->release_tex_image(dpy, drawable, buffer); |
||
2438 | } |
||
2439 | |||
2440 | /*@}*/ |
||
2441 | |||
2442 | #endif /* GLX_USE_APPLEGL */ |
||
2443 | |||
2444 | /** |
||
2445 | * \c strdup is actually not a standard ANSI C or POSIX routine. |
||
2446 | * Irix will not define it if ANSI mode is in effect. |
||
2447 | * |
||
2448 | * \sa strdup |
||
2449 | */ |
||
2450 | _X_HIDDEN char * |
||
2451 | __glXstrdup(const char *str) |
||
2452 | { |
||
2453 | char *copy; |
||
2454 | copy = malloc(strlen(str) + 1); |
||
2455 | if (!copy) |
||
2456 | return NULL; |
||
2457 | strcpy(copy, str); |
||
2458 | return copy; |
||
2459 | } |
||
2460 | |||
2461 | /* |
||
2462 | ** glXGetProcAddress support |
||
2463 | */ |
||
2464 | |||
2465 | struct name_address_pair |
||
2466 | { |
||
2467 | const char *Name; |
||
2468 | GLvoid *Address; |
||
2469 | }; |
||
2470 | |||
2471 | #define GLX_FUNCTION(f) { # f, (GLvoid *) f } |
||
2472 | #define GLX_FUNCTION2(n,f) { # n, (GLvoid *) f } |
||
2473 | |||
2474 | static const struct name_address_pair GLX_functions[] = { |
||
2475 | /*** GLX_VERSION_1_0 ***/ |
||
2476 | GLX_FUNCTION(glXChooseVisual), |
||
2477 | GLX_FUNCTION(glXCopyContext), |
||
2478 | GLX_FUNCTION(glXCreateContext), |
||
2479 | GLX_FUNCTION(glXCreateGLXPixmap), |
||
2480 | GLX_FUNCTION(glXDestroyContext), |
||
2481 | GLX_FUNCTION(glXDestroyGLXPixmap), |
||
2482 | GLX_FUNCTION(glXGetConfig), |
||
2483 | GLX_FUNCTION(glXGetCurrentContext), |
||
2484 | GLX_FUNCTION(glXGetCurrentDrawable), |
||
2485 | GLX_FUNCTION(glXIsDirect), |
||
2486 | GLX_FUNCTION(glXMakeCurrent), |
||
2487 | GLX_FUNCTION(glXQueryExtension), |
||
2488 | GLX_FUNCTION(glXQueryVersion), |
||
2489 | GLX_FUNCTION(glXSwapBuffers), |
||
2490 | GLX_FUNCTION(glXUseXFont), |
||
2491 | GLX_FUNCTION(glXWaitGL), |
||
2492 | GLX_FUNCTION(glXWaitX), |
||
2493 | |||
2494 | /*** GLX_VERSION_1_1 ***/ |
||
2495 | GLX_FUNCTION(glXGetClientString), |
||
2496 | GLX_FUNCTION(glXQueryExtensionsString), |
||
2497 | GLX_FUNCTION(glXQueryServerString), |
||
2498 | |||
2499 | /*** GLX_VERSION_1_2 ***/ |
||
2500 | GLX_FUNCTION(glXGetCurrentDisplay), |
||
2501 | |||
2502 | /*** GLX_VERSION_1_3 ***/ |
||
2503 | GLX_FUNCTION(glXChooseFBConfig), |
||
2504 | GLX_FUNCTION(glXCreateNewContext), |
||
2505 | GLX_FUNCTION(glXCreatePbuffer), |
||
2506 | GLX_FUNCTION(glXCreatePixmap), |
||
2507 | GLX_FUNCTION(glXCreateWindow), |
||
2508 | GLX_FUNCTION(glXDestroyPbuffer), |
||
2509 | GLX_FUNCTION(glXDestroyPixmap), |
||
2510 | GLX_FUNCTION(glXDestroyWindow), |
||
2511 | GLX_FUNCTION(glXGetCurrentReadDrawable), |
||
2512 | GLX_FUNCTION(glXGetFBConfigAttrib), |
||
2513 | GLX_FUNCTION(glXGetFBConfigs), |
||
2514 | GLX_FUNCTION(glXGetSelectedEvent), |
||
2515 | GLX_FUNCTION(glXGetVisualFromFBConfig), |
||
2516 | GLX_FUNCTION(glXMakeContextCurrent), |
||
2517 | GLX_FUNCTION(glXQueryContext), |
||
2518 | GLX_FUNCTION(glXQueryDrawable), |
||
2519 | GLX_FUNCTION(glXSelectEvent), |
||
2520 | |||
2521 | #ifndef GLX_USE_APPLEGL |
||
2522 | /*** GLX_SGI_swap_control ***/ |
||
2523 | GLX_FUNCTION2(glXSwapIntervalSGI, __glXSwapIntervalSGI), |
||
2524 | |||
2525 | /*** GLX_SGI_video_sync ***/ |
||
2526 | GLX_FUNCTION2(glXGetVideoSyncSGI, __glXGetVideoSyncSGI), |
||
2527 | GLX_FUNCTION2(glXWaitVideoSyncSGI, __glXWaitVideoSyncSGI), |
||
2528 | |||
2529 | /*** GLX_SGI_make_current_read ***/ |
||
2530 | GLX_FUNCTION2(glXMakeCurrentReadSGI, glXMakeContextCurrent), |
||
2531 | GLX_FUNCTION2(glXGetCurrentReadDrawableSGI, glXGetCurrentReadDrawable), |
||
2532 | |||
2533 | /*** GLX_EXT_import_context ***/ |
||
2534 | GLX_FUNCTION(glXFreeContextEXT), |
||
2535 | GLX_FUNCTION(glXGetContextIDEXT), |
||
2536 | GLX_FUNCTION2(glXGetCurrentDisplayEXT, glXGetCurrentDisplay), |
||
2537 | GLX_FUNCTION(glXImportContextEXT), |
||
2538 | GLX_FUNCTION2(glXQueryContextInfoEXT, glXQueryContext), |
||
2539 | #endif |
||
2540 | |||
2541 | /*** GLX_SGIX_fbconfig ***/ |
||
2542 | GLX_FUNCTION2(glXGetFBConfigAttribSGIX, glXGetFBConfigAttrib), |
||
2543 | GLX_FUNCTION2(glXChooseFBConfigSGIX, glXChooseFBConfig), |
||
2544 | GLX_FUNCTION(glXCreateGLXPixmapWithConfigSGIX), |
||
2545 | GLX_FUNCTION(glXCreateContextWithConfigSGIX), |
||
2546 | GLX_FUNCTION2(glXGetVisualFromFBConfigSGIX, glXGetVisualFromFBConfig), |
||
2547 | GLX_FUNCTION(glXGetFBConfigFromVisualSGIX), |
||
2548 | |||
2549 | #ifndef GLX_USE_APPLEGL |
||
2550 | /*** GLX_SGIX_pbuffer ***/ |
||
2551 | GLX_FUNCTION(glXCreateGLXPbufferSGIX), |
||
2552 | GLX_FUNCTION(glXDestroyGLXPbufferSGIX), |
||
2553 | GLX_FUNCTION(glXQueryGLXPbufferSGIX), |
||
2554 | GLX_FUNCTION(glXSelectEventSGIX), |
||
2555 | GLX_FUNCTION(glXGetSelectedEventSGIX), |
||
2556 | |||
2557 | /*** GLX_SGIX_swap_group ***/ |
||
2558 | GLX_FUNCTION2(glXJoinSwapGroupSGIX, __glXJoinSwapGroupSGIX), |
||
2559 | |||
2560 | /*** GLX_SGIX_swap_barrier ***/ |
||
2561 | GLX_FUNCTION2(glXBindSwapBarrierSGIX, __glXBindSwapBarrierSGIX), |
||
2562 | GLX_FUNCTION2(glXQueryMaxSwapBarriersSGIX, __glXQueryMaxSwapBarriersSGIX), |
||
2563 | |||
2564 | /*** GLX_MESA_copy_sub_buffer ***/ |
||
2565 | GLX_FUNCTION2(glXCopySubBufferMESA, __glXCopySubBufferMESA), |
||
2566 | |||
2567 | /*** GLX_MESA_pixmap_colormap ***/ |
||
2568 | GLX_FUNCTION(glXCreateGLXPixmapMESA), |
||
2569 | |||
2570 | /*** GLX_MESA_release_buffers ***/ |
||
2571 | GLX_FUNCTION2(glXReleaseBuffersMESA, __glXReleaseBuffersMESA), |
||
2572 | |||
2573 | /*** GLX_MESA_swap_control ***/ |
||
2574 | GLX_FUNCTION2(glXSwapIntervalMESA, __glXSwapIntervalMESA), |
||
2575 | GLX_FUNCTION2(glXGetSwapIntervalMESA, __glXGetSwapIntervalMESA), |
||
2576 | #endif |
||
2577 | |||
2578 | /*** GLX_ARB_get_proc_address ***/ |
||
2579 | GLX_FUNCTION(glXGetProcAddressARB), |
||
2580 | |||
2581 | /*** GLX 1.4 ***/ |
||
2582 | GLX_FUNCTION2(glXGetProcAddress, glXGetProcAddressARB), |
||
2583 | |||
2584 | #ifndef GLX_USE_APPLEGL |
||
2585 | /*** GLX_OML_sync_control ***/ |
||
2586 | GLX_FUNCTION2(glXWaitForSbcOML, __glXWaitForSbcOML), |
||
2587 | GLX_FUNCTION2(glXWaitForMscOML, __glXWaitForMscOML), |
||
2588 | GLX_FUNCTION2(glXSwapBuffersMscOML, __glXSwapBuffersMscOML), |
||
2589 | GLX_FUNCTION2(glXGetMscRateOML, __glXGetMscRateOML), |
||
2590 | GLX_FUNCTION2(glXGetSyncValuesOML, __glXGetSyncValuesOML), |
||
2591 | |||
2592 | /*** GLX_EXT_texture_from_pixmap ***/ |
||
2593 | GLX_FUNCTION2(glXBindTexImageEXT, __glXBindTexImageEXT), |
||
2594 | GLX_FUNCTION2(glXReleaseTexImageEXT, __glXReleaseTexImageEXT), |
||
2595 | #endif |
||
2596 | |||
2597 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
2598 | /*** DRI configuration ***/ |
||
2599 | GLX_FUNCTION(glXGetScreenDriver), |
||
2600 | GLX_FUNCTION(glXGetDriverConfig), |
||
2601 | #endif |
||
2602 | |||
2603 | /*** GLX_ARB_create_context and GLX_ARB_create_context_profile ***/ |
||
2604 | GLX_FUNCTION(glXCreateContextAttribsARB), |
||
2605 | |||
2606 | {NULL, NULL} /* end of list */ |
||
2607 | }; |
||
2608 | |||
2609 | static const GLvoid * |
||
2610 | get_glx_proc_address(const char *funcName) |
||
2611 | { |
||
2612 | GLuint i; |
||
2613 | |||
2614 | /* try static functions */ |
||
2615 | for (i = 0; GLX_functions[i].Name; i++) { |
||
2616 | if (strcmp(GLX_functions[i].Name, funcName) == 0) |
||
2617 | return GLX_functions[i].Address; |
||
2618 | } |
||
2619 | |||
2620 | return NULL; |
||
2621 | } |
||
2622 | |||
2623 | /** |
||
2624 | * Get the address of a named GL function. This is the pre-GLX 1.4 name for |
||
2625 | * \c glXGetProcAddress. |
||
2626 | * |
||
2627 | * \param procName Name of a GL or GLX function. |
||
2628 | * \returns A pointer to the named function |
||
2629 | * |
||
2630 | * \sa glXGetProcAddress |
||
2631 | */ |
||
2632 | _X_EXPORT void (*glXGetProcAddressARB(const GLubyte * procName)) (void) |
||
2633 | { |
||
2634 | typedef void (*gl_function) (void); |
||
2635 | gl_function f; |
||
2636 | |||
2637 | |||
2638 | /* Search the table of GLX and internal functions first. If that |
||
2639 | * fails and the supplied name could be a valid core GL name, try |
||
2640 | * searching the core GL function table. This check is done to prevent |
||
2641 | * DRI based drivers from searching the core GL function table for |
||
2642 | * internal API functions. |
||
2643 | */ |
||
2644 | f = (gl_function) get_glx_proc_address((const char *) procName); |
||
2645 | if ((f == NULL) && (procName[0] == 'g') && (procName[1] == 'l') |
||
2646 | && (procName[2] != 'X')) { |
||
2647 | #ifdef GLX_SHARED_GLAPI |
||
2648 | f = (gl_function) __indirect_get_proc_address((const char *) procName); |
||
2649 | #endif |
||
2650 | if (!f) |
||
2651 | f = (gl_function) _glapi_get_proc_address((const char *) procName); |
||
2652 | if (!f) { |
||
2653 | struct glx_context *gc = __glXGetCurrentContext(); |
||
2654 | |||
2655 | if (gc != NULL && gc->vtable->get_proc_address != NULL) |
||
2656 | f = gc->vtable->get_proc_address((const char *) procName); |
||
2657 | } |
||
2658 | } |
||
2659 | return f; |
||
2660 | } |
||
2661 | |||
2662 | /** |
||
2663 | * Get the address of a named GL function. This is the GLX 1.4 name for |
||
2664 | * \c glXGetProcAddressARB. |
||
2665 | * |
||
2666 | * \param procName Name of a GL or GLX function. |
||
2667 | * \returns A pointer to the named function |
||
2668 | * |
||
2669 | * \sa glXGetProcAddressARB |
||
2670 | */ |
||
2671 | _X_EXPORT void (*glXGetProcAddress(const GLubyte * procName)) (void) |
||
2672 | #if defined(__GNUC__) && !defined(GLX_ALIAS_UNSUPPORTED) |
||
2673 | __attribute__ ((alias("glXGetProcAddressARB"))); |
||
2674 | #else |
||
2675 | { |
||
2676 | return glXGetProcAddressARB(procName); |
||
2677 | } |
||
2678 | #endif /* __GNUC__ */ |
||
2679 | |||
2680 | |||
2681 | #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) |
||
2682 | /** |
||
2683 | * Get the unadjusted system time (UST). Currently, the UST is measured in |
||
2684 | * microseconds since Epoc. The actual resolution of the UST may vary from |
||
2685 | * system to system, and the units may vary from release to release. |
||
2686 | * Drivers should not call this function directly. They should instead use |
||
2687 | * \c glXGetProcAddress to obtain a pointer to the function. |
||
2688 | * |
||
2689 | * \param ust Location to store the 64-bit UST |
||
2690 | * \returns Zero on success or a negative errno value on failure. |
||
2691 | * |
||
2692 | * \sa glXGetProcAddress, PFNGLXGETUSTPROC |
||
2693 | * |
||
2694 | * \since Internal API version 20030317. |
||
2695 | */ |
||
2696 | _X_HIDDEN int |
||
2697 | __glXGetUST(int64_t * ust) |
||
2698 | { |
||
2699 | struct timeval tv; |
||
2700 | |||
2701 | if (ust == NULL) { |
||
2702 | return -EFAULT; |
||
2703 | } |
||
2704 | |||
2705 | if (gettimeofday(&tv, NULL) == 0) { |
||
2706 | ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; |
||
2707 | return 0; |
||
2708 | } |
||
2709 | else { |
||
2710 | return -errno; |
||
2711 | } |
||
2712 | } |
||
2713 | #endif /* GLX_DIRECT_RENDERING */>>>>>>>>=>=>=>>=>>>>>> |