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