Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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