st/egl_g3d: Add support for probe to native displays.
authorChia-I Wu <olvaffe@gmail.com>
Wed, 20 Jan 2010 07:52:50 +0000 (15:52 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Wed, 20 Jan 2010 10:15:26 +0000 (18:15 +0800)
The functions can be used to check if a display is supported without
creating a struct native_display.  It uses a probe object that can be
shared across drivers.

src/gallium/state_trackers/egl_g3d/common/native.h
src/gallium/state_trackers/egl_g3d/kms/native_kms.c
src/gallium/state_trackers/egl_g3d/x11/native_x11.c
src/gallium/state_trackers/egl_g3d/x11/x11_screen.c
src/gallium/state_trackers/egl_g3d/x11/x11_screen.h

index f374f2e4a68930021a845ca80853b955648740a8..72a9cec7ef1ab830b8661de4108adbe23275607a 100644 (file)
@@ -47,6 +47,27 @@ enum native_attachment {
    NUM_NATIVE_ATTACHMENTS
 };
 
+/**
+ * Enumerations for probe results.
+ */
+enum native_probe_result {
+   NATIVE_PROBE_UNKNOWN,
+   NATIVE_PROBE_FALLBACK,
+   NATIVE_PROBE_SUPPORTED,
+   NATIVE_PROBE_EXACT,
+};
+
+/**
+ * A probe object for display probe.
+ */
+struct native_probe {
+   int magic;
+   EGLNativeDisplayType display;
+   void *data;
+
+   void (*destroy)(struct native_probe *nprobe);
+};
+
 struct native_surface {
    void (*destroy)(struct native_surface *nsurf);
 
@@ -231,6 +252,22 @@ native_attachment_mask_test(uint mask, enum native_attachment att)
    return !!(mask & (1 << att));
 }
 
+/**
+ * Return a probe object for the given display.
+ *
+ * Note that the returned object may be cached and used by different native
+ * display modules.  It allows fast probing when multiple modules probe the
+ * same display.
+ */
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy);
+
+/**
+ * Probe the probe object.
+ */
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe);
+
 const char *
 native_get_name(void);
 
index dc664366305bb39526798bdd1bc9d6ce2719cb38..d5baf2c2f0580aff128428f58ecee9b9498cfd49 100644 (file)
@@ -820,6 +820,18 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
    return &kdpy->base;
 }
 
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy)
+{
+   return NULL;
+}
+
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe)
+{
+   return NATIVE_PROBE_UNKNOWN;
+}
+
 /* the api is destroyed with the native display */
 static struct drm_api *drm_api;
 
index 583ce3d32932f5b7edb6b30b545600e73a0f0639..695ab88010b3c9683cf3b0c1bed8a26d8f45c0e4 100644 (file)
 
 #include <string.h>
 #include "util/u_debug.h"
+#include "util/u_memory.h"
 #include "state_tracker/drm_api.h"
 #include "egllog.h"
 
 #include "native_x11.h"
+#include "x11_screen.h"
+
+#define X11_PROBE_MAGIC 0x11980BE /* "X11PROBE" */
 
 static struct drm_api *api;
 
+static void
+x11_probe_destroy(struct native_probe *nprobe)
+{
+   if (nprobe->data)
+      free(nprobe->data);
+   free(nprobe);
+}
+
+struct native_probe *
+native_create_probe(EGLNativeDisplayType dpy)
+{
+   struct native_probe *nprobe;
+   struct x11_screen *xscr;
+   int scr;
+   const char *driver_name = NULL;
+   Display *xdpy;
+
+   nprobe = CALLOC_STRUCT(native_probe);
+   if (!nprobe)
+      return NULL;
+
+   xdpy = dpy;
+   if (!xdpy) {
+      xdpy = XOpenDisplay(NULL);
+      if (!xdpy) {
+         free(nprobe);
+         return NULL;
+      }
+   }
+
+   scr = DefaultScreen(xdpy);
+   xscr = x11_screen_create(xdpy, scr);
+   if (xscr) {
+      if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) {
+         driver_name = x11_screen_probe_dri2(xscr);
+         nprobe->data = strdup(driver_name);
+      }
+
+      x11_screen_destroy(xscr);
+   }
+
+   if (xdpy != dpy)
+      XCloseDisplay(xdpy);
+
+   nprobe->magic = X11_PROBE_MAGIC;
+   nprobe->display = dpy;
+
+   nprobe->destroy = x11_probe_destroy;
+
+   return nprobe;
+}
+
+enum native_probe_result
+native_get_probe_result(struct native_probe *nprobe)
+{
+   if (!nprobe || nprobe->magic != X11_PROBE_MAGIC)
+      return NATIVE_PROBE_UNKNOWN;
+
+   if (!api)
+      api = drm_api_create();
+
+   /* this is a software driver */
+   if (!api)
+      return NATIVE_PROBE_SUPPORTED;
+
+   /* the display does not support DRI2 or the driver mismatches */
+   if (!nprobe->data || strcmp(api->name, (const char *) nprobe->data) != 0)
+      return NATIVE_PROBE_FALLBACK;
+
+   return NATIVE_PROBE_EXACT;
+}
+
 const char *
 native_get_name(void)
 {
index 4d68a88d2e66ff529bd41eb1a48331271254bcbb..fef7878ab9aec149044b842b35df67d526f711cb 100644 (file)
@@ -249,6 +249,22 @@ 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)
+{
+   /* 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;
+   }
+
+   return xscr->dri_driver;
+}
+
 /**
  * Enable DRI2 and returns the file descriptor of the DRM device.  The file
  * descriptor will be closed automatically when the screen is destoryed.
@@ -261,13 +277,8 @@ x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver)
       drm_magic_t magic;
 
       /* get the driver name and the device name first */
-      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;
-            return -1;
-         }
-      }
+      if (!x11_screen_probe_dri2(xscr))
+         return -1;
 
       if (!x11_screen_is_driver_equal(xscr, driver)) {
          _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
index bf482189053296369f8dcc0fb97ee8432914722e..5432858ac3ea2e85d40a1789cb7c61cc7172f104 100644 (file)
@@ -70,6 +70,9 @@ x11_screen_get_glx_configs(struct x11_screen *xscr);
 const __GLcontextModes *
 x11_screen_get_glx_visuals(struct x11_screen *xscr);
 
+const char *
+x11_screen_probe_dri2(struct x11_screen *xscr);
+
 int
 x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver);