glx: Move WaitGL, WaitX, UseXFont to context vtable functions
[mesa.git] / src / glx / dri_glx.c
1 /**************************************************************************
2
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sub license, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice (including the
15 next paragraph) shall be included in all copies or substantial portions
16 of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Kevin E. Martin <kevin@precisioninsight.com>
31 * Brian Paul <brian@precisioninsight.com>
32 *
33 */
34
35 #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
36
37 #include <X11/Xlib.h>
38 #include <X11/extensions/Xfixes.h>
39 #include <X11/extensions/Xdamage.h>
40 #include "glxclient.h"
41 #include "xf86dri.h"
42 #include "dri2.h"
43 #include "sarea.h"
44 #include <dlfcn.h>
45 #include <sys/types.h>
46 #include <sys/mman.h>
47 #include "xf86drm.h"
48 #include "dri_common.h"
49
50 struct dri_display
51 {
52 __GLXDRIdisplay base;
53
54 /*
55 ** XFree86-DRI version information
56 */
57 int driMajor;
58 int driMinor;
59 int driPatch;
60 };
61
62 struct dri_screen
63 {
64 __GLXscreenConfigs base;
65
66 __DRIscreen *driScreen;
67 __GLXDRIscreen vtable;
68 const __DRIlegacyExtension *legacy;
69 const __DRIcoreExtension *core;
70 const __DRIswapControlExtension *swapControl;
71 const __DRImediaStreamCounterExtension *msc;
72 const __DRIconfig **driver_configs;
73 const __DRIcopySubBufferExtension *driCopySubBuffer;
74
75 void *driver;
76 int fd;
77 };
78
79 struct dri_context
80 {
81 __GLXcontext base;
82 __GLXDRIcontext dri_vtable;
83 __DRIcontext *driContext;
84 XID hwContextID;
85 __GLXscreenConfigs *psc;
86 };
87
88 struct dri_drawable
89 {
90 __GLXDRIdrawable base;
91
92 __DRIdrawable *driDrawable;
93 };
94
95 static const struct glx_context_vtable dri_context_vtable = {
96 NULL,
97 NULL,
98 DRI_glXUseXFont,
99 NULL,
100 NULL,
101 };
102
103 /*
104 * Given a display pointer and screen number, determine the name of
105 * the DRI driver for the screen. (I.e. "r128", "tdfx", etc).
106 * Return True for success, False for failure.
107 */
108 static Bool
109 driGetDriverName(Display * dpy, int scrNum, char **driverName)
110 {
111 int directCapable;
112 Bool b;
113 int event, error;
114 int driverMajor, driverMinor, driverPatch;
115
116 *driverName = NULL;
117
118 if (XF86DRIQueryExtension(dpy, &event, &error)) { /* DRI1 */
119 if (!XF86DRIQueryDirectRenderingCapable(dpy, scrNum, &directCapable)) {
120 ErrorMessageF("XF86DRIQueryDirectRenderingCapable failed\n");
121 return False;
122 }
123 if (!directCapable) {
124 ErrorMessageF("XF86DRIQueryDirectRenderingCapable returned false\n");
125 return False;
126 }
127
128 b = XF86DRIGetClientDriverName(dpy, scrNum, &driverMajor, &driverMinor,
129 &driverPatch, driverName);
130 if (!b) {
131 ErrorMessageF("Cannot determine driver name for screen %d\n",
132 scrNum);
133 return False;
134 }
135
136 InfoMessageF("XF86DRIGetClientDriverName: %d.%d.%d %s (screen %d)\n",
137 driverMajor, driverMinor, driverPatch, *driverName,
138 scrNum);
139
140 return True;
141 }
142 else if (DRI2QueryExtension(dpy, &event, &error)) { /* DRI2 */
143 char *dev;
144 Bool ret = DRI2Connect(dpy, RootWindow(dpy, scrNum), driverName, &dev);
145
146 if (ret)
147 Xfree(dev);
148
149 return ret;
150 }
151
152 return False;
153 }
154
155 /*
156 * Exported function for querying the DRI driver for a given screen.
157 *
158 * The returned char pointer points to a static array that will be
159 * overwritten by subsequent calls.
160 */
161 PUBLIC const char *
162 glXGetScreenDriver(Display * dpy, int scrNum)
163 {
164 static char ret[32];
165 char *driverName;
166 if (driGetDriverName(dpy, scrNum, &driverName)) {
167 int len;
168 if (!driverName)
169 return NULL;
170 len = strlen(driverName);
171 if (len >= 31)
172 return NULL;
173 memcpy(ret, driverName, len + 1);
174 Xfree(driverName);
175 return ret;
176 }
177 return NULL;
178 }
179
180 /*
181 * Exported function for obtaining a driver's option list (UTF-8 encoded XML).
182 *
183 * The returned char pointer points directly into the driver. Therefore
184 * it should be treated as a constant.
185 *
186 * If the driver was not found or does not support configuration NULL is
187 * returned.
188 *
189 * Note: The driver remains opened after this function returns.
190 */
191 PUBLIC const char *
192 glXGetDriverConfig(const char *driverName)
193 {
194 void *handle = driOpenDriver(driverName);
195 if (handle)
196 return dlsym(handle, "__driConfigOptions");
197 else
198 return NULL;
199 }
200
201 #ifdef XDAMAGE_1_1_INTERFACE
202
203 static GLboolean
204 has_damage_post(Display * dpy)
205 {
206 static GLboolean inited = GL_FALSE;
207 static GLboolean has_damage;
208
209 if (!inited) {
210 int major, minor;
211
212 if (XDamageQueryVersion(dpy, &major, &minor) &&
213 major == 1 && minor >= 1) {
214 has_damage = GL_TRUE;
215 }
216 else {
217 has_damage = GL_FALSE;
218 }
219 inited = GL_TRUE;
220 }
221
222 return has_damage;
223 }
224
225 static void
226 __glXReportDamage(__DRIdrawable * driDraw,
227 int x, int y,
228 drm_clip_rect_t * rects, int num_rects,
229 GLboolean front_buffer, void *loaderPrivate)
230 {
231 XRectangle *xrects;
232 XserverRegion region;
233 int i;
234 int x_off, y_off;
235 __GLXDRIdrawable *glxDraw = loaderPrivate;
236 __GLXscreenConfigs *psc = glxDraw->psc;
237 Display *dpy = psc->dpy;
238 Drawable drawable;
239
240 if (!has_damage_post(dpy))
241 return;
242
243 if (front_buffer) {
244 x_off = x;
245 y_off = y;
246 drawable = RootWindow(dpy, psc->scr);
247 }
248 else {
249 x_off = 0;
250 y_off = 0;
251 drawable = glxDraw->xDrawable;
252 }
253
254 xrects = malloc(sizeof(XRectangle) * num_rects);
255 if (xrects == NULL)
256 return;
257
258 for (i = 0; i < num_rects; i++) {
259 xrects[i].x = rects[i].x1 + x_off;
260 xrects[i].y = rects[i].y1 + y_off;
261 xrects[i].width = rects[i].x2 - rects[i].x1;
262 xrects[i].height = rects[i].y2 - rects[i].y1;
263 }
264 region = XFixesCreateRegion(dpy, xrects, num_rects);
265 free(xrects);
266 XDamageAdd(dpy, drawable, region);
267 XFixesDestroyRegion(dpy, region);
268 }
269
270 static const __DRIdamageExtension damageExtension = {
271 {__DRI_DAMAGE, __DRI_DAMAGE_VERSION},
272 __glXReportDamage,
273 };
274
275 #endif
276
277 static GLboolean
278 __glXDRIGetDrawableInfo(__DRIdrawable * drawable,
279 unsigned int *index, unsigned int *stamp,
280 int *X, int *Y, int *W, int *H,
281 int *numClipRects, drm_clip_rect_t ** pClipRects,
282 int *backX, int *backY,
283 int *numBackClipRects,
284 drm_clip_rect_t ** pBackClipRects,
285 void *loaderPrivate)
286 {
287 __GLXDRIdrawable *glxDraw = loaderPrivate;
288 __GLXscreenConfigs *psc = glxDraw->psc;
289 Display *dpy = psc->dpy;
290
291 return XF86DRIGetDrawableInfo(dpy, psc->scr, glxDraw->drawable,
292 index, stamp, X, Y, W, H,
293 numClipRects, pClipRects,
294 backX, backY,
295 numBackClipRects, pBackClipRects);
296 }
297
298 static const __DRIgetDrawableInfoExtension getDrawableInfoExtension = {
299 {__DRI_GET_DRAWABLE_INFO, __DRI_GET_DRAWABLE_INFO_VERSION},
300 __glXDRIGetDrawableInfo
301 };
302
303 static const __DRIextension *loader_extensions[] = {
304 &systemTimeExtension.base,
305 &getDrawableInfoExtension.base,
306 #ifdef XDAMAGE_1_1_INTERFACE
307 &damageExtension.base,
308 #endif
309 NULL
310 };
311
312 /**
313 * Perform the required libGL-side initialization and call the client-side
314 * driver's \c __driCreateNewScreen function.
315 *
316 * \param dpy Display pointer.
317 * \param scrn Screen number on the display.
318 * \param psc DRI screen information.
319 * \param driDpy DRI display information.
320 * \param createNewScreen Pointer to the client-side driver's
321 * \c __driCreateNewScreen function.
322 * \returns A pointer to the \c __DRIscreen structure returned by
323 * the client-side driver on success, or \c NULL on failure.
324 */
325 static void *
326 CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc,
327 struct dri_display * driDpy)
328 {
329 void *psp = NULL;
330 drm_handle_t hSAREA;
331 drmAddress pSAREA = MAP_FAILED;
332 char *BusID;
333 __DRIversion ddx_version;
334 __DRIversion dri_version;
335 __DRIversion drm_version;
336 __DRIframebuffer framebuffer;
337 int fd = -1;
338 int status;
339
340 drm_magic_t magic;
341 drmVersionPtr version;
342 int newlyopened;
343 char *driverName;
344 drm_handle_t hFB;
345 int junk;
346 const __DRIconfig **driver_configs;
347 __GLcontextModes *visual;
348
349 /* DRI protocol version. */
350 dri_version.major = driDpy->driMajor;
351 dri_version.minor = driDpy->driMinor;
352 dri_version.patch = driDpy->driPatch;
353
354 framebuffer.base = MAP_FAILED;
355 framebuffer.dev_priv = NULL;
356 framebuffer.size = 0;
357
358 if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
359 ErrorMessageF("XF86DRIOpenConnection failed\n");
360 goto handle_error;
361 }
362
363 fd = drmOpenOnce(NULL, BusID, &newlyopened);
364
365 Xfree(BusID); /* No longer needed */
366
367 if (fd < 0) {
368 ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd));
369 goto handle_error;
370 }
371
372 if (drmGetMagic(fd, &magic)) {
373 ErrorMessageF("drmGetMagic failed\n");
374 goto handle_error;
375 }
376
377 version = drmGetVersion(fd);
378 if (version) {
379 drm_version.major = version->version_major;
380 drm_version.minor = version->version_minor;
381 drm_version.patch = version->version_patchlevel;
382 drmFreeVersion(version);
383 }
384 else {
385 drm_version.major = -1;
386 drm_version.minor = -1;
387 drm_version.patch = -1;
388 }
389
390 if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) {
391 ErrorMessageF("XF86DRIAuthConnection failed\n");
392 goto handle_error;
393 }
394
395 /* Get device name (like "tdfx") and the ddx version numbers.
396 * We'll check the version in each DRI driver's "createNewScreen"
397 * function. */
398 if (!XF86DRIGetClientDriverName(dpy, scrn,
399 &ddx_version.major,
400 &ddx_version.minor,
401 &ddx_version.patch, &driverName)) {
402 ErrorMessageF("XF86DRIGetClientDriverName failed\n");
403 goto handle_error;
404 }
405
406 Xfree(driverName); /* No longer needed. */
407
408 /*
409 * Get device-specific info. pDevPriv will point to a struct
410 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that
411 * has information about the screen size, depth, pitch, ancilliary
412 * buffers, DRM mmap handles, etc.
413 */
414 if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk,
415 &framebuffer.size, &framebuffer.stride,
416 &framebuffer.dev_priv_size,
417 &framebuffer.dev_priv)) {
418 ErrorMessageF("XF86DRIGetDeviceInfo failed");
419 goto handle_error;
420 }
421
422 framebuffer.width = DisplayWidth(dpy, scrn);
423 framebuffer.height = DisplayHeight(dpy, scrn);
424
425 /* Map the framebuffer region. */
426 status = drmMap(fd, hFB, framebuffer.size,
427 (drmAddressPtr) & framebuffer.base);
428 if (status != 0) {
429 ErrorMessageF("drmMap of framebuffer failed (%s)", strerror(-status));
430 goto handle_error;
431 }
432
433 /* Map the SAREA region. Further mmap regions may be setup in
434 * each DRI driver's "createNewScreen" function.
435 */
436 status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
437 if (status != 0) {
438 ErrorMessageF("drmMap of SAREA failed (%s)", strerror(-status));
439 goto handle_error;
440 }
441
442 psp = (*psc->legacy->createNewScreen) (scrn,
443 &ddx_version,
444 &dri_version,
445 &drm_version,
446 &framebuffer,
447 pSAREA,
448 fd,
449 loader_extensions,
450 &driver_configs, psc);
451
452 if (psp == NULL) {
453 ErrorMessageF("Calling driver entry point failed");
454 goto handle_error;
455 }
456
457 psc->base.configs =
458 driConvertConfigs(psc->core, psc->base.configs, driver_configs);
459 psc->base.visuals =
460 driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
461
462 psc->driver_configs = driver_configs;
463
464 /* Visuals with depth != screen depth are subject to automatic compositing
465 * in the X server, so DRI1 can't render to them properly. Mark them as
466 * non-conformant to prevent apps from picking them up accidentally.
467 */
468 for (visual = psc->base.visuals; visual; visual = visual->next) {
469 XVisualInfo template;
470 XVisualInfo *visuals;
471 int num_visuals;
472 long mask;
473
474 template.visualid = visual->visualID;
475 mask = VisualIDMask;
476 visuals = XGetVisualInfo(dpy, mask, &template, &num_visuals);
477
478 if (visuals) {
479 if (num_visuals > 0 && visuals->depth != DefaultDepth(dpy, scrn))
480 visual->visualRating = GLX_NON_CONFORMANT_CONFIG;
481
482 XFree(visuals);
483 }
484 }
485
486 return psp;
487
488 handle_error:
489 if (pSAREA != MAP_FAILED)
490 drmUnmap(pSAREA, SAREA_MAX);
491
492 if (framebuffer.base != MAP_FAILED)
493 drmUnmap((drmAddress) framebuffer.base, framebuffer.size);
494
495 if (framebuffer.dev_priv != NULL)
496 Xfree(framebuffer.dev_priv);
497
498 if (fd >= 0)
499 drmCloseOnce(fd);
500
501 XF86DRICloseConnection(dpy, scrn);
502
503 ErrorMessageF("reverting to software direct rendering\n");
504
505 return NULL;
506 }
507
508 static void
509 driDestroyContext(__GLXcontext * context)
510 {
511 struct dri_context *pcp = (struct dri_context *) context;
512 struct dri_screen *psc = (struct dri_screen *) context->psc;
513
514 (*psc->core->destroyContext) (pcp->driContext);
515
516 XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
517 Xfree(pcp);
518 }
519
520 static Bool
521 driBindContext(__GLXcontext *context,
522 __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
523 {
524 struct dri_context *pcp = (struct dri_context *) context;
525 struct dri_screen *psc = (struct dri_screen *) pcp->psc;
526 struct dri_drawable *pdr = (struct dri_drawable *) draw;
527 struct dri_drawable *prd = (struct dri_drawable *) read;
528
529 return (*psc->core->bindContext) (pcp->driContext,
530 pdr->driDrawable, prd->driDrawable);
531 }
532
533 static void
534 driUnbindContext(__GLXcontext * context)
535 {
536 struct dri_context *pcp = (struct dri_context *) context;
537 struct dri_screen *psc = (struct dri_screen *) pcp->psc;
538
539 (*psc->core->unbindContext) (pcp->driContext);
540 }
541
542 static __GLXcontext *
543 driCreateContext(__GLXscreenConfigs *base,
544 const __GLcontextModes * mode,
545 GLXContext shareList, int renderType)
546 {
547 struct dri_context *pcp, *pcp_shared;
548 struct dri_screen *psc = (struct dri_screen *) base;
549 drm_context_t hwContext;
550 __DRIcontext *shared = NULL;
551 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) mode;
552
553 if (!psc->base.driScreen)
554 return NULL;
555
556 if (shareList) {
557 pcp_shared = (struct dri_context *) shareList->driContext;
558 shared = pcp_shared->driContext;
559 }
560
561 pcp = Xmalloc(sizeof *pcp);
562 if (pcp == NULL)
563 return NULL;
564
565 memset(pcp, 0, sizeof *pcp);
566 if (!glx_context_init(&pcp->base, &psc->base, mode)) {
567 Xfree(pcp);
568 return NULL;
569 }
570
571 if (!XF86DRICreateContextWithConfig(psc->base.dpy, psc->base.scr,
572 mode->visualID,
573 &pcp->hwContextID, &hwContext)) {
574 Xfree(pcp);
575 return NULL;
576 }
577
578 pcp->driContext =
579 (*psc->legacy->createNewContext) (psc->driScreen,
580 config->driConfig,
581 renderType, shared, hwContext, pcp);
582 if (pcp->driContext == NULL) {
583 XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
584 Xfree(pcp);
585 return NULL;
586 }
587
588 pcp->base.vtable = &dri_context_vtable;
589 pcp->base.driContext = &pcp->dri_vtable;
590 pcp->dri_vtable.destroyContext = driDestroyContext;
591 pcp->dri_vtable.bindContext = driBindContext;
592 pcp->dri_vtable.unbindContext = driUnbindContext;
593
594 return &pcp->base;
595 }
596
597 static void
598 driDestroyDrawable(__GLXDRIdrawable * pdraw)
599 {
600 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
601 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
602
603 (*psc->core->destroyDrawable) (pdp->driDrawable);
604 XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, pdraw->drawable);
605 Xfree(pdraw);
606 }
607
608 static __GLXDRIdrawable *
609 driCreateDrawable(__GLXscreenConfigs *base,
610 XID xDrawable,
611 GLXDrawable drawable, const __GLcontextModes * modes)
612 {
613 drm_drawable_t hwDrawable;
614 void *empty_attribute_list = NULL;
615 __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
616 struct dri_screen *psc = (struct dri_screen *) base;
617 struct dri_drawable *pdp;
618
619 /* Old dri can't handle GLX 1.3+ drawable constructors. */
620 if (xDrawable != drawable)
621 return NULL;
622
623 pdp = Xmalloc(sizeof *pdp);
624 if (!pdp)
625 return NULL;
626
627 pdp->base.drawable = drawable;
628 pdp->base.psc = &psc->base;
629
630 if (!XF86DRICreateDrawable(psc->base.dpy, psc->base.scr,
631 drawable, &hwDrawable)) {
632 Xfree(pdp);
633 return NULL;
634 }
635
636 /* Create a new drawable */
637 pdp->driDrawable =
638 (*psc->legacy->createNewDrawable) (psc->driScreen,
639 config->driConfig,
640 hwDrawable,
641 GLX_WINDOW_BIT,
642 empty_attribute_list, pdp);
643
644 if (!pdp->driDrawable) {
645 XF86DRIDestroyDrawable(psc->base.dpy, psc->base.scr, drawable);
646 Xfree(pdp);
647 return NULL;
648 }
649
650 pdp->base.destroyDrawable = driDestroyDrawable;
651
652 return &pdp->base;
653 }
654
655 static int64_t
656 driSwapBuffers(__GLXDRIdrawable * pdraw, int64_t unused1, int64_t unused2,
657 int64_t unused3)
658 {
659 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
660 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
661
662 (*psc->core->swapBuffers) (pdp->driDrawable);
663 return 0;
664 }
665
666 static void
667 driCopySubBuffer(__GLXDRIdrawable * pdraw,
668 int x, int y, int width, int height)
669 {
670 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
671 struct dri_screen *psc = (struct dri_screen *) pdp->base.psc;
672
673 (*psc->driCopySubBuffer->copySubBuffer) (pdp->driDrawable,
674 x, y, width, height);
675 }
676
677 static void
678 driDestroyScreen(__GLXscreenConfigs *base)
679 {
680 struct dri_screen *psc = (struct dri_screen *) base;
681
682 /* Free the direct rendering per screen data */
683 if (psc->driScreen)
684 (*psc->core->destroyScreen) (psc->driScreen);
685 driDestroyConfigs(psc->driver_configs);
686 psc->driScreen = NULL;
687 if (psc->driver)
688 dlclose(psc->driver);
689 }
690
691 #ifdef __DRI_SWAP_BUFFER_COUNTER
692
693 static int
694 driDrawableGetMSC(__GLXscreenConfigs *base, __GLXDRIdrawable *pdraw,
695 int64_t *ust, int64_t *msc, int64_t *sbc)
696 {
697 struct dri_screen *psc = (struct dri_screen *) base;
698 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
699
700 if (pdp && psc->sbc && psc->msc)
701 return ( (*psc->msc->getMSC)(psc->driScreen, msc) == 0 &&
702 (*psc->sbc->getSBC)(pdp->driDrawable, sbc) == 0 &&
703 __glXGetUST(ust) == 0 );
704 }
705
706 static int
707 driWaitForMSC(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
708 int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc)
709 {
710 struct dri_screen *psc = (struct dri_screen *) pdraw->psc;
711 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
712
713 if (pdp != NULL && psc->msc != NULL) {
714 ret = (*psc->msc->waitForMSC) (pdp->driDrawable, target_msc,
715 divisor, remainder, msc, sbc);
716
717 /* __glXGetUST returns zero on success and non-zero on failure.
718 * This function returns True on success and False on failure.
719 */
720 return ret == 0 && __glXGetUST(ust) == 0;
721 }
722 }
723
724 static int
725 driWaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
726 int64_t *msc, int64_t *sbc)
727 {
728 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
729
730 if (pdp != NULL && psc->sbc != NULL) {
731 ret =
732 (*psc->sbc->waitForSBC) (pdp->driDrawable, target_sbc, msc, sbc);
733
734 /* __glXGetUST returns zero on success and non-zero on failure.
735 * This function returns True on success and False on failure.
736 */
737 return ((ret == 0) && (__glXGetUST(ust) == 0));
738 }
739
740 return DRI2WaitSBC(pdp->base.psc->dpy,
741 pdp->base.xDrawable, target_sbc, ust, msc, sbc);
742 }
743
744 #endif
745
746 static int
747 driSetSwapInterval(__GLXDRIdrawable *pdraw, int interval)
748 {
749 GLXContext gc = __glXGetCurrentContext();
750 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
751 struct dri_screen *psc;
752
753 if (gc->driContext) {
754 psc = (struct dri_screen *) pdraw->psc;
755
756 if (psc->swapControl != NULL && pdraw != NULL) {
757 psc->swapControl->setSwapInterval(pdp->driDrawable, interval);
758 return 0;
759 }
760 }
761
762 return GLX_BAD_CONTEXT;
763 }
764
765 static int
766 driGetSwapInterval(__GLXDRIdrawable *pdraw)
767 {
768 GLXContext gc = __glXGetCurrentContext();
769 struct dri_drawable *pdp = (struct dri_drawable *) pdraw;
770 struct dri_screen *psc;
771
772 if (gc != NULL && gc->driContext) {
773 psc = (struct dri_screen *) pdraw->psc;
774
775 if (psc->swapControl != NULL && pdraw != NULL) {
776 return psc->swapControl->getSwapInterval(pdp->driDrawable);
777 }
778 }
779
780 return 0;
781 }
782
783 /* Bind DRI1 specific extensions */
784 static void
785 driBindExtensions(struct dri_screen *psc, const __DRIextension **extensions)
786 {
787 int i;
788
789 for (i = 0; extensions[i]; i++) {
790 /* No DRI2 support for swap_control at the moment, since SwapBuffers
791 * is done by the X server */
792 if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
793 psc->swapControl = (__DRIswapControlExtension *) extensions[i];
794 __glXEnableDirectExtension(&psc->base, "GLX_SGI_swap_control");
795 __glXEnableDirectExtension(&psc->base, "GLX_MESA_swap_control");
796 }
797
798 if (strcmp(extensions[i]->name, __DRI_MEDIA_STREAM_COUNTER) == 0) {
799 psc->msc = (__DRImediaStreamCounterExtension *) extensions[i];
800 __glXEnableDirectExtension(&psc->base, "GLX_SGI_video_sync");
801 }
802
803 if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0) {
804 psc->driCopySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
805 __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
806 }
807
808 if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
809 __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
810 }
811 /* Ignore unknown extensions */
812 }
813 }
814
815 static __GLXscreenConfigs *
816 driCreateScreen(int screen, __GLXdisplayPrivate *priv)
817 {
818 struct dri_display *pdp;
819 __GLXDRIscreen *psp;
820 const __DRIextension **extensions;
821 struct dri_screen *psc;
822 char *driverName;
823 int i;
824
825 psc = Xcalloc(1, sizeof *psc);
826 if (psc == NULL)
827 return NULL;
828
829 memset(psc, 0, sizeof *psc);
830 if (!glx_screen_init(&psc->base, screen, priv))
831 return NULL;
832
833 if (!driGetDriverName(priv->dpy, screen, &driverName)) {
834 Xfree(psc);
835 return NULL;
836 }
837
838 psc->driver = driOpenDriver(driverName);
839 Xfree(driverName);
840 if (psc->driver == NULL) {
841 Xfree(psc);
842 return NULL;
843 }
844
845 extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
846 if (extensions == NULL) {
847 ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
848 Xfree(psc);
849 return NULL;
850 }
851
852 for (i = 0; extensions[i]; i++) {
853 if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
854 psc->core = (__DRIcoreExtension *) extensions[i];
855 if (strcmp(extensions[i]->name, __DRI_LEGACY) == 0)
856 psc->legacy = (__DRIlegacyExtension *) extensions[i];
857 }
858
859 if (psc->core == NULL || psc->legacy == NULL) {
860 Xfree(psc);
861 return NULL;
862 }
863
864 pdp = (struct dri_display *) priv->driDisplay;
865 psc->driScreen =
866 CallCreateNewScreen(psc->base.dpy, screen, psc, pdp);
867 if (psc->driScreen == NULL) {
868 dlclose(psc->driver);
869 Xfree(psc);
870 return NULL;
871 }
872
873 extensions = psc->core->getExtensions(psc->driScreen);
874 driBindExtensions(psc, extensions);
875
876 psp = &psc->vtable;
877 psc->base.driScreen = psp;
878 if (psc->driCopySubBuffer)
879 psp->copySubBuffer = driCopySubBuffer;
880
881 psp->destroyScreen = driDestroyScreen;
882 psp->createContext = driCreateContext;
883 psp->createDrawable = driCreateDrawable;
884 psp->swapBuffers = driSwapBuffers;
885
886 #ifdef __DRI_SWAP_BUFFER_COUNTER
887 psp->getDrawableMSC = driDrawableGetMSC;
888 psp->waitForMSC = driWaitForMSC;
889 psp->waitForSBC = driWaitForSBC;
890 #endif
891
892 psp->setSwapInterval = driSetSwapInterval;
893 psp->getSwapInterval = driGetSwapInterval;
894
895 return &psc->base;
896 }
897
898 /* Called from __glXFreeDisplayPrivate.
899 */
900 static void
901 driDestroyDisplay(__GLXDRIdisplay * dpy)
902 {
903 Xfree(dpy);
904 }
905
906 /*
907 * Allocate, initialize and return a __DRIdisplayPrivate object.
908 * This is called from __glXInitialize() when we are given a new
909 * display pointer.
910 */
911 _X_HIDDEN __GLXDRIdisplay *
912 driCreateDisplay(Display * dpy)
913 {
914 struct dri_display *pdpyp;
915 int eventBase, errorBase;
916 int major, minor, patch;
917
918 if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
919 return NULL;
920 }
921
922 if (!XF86DRIQueryVersion(dpy, &major, &minor, &patch)) {
923 return NULL;
924 }
925
926 pdpyp = Xmalloc(sizeof *pdpyp);
927 if (!pdpyp) {
928 return NULL;
929 }
930
931 pdpyp->driMajor = major;
932 pdpyp->driMinor = minor;
933 pdpyp->driPatch = patch;
934
935 pdpyp->base.destroyDisplay = driDestroyDisplay;
936 pdpyp->base.createScreen = driCreateScreen;
937
938 return &pdpyp->base;
939 }
940
941 #endif /* GLX_DIRECT_RENDERING */