+/**
+ * Implement \c __DRIinterfaceMethods::getProcAddress.
+ */
+static __DRIfuncPtr get_proc_address( const char * proc_name )
+{
+ (void) proc_name;
+ return NULL;
+}
+
+
+/**
+ * Table of functions exported by the loader to the driver.
+ */
+static const __DRIinterfaceMethods interface_methods = {
+ get_proc_address,
+
+ _gl_context_modes_create,
+ _gl_context_modes_destroy,
+
+ __glXFindDRIScreen,
+ __glXWindowExists,
+
+ __glXCreateContextWithConfig,
+ xf86DRI_DestroyContext,
+
+ xf86DRI_CreateDrawable,
+ xf86DRI_DestroyDrawable,
+ __glXGetDrawableInfo,
+
+ __glXGetUST,
+ __glXGetMscRate,
+};
+
+
+static void *
+CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc)
+{
+ void *psp = NULL;
+ drm_handle_t hSAREA;
+ drmAddress pSAREA;
+ const char *BusID;
+ int i;
+ __DRIversion ddx_version;
+ __DRIversion dri_version;
+ __DRIversion drm_version;
+ __DRIframebuffer framebuffer;
+ int fd = -1;
+ int status;
+ const char * err_msg;
+ const char * err_extra;
+ drmVersionPtr version;
+ drm_handle_t hFB;
+ drm_magic_t magic;
+
+
+ hSAREA = dpy->driverContext.shared.hSAREA;
+ BusID = dpy->driverContext.pciBusID;
+
+ fd = drmOpen(NULL, BusID);
+
+ err_msg = "open DRM";
+ err_extra = strerror( -fd );
+
+ if (fd < 0) goto done;
+
+ err_msg = "drmGetMagic";
+ err_extra = NULL;
+
+ if (drmGetMagic(fd, &magic)) goto done;
+
+ dpy->authorized = False;
+ send_char_msg( dpy, 0, _Authorize );
+ send_msg( dpy, 0, &magic, sizeof(magic));
+
+ /* force net buffer flush */
+ while (!dpy->authorized)
+ handle_fd_events( dpy, 0 );
+
+ version = drmGetVersion(fd);
+ if (version) {
+ drm_version.major = version->version_major;
+ drm_version.minor = version->version_minor;
+ drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+ else {
+ drm_version.major = -1;
+ drm_version.minor = -1;
+ drm_version.patch = -1;
+ }
+
+ /*
+ * Get device name (like "tdfx") and the ddx version numbers.
+ * We'll check the version in each DRI driver's "createScreen"
+ * function.
+ */
+ ddx_version.major = -1;
+ ddx_version.minor = 0;
+ ddx_version.patch = 0;
+
+ /*
+ * Get the DRI X extension version.
+ */
+ dri_version.major = 4;
+ dri_version.minor = 0;
+ dri_version.patch = 0;
+
+ /*
+ * Get device-specific info. pDevPriv will point to a struct
+ * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
+ * that has information about the screen size, depth, pitch,
+ * ancilliary buffers, DRM mmap handles, etc.
+ */
+ hFB = dpy->driverContext.shared.hFrameBuffer;
+ framebuffer.size = dpy->driverContext.shared.fbSize;
+ framebuffer.stride = dpy->driverContext.shared.fbStride;
+ framebuffer.dev_priv_size = dpy->driverContext.driverClientMsgSize;
+ framebuffer.dev_priv = dpy->driverContext.driverClientMsg;
+ framebuffer.width = dpy->driverContext.shared.virtualWidth;
+ framebuffer.height = dpy->driverContext.shared.virtualHeight;
+
+ /*
+ * Map the framebuffer region.
+ */
+ status = drmMap(fd, hFB, framebuffer.size,
+ (drmAddressPtr)&framebuffer.base);
+
+ err_msg = "drmMap of framebuffer";
+ err_extra = strerror( -status );
+
+ if ( status != 0 ) goto done;
+
+ /*
+ * Map the SAREA region. Further mmap regions may be setup in
+ * each DRI driver's "createScreen" function.
+ */
+ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA);
+
+ err_msg = "drmMap of sarea";
+ err_extra = strerror( -status );
+
+ if ( status == 0 ) {
+ err_msg = "InitDriver";
+ err_extra = NULL;
+ psp = dpy->createNewScreen(dpy, scrn, psc, NULL,
+ & ddx_version,
+ & dri_version,
+ & drm_version,
+ & framebuffer,
+ pSAREA,
+ fd,
+ 20050727,
+ & interface_methods,
+ (__GLcontextModes **) &dpy->driver_modes);
+
+ /* fill in dummy visual ids */
+ {
+ __GLcontextModes *temp;
+ temp = (__GLcontextModes *)dpy->driver_modes;
+ i = 1;
+ while (temp)
+ {
+ temp->visualID = i++;
+ temp=temp->next;
+ }
+ }
+ }
+
+done:
+ if ( psp == NULL ) {
+ if ( pSAREA != MAP_FAILED ) {
+ (void)drmUnmap(pSAREA, SAREA_MAX);
+ }
+
+ if ( framebuffer.base != MAP_FAILED ) {
+ (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
+ }
+
+ if ( framebuffer.dev_priv != NULL ) {
+ free(framebuffer.dev_priv);
+ }
+
+ if ( fd >= 0 ) {
+ (void)drmClose(fd);
+ }
+
+ if ( err_extra != NULL ) {
+ fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
+ err_extra);
+ }
+ else {
+ fprintf(stderr, "libGL error: %s failed\n", err_msg );
+ }
+
+ fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
+ }
+
+ return psp;
+}
+