Merge branch 'mesa_7_5_branch'
[mesa.git] / src / egl / drivers / dri / egldri.c
index 504fa9f43d0bc1c064f6059fc401b3672b1b9fc7..9e400be6248b805b0f445703a88953eb79cc3b00 100644 (file)
@@ -1,5 +1,6 @@
 /**
- * Generic EGL driver for DRI.
+ * Generic EGL driver for DRI.  This is basically an "adaptor" driver
+ * that allows libEGL to load/use regular DRI drivers.
  *
  * This file contains all the code needed to interface DRI-based drivers
  * with libEGL.
@@ -23,6 +24,7 @@
 #include "egldisplay.h"
 #include "eglcontext.h"
 #include "eglconfig.h"
+#include "eglconfigutil.h"
 #include "eglsurface.h"
 #include "eglscreen.h"
 #include "eglglobals.h"
 #include "egldri.h"
 
 const char *sysfs = "/sys/class";
-#define None 0
+
 static const int empty_attribute_list[1] = { None };
 
 
+
+/**
+ * Given a card number, return the name of the DRI driver to use.
+ * This generally means reading the contents of
+ * /sys/class/drm/cardX/dri_library_name, where X is the card number
+ */
+static EGLBoolean
+driver_name_from_card_number(int card, char *driverName, int maxDriverName)
+{
+   char path[2000];
+   FILE *f;
+   int length;
+
+   snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", sysfs, card);
+
+   f = fopen(path, "r");
+   if (!f)
+      return EGL_FALSE;
+
+   fgets(driverName, maxDriverName, f);
+   fclose(f);
+
+   if ((length = strlen(driverName)) > 1) {
+      /* remove the trailing newline from sysfs */
+      driverName[length - 1] = '\0';
+      strncat(driverName, "_dri", maxDriverName);
+      return EGL_TRUE;
+   }
+   else {
+      return EGL_FALSE;
+   }   
+}
+
+
+
 /**
  * The bootstrap function.
  * Return a new driDriver object and plug in API functions.
  * This function, in turn, loads a specific DRI driver (ex: r200_dri.so).
  */
 _EGLDriver *
-_eglMain(_EGLDisplay *dpy)
+_eglMain(_EGLDisplay *dpy, const char *args)
 {
+#if 1
+   const int card = args ? atoi(args) : 0;
+   _EGLDriver *driver = NULL;
+   char driverName[1000];
+
+   if (!driver_name_from_card_number(card, driverName, sizeof(driverName))) {
+      _eglLog(_EGL_WARNING,
+              "Unable to determine driver name for card %d\n", card);
+      return NULL;
+   }
+
+   _eglLog(_EGL_DEBUG, "Driver name: %s\n", driverName);
+
+   driver = _eglOpenDriver(dpy, driverName, args);
+
+   return driver;
+
+#else
+
    int length;
    char path[NAME_MAX];
    struct dirent *dirent;
@@ -58,14 +114,19 @@ _eglMain(_EGLDisplay *dpy)
       _eglLog(_EGL_WARNING, "%s DRM devices not found.", path);
       return EGL_FALSE;
    }
+
+   /* loop over dir entries looking for cardX where "X" is in the
+    * dpy->DriverName ":X" string.
+    */
    while ((dirent = readdir(dir))) {
 
       if (strncmp(&dirent->d_name[0], "card", 4) != 0)
          continue;
-      if (strcmp(&dirent->d_name[4], &dpy->Name[1]) != 0)
+      if (strcmp(&dirent->d_name[4], &driverName[1]) != 0)
          continue;
 
-      snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name", sysfs, &dpy->Name[1]);
+      snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name",
+               sysfs, &driverName[1]);
       _eglLog(_EGL_INFO, "Opening %s", path);
 #if 1
       file = fopen(path, "r");
@@ -89,6 +150,7 @@ _eglMain(_EGLDisplay *dpy)
    closedir(dir);
 
    return driver;
+#endif
 }
 
 
@@ -109,7 +171,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
    if (!c)
       return EGL_NO_CONTEXT;
 
-   if (!_eglInitContext(drv, dpy, &c->Base, config, attrib_list)) {
+   conf = _eglLookupConfig(drv, dpy, config);
+   assert(conf);
+
+   if (!_eglInitContext(drv, &c->Base, conf, attrib_list)) {
       free(c);
       return EGL_NO_CONTEXT;
    }
@@ -127,8 +192,6 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
    else
       sharePriv = NULL;
 
-   conf = _eglLookupConfig(drv, dpy, config);
-   assert(conf);
    _eglConfigToContextModesRec(conf, &visMode);
 
    c->driContext.private = disp->driScreen.createNewContext(disp, &visMode,
@@ -138,10 +201,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
       return EGL_FALSE;
    }
 
-   /* generate handle and insert into hash table */
-   _eglSaveContext(&c->Base);
+   /* link to display */
+   _eglLinkContext(&c->Base, &disp->Base);
 
-   return c->Base.Handle;
+   return _eglGetContextHandle(&c->Base);
 }
 
 
@@ -152,13 +215,15 @@ _eglDRIMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw,
    driDisplay *disp = Lookup_driDisplay(dpy);
    driContext *ctx = Lookup_driContext(context);
    EGLBoolean b;
+   __DRIid drawBuf = (__DRIid) draw;
+   __DRIid readBuf = (__DRIid) read;
 
    b = _eglMakeCurrent(drv, dpy, draw, read, context);
    if (!b)
       return EGL_FALSE;
 
    if (ctx) {
-      ctx->driContext.bindContext(disp, 0, read, draw, &ctx->driContext);
+      ctx->driContext.bindContext(disp, 0, drawBuf, readBuf, &ctx->driContext);
    }
    else {
       /* what's this??? */
@@ -173,14 +238,18 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
                             const EGLint *attrib_list)
 {
    driSurface *surf;
+   _EGLConfig *conf;
+
+   conf = _eglLookupConfig(drv, dpy, config);
+   assert(conf);
 
    surf = (driSurface *) calloc(1, sizeof(*surf));
    if (!surf) {
       return EGL_NO_SURFACE;
    }
 
-   if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT,
-                        config, attrib_list)) {
+   if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT,
+                        conf, attrib_list)) {
       free(surf);
       return EGL_NO_SURFACE;
    }
@@ -190,7 +259,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
 #if 0
       GLcontext *ctx = NULL; /* this _should_ be OK */
 #endif
-      GLvisual visMode;
+      __GLcontextModes visMode;
       _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
       assert(conf); /* bad config should be caught earlier */
       _eglConfigToContextModesRec(conf, &visMode);
@@ -211,7 +280,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
 #endif
    }
 
-   _eglSaveSurface(&surf->Base);
+   _eglLinkSurface(&surf->Base, _eglLookupDisplay(dpy));
 
    return surf->Base.Handle;
 }
@@ -223,16 +292,12 @@ _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
    driDisplay *disp = Lookup_driDisplay(dpy);
    driSurface *fs = Lookup_driSurface(surface);
 
-   _eglRemoveSurface(&fs->Base);
+   _eglUnlinkSurface(&fs->Base);
 
    fs->drawable.destroyDrawable(disp, fs->drawable.private);
 
-   if (fs->Base.IsBound) {
-      fs->Base.DeletePending = EGL_TRUE;
-   }
-   else {
+   if (!_eglIsSurfaceBound(&fs->Base))
       free(fs);
-   }
    return EGL_TRUE;
 }
 
@@ -243,16 +308,12 @@ _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
    driDisplay *disp = Lookup_driDisplay(dpy);
    driContext *fc = Lookup_driContext(context);
 
-   _eglRemoveContext(&fc->Base);
+   _eglUnlinkContext(&fc->Base);
 
    fc->driContext.destroyContext(disp, 0, fc->driContext.private);
 
-   if (fc->Base.IsBound) {
-      fc->Base.DeletePending = EGL_TRUE;
-   }
-   else {
+   if (!_eglIsContextBound(&fc->Base))
       free(fc);
-   }
    return EGL_TRUE;
 }
 
@@ -267,7 +328,8 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
    _EGLConfig *config = _eglLookupConfig(drv, dpy, cfg);
    driDisplay *disp = Lookup_driDisplay(dpy);
    driSurface *surface;
-   GLvisual visMode;
+   __GLcontextModes visMode;
+   __DRIid drawBuf;
 
    surface = (driSurface *) calloc(1, sizeof(*surface));
    if (!surface) {
@@ -275,13 +337,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
    }
 
    /* init base class, do error checking, etc. */
-   if (!_eglInitSurface(drv, dpy, &surface->Base, EGL_SCREEN_BIT_MESA,
-                        cfg, attrib_list)) {
+   if (!_eglInitSurface(drv, &surface->Base, EGL_SCREEN_BIT_MESA,
+                        config, attrib_list)) {
       free(surface);
       return EGL_NO_SURFACE;
    }
 
-   _eglSaveSurface(&surface->Base);
+   _eglLinkSurface(&surface->Base &disp->Base);
 
 
    /*
@@ -292,11 +354,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
    /* convert EGLConfig to GLvisual */
    _eglConfigToContextModesRec(config, &visMode);
 
+   drawBuf = (__DRIid) _eglGetSurfaceHandle(&surface->Base);
+
    /* Create a new DRI drawable */
-   if (!disp->driScreen.createNewDrawable(disp, &visMode, surface->Base.Handle,
+   if (!disp->driScreen.createNewDrawable(disp, &visMode, drawBuf,
                                           &surface->drawable, GLX_WINDOW_BIT,
                                           empty_attribute_list)) {
-      _eglRemoveSurface(&surface->Base);
+      _eglUnlinkSurface(&surface->Base);
       free(surface);
       return EGL_NO_SURFACE;
    }
@@ -713,17 +777,32 @@ __eglGetDrawableInfo(__DRInativeDisplay * ndpy, int screen, __DRIid drawable,
                      int* backX, int* backY,
                      int* numBackClipRects, drm_clip_rect_t ** pBackClipRects )
 {
-   driSurface *surf = Lookup_driSurface(drawable);
+    __DRIscreen *pDRIScreen;
+    __DRIscreenPrivate *psp;
+    driSurface *surf = Lookup_driSurface((EGLSurface) drawable);
+
+   pDRIScreen = __eglFindDRIScreen(ndpy, screen);
 
+   if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+       return GL_FALSE;
+   }
+   psp = (__DRIscreenPrivate *) pDRIScreen->private;
    *X = 0;
    *Y = 0;
    *W = surf->Base.Width;
    *H = surf->Base.Height;
 
+   *backX = 0;
+   *backY = 0;
+   *numBackClipRects = 0;
+   *pBackClipRects = NULL;
+
    *numClipRects = 1;
    *pClipRects = malloc(sizeof(**pClipRects));
    **pClipRects = (drm_clip_rect_t){0, 0, surf->Base.Width, surf->Base.Height};
 
+   psp->pSAREA->drawableTable[0].stamp = 1;
+   *stamp = 1;
 #if 0
     GLXDrawable drawable = (GLXDrawable) draw;
     drm_clip_rect_t * cliprect;
@@ -1004,8 +1083,10 @@ _eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer)
                             api_ver,
                             & interface_methods,
                             NULL);
-   if (!dpy->driScreen.private)
+   if (!dpy->driScreen.private) {
+      _eglLog(_EGL_WARNING, "egldri.c: DRI create new screen failed");
       return EGL_FALSE;
+   }
 
    DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext );
 
@@ -1065,6 +1146,7 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy,
 {
    _EGLDisplay *disp = _eglLookupDisplay(dpy);
    driDisplay *display;
+   const char *driverName = (const char *) disp->NativeDisplay;
 
    assert(disp);
 
@@ -1073,13 +1155,13 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy,
     */
    display = calloc(1, sizeof(*display));
    display->Base = *disp;
-   _eglHashInsert(_eglGlobal.Displays, disp->Handle, display);
+   _eglSaveDisplay(&display->Base);
    free(disp);
 
    *major = 1;
    *minor = 0;
 
-   sscanf(&disp->Name[1], "%d", &display->minor);
+   sscanf(driverName + 1, "%d", &display->minor);
 
    drv->Initialized = EGL_TRUE;
    return EGL_TRUE;