drisw_glx.c revision cfec000e7514342fd51859906e173ba2d474a55c
1579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata/*
2579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * Copyright 2008 George Sapountzis
3579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata *
4579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * Permission is hereby granted, free of charge, to any person obtaining a
5579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * copy of this software and associated documentation files (the "Software"),
6579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * to deal in the Software without restriction, including without limitation
7579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b370df27c76fd875f3312be487868528121a4838Enrico Granata * and/or sell copies of the Software, and to permit persons to whom the
90d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * Software is furnished to do so, subject to the following conditions:
100d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata *
11b370df27c76fd875f3312be487868528121a4838Enrico Granata * The above copyright notice and this permission notice (including the next
12b370df27c76fd875f3312be487868528121a4838Enrico Granata * paragraph) shall be included in all copies or substantial portions of the
130d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * Software.
14b370df27c76fd875f3312be487868528121a4838Enrico Granata *
150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b370df27c76fd875f3312be487868528121a4838Enrico Granata * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b370df27c76fd875f3312be487868528121a4838Enrico Granata * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b370df27c76fd875f3312be487868528121a4838Enrico Granata * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b370df27c76fd875f3312be487868528121a4838Enrico Granata * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20b370df27c76fd875f3312be487868528121a4838Enrico Granata * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21b370df27c76fd875f3312be487868528121a4838Enrico Granata * SOFTWARE.
22b370df27c76fd875f3312be487868528121a4838Enrico Granata */
23f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
24b370df27c76fd875f3312be487868528121a4838Enrico Granata#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
25f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
260d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata#include <X11/Xlib.h>
27b370df27c76fd875f3312be487868528121a4838Enrico Granata#include "glxclient.h"
28f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata#include <dlfcn.h>
29f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata#include "dri_common.h"
30f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
31b370df27c76fd875f3312be487868528121a4838Enrico Granatastruct drisw_display
32b370df27c76fd875f3312be487868528121a4838Enrico Granata{
33b370df27c76fd875f3312be487868528121a4838Enrico Granata   __GLXDRIdisplay base;
340d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata};
35b370df27c76fd875f3312be487868528121a4838Enrico Granata
36b370df27c76fd875f3312be487868528121a4838Enrico Granatastruct drisw_context
37f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata{
380d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata   struct glx_context base;
39f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   __DRIcontext *driContext;
40f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
410d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata};
42f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
43b370df27c76fd875f3312be487868528121a4838Enrico Granatastruct drisw_screen
44b370df27c76fd875f3312be487868528121a4838Enrico Granata{
450d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata   struct glx_screen base;
46b370df27c76fd875f3312be487868528121a4838Enrico Granata
47f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   __DRIscreen *driScreen;
48f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   __GLXDRIscreen vtable;
49b370df27c76fd875f3312be487868528121a4838Enrico Granata   const __DRIcoreExtension *core;
50f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   const __DRIswrastExtension *swrast;
51f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   const __DRIconfig **driver_configs;
527b9aacf4a454465af905e505f74245173714b23bEnrico Granata
53b370df27c76fd875f3312be487868528121a4838Enrico Granata   void *driver;
54b370df27c76fd875f3312be487868528121a4838Enrico Granata};
55b370df27c76fd875f3312be487868528121a4838Enrico Granata
56f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granatastruct drisw_drawable
57b370df27c76fd875f3312be487868528121a4838Enrico Granata{
58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   __GLXDRIdrawable base;
590d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata
60b370df27c76fd875f3312be487868528121a4838Enrico Granata   GC gc;
61f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   GC swapgc;
62f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata
63b370df27c76fd875f3312be487868528121a4838Enrico Granata   __DRIdrawable *driDrawable;
64b370df27c76fd875f3312be487868528121a4838Enrico Granata   XVisualInfo *visinfo;
650d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata   XImage *ximage;
66b370df27c76fd875f3312be487868528121a4838Enrico Granata};
67b370df27c76fd875f3312be487868528121a4838Enrico Granata
68b370df27c76fd875f3312be487868528121a4838Enrico Granatastatic Bool
690d235d5864e996d95f485df1a0df406126e1ccdeEnrico GranataXCreateDrawable(struct drisw_drawable * pdp,
70b370df27c76fd875f3312be487868528121a4838Enrico Granata                Display * dpy, XID drawable, int visualid)
71b370df27c76fd875f3312be487868528121a4838Enrico Granata{
72b370df27c76fd875f3312be487868528121a4838Enrico Granata   XGCValues gcvalues;
73b370df27c76fd875f3312be487868528121a4838Enrico Granata   long visMask;
74579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   XVisualInfo visTemp;
75579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   int num_visuals;
76579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
77b370df27c76fd875f3312be487868528121a4838Enrico Granata   /* create GC's */
78b370df27c76fd875f3312be487868528121a4838Enrico Granata   pdp->gc = XCreateGC(dpy, drawable, 0, NULL);
79b370df27c76fd875f3312be487868528121a4838Enrico Granata   pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL);
800d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata
81b370df27c76fd875f3312be487868528121a4838Enrico Granata   gcvalues.function = GXcopy;
82a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata   gcvalues.graphics_exposures = False;
83579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues);
84579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues);
85b370df27c76fd875f3312be487868528121a4838Enrico Granata   XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues);
86b370df27c76fd875f3312be487868528121a4838Enrico Granata
878f18240a09893310c43673901d863892ae7b0611Enrico Granata   /* visual */
888f18240a09893310c43673901d863892ae7b0611Enrico Granata   visTemp.screen = DefaultScreen(dpy);
89b370df27c76fd875f3312be487868528121a4838Enrico Granata   visTemp.visualid = visualid;
90f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   visMask = (VisualScreenMask | VisualIDMask);
91b370df27c76fd875f3312be487868528121a4838Enrico Granata   pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals);
92b370df27c76fd875f3312be487868528121a4838Enrico Granata
93f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata   /* create XImage */
94805f79b15edd61887c26a3f0ea80457790ba5807Enrico Granata   pdp->ximage = XCreateImage(dpy,
95b370df27c76fd875f3312be487868528121a4838Enrico Granata                              pdp->visinfo->visual,
96b370df27c76fd875f3312be487868528121a4838Enrico Granata                              pdp->visinfo->depth,
97b370df27c76fd875f3312be487868528121a4838Enrico Granata                              ZPixmap, 0,             /* format, offset */
980d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata                              NULL,                   /* data */
99b370df27c76fd875f3312be487868528121a4838Enrico Granata                              0, 0,                   /* width, height */
100b370df27c76fd875f3312be487868528121a4838Enrico Granata                              32,                     /* bitmap_pad */
101a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata                              0);                     /* bytes_per_line */
102579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
103579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata  /**
104579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   * swrast does not handle 24-bit depth with 24 bpp, so let X do the
105579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   * the conversion for us.
106579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   */
1078f18240a09893310c43673901d863892ae7b0611Enrico Granata  if (pdp->ximage->bits_per_pixel == 24)
108579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata     pdp->ximage->bits_per_pixel = 32;
109579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
110579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata   return True;
111579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata}
112b370df27c76fd875f3312be487868528121a4838Enrico Granata
113b370df27c76fd875f3312be487868528121a4838Enrico Granatastatic void
114b370df27c76fd875f3312be487868528121a4838Enrico GranataXDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
115{
116   XDestroyImage(pdp->ximage);
117   XFree(pdp->visinfo);
118
119   XFreeGC(dpy, pdp->gc);
120   XFreeGC(dpy, pdp->swapgc);
121}
122
123/**
124 * swrast loader functions
125 */
126
127static void
128swrastGetDrawableInfo(__DRIdrawable * draw,
129                      int *x, int *y, int *w, int *h,
130                      void *loaderPrivate)
131{
132   struct drisw_drawable *pdp = loaderPrivate;
133   __GLXDRIdrawable *pdraw = &(pdp->base);
134   Display *dpy = pdraw->psc->dpy;
135   Drawable drawable;
136
137   Window root;
138   unsigned uw, uh, bw, depth;
139
140   drawable = pdraw->xDrawable;
141
142   XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth);
143   *w = uw;
144   *h = uh;
145}
146
147/**
148 * Align renderbuffer pitch.
149 *
150 * This should be chosen by the driver and the loader (libGL, xserver/glx)
151 * should use the driver provided pitch.
152 *
153 * It seems that the xorg loader (that is the xserver loading swrast_dri for
154 * indirect rendering, not client-side libGL) requires that the pitch is
155 * exactly the image width padded to 32 bits. XXX
156 *
157 * The above restriction can probably be overcome by using ScratchPixmap and
158 * CopyArea in the xserver, similar to ShmPutImage, and setting the width of
159 * the scratch pixmap to 'pitch / cpp'.
160 */
161static inline int
162bytes_per_line(unsigned pitch_bits, unsigned mul)
163{
164   unsigned mask = mul - 1;
165
166   return ((pitch_bits + mask) & ~mask) / 8;
167}
168
169static void
170swrastPutImage(__DRIdrawable * draw, int op,
171               int x, int y, int w, int h,
172               char *data, void *loaderPrivate)
173{
174   struct drisw_drawable *pdp = loaderPrivate;
175   __GLXDRIdrawable *pdraw = &(pdp->base);
176   Display *dpy = pdraw->psc->dpy;
177   Drawable drawable;
178   XImage *ximage;
179   GC gc;
180
181   switch (op) {
182   case __DRI_SWRAST_IMAGE_OP_DRAW:
183      gc = pdp->gc;
184      break;
185   case __DRI_SWRAST_IMAGE_OP_SWAP:
186      gc = pdp->swapgc;
187      break;
188   default:
189      return;
190   }
191
192   drawable = pdraw->xDrawable;
193
194   ximage = pdp->ximage;
195   ximage->data = data;
196   ximage->width = w;
197   ximage->height = h;
198   ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
199
200   XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
201
202   ximage->data = NULL;
203}
204
205static void
206swrastGetImage(__DRIdrawable * read,
207               int x, int y, int w, int h,
208               char *data, void *loaderPrivate)
209{
210   struct drisw_drawable *prp = loaderPrivate;
211   __GLXDRIdrawable *pread = &(prp->base);
212   Display *dpy = pread->psc->dpy;
213   Drawable readable;
214   XImage *ximage;
215
216   readable = pread->xDrawable;
217
218   ximage = prp->ximage;
219   ximage->data = data;
220   ximage->width = w;
221   ximage->height = h;
222   ximage->bytes_per_line = bytes_per_line(w * ximage->bits_per_pixel, 32);
223
224   XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
225
226   ximage->data = NULL;
227}
228
229static const __DRIswrastLoaderExtension swrastLoaderExtension = {
230   {__DRI_SWRAST_LOADER, __DRI_SWRAST_LOADER_VERSION},
231   swrastGetDrawableInfo,
232   swrastPutImage,
233   swrastGetImage
234};
235
236static const __DRIextension *loader_extensions[] = {
237   &systemTimeExtension.base,
238   &swrastLoaderExtension.base,
239   NULL
240};
241
242/**
243 * GLXDRI functions
244 */
245
246static void
247drisw_destroy_context(struct glx_context *context)
248{
249   struct drisw_context *pcp = (struct drisw_context *) context;
250   struct drisw_screen *psc = (struct drisw_screen *) context->psc;
251
252   driReleaseDrawables(&pcp->base);
253
254   if (context->xid)
255      glx_send_destroy_context(psc->base.dpy, context->xid);
256
257   if (context->extensions)
258      XFree((char *) context->extensions);
259
260   (*psc->core->destroyContext) (pcp->driContext);
261
262   Xfree(pcp);
263}
264
265static int
266drisw_bind_context(struct glx_context *context, struct glx_context *old,
267		   GLXDrawable draw, GLXDrawable read)
268{
269   struct drisw_context *pcp = (struct drisw_context *) context;
270   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
271   struct drisw_drawable *pdraw, *pread;
272
273   pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
274   pread = (struct drisw_drawable *) driFetchDrawable(context, read);
275
276   driReleaseDrawables(&pcp->base);
277
278   if (pdraw == NULL || pread == NULL)
279      return GLXBadDrawable;
280
281   if ((*psc->core->bindContext) (pcp->driContext,
282				  pdraw->driDrawable, pread->driDrawable))
283      return Success;
284
285   return GLXBadContext;
286}
287
288static void
289drisw_unbind_context(struct glx_context *context, struct glx_context *new)
290{
291   struct drisw_context *pcp = (struct drisw_context *) context;
292   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
293
294   (*psc->core->unbindContext) (pcp->driContext);
295}
296
297static const struct glx_context_vtable drisw_context_vtable = {
298   drisw_destroy_context,
299   drisw_bind_context,
300   drisw_unbind_context,
301   NULL,
302   NULL,
303   DRI_glXUseXFont,
304   NULL,
305   NULL,
306   NULL, /* get_proc_address */
307};
308
309static struct glx_context *
310drisw_create_context(struct glx_screen *base,
311		     struct glx_config *config_base,
312		     struct glx_context *shareList, int renderType)
313{
314   struct drisw_context *pcp, *pcp_shared;
315   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
316   struct drisw_screen *psc = (struct drisw_screen *) base;
317   __DRIcontext *shared = NULL;
318
319   if (!psc->base.driScreen)
320      return NULL;
321
322   if (shareList) {
323      pcp_shared = (struct drisw_context *) shareList;
324      shared = pcp_shared->driContext;
325   }
326
327   pcp = Xmalloc(sizeof *pcp);
328   if (pcp == NULL)
329      return NULL;
330
331   memset(pcp, 0, sizeof *pcp);
332   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
333      Xfree(pcp);
334      return NULL;
335   }
336
337   pcp->driContext =
338      (*psc->core->createNewContext) (psc->driScreen,
339				      config->driConfig, shared, pcp);
340   if (pcp->driContext == NULL) {
341      Xfree(pcp);
342      return NULL;
343   }
344
345   pcp->base.vtable = &drisw_context_vtable;
346
347   return &pcp->base;
348}
349
350static void
351driswDestroyDrawable(__GLXDRIdrawable * pdraw)
352{
353   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
354   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
355
356   (*psc->core->destroyDrawable) (pdp->driDrawable);
357
358   XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
359   Xfree(pdp);
360}
361
362static __GLXDRIdrawable *
363driswCreateDrawable(struct glx_screen *base, XID xDrawable,
364		    GLXDrawable drawable, struct glx_config *modes)
365{
366   struct drisw_drawable *pdp;
367   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
368   struct drisw_screen *psc = (struct drisw_screen *) base;
369
370   const __DRIswrastExtension *swrast = psc->swrast;
371
372   pdp = Xmalloc(sizeof(*pdp));
373   if (!pdp)
374      return NULL;
375
376   memset(pdp, 0, sizeof *pdp);
377   pdp->base.xDrawable = xDrawable;
378   pdp->base.drawable = drawable;
379   pdp->base.psc = &psc->base;
380
381   XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID);
382
383   /* Create a new drawable */
384   pdp->driDrawable =
385      (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp);
386
387   if (!pdp->driDrawable) {
388      XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
389      Xfree(pdp);
390      return NULL;
391   }
392
393   pdp->base.destroyDrawable = driswDestroyDrawable;
394
395   return &pdp->base;
396}
397
398static int64_t
399driswSwapBuffers(__GLXDRIdrawable * pdraw,
400                 int64_t target_msc, int64_t divisor, int64_t remainder)
401{
402   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
403   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
404
405   (void) target_msc;
406   (void) divisor;
407   (void) remainder;
408
409   (*psc->core->swapBuffers) (pdp->driDrawable);
410
411   return 0;
412}
413
414static void
415driswDestroyScreen(struct glx_screen *base)
416{
417   struct drisw_screen *psc = (struct drisw_screen *) base;
418
419   /* Free the direct rendering per screen data */
420   (*psc->core->destroyScreen) (psc->driScreen);
421   driDestroyConfigs(psc->driver_configs);
422   psc->driScreen = NULL;
423   if (psc->driver)
424      dlclose(psc->driver);
425}
426
427static void *
428driOpenSwrast(void)
429{
430   void *driver = NULL;
431
432   if (driver == NULL)
433      driver = driOpenDriver("swrast");
434
435   return driver;
436}
437
438static const struct glx_screen_vtable drisw_screen_vtable = {
439   drisw_create_context
440};
441
442static struct glx_screen *
443driswCreateScreen(int screen, struct glx_display *priv)
444{
445   __GLXDRIscreen *psp;
446   const __DRIconfig **driver_configs;
447   const __DRIextension **extensions;
448   struct drisw_screen *psc;
449   int i;
450
451   psc = Xcalloc(1, sizeof *psc);
452   if (psc == NULL)
453      return NULL;
454
455   memset(psc, 0, sizeof *psc);
456   if (!glx_screen_init(&psc->base, screen, priv)) {
457      Xfree(psc);
458      return NULL;
459   }
460
461   psc->driver = driOpenSwrast();
462   if (psc->driver == NULL)
463      goto handle_error;
464
465   extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS);
466   if (extensions == NULL) {
467      ErrorMessageF("driver exports no extensions (%s)\n", dlerror());
468      goto handle_error;
469   }
470
471   for (i = 0; extensions[i]; i++) {
472      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
473	 psc->core = (__DRIcoreExtension *) extensions[i];
474      if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
475	 psc->swrast = (__DRIswrastExtension *) extensions[i];
476   }
477
478   if (psc->core == NULL || psc->swrast == NULL) {
479      ErrorMessageF("core dri extension not found\n");
480      goto handle_error;
481   }
482
483   psc->driScreen =
484      psc->swrast->createNewScreen(screen, loader_extensions,
485				   &driver_configs, psc);
486   if (psc->driScreen == NULL) {
487      ErrorMessageF("failed to create dri screen\n");
488      goto handle_error;
489   }
490
491   psc->base.configs =
492      driConvertConfigs(psc->core, psc->base.configs, driver_configs);
493   psc->base.visuals =
494      driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
495
496   psc->driver_configs = driver_configs;
497
498   psc->base.vtable = &drisw_screen_vtable;
499   psp = &psc->vtable;
500   psc->base.driScreen = psp;
501   psp->destroyScreen = driswDestroyScreen;
502   psp->createDrawable = driswCreateDrawable;
503   psp->swapBuffers = driswSwapBuffers;
504
505   return &psc->base;
506
507 handle_error:
508   if (psc->driver)
509      dlclose(psc->driver);
510   glx_screen_cleanup(&psc->base);
511   Xfree(psc);
512
513   ErrorMessageF("reverting to indirect rendering\n");
514
515   return NULL;
516}
517
518/* Called from __glXFreeDisplayPrivate.
519 */
520static void
521driswDestroyDisplay(__GLXDRIdisplay * dpy)
522{
523   Xfree(dpy);
524}
525
526/*
527 * Allocate, initialize and return a __DRIdisplayPrivate object.
528 * This is called from __glXInitialize() when we are given a new
529 * display pointer.
530 */
531_X_HIDDEN __GLXDRIdisplay *
532driswCreateDisplay(Display * dpy)
533{
534   struct drisw_display *pdpyp;
535
536   pdpyp = Xmalloc(sizeof *pdpyp);
537   if (pdpyp == NULL)
538      return NULL;
539
540   pdpyp->base.destroyDisplay = driswDestroyDisplay;
541   pdpyp->base.createScreen = driswCreateScreen;
542
543   return &pdpyp->base;
544}
545
546#endif /* GLX_DIRECT_RENDERING */
547