drisw_glx.c revision 848b8605
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
180swrastGetImage(__DRIdrawable * read,
181               int x, int y, int w, int h,
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 = 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 const __DRIswrastLoaderExtension swrastLoaderExtension = {
204   .base = {__DRI_SWRAST_LOADER, 2 },
205
206   .getDrawableInfo     = swrastGetDrawableInfo,
207   .putImage            = swrastPutImage,
208   .getImage            = swrastGetImage,
209   .putImage2           = swrastPutImage2,
210};
211
212static const __DRIextension *loader_extensions[] = {
213   &systemTimeExtension.base,
214   &swrastLoaderExtension.base,
215   NULL
216};
217
218/**
219 * GLXDRI functions
220 */
221
222static void
223drisw_destroy_context(struct glx_context *context)
224{
225   struct drisw_context *pcp = (struct drisw_context *) context;
226   struct drisw_screen *psc = (struct drisw_screen *) context->psc;
227
228   driReleaseDrawables(&pcp->base);
229
230   free((char *) context->extensions);
231
232   (*psc->core->destroyContext) (pcp->driContext);
233
234   free(pcp);
235}
236
237static int
238drisw_bind_context(struct glx_context *context, struct glx_context *old,
239		   GLXDrawable draw, GLXDrawable read)
240{
241   struct drisw_context *pcp = (struct drisw_context *) context;
242   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
243   struct drisw_drawable *pdraw, *pread;
244
245   pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
246   pread = (struct drisw_drawable *) driFetchDrawable(context, read);
247
248   driReleaseDrawables(&pcp->base);
249
250   if (pdraw == NULL || pread == NULL)
251      return GLXBadDrawable;
252
253   if ((*psc->core->bindContext) (pcp->driContext,
254				  pdraw->driDrawable, pread->driDrawable))
255      return Success;
256
257   return GLXBadContext;
258}
259
260static void
261drisw_unbind_context(struct glx_context *context, struct glx_context *new)
262{
263   struct drisw_context *pcp = (struct drisw_context *) context;
264   struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc;
265
266   (*psc->core->unbindContext) (pcp->driContext);
267}
268
269static void
270drisw_bind_tex_image(Display * dpy,
271		    GLXDrawable drawable,
272		    int buffer, const int *attrib_list)
273{
274   struct glx_context *gc = __glXGetCurrentContext();
275   struct drisw_context *pcp = (struct drisw_context *) gc;
276   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
277   struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
278   struct drisw_screen *psc;
279
280   __glXInitialize(dpy);
281
282   if (pdraw != NULL) {
283      psc = (struct drisw_screen *) base->psc;
284
285      if (!psc->texBuffer)
286         return;
287
288      if (psc->texBuffer->base.version >= 2 &&
289        psc->texBuffer->setTexBuffer2 != NULL) {
290	      (*psc->texBuffer->setTexBuffer2) (pcp->driContext,
291					   pdraw->base.textureTarget,
292					   pdraw->base.textureFormat,
293					   pdraw->driDrawable);
294      }
295      else {
296	      (*psc->texBuffer->setTexBuffer) (pcp->driContext,
297					  pdraw->base.textureTarget,
298					  pdraw->driDrawable);
299      }
300   }
301}
302
303static void
304drisw_release_tex_image(Display * dpy, GLXDrawable drawable, int buffer)
305{
306   struct glx_context *gc = __glXGetCurrentContext();
307   struct drisw_context *pcp = (struct drisw_context *) gc;
308   __GLXDRIdrawable *base = GetGLXDRIDrawable(dpy, drawable);
309   struct glx_display *dpyPriv = __glXInitialize(dpy);
310   struct drisw_drawable *pdraw = (struct drisw_drawable *) base;
311   struct drisw_screen *psc;
312
313   if (dpyPriv != NULL && pdraw != NULL) {
314      psc = (struct drisw_screen *) base->psc;
315
316      if (!psc->texBuffer)
317         return;
318
319      if (psc->texBuffer->base.version >= 3 &&
320          psc->texBuffer->releaseTexBuffer != NULL) {
321         (*psc->texBuffer->releaseTexBuffer) (pcp->driContext,
322                                           pdraw->base.textureTarget,
323                                           pdraw->driDrawable);
324      }
325   }
326}
327
328static const struct glx_context_vtable drisw_context_vtable = {
329   .destroy             = drisw_destroy_context,
330   .bind                = drisw_bind_context,
331   .unbind              = drisw_unbind_context,
332   .wait_gl             = NULL,
333   .wait_x              = NULL,
334   .use_x_font          = DRI_glXUseXFont,
335   .bind_tex_image      = drisw_bind_tex_image,
336   .release_tex_image   = drisw_release_tex_image,
337   .get_proc_address    = NULL,
338};
339
340static struct glx_context *
341drisw_create_context(struct glx_screen *base,
342		     struct glx_config *config_base,
343		     struct glx_context *shareList, int renderType)
344{
345   struct drisw_context *pcp, *pcp_shared;
346   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
347   struct drisw_screen *psc = (struct drisw_screen *) base;
348   __DRIcontext *shared = NULL;
349
350   if (!psc->base.driScreen)
351      return NULL;
352
353   /* Check the renderType value */
354   if (!validate_renderType_against_config(config_base, renderType))
355       return NULL;
356
357   if (shareList) {
358      /* If the shareList context is not a DRISW context, we cannot possibly
359       * create a DRISW context that shares it.
360       */
361      if (shareList->vtable->destroy != drisw_destroy_context) {
362	 return NULL;
363      }
364
365      pcp_shared = (struct drisw_context *) shareList;
366      shared = pcp_shared->driContext;
367   }
368
369   pcp = calloc(1, sizeof *pcp);
370   if (pcp == NULL)
371      return NULL;
372
373   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
374      free(pcp);
375      return NULL;
376   }
377
378   pcp->base.renderType = renderType;
379
380   pcp->driContext =
381      (*psc->core->createNewContext) (psc->driScreen,
382				      config->driConfig, shared, pcp);
383   if (pcp->driContext == NULL) {
384      free(pcp);
385      return NULL;
386   }
387
388   pcp->base.vtable = &drisw_context_vtable;
389
390   return &pcp->base;
391}
392
393static struct glx_context *
394drisw_create_context_attribs(struct glx_screen *base,
395			     struct glx_config *config_base,
396			     struct glx_context *shareList,
397			     unsigned num_attribs,
398			     const uint32_t *attribs,
399			     unsigned *error)
400{
401   struct drisw_context *pcp, *pcp_shared;
402   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) config_base;
403   struct drisw_screen *psc = (struct drisw_screen *) base;
404   __DRIcontext *shared = NULL;
405
406   uint32_t minor_ver;
407   uint32_t major_ver;
408   uint32_t renderType;
409   uint32_t flags;
410   unsigned api;
411   int reset;
412   uint32_t ctx_attribs[2 * 4];
413   unsigned num_ctx_attribs = 0;
414
415   if (!psc->base.driScreen)
416      return NULL;
417
418   if (psc->swrast->base.version < 3)
419      return NULL;
420
421   /* Remap the GLX tokens to DRI2 tokens.
422    */
423   if (!dri2_convert_glx_attribs(num_attribs, attribs,
424                                 &major_ver, &minor_ver, &renderType, &flags,
425                                 &api, &reset, error))
426      return NULL;
427
428   /* Check the renderType value */
429   if (!validate_renderType_against_config(config_base, renderType)) {
430       return NULL;
431   }
432
433   if (reset != __DRI_CTX_RESET_NO_NOTIFICATION)
434      return NULL;
435
436   if (shareList) {
437      pcp_shared = (struct drisw_context *) shareList;
438      shared = pcp_shared->driContext;
439   }
440
441   pcp = calloc(1, sizeof *pcp);
442   if (pcp == NULL)
443      return NULL;
444
445   if (!glx_context_init(&pcp->base, &psc->base, &config->base)) {
446      free(pcp);
447      return NULL;
448   }
449
450   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION;
451   ctx_attribs[num_ctx_attribs++] = major_ver;
452   ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION;
453   ctx_attribs[num_ctx_attribs++] = minor_ver;
454
455   if (flags != 0) {
456      ctx_attribs[num_ctx_attribs++] = __DRI_CTX_ATTRIB_FLAGS;
457
458      /* The current __DRI_CTX_FLAG_* values are identical to the
459       * GLX_CONTEXT_*_BIT values.
460       */
461      ctx_attribs[num_ctx_attribs++] = flags;
462   }
463
464   pcp->base.renderType = renderType;
465
466   pcp->driContext =
467      (*psc->swrast->createContextAttribs) (psc->driScreen,
468					    api,
469					    config->driConfig,
470					    shared,
471					    num_ctx_attribs / 2,
472					    ctx_attribs,
473					    error,
474					    pcp);
475   if (pcp->driContext == NULL) {
476      free(pcp);
477      return NULL;
478   }
479
480   pcp->base.vtable = &drisw_context_vtable;
481
482   return &pcp->base;
483}
484
485static void
486driswDestroyDrawable(__GLXDRIdrawable * pdraw)
487{
488   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
489   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
490
491   (*psc->core->destroyDrawable) (pdp->driDrawable);
492
493   XDestroyDrawable(pdp, pdraw->psc->dpy, pdraw->drawable);
494   free(pdp);
495}
496
497static __GLXDRIdrawable *
498driswCreateDrawable(struct glx_screen *base, XID xDrawable,
499		    GLXDrawable drawable, struct glx_config *modes)
500{
501   struct drisw_drawable *pdp;
502   __GLXDRIconfigPrivate *config = (__GLXDRIconfigPrivate *) modes;
503   struct drisw_screen *psc = (struct drisw_screen *) base;
504   Bool ret;
505   const __DRIswrastExtension *swrast = psc->swrast;
506
507   pdp = calloc(1, sizeof(*pdp));
508   if (!pdp)
509      return NULL;
510
511   pdp->base.xDrawable = xDrawable;
512   pdp->base.drawable = drawable;
513   pdp->base.psc = &psc->base;
514
515   ret = XCreateDrawable(pdp, psc->base.dpy, xDrawable, modes->visualID);
516   if (!ret) {
517      free(pdp);
518      return NULL;
519   }
520
521   /* Create a new drawable */
522   pdp->driDrawable =
523      (*swrast->createNewDrawable) (psc->driScreen, config->driConfig, pdp);
524
525   if (!pdp->driDrawable) {
526      XDestroyDrawable(pdp, psc->base.dpy, xDrawable);
527      free(pdp);
528      return NULL;
529   }
530
531   pdp->base.destroyDrawable = driswDestroyDrawable;
532
533   return &pdp->base;
534}
535
536static int64_t
537driswSwapBuffers(__GLXDRIdrawable * pdraw,
538                 int64_t target_msc, int64_t divisor, int64_t remainder,
539                 Bool flush)
540{
541   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
542   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
543
544   (void) target_msc;
545   (void) divisor;
546   (void) remainder;
547
548   if (flush) {
549      glFlush();
550   }
551
552   (*psc->core->swapBuffers) (pdp->driDrawable);
553
554   return 0;
555}
556
557static void
558driswCopySubBuffer(__GLXDRIdrawable * pdraw,
559                   int x, int y, int width, int height, Bool flush)
560{
561   struct drisw_drawable *pdp = (struct drisw_drawable *) pdraw;
562   struct drisw_screen *psc = (struct drisw_screen *) pdp->base.psc;
563
564   if (flush) {
565      glFlush();
566   }
567
568   (*psc->copySubBuffer->copySubBuffer) (pdp->driDrawable,
569					    x, y, width, height);
570}
571
572static void
573driswDestroyScreen(struct glx_screen *base)
574{
575   struct drisw_screen *psc = (struct drisw_screen *) base;
576
577   /* Free the direct rendering per screen data */
578   (*psc->core->destroyScreen) (psc->driScreen);
579   driDestroyConfigs(psc->driver_configs);
580   psc->driScreen = NULL;
581   if (psc->driver)
582      dlclose(psc->driver);
583   free(psc);
584}
585
586#define SWRAST_DRIVER_NAME "swrast"
587
588static void *
589driOpenSwrast(void)
590{
591   void *driver = NULL;
592
593   if (driver == NULL)
594      driver = driOpenDriver(SWRAST_DRIVER_NAME);
595
596   return driver;
597}
598
599static const struct glx_screen_vtable drisw_screen_vtable = {
600   .create_context         = drisw_create_context,
601   .create_context_attribs = drisw_create_context_attribs,
602   .query_renderer_integer = drisw_query_renderer_integer,
603   .query_renderer_string  = drisw_query_renderer_string,
604};
605
606static void
607driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
608{
609   int i;
610
611   __glXEnableDirectExtension(&psc->base, "GLX_SGI_make_current_read");
612
613   if (psc->swrast->base.version >= 3) {
614      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context");
615      __glXEnableDirectExtension(&psc->base, "GLX_ARB_create_context_profile");
616
617      /* DRISW version >= 2 implies support for OpenGL ES 2.0.
618       */
619      __glXEnableDirectExtension(&psc->base,
620				 "GLX_EXT_create_context_es2_profile");
621   }
622
623   if (psc->copySubBuffer)
624      __glXEnableDirectExtension(&psc->base, "GLX_MESA_copy_sub_buffer");
625
626   /* FIXME: Figure out what other extensions can be ported here from dri2. */
627   for (i = 0; extensions[i]; i++) {
628      if ((strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0)) {
629	 psc->texBuffer = (__DRItexBufferExtension *) extensions[i];
630	 __glXEnableDirectExtension(&psc->base, "GLX_EXT_texture_from_pixmap");
631      }
632      /* DRISW version 3 is also required because GLX_MESA_query_renderer
633       * requires GLX_ARB_create_context_profile.
634       */
635      if (psc->swrast->base.version >= 3
636          && strcmp(extensions[i]->name, __DRI2_RENDERER_QUERY) == 0) {
637         psc->rendererQuery = (__DRI2rendererQueryExtension *) extensions[i];
638         __glXEnableDirectExtension(&psc->base, "GLX_MESA_query_renderer");
639      }
640   }
641}
642
643static struct glx_screen *
644driswCreateScreen(int screen, struct glx_display *priv)
645{
646   __GLXDRIscreen *psp;
647   const __DRIconfig **driver_configs;
648   const __DRIextension **extensions;
649   struct drisw_screen *psc;
650   struct glx_config *configs = NULL, *visuals = NULL;
651   int i;
652
653   psc = calloc(1, sizeof *psc);
654   if (psc == NULL)
655      return NULL;
656
657   if (!glx_screen_init(&psc->base, screen, priv)) {
658      free(psc);
659      return NULL;
660   }
661
662   psc->driver = driOpenSwrast();
663   if (psc->driver == NULL)
664      goto handle_error;
665
666   extensions = driGetDriverExtensions(psc->driver, SWRAST_DRIVER_NAME);
667   if (extensions == NULL)
668      goto handle_error;
669
670   for (i = 0; extensions[i]; i++) {
671      if (strcmp(extensions[i]->name, __DRI_CORE) == 0)
672	 psc->core = (__DRIcoreExtension *) extensions[i];
673      if (strcmp(extensions[i]->name, __DRI_SWRAST) == 0)
674	 psc->swrast = (__DRIswrastExtension *) extensions[i];
675      if (strcmp(extensions[i]->name, __DRI_COPY_SUB_BUFFER) == 0)
676	 psc->copySubBuffer = (__DRIcopySubBufferExtension *) extensions[i];
677   }
678
679   if (psc->core == NULL || psc->swrast == NULL) {
680      ErrorMessageF("core dri extension not found\n");
681      goto handle_error;
682   }
683
684   if (psc->swrast->base.version >= 4) {
685      psc->driScreen =
686         psc->swrast->createNewScreen2(screen, loader_extensions,
687                                       extensions,
688                                       &driver_configs, psc);
689   } else {
690      psc->driScreen =
691         psc->swrast->createNewScreen(screen, loader_extensions,
692                                      &driver_configs, psc);
693   }
694   if (psc->driScreen == NULL) {
695      ErrorMessageF("failed to create dri screen\n");
696      goto handle_error;
697   }
698
699   extensions = psc->core->getExtensions(psc->driScreen);
700   driswBindExtensions(psc, extensions);
701
702   configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs);
703   visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs);
704
705   if (!configs || !visuals) {
706       ErrorMessageF("No matching fbConfigs or visuals found\n");
707       goto handle_error;
708   }
709
710   glx_config_destroy_list(psc->base.configs);
711   psc->base.configs = configs;
712   glx_config_destroy_list(psc->base.visuals);
713   psc->base.visuals = visuals;
714
715   psc->driver_configs = driver_configs;
716
717   psc->base.vtable = &drisw_screen_vtable;
718   psp = &psc->vtable;
719   psc->base.driScreen = psp;
720   psp->destroyScreen = driswDestroyScreen;
721   psp->createDrawable = driswCreateDrawable;
722   psp->swapBuffers = driswSwapBuffers;
723
724   if (psc->copySubBuffer)
725      psp->copySubBuffer = driswCopySubBuffer;
726
727   return &psc->base;
728
729 handle_error:
730   if (configs)
731       glx_config_destroy_list(configs);
732   if (visuals)
733       glx_config_destroy_list(visuals);
734   if (psc->driScreen)
735       psc->core->destroyScreen(psc->driScreen);
736   psc->driScreen = NULL;
737
738   if (psc->driver)
739      dlclose(psc->driver);
740   glx_screen_cleanup(&psc->base);
741   free(psc);
742
743   CriticalErrorMessageF("failed to load driver: %s\n", SWRAST_DRIVER_NAME);
744
745   return NULL;
746}
747
748/* Called from __glXFreeDisplayPrivate.
749 */
750static void
751driswDestroyDisplay(__GLXDRIdisplay * dpy)
752{
753   free(dpy);
754}
755
756/*
757 * Allocate, initialize and return a __DRIdisplayPrivate object.
758 * This is called from __glXInitialize() when we are given a new
759 * display pointer.
760 */
761_X_HIDDEN __GLXDRIdisplay *
762driswCreateDisplay(Display * dpy)
763{
764   struct drisw_display *pdpyp;
765
766   pdpyp = malloc(sizeof *pdpyp);
767   if (pdpyp == NULL)
768      return NULL;
769
770   pdpyp->base.destroyDisplay = driswDestroyDisplay;
771   pdpyp->base.createScreen = driswCreateScreen;
772
773   return &pdpyp->base;
774}
775
776#endif /* GLX_DIRECT_RENDERING */
777