st/egl: reorganize backend initialization
[mesa.git] / src / gallium / state_trackers / egl / x11 / native_dri2.c
index d37f66da07e479c9cfff82a725a8b0000f117951..2a3a1062544213ce33a18c425c3d09f79126f633 100644 (file)
 #include "pipe/p_screen.h"
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
-#include "state_tracker/drm_api.h"
+#include "state_tracker/drm_driver.h"
 #include "egllog.h"
 
 #include "native_x11.h"
 #include "x11_screen.h"
 
-enum dri2_surface_type {
-   DRI2_SURFACE_TYPE_WINDOW,
-   DRI2_SURFACE_TYPE_PIXMAP,
-};
+#ifdef HAVE_WAYLAND_BACKEND
+#include "common/native_wayland_drm_bufmgr_helper.h"
+#endif
+
+#ifdef GLX_DIRECT_RENDERING
 
 struct dri2_display {
    struct native_display base;
    Display *dpy;
    boolean own_dpy;
 
-   struct native_event_handler *event_handler;
+   const struct native_event_handler *event_handler;
 
-   struct drm_api *api;
    struct x11_screen *xscr;
    int xscr_number;
    const char *dri_driver;
@@ -60,12 +60,14 @@ struct dri2_display {
    int num_configs;
 
    struct util_hash_table *surfaces;
+#ifdef HAVE_WAYLAND_BACKEND
+   struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */
+#endif
 };
 
 struct dri2_surface {
    struct native_surface base;
    Drawable drawable;
-   enum dri2_surface_type type;
    enum pipe_format color_format;
    struct dri2_display *dri2dpy;
 
@@ -135,6 +137,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
    templ.width0 = dri2surf->width;
    templ.height0 = dri2surf->height;
    templ.depth0 = 1;
+   templ.array_size = 1;
    templ.format = dri2surf->color_format;
    templ.bind = PIPE_BIND_RENDER_TARGET;
 
@@ -336,6 +339,32 @@ dri2_surface_swap_buffers(struct native_surface *nsurf)
    return TRUE;
 }
 
+static boolean
+dri2_surface_present(struct native_surface *nsurf,
+                     enum native_attachment natt,
+                     boolean preserve,
+                     uint swap_interval)
+{
+   boolean ret;
+
+   if (swap_interval)
+      return FALSE;
+
+   switch (natt) {
+   case NATIVE_ATTACHMENT_FRONT_LEFT:
+      ret = dri2_surface_flush_frontbuffer(nsurf);
+      break;
+   case NATIVE_ATTACHMENT_BACK_LEFT:
+      ret = dri2_surface_swap_buffers(nsurf);
+      break;
+   default:
+      ret = FALSE;
+      break;
+   }
+
+   return ret;
+}
+
 static boolean
 dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
                       unsigned int *seq_num, struct pipe_resource **textures,
@@ -411,12 +440,10 @@ dri2_surface_destroy(struct native_surface *nsurf)
 
 static struct dri2_surface *
 dri2_display_create_surface(struct native_display *ndpy,
-                            enum dri2_surface_type type,
                             Drawable drawable,
-                            const struct native_config *nconf)
+                            enum pipe_format color_format)
 {
    struct dri2_display *dri2dpy = dri2_display(ndpy);
-   struct dri2_config *dri2conf = dri2_config(nconf);
    struct dri2_surface *dri2surf;
 
    dri2surf = CALLOC_STRUCT(dri2_surface);
@@ -424,13 +451,11 @@ dri2_display_create_surface(struct native_display *ndpy,
       return NULL;
 
    dri2surf->dri2dpy = dri2dpy;
-   dri2surf->type = type;
    dri2surf->drawable = drawable;
-   dri2surf->color_format = dri2conf->base.color_format;
+   dri2surf->color_format = color_format;
 
    dri2surf->base.destroy = dri2_surface_destroy;
-   dri2surf->base.swap_buffers = dri2_surface_swap_buffers;
-   dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer;
+   dri2surf->base.present = dri2_surface_present;
    dri2surf->base.validate = dri2_surface_validate;
    dri2surf->base.wait = dri2_surface_wait;
 
@@ -453,8 +478,8 @@ dri2_display_create_window_surface(struct native_display *ndpy,
 {
    struct dri2_surface *dri2surf;
 
-   dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_WINDOW,
-         (Drawable) win, nconf);
+   dri2surf = dri2_display_create_surface(ndpy,
+         (Drawable) win, nconf->color_format);
    return (dri2surf) ? &dri2surf->base : NULL;
 }
 
@@ -465,8 +490,29 @@ dri2_display_create_pixmap_surface(struct native_display *ndpy,
 {
    struct dri2_surface *dri2surf;
 
-   dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PIXMAP,
-         (Drawable) pix, nconf);
+   if (!nconf) {
+      struct dri2_display *dri2dpy = dri2_display(ndpy);
+      uint depth, nconf_depth;
+      int i;
+
+      depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix);
+      for (i = 0; i < dri2dpy->num_configs; i++) {
+         nconf_depth = util_format_get_blocksizebits(
+               dri2dpy->configs[i].base.color_format);
+         /* simple depth match for now */
+         if (depth == nconf_depth ||
+             (depth == 24 && depth + 8 == nconf_depth)) {
+            nconf = &dri2dpy->configs[i].base;
+            break;
+         }
+      }
+
+      if (!nconf)
+         return NULL;
+   }
+
+   dri2surf = dri2_display_create_surface(ndpy,
+         (Drawable) pix, nconf->color_format);
    return (dri2surf) ? &dri2surf->base : NULL;
 }
 
@@ -498,11 +544,11 @@ choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
 
 static boolean
 is_format_supported(struct pipe_screen *screen,
-                    enum pipe_format fmt, boolean is_color)
+                    enum pipe_format fmt, unsigned sample_count, boolean is_color)
 {
-   return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
+   return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count,
          (is_color) ? PIPE_BIND_RENDER_TARGET :
-         PIPE_BIND_DEPTH_STENCIL, 0);
+         PIPE_BIND_DEPTH_STENCIL);
 }
 
 static boolean
@@ -512,18 +558,19 @@ dri2_display_convert_config(struct native_display *ndpy,
 {
    enum pipe_format formats[32];
    int num_formats, i;
+   int sample_count = 0;
 
    if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode)
       return FALSE;
 
-   /* skip single-buffered configs */
-   if (!mode->doubleBufferMode)
-      return FALSE;
-
    /* only interested in native renderable configs */
    if (!mode->xRenderable || !mode->drawableType)
       return FALSE;
 
+   /* fast/slow configs are probably not relevant */
+   if (mode->visualRating == GLX_SLOW_CONFIG)
+      return FALSE;
+
    nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
    if (mode->doubleBufferMode)
       nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
@@ -536,7 +583,7 @@ dri2_display_convert_config(struct native_display *ndpy,
    /* choose color format */
    num_formats = choose_color_format(mode, formats);
    for (i = 0; i < num_formats; i++) {
-      if (is_format_supported(ndpy->screen, formats[i], TRUE)) {
+      if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) {
          nconf->color_format = formats[i];
          break;
       }
@@ -544,17 +591,33 @@ dri2_display_convert_config(struct native_display *ndpy,
    if (nconf->color_format == PIPE_FORMAT_NONE)
       return FALSE;
 
-   if (mode->drawableType & GLX_WINDOW_BIT)
+   if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID)
       nconf->window_bit = TRUE;
    if (mode->drawableType & GLX_PIXMAP_BIT)
       nconf->pixmap_bit = TRUE;
 
    nconf->native_visual_id = mode->visualID;
-   nconf->native_visual_type = mode->visualType;
+   switch (mode->visualType) {
+   case GLX_TRUE_COLOR:
+      nconf->native_visual_type = TrueColor;
+      break;
+   case GLX_DIRECT_COLOR:
+      nconf->native_visual_type = DirectColor;
+      break;
+   case GLX_PSEUDO_COLOR:
+      nconf->native_visual_type = PseudoColor;
+      break;
+   case GLX_STATIC_COLOR:
+      nconf->native_visual_type = StaticColor;
+      break;
+   case GLX_GRAY_SCALE:
+      nconf->native_visual_type = GrayScale;
+      break;
+   case GLX_STATIC_GRAY:
+      nconf->native_visual_type = StaticGray;
+      break;
+   }
    nconf->level = mode->level;
-   nconf->samples = mode->samples;
-
-   nconf->slow_config = (mode->visualRating == GLX_SLOW_CONFIG);
 
    if (mode->transparentPixel == GLX_TRANSPARENT_RGB) {
       nconf->transparent_rgb = TRUE;
@@ -590,8 +653,17 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
       count = 0;
       for (i = 0; i < num_modes; i++) {
          struct native_config *nconf = &dri2dpy->configs[count].base;
-         if (dri2_display_convert_config(&dri2dpy->base, modes, nconf))
-            count++;
+
+         if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) {
+            int j;
+            /* look for duplicates */
+            for (j = 0; j < count; j++) {
+               if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0)
+                  break;
+            }
+            if (j == count)
+               count++;
+         }
          modes = modes->next;
       }
 
@@ -632,9 +704,14 @@ dri2_display_get_param(struct native_display *ndpy,
 
    switch (param) {
    case NATIVE_PARAM_USE_NATIVE_BUFFER:
-      /* DRI2GetBuffers use the native buffers */
+      /* DRI2GetBuffers uses the native buffers */
+      val = TRUE;
+      break;
+   case NATIVE_PARAM_PRESERVE_BUFFER:
+      /* DRI2CopyRegion is used */
       val = TRUE;
       break;
+   case NATIVE_PARAM_MAX_SWAP_INTERVAL:
    default:
       val = 0;
       break;
@@ -661,8 +738,6 @@ dri2_display_destroy(struct native_display *ndpy)
       x11_screen_destroy(dri2dpy->xscr);
    if (dri2dpy->own_dpy)
       XCloseDisplay(dri2dpy->dpy);
-   if (dri2dpy->api && dri2dpy->api->destroy)
-      dri2dpy->api->destroy(dri2dpy->api);
    FREE(dri2dpy);
 }
 
@@ -694,7 +769,6 @@ static boolean
 dri2_display_init_screen(struct native_display *ndpy)
 {
    struct dri2_display *dri2dpy = dri2_display(ndpy);
-   const char *driver = dri2dpy->api->name;
    int fd;
 
    if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
@@ -705,21 +779,17 @@ dri2_display_init_screen(struct native_display *ndpy)
 
    dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr,
          &dri2dpy->dri_major, &dri2dpy->dri_minor);
-   if (!dri2dpy->dri_driver || !driver ||
-       strcmp(dri2dpy->dri_driver, driver) != 0) {
-      _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s",
-            dri2dpy->dri_driver, dri2dpy->api->name);
-      return FALSE;
-   }
 
    fd = x11_screen_enable_dri2(dri2dpy->xscr,
          dri2_display_invalidate_buffers, &dri2dpy->base);
    if (fd < 0)
       return FALSE;
 
-   dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, NULL);
+   dri2dpy->base.screen =
+      dri2dpy->event_handler->new_drm_screen(&dri2dpy->base,
+            dri2dpy->dri_driver, fd);
    if (!dri2dpy->base.screen) {
-      _eglLog(_EGL_WARNING, "failed to create DRM screen");
+      _eglLog(_EGL_DEBUG, "failed to create DRM screen");
       return FALSE;
    }
 
@@ -736,13 +806,71 @@ dri2_display_hash_table_hash(void *key)
 static int
 dri2_display_hash_table_compare(void *key1, void *key2)
 {
-   return (key1 - key2);
+   return ((char *) key1 - (char *) key2);
 }
 
+static int
+dri2_display_authenticate(void *user_data, uint32_t magic)
+{
+   struct native_display *ndpy = user_data;
+   struct dri2_display *dri2dpy = dri2_display(ndpy);
+
+   return x11_screen_authenticate(dri2dpy->xscr, magic);
+}
+
+#ifdef HAVE_WAYLAND_BACKEND
+
+static struct wayland_drm_callbacks wl_drm_callbacks = {
+   dri2_display_authenticate,
+   egl_g3d_wl_drm_helper_reference_buffer,
+   egl_g3d_wl_drm_helper_unreference_buffer
+};
+
+static boolean
+dri2_display_bind_wayland_display(struct native_display *ndpy,
+                                  struct wl_display *wl_dpy)
+{
+   struct dri2_display *dri2dpy = dri2_display(ndpy);
+
+   if (dri2dpy->wl_server_drm)
+      return FALSE;
+
+   dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy,
+         x11_screen_get_device_name(dri2dpy->xscr),
+         &wl_drm_callbacks, ndpy);
+
+   if (!dri2dpy->wl_server_drm)
+      return FALSE;
+   
+   return TRUE;
+}
+
+static boolean
+dri2_display_unbind_wayland_display(struct native_display *ndpy,
+                                    struct wl_display *wl_dpy)
+{
+   struct dri2_display *dri2dpy = dri2_display(ndpy);
+
+   if (!dri2dpy->wl_server_drm)
+      return FALSE;
+
+   wayland_drm_uninit(dri2dpy->wl_server_drm);
+   dri2dpy->wl_server_drm = NULL;
+
+   return TRUE;
+}
+
+static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = {
+   dri2_display_bind_wayland_display,
+   dri2_display_unbind_wayland_display,
+   egl_g3d_wl_drm_common_wl_buffer_get_resource
+};
+
+#endif /* HAVE_WAYLAND_BACKEND */
+
 struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy,
-                        struct native_event_handler *event_handler,
-                        struct drm_api *api)
+x11_create_dri2_display(Display *dpy,
+                        const struct native_event_handler *event_handler)
 {
    struct dri2_display *dri2dpy;
 
@@ -751,7 +879,6 @@ x11_create_dri2_display(EGLNativeDisplayType dpy,
       return NULL;
 
    dri2dpy->event_handler = event_handler;
-   dri2dpy->api = api;
 
    dri2dpy->dpy = dpy;
    if (!dri2dpy->dpy) {
@@ -770,11 +897,6 @@ x11_create_dri2_display(EGLNativeDisplayType dpy,
       return NULL;
    }
 
-   if (!dri2_display_init_screen(&dri2dpy->base)) {
-      dri2_display_destroy(&dri2dpy->base);
-      return NULL;
-   }
-
    dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash,
          dri2_display_hash_table_compare);
    if (!dri2dpy->surfaces) {
@@ -782,12 +904,28 @@ x11_create_dri2_display(EGLNativeDisplayType dpy,
       return NULL;
    }
 
+   dri2dpy->base.init_screen = dri2_display_init_screen;
    dri2dpy->base.destroy = dri2_display_destroy;
    dri2dpy->base.get_param = dri2_display_get_param;
    dri2dpy->base.get_configs = dri2_display_get_configs;
    dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported;
    dri2dpy->base.create_window_surface = dri2_display_create_window_surface;
    dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface;
+#ifdef HAVE_WAYLAND_BACKEND
+   dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr;
+#endif
 
    return &dri2dpy->base;
 }
+
+#else /* GLX_DIRECT_RENDERING */
+
+struct native_display *
+x11_create_dri2_display(Display *dpy,
+                        struct native_event_handler *event_handler,
+                        void *user_data)
+{
+   return NULL;
+}
+
+#endif /* GLX_DIRECT_RENDERING */