st/egl: Add native_surface::present callback.
[mesa.git] / src / gallium / state_trackers / egl / x11 / native_dri2.c
index d77b9b94943ceff477cf34e5d5625afa6f93eba4..a8df58a076d87b234a22c7cfa580e1b36d6c5ae2 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"
 
+#ifdef GLX_DIRECT_RENDERING
+
 enum dri2_surface_type {
    DRI2_SURFACE_TYPE_WINDOW,
    DRI2_SURFACE_TYPE_PIXMAP,
@@ -50,7 +52,6 @@ struct dri2_display {
 
    struct native_event_handler *event_handler;
 
-   struct drm_api *api;
    struct x11_screen *xscr;
    int xscr_number;
    const char *dri_driver;
@@ -192,9 +193,19 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
 {
    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
-   unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
+   unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
    int num_ins, num_outs, att;
    struct x11_drawable_buffer *xbufs;
+   uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
+   boolean with_format = FALSE; /* never ask for depth/stencil */
+
+   /* We must get the front on servers which doesn't support with format
+    * due to a silly bug in core dri2. You can't copy to/from a buffer
+    * that you haven't requested and you recive BadValue errors */
+   if (dri2surf->dri2dpy->dri_minor < 1) {
+      with_format = FALSE;
+      buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
+   }
 
    /* prepare the attachments */
    num_ins = 0;
@@ -221,14 +232,17 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
             break;
          }
 
-         dri2atts[num_ins] = dri2att;
-         num_ins++;
+         dri2atts[num_ins++] = dri2att;
+         if (with_format)
+            dri2atts[num_ins++] = bpp;
       }
    }
+   if (with_format)
+      num_ins /= 2;
 
    xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
                                     &dri2surf->width, &dri2surf->height,
-                                    dri2atts, FALSE, num_ins, &num_outs);
+                                    dri2atts, with_format, num_ins, &num_outs);
 
    /* we should be able to do better... */
    if (xbufs && dri2surf->last_num_xbufs == num_outs &&
@@ -323,6 +337,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,
@@ -418,6 +458,7 @@ dri2_display_create_surface(struct native_display *ndpy,
    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;
 
@@ -485,9 +526,9 @@ 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);
 }
@@ -499,14 +540,11 @@ 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;
@@ -523,7 +561,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;
       }
@@ -619,9 +657,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;
@@ -648,8 +691,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);
 }
 
@@ -681,8 +722,6 @@ static boolean
 dri2_display_init_screen(struct native_display *ndpy)
 {
    struct dri2_display *dri2dpy = dri2_display(ndpy);
-   const char *driver = dri2dpy->api->name;
-   struct drm_create_screen_arg arg;
    int fd;
 
    if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) ||
@@ -693,21 +732,15 @@ 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;
 
-   memset(&arg, 0, sizeof(arg));
-   arg.mode = DRM_CREATE_NORMAL;
-   dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg);
+   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");
       return FALSE;
@@ -730,9 +763,9 @@ dri2_display_hash_table_compare(void *key1, void *key2)
 }
 
 struct native_display *
-x11_create_dri2_display(EGLNativeDisplayType dpy,
+x11_create_dri2_display(Display *dpy,
                         struct native_event_handler *event_handler,
-                        struct drm_api *api)
+                        void *user_data)
 {
    struct dri2_display *dri2dpy;
 
@@ -741,7 +774,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy,
       return NULL;
 
    dri2dpy->event_handler = event_handler;
-   dri2dpy->api = api;
+   dri2dpy->base.user_data = user_data;
 
    dri2dpy->dpy = dpy;
    if (!dri2dpy->dpy) {
@@ -781,3 +814,15 @@ x11_create_dri2_display(EGLNativeDisplayType dpy,
 
    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 */