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