Merge commit 'origin/7.8'
[mesa.git] / src / gallium / state_trackers / egl / x11 / x11_screen.c
index 76ce45ee574186efd7ea28c90ffa8bfc496ecd77..6bdff26ec08e198eae2b950b08634d08ce8b0df4 100644 (file)
  * The above copyright notice and this permission notice shall be included
  * in all copies or substantial portions of the Software.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  */
 
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <xf86drm.h>
 #include <X11/Xlibint.h>
 #include <X11/extensions/XShm.h>
+
 #include "util/u_memory.h"
-#include "util/u_math.h"
-#include "util/u_format.h"
-#include "xf86drm.h"
 #include "egllog.h"
 
 #include "x11_screen.h"
 #include "glxinit.h"
 
 struct x11_screen {
+   /* dummy base class */
+   struct __GLXDRIdisplayRec base;
+
    Display *dpy;
    int number;
 
    /*
-    * This is used to fetch GLX visuals/fbconfigs.  It uses code from egl_xdri.
+    * This is used to fetch GLX visuals/fbconfigs.  It steals code from GLX.
     * It might be better to rewrite the part in Xlib or XCB.
     */
    __GLXdisplayPrivate *glx_dpy;
@@ -53,6 +56,9 @@ struct x11_screen {
    char *dri_device;
    int dri_fd;
 
+   x11_drawable_invalidate_buffers dri_invalidate_buffers;
+   void *dri_user_data;
+
    XVisualInfo *visuals;
    int num_visuals;
 
@@ -98,10 +104,12 @@ x11_screen_destroy(struct x11_screen *xscr)
       Xfree(xscr->dri_device);
 
    /* xscr->glx_dpy will be destroyed with the X display */
+   if (xscr->glx_dpy)
+      xscr->glx_dpy->dri2Display = NULL;
 
    if (xscr->visuals)
       XFree(xscr->visuals);
-   free(xscr);
+   FREE(xscr);
 }
 
 static boolean
@@ -168,63 +176,6 @@ x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals)
    return xscr->visuals;
 }
 
-void
-x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual,
-                          __GLcontextModes *mode)
-{
-   int r, g, b, a;
-   int visual_type;
-
-   r = util_bitcount(visual->red_mask);
-   g = util_bitcount(visual->green_mask);
-   b = util_bitcount(visual->blue_mask);
-   a = visual->depth - (r + g + b);
-#if defined(__cplusplus) || defined(c_plusplus)
-   visual_type = visual->c_class;
-#else
-   visual_type = visual->class;
-#endif
-
-   /* convert to GLX visual type */
-   switch (visual_type) {
-   case TrueColor:
-      visual_type = GLX_TRUE_COLOR;
-      break;
-   case DirectColor:
-      visual_type = GLX_DIRECT_COLOR;
-      break;
-   case PseudoColor:
-      visual_type = GLX_PSEUDO_COLOR;
-      break;
-   case StaticColor:
-      visual_type = GLX_STATIC_COLOR;
-      break;
-   case GrayScale:
-      visual_type = GLX_GRAY_SCALE;
-      break;
-   case StaticGray:
-      visual_type = GLX_STATIC_GRAY;
-      break;
-   default:
-      visual_type = GLX_NONE;
-      break;
-   }
-
-   mode->rgbBits = r + g + b + a;
-   mode->redBits = r;
-   mode->greenBits = g;
-   mode->blueBits = b;
-   mode->alphaBits = a;
-   mode->visualID = visual->visualid;
-   mode->visualType = visual_type;
-
-   /* sane defaults */
-   mode->renderType = GLX_RGBA_BIT;
-   mode->rgbMode = TRUE;
-   mode->visualRating = GLX_SLOW_CONFIG;
-   mode->xRenderable = TRUE;
-}
-
 /**
  * Return the GLX fbconfigs.
  */
@@ -247,24 +198,25 @@ x11_screen_get_glx_visuals(struct x11_screen *xscr)
       : NULL;
 }
 
-static boolean
-x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver)
-{
-   return (strcmp(xscr->dri_driver, driver) == 0);
-}
-
 /**
  * Probe the screen for the DRI2 driver name.
  */
 const char *
-x11_screen_probe_dri2(struct x11_screen *xscr)
+x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor)
 {
+   if (!x11_screen_init_dri2(xscr))
+      return NULL;
+
    /* get the driver name and the device name */
    if (!xscr->dri_driver) {
       if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number),
                &xscr->dri_driver, &xscr->dri_device))
          xscr->dri_driver = xscr->dri_device = NULL;
    }
+   if (major)
+      *major = xscr->dri_major;
+   if (minor)
+      *minor = xscr->dri_minor;
 
    return xscr->dri_driver;
 }
@@ -274,21 +226,17 @@ x11_screen_probe_dri2(struct x11_screen *xscr)
  * descriptor will be closed automatically when the screen is destoryed.
  */
 int
-x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
+x11_screen_enable_dri2(struct x11_screen *xscr,
+                       x11_drawable_invalidate_buffers invalidate_buffers,
+                       void *user_data)
 {
    if (xscr->dri_fd < 0) {
       int fd;
       drm_magic_t magic;
 
       /* get the driver name and the device name first */
-      if (!x11_screen_probe_dri2(xscr))
-         return -1;
-
-      if (!x11_screen_is_driver_equal(xscr, driver)) {
-         _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
-               xscr->dri_driver, driver);
+      if (!x11_screen_probe_dri2(xscr, NULL, NULL))
          return -1;
-      }
 
       fd = open(xscr->dri_device, O_RDWR);
       if (fd < 0) {
@@ -310,6 +258,22 @@ x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
          return -1;
       }
 
+      if (!x11_screen_init_glx(xscr)) {
+         _eglLog(_EGL_WARNING, "failed to initialize GLX");
+         close(fd);
+         return -1;
+      }
+      if (xscr->glx_dpy->dri2Display) {
+         _eglLog(_EGL_WARNING,
+               "display is already managed by another x11 screen");
+         close(fd);
+         return -1;
+      }
+
+      xscr->glx_dpy->dri2Display = (__GLXDRIdisplay *) xscr;
+      xscr->dri_invalidate_buffers = invalidate_buffers;
+      xscr->dri_user_data = user_data;
+
       xscr->dri_fd = fd;
    }
 
@@ -414,7 +378,7 @@ x11_context_modes_create(unsigned count)
 
    next = &base;
    for (i = 0; i < count; i++) {
-      *next = (__GLcontextModes *) calloc(1, size);
+      *next = (__GLcontextModes *) CALLOC(1, size);
       if (*next == NULL) {
          x11_context_modes_destroy(base);
          base = NULL;
@@ -434,7 +398,7 @@ x11_context_modes_destroy(__GLcontextModes *modes)
 {
    while (modes != NULL) {
       __GLcontextModes *next = modes->next;
-      free(modes);
+      FREE(modes);
       modes = next;
    }
 }
@@ -451,3 +415,20 @@ x11_context_modes_count(const __GLcontextModes *modes)
       count++;
    return count;
 }
+
+/**
+ * This is called from src/glx/dri2.c.
+ */
+void
+dri2InvalidateBuffers(Display *dpy, XID drawable)
+{
+   __GLXdisplayPrivate *priv = __glXInitialize(dpy);
+   struct x11_screen *xscr = NULL;
+
+   if (priv && priv->dri2Display)
+      xscr = (struct x11_screen *) priv->dri2Display;
+   if (!xscr || !xscr->dri_invalidate_buffers)
+      return;
+
+   xscr->dri_invalidate_buffers(xscr, drawable, xscr->dri_user_data);
+}