st/egl: Add native_surface::present callback.
[mesa.git] / src / gallium / state_trackers / egl / x11 / native_dri2.c
index 167115708cb0861c38c58a7a2cc64ffd285724f1..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,19 +232,22 @@ 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 &&
        memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
-      free(xbufs);
+      FREE(xbufs);
       dri2surf->client_stamp = dri2surf->server_stamp;
       return;
    }
@@ -244,7 +258,7 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
    dri2surf->client_stamp = dri2surf->server_stamp;
 
    if (dri2surf->last_xbufs)
-      free(dri2surf->last_xbufs);
+      FREE(dri2surf->last_xbufs);
    dri2surf->last_xbufs = 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,
@@ -379,7 +419,7 @@ dri2_surface_destroy(struct native_surface *nsurf)
    int i;
 
    if (dri2surf->last_xbufs)
-      free(dri2surf->last_xbufs);
+      FREE(dri2surf->last_xbufs);
 
    for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
       struct pipe_resource *ptex = dri2surf->textures[i];
@@ -393,7 +433,7 @@ dri2_surface_destroy(struct native_surface *nsurf)
       util_hash_table_remove(dri2surf->dri2dpy->surfaces,
             (void *) dri2surf->drawable);
    }
-   free(dri2surf);
+   FREE(dri2surf);
 }
 
 static struct dri2_surface *
@@ -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;
 
@@ -483,41 +524,11 @@ choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32])
    return count;
 }
 
-static int
-choose_depth_stencil_format(const __GLcontextModes *mode,
-                            enum pipe_format formats[32])
-{
-   int count = 0;
-
-   switch (mode->depthBits) {
-   case 32:
-      formats[count++] = PIPE_FORMAT_Z32_UNORM;
-      break;
-   case 24:
-      if (mode->stencilBits) {
-         formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_USCALED;
-         formats[count++] = PIPE_FORMAT_S8_USCALED_Z24_UNORM;
-      }
-      else {
-         formats[count++] = PIPE_FORMAT_Z24X8_UNORM;
-         formats[count++] = PIPE_FORMAT_X8Z24_UNORM;
-      }
-      break;
-   case 16:
-      formats[count++] = PIPE_FORMAT_Z16_UNORM;
-      break;
-   default:
-      break;
-   }
-
-   return count;
-}
-
 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);
 }
@@ -529,22 +540,15 @@ 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;
 
-   nconf->color_format = PIPE_FORMAT_NONE;
-   nconf->depth_format = PIPE_FORMAT_NONE;
-   nconf->stencil_format = PIPE_FORMAT_NONE;
-
    nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT;
    if (mode->doubleBufferMode)
       nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT;
@@ -557,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;
       }
@@ -565,19 +569,6 @@ dri2_display_convert_config(struct native_display *ndpy,
    if (nconf->color_format == PIPE_FORMAT_NONE)
       return FALSE;
 
-   /* choose depth/stencil format */
-   num_formats = choose_depth_stencil_format(mode, formats);
-   for (i = 0; i < num_formats; i++) {
-      if (is_format_supported(ndpy->screen, formats[i], FALSE)) {
-         nconf->depth_format = formats[i];
-         nconf->stencil_format = formats[i];
-         break;
-      }
-   }
-   if ((mode->depthBits && nconf->depth_format == PIPE_FORMAT_NONE) ||
-       (mode->stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE))
-      return FALSE;
-
    if (mode->drawableType & GLX_WINDOW_BIT)
       nconf->window_bit = TRUE;
    if (mode->drawableType & GLX_PIXMAP_BIT)
@@ -617,7 +608,7 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
          return NULL;
       num_modes = x11_context_modes_count(modes);
 
-      dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs));
+      dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs));
       if (!dri2dpy->configs)
          return NULL;
 
@@ -632,7 +623,7 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs)
       dri2dpy->num_configs = count;
    }
 
-   configs = malloc(dri2dpy->num_configs * sizeof(*configs));
+   configs = MALLOC(dri2dpy->num_configs * sizeof(*configs));
    if (configs) {
       for (i = 0; i < dri2dpy->num_configs; i++)
          configs[i] = (const struct native_config *) &dri2dpy->configs[i];
@@ -666,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;
@@ -683,7 +679,7 @@ dri2_display_destroy(struct native_display *ndpy)
    struct dri2_display *dri2dpy = dri2_display(ndpy);
 
    if (dri2dpy->configs)
-      free(dri2dpy->configs);
+      FREE(dri2dpy->configs);
 
    if (dri2dpy->base.screen)
       dri2dpy->base.screen->destroy(dri2dpy->base.screen);
@@ -695,9 +691,7 @@ 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);
+   FREE(dri2dpy);
 }
 
 static void
@@ -728,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) ||
@@ -740,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;
@@ -777,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;
 
@@ -788,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) {
@@ -828,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 */