Mesa (master): st/egl_g3d: Use a sequence number to decide if validation is required.

Chia-I Wu olv at kemper.freedesktop.org
Thu Jan 14 09:37:22 UTC 2010


Module: Mesa
Branch: master
Commit: 6cb89b23eeac50cfb0c5fb8d77e19f869b524eac
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=6cb89b23eeac50cfb0c5fb8d77e19f869b524eac

Author: Chia-I Wu <olvaffe at gmail.com>
Date:   Tue Jan 12 18:08:02 2010 +0800

st/egl_g3d: Use a sequence number to decide if validation is required.

It is not safe to assume that the native surface has not changed since
the last validation by checking the geometry alone.  Add a sequence
number to "validate" callback for that purpose.  This is inspired by
Luca Barbieri's work.

---

 .../state_trackers/egl_g3d/common/egl_g3d.c        |   35 +++++++++++++-------
 .../state_trackers/egl_g3d/common/egl_g3d.h        |    1 +
 src/gallium/state_trackers/egl_g3d/common/native.h |    7 ++--
 .../state_trackers/egl_g3d/kms/native_kms.c        |    9 ++++-
 .../state_trackers/egl_g3d/kms/native_kms.h        |    1 +
 .../state_trackers/egl_g3d/x11/native_dri2.c       |   20 +++++++++--
 .../state_trackers/egl_g3d/x11/native_ximage.c     |   14 +++++++-
 7 files changed, 66 insertions(+), 21 deletions(-)

diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
index 741e5b4..9d5734d 100644
--- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
@@ -63,22 +63,19 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
       }
 
       if (!gctx->force_validate) {
-         EGLint cur_w, cur_h;
+         unsigned int seq_num;
 
-         cur_w = gsurf->base.Width;
-         cur_h = gsurf->base.Height;
          gsurf->native->validate(gsurf->native,
                gbuf->native_atts, gbuf->num_atts,
-               NULL,
-               &gsurf->base.Width, &gsurf->base.Height);
-         /* validate only when the geometry changed */
-         if (gsurf->base.Width == cur_w && gsurf->base.Height == cur_h)
+               &seq_num, NULL, NULL, NULL);
+         /* skip validation */
+         if (gsurf->sequence_number == seq_num)
             continue;
       }
 
       gsurf->native->validate(gsurf->native,
             gbuf->native_atts, gbuf->num_atts,
-            (struct pipe_texture **) textures,
+            &gsurf->sequence_number, textures,
             &gsurf->base.Width, &gsurf->base.Height);
       for (i = 0; i < gbuf->num_atts; i++) {
          struct pipe_texture *pt = textures[i];
@@ -599,6 +596,16 @@ egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
    return EGL_TRUE;
 }
 
+static EGLBoolean
+init_surface_geometry(_EGLSurface *surf)
+{
+   struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
+
+   return gsurf->native->validate(gsurf->native, NULL, 0,
+         &gsurf->sequence_number, NULL,
+         &gsurf->base.Width, &gsurf->base.Height);
+}
+
 static _EGLSurface *
 egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
                               _EGLConfig *conf, EGLNativeWindowType win,
@@ -626,8 +633,7 @@ egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL,
-            &gsurf->base.Width, &gsurf->base.Height)) {
+   if (!init_surface_geometry(&gsurf->base)) {
       gsurf->native->destroy(gsurf->native);
       free(gsurf);
       return NULL;
@@ -667,8 +673,7 @@ egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
-   if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL,
-            &gsurf->base.Width, &gsurf->base.Height)) {
+   if (!init_surface_geometry(&gsurf->base)) {
       gsurf->native->destroy(gsurf->native);
       free(gsurf);
       return NULL;
@@ -706,6 +711,12 @@ egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy,
       return NULL;
    }
 
+   if (!init_surface_geometry(&gsurf->base)) {
+      gsurf->native->destroy(gsurf->native);
+      free(gsurf);
+      return NULL;
+   }
+
    gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ?
       NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT;
 
diff --git a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
index 33894b6..4c8b8df 100644
--- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
@@ -73,6 +73,7 @@ struct egl_g3d_surface {
    struct native_surface *native;
    enum native_attachment render_att;
    struct pipe_surface *render_surface;
+   unsigned int sequence_number;
 };
 
 struct egl_g3d_config {
diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h b/src/gallium/state_trackers/egl_g3d/common/native.h
index 5ddcf67..4714e24 100644
--- a/src/gallium/state_trackers/egl_g3d/common/native.h
+++ b/src/gallium/state_trackers/egl_g3d/common/native.h
@@ -65,8 +65,9 @@ struct native_surface {
 
    /**
     * Validate the buffers of the surface.  The returned textures are owned by
-    * the caller.  It is possible that this function is called with textures,
-    * width, or height being NULL.
+    * the caller.  A sequence number is also returned.  The caller can use it
+    * to check if anything has changed since the last call. Any of the pointers
+    * may be NULL and it indicates the caller has no interest in those values.
     *
     * If this function is called multiple times with different attachments,
     * those not listed in the latest call might be destroyed.  This behavior
@@ -75,7 +76,7 @@ struct native_surface {
    boolean (*validate)(struct native_surface *nsurf,
                        const enum native_attachment *natts,
                        unsigned num_natts,
-                       struct pipe_texture **textures,
+                       unsigned int *seq_num, struct pipe_texture **textures,
                        int *width, int *height);
 
    /**
diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c
index 0e0babd..a44b9b9 100644
--- a/src/gallium/state_trackers/egl_g3d/kms/native_kms.c
+++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.c
@@ -36,7 +36,7 @@ static boolean
 kms_surface_validate(struct native_surface *nsurf,
                      const enum native_attachment *natts,
                      unsigned num_natts,
-                     struct pipe_texture **textures,
+                     unsigned int *seq_num, struct pipe_texture **textures,
                      int *width, int *height)
 {
    struct kms_surface *ksurf = kms_surface(nsurf);
@@ -75,6 +75,8 @@ kms_surface_validate(struct native_surface *nsurf,
          pipe_texture_reference(&textures[i], ptex);
    }
 
+   if (seq_num)
+      *seq_num = ksurf->sequence_number;
    if (width)
       *width = ksurf->width;
    if (height)
@@ -111,7 +113,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
 
       if (!fb->texture) {
          /* make sure the texture has been allocated */
-         kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL);
+         kms_surface_validate(&ksurf->base, &natt, 1, NULL, NULL, NULL, NULL);
          if (!ksurf->textures[natt])
             return FALSE;
 
@@ -196,6 +198,9 @@ kms_surface_swap_buffers(struct native_surface *nsurf)
       ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
    ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
 
+   /* the front/back textures are swapped */
+   ksurf->sequence_number++;
+
    return TRUE;
 }
 
diff --git a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h
index 3f869b2..095186e 100644
--- a/src/gallium/state_trackers/egl_g3d/kms/native_kms.h
+++ b/src/gallium/state_trackers/egl_g3d/kms/native_kms.h
@@ -81,6 +81,7 @@ struct kms_surface {
    int width, height;
 
    struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
+   unsigned int sequence_number;
    struct kms_framebuffer front_fb, back_fb;
 
    boolean is_shown;
diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
index 0dda786..2192a13 100644
--- a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
@@ -64,6 +64,7 @@ struct dri2_surface {
    struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS];
    boolean have_back, have_fake;
    int width, height;
+   unsigned int sequence_number;
 };
 
 struct dri2_config {
@@ -136,6 +137,7 @@ static boolean
 dri2_surface_validate(struct native_surface *nsurf,
                              const enum native_attachment *natts,
                              unsigned num_natts,
+                             unsigned int *seq_num,
                              struct pipe_texture **textures,
                              int *width, int *height)
 {
@@ -178,6 +180,8 @@ dri2_surface_validate(struct native_surface *nsurf,
             pipe_texture_reference(&textures[i], ptex);
       }
 
+      if (seq_num)
+         *seq_num = dri2surf->sequence_number;
       if (width)
          *width = dri2surf->width;
       if (height)
@@ -219,15 +223,23 @@ dri2_surface_validate(struct native_surface *nsurf,
    dri2surf->have_back = FALSE;
    dri2surf->have_fake = FALSE;
 
+   /* remember old geometry */
+   templ.width0 = dri2surf->width;
+   templ.height0 = dri2surf->height;
+
    xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
                                     &dri2surf->width, &dri2surf->height,
                                     dri2atts, FALSE, num_ins, &num_outs);
    if (!xbufs)
       return FALSE;
 
-   /* update width and height */
-   templ.width0 = dri2surf->width;
-   templ.height0 = dri2surf->height;
+   if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) {
+      /* are there cases where the buffers change and the geometry doesn't? */
+      dri2surf->sequence_number++;
+
+      templ.width0 = dri2surf->width;
+      templ.height0 = dri2surf->height;
+   }
 
    for (i = 0; i < num_outs; i++) {
       struct x11_drawable_buffer *xbuf = &xbufs[i];
@@ -279,6 +291,8 @@ dri2_surface_validate(struct native_surface *nsurf,
 
    free(xbufs);
 
+   if (seq_num)
+      *seq_num = dri2surf->sequence_number;
    if (width)
       *width = dri2surf->width;
    if (height)
diff --git a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
index e02faa9..1a1844e 100644
--- a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
@@ -83,6 +83,7 @@ struct ximage_surface {
    GC gc;
 
    struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
+   unsigned int sequence_number;
 };
 
 struct ximage_config {
@@ -260,6 +261,9 @@ ximage_surface_swap_buffers(struct native_surface *nsurf)
    *xfront = *xback;
    *xback = xtmp;
 
+   /* the front/back textures are swapped */
+   xsurf->sequence_number++;
+
    return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
 }
 
@@ -288,11 +292,12 @@ static boolean
 ximage_surface_validate(struct native_surface *nsurf,
                                const enum native_attachment *natts,
                                unsigned num_natts,
+                               unsigned int *seq_num,
                                struct pipe_texture **textures,
                                int *width, int *height)
 {
    struct ximage_surface *xsurf = ximage_surface(nsurf);
-   boolean error = FALSE;
+   boolean new_buffers = FALSE, error = FALSE;
    unsigned i;
 
    ximage_surface_update_geometry(&xsurf->base);
@@ -311,6 +316,7 @@ ximage_surface_validate(struct native_surface *nsurf,
       if (!xbuf->texture ||
           xsurf->width != xbuf->texture->width0 ||
           xsurf->height != xbuf->texture->height0) {
+         new_buffers = TRUE;
          if (ximage_surface_alloc_buffer(&xsurf->base, natt)) {
             /* update ximage */
             if (xbuf->ximage) {
@@ -336,6 +342,12 @@ ximage_surface_validate(struct native_surface *nsurf,
          pipe_texture_reference(&textures[i], xbuf->texture);
    }
 
+   /* increase the sequence number so that caller knows */
+   if (new_buffers)
+      xsurf->sequence_number++;
+
+   if (seq_num)
+      *seq_num = xsurf->sequence_number;
    if (width)
       *width = xsurf->width;
    if (height)




More information about the mesa-commit mailing list