1/*
2 * Copyright 2008 George Sapountzis
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)
25
26#include <X11/Xlib.h>
27#include "glxclient.h"
28#include <dlfcn.h>
29#include "dri_common.h"
30#include "drisw_priv.h"
31
32static Bool
33XCreateDrawable(struct drisw_drawable * pdp,
34                Display * dpy, XID drawable, int visualid)
35{
36   XGCValues gcvalues;
37   long visMask;
38   XVisualInfo visTemp;
39   int num_visuals;
40
41   /* create GC's */
42   pdp->gc = XCreateGC(dpy, drawable, 0, NULL);
43   pdp->swapgc = XCreateGC(dpy, drawable, 0, NULL);
44
45   gcvalues.function = GXcopy;
46   gcvalues.graphics_exposures = False;
47   XChangeGC(dpy, pdp->gc, GCFunction, &gcvalues);
48   XChangeGC(dpy, pdp->swapgc, GCFunction, &gcvalues);
49   XChangeGC(dpy, pdp->swapgc, GCGraphicsExposures, &gcvalues);
50
51   /* visual */
52   visTemp.visualid = visualid;
53   visMask = VisualIDMask;
54   pdp->visinfo = XGetVisualInfo(dpy, visMask, &visTemp, &num_visuals);
55
56   if (!pdp->visinfo || num_visuals == 0)
57      return False;
58
59   /* create XImage */
60   pdp->ximage = XCreateImage(dpy,
61                              pdp->visinfo->visual,
62                              pdp->visinfo->depth,
63                              ZPixmap, 0,             /* format, offset */
64                              NULL,                   /* data */
65                              0, 0,                   /* width, height */
66                              32,                     /* bitmap_pad */
67                              0);                     /* bytes_per_line */
68
69  /**
70   * swrast does not handle 24-bit depth with 24 bpp, so let X do the
71   * the conversion for us.
72   */
73  if (pdp->ximage->bits_per_pixel == 24)
74     pdp->ximage->bits_per_pixel = 32;
75
76   return True;
77}
78
79static void
80XDestroyDrawable(struct drisw_drawable * pdp, Display * dpy, XID drawable)
81{
82   XDestroyImage(pdp->ximage);
83   free(pdp->visinfo);
84
85   XFreeGC(dpy, pdp->gc);
86   XFreeGC(dpy, pdp->swapgc);
87}
88
89/**
90 * swrast loader functions
91 */
92
93static void
94swrastGetDrawableInfo(__DRIdrawable * draw,
95                      int *x, int *y, int *w, int *h,
96                      void *loaderPrivate)
97{
98   struct drisw_drawable *pdp = loaderPrivate;
99   __GLXDRIdrawable *pdraw = &(pdp->base);
100   Display *dpy = pdraw->psc->dpy;
101   Drawable drawable;
102
103   Window root;
104   unsigned uw, uh, bw, depth;
105
106   drawable = pdraw->xDrawable;
107
108   XGetGeometry(dpy, drawable, &root, x, y, &uw, &uh, &bw, &depth);
109   *w = uw;
110   *h = uh;
111}
112
113/**
114 * Align renderbuffer pitch.
115 *
116 * This should be chosen by the driver and the loader (libGL, xserver/glx)
117 * should use the driver provided pitch.
118 *
119 * It seems that the xorg loader (that is the xserver loading swrast_dri for
120 * indirect rendering, not client-side libGL) requires that the pitch is
121 * exactly the image width padded to 32 bits. XXX
122 *
123 * The above restriction can probably be overcome by using ScratchPixmap and
124 * CopyArea in the xserver, similar to ShmPutImage, and setting the width of
125 * the scratch pixmap to 'pitch / cpp'.
126 */
127static inline int
128bytes_per_line(unsigned pitch_bits, unsigned mul)
129{
130   unsigned mask = mul - 1;
131
132   return ((pitch_bits + mask) & ~mask) / 8;
133}
134
135static void
136swrastPutImage2(__DRIdrawable * draw, int op,
137                int x, int y, int w, int h, int stride,
138                char *data, void *loaderPrivate)
139{
140   struct drisw_drawable *pdp = loaderPrivate;
141   __GLXDRIdrawable *pdraw = &(pdp->base);
142   Display *dpy = pdraw->psc->dpy;
143   Drawable drawable;
144   XImage *ximage;
145   GC gc;
146
147   switch (op) {
148   case __DRI_SWRAST_IMAGE_OP_DRAW:
149      gc = pdp->gc;
150      break;
151   case __DRI_SWRAST_IMAGE_OP_SWAP:
152      gc = pdp->swapgc;
153      break;
154   default:
155      return;
156   }
157
158   drawable = pdraw->xDrawable;
159
160   ximage = pdp->ximage;
161   ximage->data = data;
162   ximage->width = w;
163   ximage->height = h;
164   ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
165
166   XPutImage(dpy, drawable, gc, ximage, 0, 0, x, y, w, h);
167
168   ximage->data = NULL;
169}
170
171static void
172swrastPutImage(__DRIdrawable * draw, int op,
173               int x, int y, int w, int h,
174               char *data, void *loaderPrivate)
175{
176   swrastPutImage2(draw, op, x, y, w, h, 0, data, loaderPrivate);
177}
178
179static void
180swrastGetImage2(__DRIdrawable * read,
181                int x, int y, int w, int h, int stride,
182                char *data, void *loaderPrivate)
183{
184   struct drisw_drawable *prp = loaderPrivate;
185   __GLXDRIdrawable *pread = &(prp->base);
186   Display *dpy = pread->psc->dpy;
187   Drawable readable;
188   XImage *ximage;
189
190   readable = pread->xDrawable;
191
192   ximage = prp->ximage;
193   ximage->data = data;
194   ximage->width = w;
195   ximage->height = h;
196   ximage->bytes_per_line = stride ? stride : bytes_per_line(w * ximage->bits_per_pixel, 32);
197
198   XGetSubImage(dpy, readable, x, y, w, h, ~0L, ZPixmap, ximage, 0, 0);
199
200   ximage->data = NULL;
201}
202
203static void
204swrastGetImage(__DRIdrawable * read,
205               int x, int y, int w, int h,
206               char *data, void *loaderPrivate)
207{
208   swrastGetImage2(read, x, y, w, h, 0, data, loaderPrivate);
209}
210
211static const __DRIswrastLoaderExtension swrastLoaderExtension = {
212   .base = {__DRI_SWRAST_LOADER, 3 },
213
214   .getDrawableInfo     = swrastGetDrawableInfo,
215   .putImage            = swrastPutImage,
216   .getImage            = swrastGetImage,
217   .putImage2           = swrastPutImage2,
218   .getImage2           = swrastGetImage2,
219};
220
221static const __DRIextension *loader_extensions[] = {
222   &systemTimeExtension.base,
223   &swrastLoaderExtension.base,
224   NULL
225};
226
227/**
228 * GLXDRI functions
229 */
230
231static void
232drisw_destroy_context(struct glx_context *context)
233{
234   struct drisw_context *pcp = (struct drisw_context *) context;
235   struct drisw_screen *psc = (struct drisw_screen *) context->psc;
236
237   driReleaseDrawables(&pcp->base);
238
239   free((char *) context->extensions);
240
241   (*psc->core->destroyContext) (pcp->driContext);
242
243   free(pcp);
244}
245
246static int
247drisw_bind_context(struct glx_context *context, struct glx_context *old,
248		   GLXDrawable draw, GLXDrawable read)
249{
250   struct drisw_context *pcp = (struct drisw_context *) context;
251   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
252   struct drisw_drawable *pdraw, *pread;
253
254   pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
255   pread = (struct drisw_drawable *) driFetchDrawable(context, read);
256
257   driReleaseDrawables(&pcp->base);
258
259   if (pdraw == NULL || pread == NULL)
260      return GLXBadDrawable;
261
262   if ((*psc->core->bindContext) (pcp->driContext,
263				  pdraw->driDrawable, pread->driDrawable))
264      return Success;
265
266   return GLXBadContext;
267}
268
269static void
270drisw_unbind_context(struct glx_context *context, struct glx_context *new)
271{
272   struct drisw_context *pcp = (struct drisw_context *) context;
273   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
274
275   (*psc->core->unbindContext) (pcp->driContext);
276}
277
278static void
279drisw_bind_tex_image(Display * dpy,
280		    GLXDrawable drawable,
281		    int buffer, const int *attrib_list)
282{
283   struct glx_context *gc = __glXGetCurrentContext();
284   struct drisw_context *pcp = (struct drisw_context *) gc;
285   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
286   struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
287   struct drisw_screen *psc;
288
289   __glXInitialize(dpy);
290
291   if (pdraw != NULL) {
292      psc = (struct drisw_screen *) base->psc;
293
294      if (!psc->texBuffer)
295         return;
296
297      if (psc->texBuffer->base.version >= 2 &&
298        psc->texBuffer->setTexBuffer2 != NULL) {
299	      (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
300					   pdraw->base.textureTarget,
301					   pdraw->base.textureFormat,
302					   pdraw->driDrawable);
303      }
304      else {
305	      (*psc->texBuffer->setTexBuffer) (pcp->driContext,
306					  pdraw->base.textureTarget,
307					  pdraw->driDrawable);
308      }
309   }
310}
311
312static void
313drisw_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
314{
315   struct glx_context *gc = __glXGetCurrentContext();
316   struct drisw_context *pcp = (struct drisw_context *) gc;
317   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
318   struct glx_display *dpyPriv = __glXInitialize(dpy);
319   struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
320   struct drisw_screen *psc;
321
322   if (dpyPriv != NULL && pdraw != NULL) {
323      psc = (struct drisw_screen *) base->psc;
324
325      if (!psc->texBuffer)
326         return;
327
328      if (psc->texBuffer->base.version >= 3 &&
329          psc->texBuffer->releaseTexBuffer != NULL) {
330         (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
331                                           pdraw->base.textureTarget,
332                                           pdraw->driDrawable);
333      }
334   }
335}
336
337static const struct glx_context_vtable drisw_context_vtable = {
338   .destroy             = drisw_destroy_context,
339   .bind                = drisw_bind_context,
340   .unbind              = drisw_unbind_context,
341   .wait_gl             = NULL,
342   .wait_x              = NULL,
343   .use_x_font          = DRI_glXUseXFont,
344   .bind_tex_image      = drisw_bind_tex_image,
345   .release_tex_image   = drisw_release_tex_image,
346   .get_proc_address    = NULL,
347};
348
349static struct glx_context *
350drisw_create_context(struct glx_screen *base,
351		     struct glx_config *config_base,
352		     struct glx_context *shareList, int renderType)
353{
354   struct drisw_context *pcp, *pcp_shared;
355   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
356   struct drisw_screen *psc = (struct drisw_screen *) base;
357   __DRIcontext *shared = NULL;
358
359   if (!psc->base.driScreen)
360      return NULL;
361
362   /* Check the renderType value */
363   if (!validate_renderType_against_config(config_base, renderType))
364       return NULL;
365
366   if (shareList) {
367      /* If the shareList context is not a DRISW context, we cannot possibly
368       * create a DRISW context that shares it.
369       */
370      if (shareList->vtable->destroy != drisw_destroy_context) {
371	 return NULL;
372      }
373
374      pcp_shared = (struct drisw_context *) shareList;
375      shared = pcp_shared->driContext;
376   }
377
378   pcp = calloc(1, sizeof *pcp);
379   if (pcp == NULL)
380      return NULL;
381
382   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
383      free(pcp);
384      return NULL;
385   }
386
387   pcp->base.renderType = renderType;
388
389   pcp->driContext =
390      (*psc->core->createNewContext) (psc->driScreen,
391				      config->driConfig, shared, pcp);
392   if (pcp->driContext == NULL) {
393      free(pcp);
394      return NULL;
395   }
396
397   pcp->base.vtable = &drisw_context_vtable;
398
399   return &pcp->base;
400}
401
402static struct glx_context *
403drisw_create_context_attribs(struct glx_screen *base,
404			     struct glx_config *config_base,
405			     struct glx_context *shareList,
406			     unsigned num_attribs,
407			     const uint32_t *attribs,
408			     unsigned *error)
409{
410   struct drisw_context *pcp, *pcp_shared;
411   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
412   struct drisw_screen *psc = (struct drisw_screen *) base;
413   __DRIcontext *shared = NULL;
414
415   uint32_t minor_ver;
416   uint32_t major_ver;
417   uint32_t renderType;
418   uint32_t flags;
419   unsigned api;
420   int reset;
421   uint32_t ctx_attribs[2 * 4];
422   unsigned num_ctx_attribs = 0;
423
424   if (!psc->base.driScreen)
425      return NULL;
426
427   if (psc->swrast->base.version < 3)
428      return NULL;
429
430   /* Remap the GLX tokens to DRI2 tokens.
431    */
432   if (!dri2_convert_glx_attribs(num_attribs, attribs,
433                                 &major_ver, &minor_ver, &renderType, &flags,
434                                 &api, &reset, error))
435      return NULL;
436
437   /* Check the renderType value */
438   if (!validate_renderType_against_config(config_base, renderType)) {
439       return NULL;
440   }
441
442   if (reset != __DRI_CTX_RESET_NO_NOTIFICATION)
443      return NULL;
444
445   if (shareList) {
446      pcp_shared = (struct drisw_context *) shareList;
447      shared = pcp_shared->driContext;
448   }
449
450   pcp = calloc(1, sizeof *pcp);
451   if (pcp == NULL)
452      return NULL;
453
454   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
455      free(pcp);
456      return NULL;
457   }
458
459   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
460   ctx_attribs[num_ctx_attribs++] = major_ver;
461   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
462   ctx_attribs[num_ctx_attribs++] = minor_ver;
463
464   if (flags != 0) {
465      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
466
467      /* The current __DRI_CTX_FLAG_* values are identical to the
468       * GLX_CONTEXT_*_BIT values.
469       */
470      ctx_attribs[num_ctx_attribs++] = flags;
471   }
472
473   pcp->base.renderType = renderType;
474
475   pcp->driContext =
476      (*psc->swrast->createContextAttribs) (psc->driScreen,
477					    api,
478					    config->driConfig,
479					    shared,
480					    num_ctx_attribs / 2,
481					    ctx_attribs,
482					    error,
483					    pcp);
484   if (pcp->driContext == NULL) {
485      free(pcp);
486      return NULL;
487   }
488
489   pcp->base.vtable = &drisw_context_vtable;
490
491   return &pcp->base;
492}
493
494static void
495driswDestroyDrawable(__GLXDRIdrawable * pdraw)
496{
497   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
498   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
499
500   (*psc->core->destroyDrawable) (pdp->driDrawable);
501
502   XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
503   free(pdp);
504}
505
506static __GLXDRIdrawable *
507driswCreateDrawable(struct glx_screen *base, XID xDrawable,
508		    GLXDrawable drawable, struct glx_config *modes)
509{
510   struct drisw_drawable *pdp;
511   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
512   struct drisw_screen *psc = (struct drisw_screen *) base;
513   Bool ret;
514   const __DRIswrastExtension *swrast = psc->swrast;
515
516   pdp = calloc(1, sizeof(*pdp));
517   if (!pdp)
518      return NULL;
519
520   pdp->base.xDrawable = xDrawable;
521   pdp->base.drawable = drawable;
522   pdp->base.psc = &psc->base;
523
524   ret = XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID);
525   if (!ret) {
526      free(pdp);
527      return NULL;
528   }
529
530   /* Create a new drawable */
531   pdp->driDrawable =
532      (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp);
533
534   if (!pdp->driDrawable) {
535      XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
536      free(pdp);
537      return NULL;
538   }
539
540   pdp->base.destroyDrawable = driswDestroyDrawable;
541
542   return &pdp->base;
543}
544
545static int64_t
546driswSwapBuffers(__GLXDRIdrawable * pdraw,
547                 int64_t target_msc, int64_t divisor, int64_t remainder,
548                 Bool flush)
549{
550   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
551   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
552
553   (void) target_msc;
554   (void) divisor;
555   (void) remainder;
556
557   if (flush) {
558      glFlush();
559   }
560
561   (*psc->core->swapBuffers) (pdp->driDrawable);
562
563   return 0;
564}
565
566static void
567driswCopySubBuffer(__GLXDRIdrawable * pdraw,
568                   int x, int y, int width, int height, Bool flush)
569{
570   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
571   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
572
573   if (flush) {
574      glFlush();
575   }
576
577   (*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable,
578					    x, y, width, height);
579}
580
581static void
582driswDestroyScreen(struct glx_screen *base)
583{
584   struct drisw_screen *psc = (struct drisw_screen *) base;
585
586   /* Free the direct rendering per screen data */
587   (*psc->core->destroyScreen) (psc->driScreen);
588   driDestroyConfigs(psc->driver_configs);
589   psc->driScreen = NULL;
590   if (psc->driver)
591      dlclose(psc->driver);
592   free(psc);
593}
594
595#define SWRAST_DRIVER_NAME "swrast"
596
597static void *
598driOpenSwrast(void)
599{
600   void *driver = NULL;
601
602   if (driver == NULL)
603      driver = driOpenDriver(SWRAST_DRIVER_NAME);
604
605   return driver;
606}
607
608static const struct glx_screen_vtable drisw_screen_vtable = {
609   .create_context         = drisw_create_context,
610   .create_context_attribs = drisw_create_context_attribs,
611   .query_renderer_integer = drisw_query_renderer_integer,
612   .query_renderer_string  = drisw_query_renderer_string,
613};
614
615static void
616driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
617{
618   int i;
619
620   __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
621
622   if (psc->swrast->base.version >= 3) {
623      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
624      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
625
626      /* DRISW version >= 2 implies support for OpenGL ES.
627       */
628      __glXEnableDirectExtension(&psc->base,
629				 "GLX_EXT_create_context_es_profile");
630      __glXEnableDirectExtension(&psc->base,
631				 "GLX_EXT_create_context_es2_profile");
632   }
633
634   if (psc->copySubBuffer)
635      __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
636
637   /* FIXME: Figure out what other extensions can be ported here from dri2. */
638   for (i = 0; extensions[i]; i++) {
639      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
640	 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
641	 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
642      }
643      /* DRISW version 3 is also required because GLX_MESA_query_renderer
644       * requires GLX_ARB_create_context_profile.
645       */
646      if (psc->swrast->base.version >= 3
647          && strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
648         psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
649         __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
650      }
651   }
652}
653
654static struct glx_screen *
655driswCreateScreen(int screen, struct glx_display *priv)
656{
657   __GLXDRIscreen *psp;
658   const __DRIconfig **driver_configs;
659   const __DRIextension **extensions;
660   struct drisw_screen *psc;
661   struct glx_config *configs = NULL, *visuals = NULL;
662   int i;
663
664   psc = calloc(1, sizeof *psc);
665   if (psc == NULL)
666      return NULL;
667
668   if (!glx_screen_init(&psc->base, screen, priv)) {
669      free(psc);
670      return NULL;
671   }
672
673   psc->driver = driOpenSwrast();
674   if (psc->driver == NULL)
675      goto handle_error;
676
677   extensions = driGetDriverExtensions(psc->driver, SWRAST_DRIVER_NAME);
678   if (extensions == NULL)
679      goto handle_error;
680
681   for (i = 0; extensions[i]; i++) {
682      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
683	 psc->core = (__DRIcoreExtension *) extensions[i];
684      if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
685	 psc->swrast = (__DRIswrastExtension *) extensions[i];
686      if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0)
687	 psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
688   }
689
690   if (psc->core == NULL || psc->swrast == NULL) {
691      ErrorMessageF("core dri extension not found\n");
692      goto handle_error;
693   }
694
695   if (psc->swrast->base.version >= 4) {
696      psc->driScreen =
697         psc->swrast->createNewScreen2(screen, loader_extensions,
698                                       extensions,
699                                       &driver_configs, psc);
700   } else {
701      psc->driScreen =
702         psc->swrast->createNewScreen(screen, loader_extensions,
703                                      &driver_configs, psc);
704   }
705   if (psc->driScreen == NULL) {
706      ErrorMessageF("failed to create dri screen\n");
707      goto handle_error;
708   }
709
710   extensions = psc->core->getExtensions(psc->driScreen);
711   driswBindExtensions(psc, extensions);
712
713   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
714   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
715
716   if (!configs || !visuals) {
717       ErrorMessageF("No matching fbConfigs or visuals found\n");
718       goto handle_error;
719   }
720
721   glx_config_destroy_list(psc->base.configs);
722   psc->base.configs = configs;
723   glx_config_destroy_list(psc->base.visuals);
724   psc->base.visuals = visuals;
725
726   psc->driver_configs = driver_configs;
727
728   psc->base.vtable = &drisw_screen_vtable;
729   psp = &psc->vtable;
730   psc->base.driScreen = psp;
731   psp->destroyScreen = driswDestroyScreen;
732   psp->createDrawable = driswCreateDrawable;
733   psp->swapBuffers = driswSwapBuffers;
734
735   if (psc->copySubBuffer)
736      psp->copySubBuffer = driswCopySubBuffer;
737
738   return &psc->base;
739
740 handle_error:
741   if (configs)
742       glx_config_destroy_list(configs);
743   if (visuals)
744       glx_config_destroy_list(visuals);
745   if (psc->driScreen)
746       psc->core->destroyScreen(psc->driScreen);
747   psc->driScreen = NULL;
748
749   if (psc->driver)
750      dlclose(psc->driver);
751   glx_screen_cleanup(&psc->base);
752   free(psc);
753
754   CriticalErrorMessageF("failed to load driver: %s\n", SWRAST_DRIVER_NAME);
755
756   return NULL;
757}
758
759/* Called from __glXFreeDisplayPrivate.
760 */
761static void
762driswDestroyDisplay(__GLXDRIdisplay * dpy)
763{
764   free(dpy);
765}
766
767/*
768 * Allocate, initialize and return a __DRIdisplayPrivate object.
769 * This is called from __glXInitialize() when we are given a new
770 * display pointer.
771 */
772_X_HIDDEN __GLXDRIdisplay *
773driswCreateDisplay(Display * dpy)
774{
775   struct drisw_display *pdpyp;
776
777   pdpyp = malloc(sizeof *pdpyp);
778   if (pdpyp == NULL)
779      return NULL;
780
781   pdpyp->base.destroyDisplay = driswDestroyDisplay;
782   pdpyp->base.createScreen = driswCreateScreen;
783
784   return &pdpyp->base;
785}
786
787#endif /* GLX_DIRECT_RENDERING */
788