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