glx: fix rotation regression. bug #14963
[mesa.git] / src / glx / x11 / dri_glx.c
index 01290a42696c1e5cd937019924dac20022010f95..2e3ab06dce0e96539af63a4add1f1c3036f375e6 100644 (file)
@@ -38,13 +38,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <X11/Xlibint.h>
 #include <X11/extensions/Xext.h>
 #include <X11/extensions/extutil.h>
+#include <X11/extensions/Xfixes.h>
+#include <X11/extensions/Xdamage.h>
 #include "glheader.h"
 #include "glxclient.h"
 #include "xf86dri.h"
 #include "sarea.h"
 #include <stdio.h>
 #include <dlfcn.h>
-#include "dri_glx.h"
 #include <sys/types.h>
 #include <stdarg.h>
 #include "glcontextmodes.h"
@@ -59,6 +60,25 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define RTLD_GLOBAL 0
 #endif
 
+typedef struct __GLXDRIdisplayPrivateRec __GLXDRIdisplayPrivate;
+typedef struct __GLXDRIcontextPrivateRec __GLXDRIcontextPrivate;
+
+struct __GLXDRIdisplayPrivateRec {
+    __GLXDRIdisplay base;
+
+    /*
+    ** XFree86-DRI version information
+    */
+    int driMajor;
+    int driMinor;
+    int driPatch;
+};
+
+struct __GLXDRIcontextPrivateRec {
+    __GLXDRIcontext base;
+    __DRIcontext driContext;
+    XID hwContextID;
+};
 
 #ifndef DEFAULT_DRIVER_DIR
 /* this is normally defined in Mesa/configs/default with DRI_DRIVER_SEARCH_PATH */
@@ -127,13 +147,15 @@ static void *OpenDriver(const char *driverName)
    /* Attempt to make sure libGL symbols will be visible to the driver */
    glhandle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL);
 
-   libPaths = DEFAULT_DRIVER_DIR;
+   libPaths = NULL;
    if (geteuid() == getuid()) {
       /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */
       libPaths = getenv("LIBGL_DRIVERS_PATH");
       if (!libPaths)
          libPaths = getenv("LIBGL_DRIVERS_DIR"); /* deprecated */
    }
+   if (libPaths == NULL)
+       libPaths = DEFAULT_DRIVER_DIR;
 
    handle = NULL;
    for (p = libPaths; *p; p = next) {
@@ -359,8 +381,8 @@ static void __glXReportDamage(__DRIdrawable *driDraw,
     XserverRegion region;
     int i;
     int x_off, y_off;
-    __GLXdrawable *glxDraw =
-       containerOf(driDraw, __GLXdrawable, driDrawable);
+    __GLXDRIdrawable *glxDraw =
+       containerOf(driDraw, __GLXDRIdrawable, driDrawable);
     __GLXscreenConfigs *psc = glxDraw->psc;
     Display *dpy = psc->dpy;
     Drawable drawable;
@@ -403,8 +425,8 @@ __glXDRIGetDrawableInfo(__DRIdrawable *drawable,
                        int *backX, int *backY,
                        int *numBackClipRects, drm_clip_rect_t **pBackClipRects)
 {
-    __GLXdrawable *glxDraw =
-       containerOf(drawable, __GLXdrawable, driDrawable);
+    __GLXDRIdrawable *glxDraw =
+       containerOf(drawable, __GLXDRIdrawable, driDrawable);
     __GLXscreenConfigs *psc = glxDraw->psc;
     Display *dpy = psc->dpy;
 
@@ -469,10 +491,10 @@ static const __DRIextension *loader_extensions[] = {
  */
 static void *
 CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
-                   __DRIdisplay * driDpy,
+                   __GLXDRIdisplayPrivate * driDpy,
                    PFNCREATENEWSCREENFUNC createNewScreen)
 {
-    __DRIscreenPrivate *psp = NULL;
+    void *psp = NULL;
 #ifndef GLX_USE_APPLEGL
     drm_handle_t hSAREA;
     drmAddress pSAREA = MAP_FAILED;
@@ -486,9 +508,9 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
     const char * err_msg;
     const char * err_extra;
 
-    dri_version.major = driDpy->private->driMajor;
-    dri_version.minor = driDpy->private->driMinor;
-    dri_version.patch = driDpy->private->driPatch;
+    dri_version.major = driDpy->driMajor;
+    dri_version.minor = driDpy->driMinor;
+    dri_version.patch = driDpy->driPatch;
 
 
     err_msg = "XF86DRIOpenConnection";
@@ -591,7 +613,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
                                    err_msg = "InitDriver";
                                    err_extra = NULL;
                                    psp = (*createNewScreen)(scrn,
-                                                            &psc->driScreen,
+                                                            &psc->__driScreen,
                                                             & ddx_version,
                                                             & dri_version,
                                                             & drm_version,
@@ -647,19 +669,149 @@ CallCreateNewScreen(Display *dpy, int scrn, __GLXscreenConfigs *psc,
     return psp;
 }
 
-void
-driCreateScreen(__GLXscreenConfigs *psc, int screen,
-               __GLXdisplayPrivate *priv)
+static void driDestroyContext(__GLXDRIcontext *context,
+                             __GLXscreenConfigs *psc, Display *dpy)
 {
-    PFNCREATENEWSCREENFUNC createNewScreen;
+    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+                       
+    (*pcp->driContext.destroyContext)(&pcp->driContext);
 
-    if (priv->driDisplay.private == NULL)
-       return;
+    XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+}
 
-    /* Create drawable hash */
-    psc->drawHash = __glxHashCreate();
-    if ( psc->drawHash == NULL )
-       return;
+static Bool driBindContext(__GLXDRIcontext *context,
+                          __GLXDRIdrawable *draw, __GLXDRIdrawable *read)
+{
+    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+
+    return (*pcp->driContext.bindContext)(&pcp->driContext,
+                                         &draw->driDrawable,
+                                         &read->driDrawable);
+}
+
+static void driUnbindContext(__GLXDRIcontext *context)
+{
+    __GLXDRIcontextPrivate *pcp = (__GLXDRIcontextPrivate *) context;
+
+    (*pcp->driContext.unbindContext)(&pcp->driContext);
+}
+
+static __GLXDRIcontext *driCreateContext(__GLXscreenConfigs *psc,
+                                        const __GLcontextModes *mode,
+                                        GLXContext gc,
+                                        GLXContext shareList, int renderType)
+{
+    __GLXDRIcontextPrivate *pcp, *pcp_shared;
+    drm_context_t hwContext;
+    __DRIcontext *shared = NULL;
+
+    if (psc && psc->driScreen) {
+       if (shareList) {
+           pcp_shared = (__GLXDRIcontextPrivate *) shareList->driContext;
+           shared = &pcp_shared->driContext;
+       }
+
+       pcp = Xmalloc(sizeof *pcp);
+       if (pcp == NULL)
+           return NULL;
+
+       if (!XF86DRICreateContextWithConfig(psc->dpy, psc->scr,
+                                           mode->visualID,
+                                           &pcp->hwContextID, &hwContext)) {
+           Xfree(pcp);
+           return NULL;
+       }
+
+       pcp->driContext.private = 
+           (*psc->__driScreen.createNewContext)(&psc->__driScreen,
+                                                mode, renderType,
+                                                shared,
+                                                hwContext,
+                                                &pcp->driContext);
+       if (pcp->driContext.private == NULL) {
+           XF86DRIDestroyContext(psc->dpy, psc->scr, pcp->hwContextID);
+           Xfree(pcp);
+           return NULL;
+       }
+
+       pcp->base.destroyContext = driDestroyContext;
+       pcp->base.bindContext = driBindContext;
+       pcp->base.unbindContext = driUnbindContext;
+
+       return &pcp->base;
+    }
+
+    return NULL;
+}
+
+static void driDestroyDrawable(__GLXDRIdrawable *pdraw)
+{
+    __GLXscreenConfigs *psc = pdraw->psc;
+
+    (*pdraw->driDrawable.destroyDrawable)(&pdraw->driDrawable);
+    XF86DRIDestroyDrawable(psc->dpy, psc->scr, pdraw->drawable);
+    Xfree(pdraw);
+}
+
+static __GLXDRIdrawable *driCreateDrawable(__GLXscreenConfigs *psc,
+                                          GLXDrawable drawable,
+                                          GLXContext gc)
+{
+    __GLXDRIdrawable *pdraw;
+    drm_drawable_t hwDrawable;
+    void *empty_attribute_list = NULL;
+
+    pdraw = Xmalloc(sizeof(*pdraw));
+    if (!pdraw)
+       return NULL;
+
+    pdraw->drawable = drawable;
+    pdraw->psc = psc;
+
+    if (!XF86DRICreateDrawable(psc->dpy, psc->scr, drawable, &hwDrawable))
+       return NULL;
+
+    /* Create a new drawable */
+    pdraw->driDrawable.private =
+       (*psc->__driScreen.createNewDrawable)(&psc->__driScreen,
+                                             gc->mode,
+                                             &pdraw->driDrawable,
+                                             hwDrawable,
+                                             GLX_WINDOW_BIT,
+                                             0,
+                                             empty_attribute_list);
+
+    if (!pdraw->driDrawable.private) {
+       XF86DRIDestroyDrawable(psc->dpy, psc->scr, drawable);
+       Xfree(pdraw);
+       return NULL;
+    }
+
+    pdraw->destroyDrawable = driDestroyDrawable;
+
+    return pdraw;
+}
+
+static void driDestroyScreen(__GLXscreenConfigs *psc)
+{
+    /* Free the direct rendering per screen data */
+    if (psc->__driScreen.private)
+       (*psc->__driScreen.destroyScreen)(&psc->__driScreen);
+    psc->__driScreen.private = NULL;
+    if (psc->driver)
+       dlclose(psc->driver);
+}
+
+static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen,
+                                      __GLXdisplayPrivate *priv)
+{
+    PFNCREATENEWSCREENFUNC createNewScreen;
+    __GLXDRIdisplayPrivate *pdp;
+    __GLXDRIscreen *psp;
+
+    psp = Xmalloc(sizeof *psp);
+    if (psp == NULL)
+       return NULL;
 
     /* Initialize per screen dynamic client GLX extensions */
     psc->ext_list_first_time = GL_TRUE;
@@ -667,56 +819,39 @@ driCreateScreen(__GLXscreenConfigs *psc, int screen,
     psc->driver = driGetDriver(priv->dpy, screen);
     createNewScreen = dlsym(psc->driver, createNewScreenName);
     if (createNewScreenName == NULL)
-       return;
+       return NULL;
 
-    psc->driScreen.private =
-       CallCreateNewScreen(psc->dpy, screen, psc,
-                           &priv->driDisplay, createNewScreen);
-    if (psc->driScreen.private != NULL)
+    pdp = (__GLXDRIdisplayPrivate *) priv->driDisplay;
+    psc->__driScreen.private =
+       CallCreateNewScreen(psc->dpy, screen, psc, pdp, createNewScreen);
+    if (psc->__driScreen.private != NULL)
        __glXScrEnableDRIExtension(psc);
-}
 
-void driDestroyScreen(__GLXscreenConfigs *psc)
-{
-    /* Free the direct rendering per screen data */
-    if (psc->driScreen.private)
-       (*psc->driScreen.destroyScreen)(&psc->driScreen);
-    psc->driScreen.private = NULL;
-    if (psc->drawHash)
-       __glxHashDestroy(psc->drawHash);
-    if (psc->driver)
-       dlclose(psc->driver);
+    psp->destroyScreen = driDestroyScreen;
+    psp->createContext = driCreateContext;
+    psp->createDrawable = driCreateDrawable;
+
+    return psp;
 }
 
 /* Called from __glXFreeDisplayPrivate.
  */
-static void driDestroyDisplay(Display *dpy, void *private)
+static void driDestroyDisplay(__GLXDRIdisplay *dpy)
 {
-    __DRIdisplayPrivate *pdpyp = (__DRIdisplayPrivate *)private;
-
-    if (pdpyp)
-       Xfree(pdpyp);
+    Xfree(dpy);
 }
 
-
 /*
  * Allocate, initialize and return a __DRIdisplayPrivate object.
  * This is called from __glXInitialize() when we are given a new
  * display pointer.
  */
-void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
+_X_HIDDEN __GLXDRIdisplay *driCreateDisplay(Display *dpy)
 {
-    __DRIdisplayPrivate *pdpyp;
+    __GLXDRIdisplayPrivate *pdpyp;
     int eventBase, errorBase;
     int major, minor, patch;
 
-    /* Initialize these fields to NULL in case we fail.
-     * If we don't do this we may later get segfaults trying to free random
-     * addresses when the display is closed.
-     */
-    pdisp->private = NULL;
-    pdisp->destroyDisplay = NULL;
-
     if (!XF86DRIQueryExtension(dpy, &eventBase, &errorBase)) {
        return NULL;
     }
@@ -725,7 +860,7 @@ void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
        return NULL;
     }
 
-    pdpyp = (__DRIdisplayPrivate *)Xmalloc(sizeof(__DRIdisplayPrivate));
+    pdpyp = Xmalloc(sizeof *pdpyp);
     if (!pdpyp) {
        return NULL;
     }
@@ -734,9 +869,10 @@ void *driCreateDisplay(Display *dpy, __DRIdisplay *pdisp)
     pdpyp->driMinor = minor;
     pdpyp->driPatch = patch;
 
-    pdisp->destroyDisplay = driDestroyDisplay;
+    pdpyp->base.destroyDisplay = driDestroyDisplay;
+    pdpyp->base.createScreen = driCreateScreen;
 
-    return (void *)pdpyp;
+    return &pdpyp->base;
 }
 
 #endif /* GLX_DIRECT_RENDERING */