Add mouse and keyboard configuration file
[profile/ivi/xorg-x11-server.git] / glx / glxdri2.c
1 /*
2  * Copyright © 2007 Red Hat, Inc
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without
6  * fee, provided that the above copyright notice appear in all copies
7  * and that both that copyright notice and this permission notice
8  * appear in supporting documentation, and that the name of Red Hat,
9  * Inc not be used in advertising or publicity pertaining to
10  * distribution of the software without specific, written prior
11  * permission.  Red Hat, Inc makes no representations about the
12  * suitability of this software for any purpose.  It is provided "as
13  * is" without express or implied warranty.
14  *
15  * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17  * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
26 #endif
27
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <dlfcn.h>
33
34 #include <drm.h>
35 #include <GL/gl.h>
36 #include <GL/internal/dri_interface.h>
37 #include <GL/glxtokens.h>
38
39 #include <windowstr.h>
40 #include <os.h>
41
42 #define _XF86DRI_SERVER_
43 #include <xf86drm.h>
44 #include <xf86.h>
45 #include <dri2.h>
46
47 #include "glxserver.h"
48 #include "glxutil.h"
49 #include "glxdricommon.h"
50
51 #include "g_disptab.h"
52 #include "glapitable.h"
53 #include "glapi.h"
54 #include "glthread.h"
55 #include "dispatch.h"
56 #include "extension_string.h"
57
58 typedef struct __GLXDRIscreen   __GLXDRIscreen;
59 typedef struct __GLXDRIcontext  __GLXDRIcontext;
60 typedef struct __GLXDRIdrawable __GLXDRIdrawable;
61
62 struct __GLXDRIscreen {
63     __GLXscreen          base;
64     __DRIscreen         *driScreen;
65     void                *driver;
66     int                  fd;
67
68     xf86EnterVTProc     *enterVT;
69     xf86LeaveVTProc     *leaveVT;
70
71     const __DRIcoreExtension *core;
72     const __DRIdri2Extension *dri2;
73     const __DRI2flushExtension *flush;
74     const __DRIcopySubBufferExtension *copySubBuffer;
75     const __DRIswapControlExtension *swapControl;
76     const __DRItexBufferExtension *texBuffer;
77
78     unsigned char glx_enable_bits[__GLX_EXT_BYTES];
79 };
80
81 struct __GLXDRIcontext {
82     __GLXcontext         base;
83     __DRIcontext        *driContext;
84 };
85
86 #define MAX_DRAWABLE_BUFFERS 5
87
88 struct __GLXDRIdrawable {
89     __GLXdrawable        base;
90     __DRIdrawable       *driDrawable;
91     __GLXDRIscreen      *screen;
92
93     /* Dimensions as last reported by DRI2GetBuffers. */
94     int width;
95     int height;
96     __DRIbuffer buffers[MAX_DRAWABLE_BUFFERS];
97     int count;
98 };
99
100 static void
101 __glXDRIdrawableDestroy(__GLXdrawable *drawable)
102 {
103     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
104     const __DRIcoreExtension *core = private->screen->core;
105     
106     (*core->destroyDrawable)(private->driDrawable);
107
108     __glXDrawableRelease(drawable);
109
110     free(private);
111 }
112
113 static void
114 __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable,
115                                int x, int y, int w, int h)
116 {
117     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
118     BoxRec box;
119     RegionRec region;
120
121     box.x1 = x;
122     box.y1 = private->height - y - h;
123     box.x2 = x + w;
124     box.y2 = private->height - y;
125     RegionInit(&region, &box, 0);
126
127     DRI2CopyRegion(drawable->pDraw, &region,
128                    DRI2BufferFrontLeft, DRI2BufferBackLeft);
129 }
130
131 static void
132 __glXDRIdrawableWaitX(__GLXdrawable *drawable)
133 {
134     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
135     BoxRec box;
136     RegionRec region;
137
138     box.x1 = 0;
139     box.y1 = 0;
140     box.x2 = private->width;
141     box.y2 = private->height;
142     RegionInit(&region, &box, 0);
143
144     DRI2CopyRegion(drawable->pDraw, &region,
145                    DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
146 }
147
148 static void
149 __glXDRIdrawableWaitGL(__GLXdrawable *drawable)
150 {
151     __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable;
152     BoxRec box;
153     RegionRec region;
154
155     box.x1 = 0;
156     box.y1 = 0;
157     box.x2 = private->width;
158     box.y2 = private->height;
159     RegionInit(&region, &box, 0);
160
161     DRI2CopyRegion(drawable->pDraw, &region,
162                    DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
163 }
164
165 static void
166 __glXdriSwapEvent(ClientPtr client, void *data, int type, CARD64 ust,
167                   CARD64 msc, CARD64 sbc)
168 {
169     __GLXdrawable *drawable = data;
170     xGLXBufferSwapComplete wire;
171
172     if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
173         return;
174
175     wire.type = __glXEventBase + GLX_BufferSwapComplete;
176     switch (type) {
177     case DRI2_EXCHANGE_COMPLETE:
178         wire.event_type = GLX_EXCHANGE_COMPLETE_INTEL;
179         break;
180     case DRI2_BLIT_COMPLETE:
181         wire.event_type = GLX_BLIT_COMPLETE_INTEL;
182         break;
183     case DRI2_FLIP_COMPLETE:
184         wire.event_type = GLX_FLIP_COMPLETE_INTEL;
185         break;
186     default:
187         /* unknown swap completion type */
188         break;
189     }
190     wire.drawable = drawable->drawId;
191     wire.ust_hi = ust >> 32;
192     wire.ust_lo = ust & 0xffffffff;
193     wire.msc_hi = msc >> 32;
194     wire.msc_lo = msc & 0xffffffff;
195     wire.sbc_hi = sbc >> 32;
196     wire.sbc_lo = sbc & 0xffffffff;
197
198     WriteEventsToClient(client, 1, (xEvent *) &wire);
199 }
200
201 /*
202  * Copy or flip back to front, honoring the swap interval if possible.
203  *
204  * If the kernel supports it, we request an event for the frame when the
205  * swap should happen, then perform the copy when we receive it.
206  */
207 static GLboolean
208 __glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable)
209 {
210     __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable;
211     __GLXDRIscreen *screen = priv->screen;
212     CARD64 unused;
213
214 #if __DRI2_FLUSH_VERSION >= 3
215     if (screen->flush) {
216         (*screen->flush->flush)(priv->driDrawable);
217         (*screen->flush->invalidate)(priv->driDrawable);
218     }
219 #else
220     if (screen->flush)
221         (*screen->flush->flushInvalidate)(priv->driDrawable);
222 #endif
223
224     if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused,
225                         __glXdriSwapEvent, drawable->pDraw) != Success)
226         return FALSE;
227
228     return TRUE;
229 }
230
231 static int
232 __glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval)
233 {
234     if (interval <= 0) /* || interval > BIGNUM? */
235         return GLX_BAD_VALUE;
236
237     DRI2SwapInterval(drawable->pDraw, interval);
238
239     return 0;
240 }
241
242 static void
243 __glXDRIcontextDestroy(__GLXcontext *baseContext)
244 {
245     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
246     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
247
248     (*screen->core->destroyContext)(context->driContext);
249     __glXContextDestroy(&context->base);
250     free(context);
251 }
252
253 static int
254 __glXDRIcontextMakeCurrent(__GLXcontext *baseContext)
255 {
256     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
257     __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
258     __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
259     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
260
261     return (*screen->core->bindContext)(context->driContext,
262                                         draw->driDrawable,
263                                         read->driDrawable);
264 }                                             
265
266 static int
267 __glXDRIcontextLoseCurrent(__GLXcontext *baseContext)
268 {
269     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
270     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
271
272     return (*screen->core->unbindContext)(context->driContext);
273 }
274
275 static int
276 __glXDRIcontextCopy(__GLXcontext *baseDst, __GLXcontext *baseSrc,
277                     unsigned long mask)
278 {
279     __GLXDRIcontext *dst = (__GLXDRIcontext *) baseDst;
280     __GLXDRIcontext *src = (__GLXDRIcontext *) baseSrc;
281     __GLXDRIscreen *screen = (__GLXDRIscreen *) dst->base.pGlxScreen;
282
283     return (*screen->core->copyContext)(dst->driContext,
284                                         src->driContext, mask);
285 }
286
287 static int
288 __glXDRIcontextForceCurrent(__GLXcontext *baseContext)
289 {
290     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
291     __GLXDRIdrawable *draw = (__GLXDRIdrawable *) baseContext->drawPriv;
292     __GLXDRIdrawable *read = (__GLXDRIdrawable *) baseContext->readPriv;
293     __GLXDRIscreen *screen = (__GLXDRIscreen *) context->base.pGlxScreen;
294
295     return (*screen->core->bindContext)(context->driContext,
296                                         draw->driDrawable,
297                                         read->driDrawable);
298 }
299
300 static Bool
301 __glXDRIcontextWait(__GLXcontext *baseContext,
302                     __GLXclientState *cl, int *error)
303 {
304     if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) {
305         *error = cl->client->noClientException;
306         return TRUE;
307     }
308
309     return FALSE;
310 }
311
312 #ifdef __DRI_TEX_BUFFER
313
314 static int
315 __glXDRIbindTexImage(__GLXcontext *baseContext,
316                      int buffer,
317                      __GLXdrawable *glxPixmap)
318 {
319     __GLXDRIdrawable *drawable = (__GLXDRIdrawable *) glxPixmap;
320     const __DRItexBufferExtension *texBuffer = drawable->screen->texBuffer;
321     __GLXDRIcontext *context = (__GLXDRIcontext *) baseContext;
322
323     if (texBuffer == NULL)
324         return Success;
325
326 #if __DRI_TEX_BUFFER_VERSION >= 2
327     if (texBuffer->base.version >= 2 && texBuffer->setTexBuffer2 != NULL) {
328         (*texBuffer->setTexBuffer2)(context->driContext,
329                                     glxPixmap->target,
330                                     glxPixmap->format,
331                                     drawable->driDrawable);
332     } else
333 #endif
334     {
335         texBuffer->setTexBuffer(context->driContext,
336                                 glxPixmap->target,
337                                 drawable->driDrawable);
338     }
339
340     return Success;
341 }
342
343 static int
344 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
345                         int buffer,
346                         __GLXdrawable *pixmap)
347 {
348     /* FIXME: Just unbind the texture? */
349     return Success;
350 }
351
352 #else
353
354 static int
355 __glXDRIbindTexImage(__GLXcontext *baseContext,
356                      int buffer,
357                      __GLXdrawable *glxPixmap)
358 {
359     return Success;
360 }
361
362 static int
363 __glXDRIreleaseTexImage(__GLXcontext *baseContext,
364                         int buffer,
365                         __GLXdrawable *pixmap)
366 {
367     return Success;
368 }
369
370 #endif
371
372 static __GLXtextureFromPixmap __glXDRItextureFromPixmap = {
373     __glXDRIbindTexImage,
374     __glXDRIreleaseTexImage
375 };
376
377 static void
378 __glXDRIscreenDestroy(__GLXscreen *baseScreen)
379 {
380     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
381
382     (*screen->core->destroyScreen)(screen->driScreen);
383
384     dlclose(screen->driver);
385
386     __glXScreenDestroy(baseScreen);
387
388     free(screen);
389 }
390
391 static __GLXcontext *
392 __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
393                             __GLXconfig *glxConfig,
394                             __GLXcontext *baseShareContext)
395 {
396     __GLXDRIscreen *screen = (__GLXDRIscreen *) baseScreen;
397     __GLXDRIcontext *context, *shareContext;
398     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
399     __DRIcontext *driShare;
400
401     shareContext = (__GLXDRIcontext *) baseShareContext;
402     if (shareContext)
403         driShare = shareContext->driContext;
404     else
405         driShare = NULL;
406
407     context = calloc(1, sizeof *context);
408     if (context == NULL)
409         return NULL;
410
411     context->base.destroy           = __glXDRIcontextDestroy;
412     context->base.makeCurrent       = __glXDRIcontextMakeCurrent;
413     context->base.loseCurrent       = __glXDRIcontextLoseCurrent;
414     context->base.copy              = __glXDRIcontextCopy;
415     context->base.forceCurrent      = __glXDRIcontextForceCurrent;
416     context->base.textureFromPixmap = &__glXDRItextureFromPixmap;
417     context->base.wait              = __glXDRIcontextWait;
418
419     context->driContext =
420         (*screen->dri2->createNewContext)(screen->driScreen,
421                                           config->driConfig,
422                                           driShare, context);
423     if (context->driContext == NULL) {
424             free(context);
425         return NULL;
426     }
427
428     return &context->base;
429 }
430
431 static void
432 __glXDRIinvalidateBuffers(DrawablePtr pDraw, void *priv)
433 {
434 #if __DRI2_FLUSH_VERSION >= 3
435     __GLXDRIdrawable *private = priv;
436     __GLXDRIscreen *screen = private->screen;
437
438     if (screen->flush)
439         (*screen->flush->invalidate)(private->driDrawable);
440 #endif
441 }
442
443 static __GLXdrawable *
444 __glXDRIscreenCreateDrawable(ClientPtr client,
445                              __GLXscreen *screen,
446                              DrawablePtr pDraw,
447                              XID drawId,
448                              int type,
449                              XID glxDrawId,
450                              __GLXconfig *glxConfig)
451 {
452     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
453     __GLXDRIconfig *config = (__GLXDRIconfig *) glxConfig;
454     __GLXDRIdrawable *private;
455
456     private = calloc(1, sizeof *private);
457     if (private == NULL)
458         return NULL;
459
460     private->screen = driScreen;
461     if (!__glXDrawableInit(&private->base, screen,
462                            pDraw, type, glxDrawId, glxConfig)) {
463         free(private);
464         return NULL;
465     }
466
467     private->base.destroy       = __glXDRIdrawableDestroy;
468     private->base.swapBuffers   = __glXDRIdrawableSwapBuffers;
469     private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer;
470     private->base.waitGL        = __glXDRIdrawableWaitGL;
471     private->base.waitX         = __glXDRIdrawableWaitX;
472
473     if (DRI2CreateDrawable(client, pDraw, drawId,
474                            __glXDRIinvalidateBuffers, private)) {
475             free(private);
476             return NULL;
477     }
478
479     private->driDrawable =
480         (*driScreen->dri2->createNewDrawable)(driScreen->driScreen,
481                                               config->driConfig, private);
482
483     return &private->base;
484 }
485
486 static __DRIbuffer *
487 dri2GetBuffers(__DRIdrawable *driDrawable,
488                int *width, int *height,
489                unsigned int *attachments, int count,
490                int *out_count, void *loaderPrivate)
491 {
492     __GLXDRIdrawable *private = loaderPrivate;
493     DRI2BufferPtr *buffers;
494     int i;
495     int j;
496
497     buffers = DRI2GetBuffers(private->base.pDraw,
498                              width, height, attachments, count, out_count);
499     if (*out_count > MAX_DRAWABLE_BUFFERS) {
500         *out_count = 0;
501         return NULL;
502     }
503         
504     private->width = *width;
505     private->height = *height;
506
507     /* This assumes the DRI2 buffer attachment tokens matches the
508      * __DRIbuffer tokens. */
509     j = 0;
510     for (i = 0; i < *out_count; i++) {
511         /* Do not send the real front buffer of a window to the client.
512          */
513         if ((private->base.pDraw->type == DRAWABLE_WINDOW)
514             && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
515             continue;
516         }
517
518         private->buffers[j].attachment = buffers[i]->attachment;
519         private->buffers[j].name = buffers[i]->name;
520         private->buffers[j].pitch = buffers[i]->pitch;
521         private->buffers[j].cpp = buffers[i]->cpp;
522         private->buffers[j].flags = buffers[i]->flags;
523         j++;
524     }
525
526     *out_count = j;
527     return private->buffers;
528 }
529
530 static __DRIbuffer *
531 dri2GetBuffersWithFormat(__DRIdrawable *driDrawable,
532                          int *width, int *height,
533                          unsigned int *attachments, int count,
534                          int *out_count, void *loaderPrivate)
535 {
536     __GLXDRIdrawable *private = loaderPrivate;
537     DRI2BufferPtr *buffers;
538     int i;
539     int j = 0;
540
541     buffers = DRI2GetBuffersWithFormat(private->base.pDraw,
542                                        width, height, attachments, count,
543                                        out_count);
544     if (*out_count > MAX_DRAWABLE_BUFFERS) {
545         *out_count = 0;
546         return NULL;
547     }
548
549     private->width = *width;
550     private->height = *height;
551
552     /* This assumes the DRI2 buffer attachment tokens matches the
553      * __DRIbuffer tokens. */
554     for (i = 0; i < *out_count; i++) {
555         /* Do not send the real front buffer of a window to the client.
556          */
557         if ((private->base.pDraw->type == DRAWABLE_WINDOW)
558             && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
559             continue;
560         }
561
562         private->buffers[j].attachment = buffers[i]->attachment;
563         private->buffers[j].name = buffers[i]->name;
564         private->buffers[j].pitch = buffers[i]->pitch;
565         private->buffers[j].cpp = buffers[i]->cpp;
566         private->buffers[j].flags = buffers[i]->flags;
567         j++;
568     }
569
570     *out_count = j;
571     return private->buffers;
572 }
573
574 static void 
575 dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
576 {
577     (void) driDrawable;
578     __glXDRIdrawableWaitGL((__GLXdrawable *) loaderPrivate);
579 }
580
581 static const __DRIdri2LoaderExtension loaderExtension = {
582     { __DRI_DRI2_LOADER, __DRI_DRI2_LOADER_VERSION },
583     dri2GetBuffers,
584     dri2FlushFrontBuffer,
585     dri2GetBuffersWithFormat,
586 };
587
588 #ifdef __DRI_USE_INVALIDATE
589 static const __DRIuseInvalidateExtension dri2UseInvalidate = {
590    { __DRI_USE_INVALIDATE, __DRI_USE_INVALIDATE_VERSION }
591 };
592 #endif
593
594 static const __DRIextension *loader_extensions[] = {
595     &systemTimeExtension.base,
596     &loaderExtension.base,
597 #ifdef __DRI_USE_INVALIDATE
598     &dri2UseInvalidate,
599 #endif
600     NULL
601 };
602
603 static const char dri_driver_path[] = DRI_DRIVER_PATH;
604
605 static Bool
606 glxDRIEnterVT (int index, int flags)
607 {
608     ScrnInfoPtr scrn = xf86Screens[index];
609     Bool        ret;
610     __GLXDRIscreen *screen = (__GLXDRIscreen *) 
611         glxGetScreen(screenInfo.screens[index]);
612
613     LogMessage(X_INFO, "AIGLX: Resuming AIGLX clients after VT switch\n");
614
615     scrn->EnterVT = screen->enterVT;
616
617     ret = scrn->EnterVT (index, flags);
618
619     screen->enterVT = scrn->EnterVT;
620     scrn->EnterVT = glxDRIEnterVT;
621
622     if (!ret)
623         return FALSE;
624     
625     glxResumeClients();
626
627     return TRUE;
628 }
629
630 static void
631 glxDRILeaveVT (int index, int flags)
632 {
633     ScrnInfoPtr scrn = xf86Screens[index];
634     __GLXDRIscreen *screen = (__GLXDRIscreen *)
635         glxGetScreen(screenInfo.screens[index]);
636
637     LogMessage(X_INFO, "AIGLX: Suspending AIGLX clients for VT switch\n");
638
639     glxSuspendClients();
640
641     scrn->LeaveVT = screen->leaveVT;
642     (*screen->leaveVT) (index, flags);
643     screen->leaveVT = scrn->LeaveVT;
644     scrn->LeaveVT = glxDRILeaveVT;
645 }
646
647 static void
648 initializeExtensions(__GLXDRIscreen *screen)
649 {
650     ScreenPtr pScreen = screen->base.pScreen;
651     const __DRIextension **extensions;
652     int i;
653
654     extensions = screen->core->getExtensions(screen->driScreen);
655
656     __glXEnableExtension(screen->glx_enable_bits,
657                          "GLX_MESA_copy_sub_buffer");
658     LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
659
660     __glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
661     LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
662
663     if (DRI2HasSwapControl(pScreen)) {
664         __glXEnableExtension(screen->glx_enable_bits,
665                              "GLX_SGI_swap_control");
666         __glXEnableExtension(screen->glx_enable_bits,
667                              "GLX_MESA_swap_control");
668         LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
669     }
670
671     for (i = 0; extensions[i]; i++) {
672 #ifdef __DRI_READ_DRAWABLE
673         if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
674             __glXEnableExtension(screen->glx_enable_bits,
675                                  "GLX_SGI_make_current_read");
676
677             LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_make_current_read\n");
678         }
679 #endif
680
681 #ifdef __DRI_TEX_BUFFER
682         if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
683             screen->texBuffer =
684                 (const __DRItexBufferExtension *) extensions[i];
685             /* GLX_EXT_texture_from_pixmap is always enabled. */
686             LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n");
687         }
688 #endif
689
690 #ifdef __DRI2_FLUSH
691         if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
692             extensions[i]->version >= 3) {
693                 screen->flush = (__DRI2flushExtension *) extensions[i];
694         }
695 #endif
696
697         /* Ignore unknown extensions */
698     }
699 }
700
701 static __GLXscreen *
702 __glXDRIscreenProbe(ScreenPtr pScreen)
703 {
704     const char *driverName, *deviceName;
705     __GLXDRIscreen *screen;
706     char filename[128];
707     size_t buffer_size;
708     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
709     const __DRIextension **extensions;
710     const __DRIconfig **driConfigs;
711     int i;
712
713     screen = calloc(1, sizeof *screen);
714     if (screen == NULL)
715         return NULL;
716
717     if (!xf86LoaderCheckSymbol("DRI2Connect") ||
718         !DRI2Connect(pScreen, DRI2DriverDRI,
719                      &screen->fd, &driverName, &deviceName)) {
720         LogMessage(X_INFO,
721                    "AIGLX: Screen %d is not DRI2 capable\n", pScreen->myNum);
722         return NULL;
723     }
724
725     screen->base.destroy        = __glXDRIscreenDestroy;
726     screen->base.createContext  = __glXDRIscreenCreateContext;
727     screen->base.createDrawable = __glXDRIscreenCreateDrawable;
728     screen->base.swapInterval   = __glXDRIdrawableSwapInterval;
729     screen->base.pScreen       = pScreen;
730
731     __glXInitExtensionEnableBits(screen->glx_enable_bits);
732
733     snprintf(filename, sizeof filename,
734              "%s/%s_dri.so", dri_driver_path, driverName);
735
736     screen->driver = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
737     if (screen->driver == NULL) {
738         LogMessage(X_ERROR, "AIGLX error: dlopen of %s failed (%s)\n",
739                    filename, dlerror());
740         goto handle_error;
741     }
742
743     extensions = dlsym(screen->driver, __DRI_DRIVER_EXTENSIONS);
744     if (extensions == NULL) {
745         LogMessage(X_ERROR, "AIGLX error: %s exports no extensions (%s)\n",
746                    driverName, dlerror());
747         goto handle_error;
748     }
749     
750     for (i = 0; extensions[i]; i++) {
751         if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
752             extensions[i]->version >= 1) {
753                 screen->core = (const __DRIcoreExtension *) extensions[i];
754         }
755         if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
756             extensions[i]->version >= 1) {
757                 screen->dri2 = (const __DRIdri2Extension *) extensions[i];
758         }
759     }
760
761     if (screen->core == NULL || screen->dri2 == NULL) {
762         LogMessage(X_ERROR, "AIGLX error: %s exports no DRI extension\n",
763                    driverName);
764         goto handle_error;
765     }
766
767     screen->driScreen =
768         (*screen->dri2->createNewScreen)(pScreen->myNum,
769                                          screen->fd,
770                                          loader_extensions,
771                                          &driConfigs,
772                                          screen);
773
774     if (screen->driScreen == NULL) {
775         LogMessage(X_ERROR,
776                    "AIGLX error: Calling driver entry point failed\n");
777         goto handle_error;
778     }
779
780     initializeExtensions(screen);
781
782     screen->base.fbconfigs = glxConvertConfigs(screen->core, driConfigs,
783                                                GLX_WINDOW_BIT |
784                                                GLX_PIXMAP_BIT |
785                                                GLX_PBUFFER_BIT);
786
787     __glXScreenInit(&screen->base, pScreen);
788
789     /* The first call simply determines the length of the extension string.
790      * This allows us to allocate some memory to hold the extension string,
791      * but it requires that we call __glXGetExtensionString a second time.
792      */
793     buffer_size = __glXGetExtensionString(screen->glx_enable_bits, NULL);
794     if (buffer_size > 0) {
795         if (screen->base.GLXextensions != NULL) {
796             free(screen->base.GLXextensions);
797         }
798
799         screen->base.GLXextensions = xnfalloc(buffer_size);
800         (void) __glXGetExtensionString(screen->glx_enable_bits, 
801                                        screen->base.GLXextensions);
802     }
803
804     /* We're going to assume (perhaps incorrectly?) that all DRI2-enabled
805      * drivers support the required extensions for GLX 1.4.  The extensions
806      * we're assuming are:
807      *
808      *    - GLX_SGI_make_current_read (1.3)
809      *    - GLX_SGIX_fbconfig (1.3)
810      *    - GLX_SGIX_pbuffer (1.3)
811      *    - GLX_ARB_multisample (1.4)
812      */
813     screen->base.GLXmajor = 1;
814     screen->base.GLXminor = 4;
815     
816     screen->enterVT = pScrn->EnterVT;
817     pScrn->EnterVT = glxDRIEnterVT; 
818     screen->leaveVT = pScrn->LeaveVT;
819     pScrn->LeaveVT = glxDRILeaveVT;
820
821     LogMessage(X_INFO,
822                "AIGLX: Loaded and initialized %s\n", filename);
823
824     return &screen->base;
825
826  handle_error:
827     if (screen->driver)
828         dlclose(screen->driver);
829
830     free(screen);
831
832     LogMessage(X_ERROR, "AIGLX: reverting to software rendering\n");
833
834     return NULL;
835 }
836
837 _X_EXPORT __GLXprovider __glXDRI2Provider = {
838     __glXDRIscreenProbe,
839     "DRI2",
840     NULL
841 };