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