The current code revalidates based on whether width or height have changed.
This is unreliable (it may change two times, with another context having got 
the buffers for the intermediate size in the meantime) and causes two DRI2 
calls.
Instead, we add the notion of a drawable sequence number, which tracks the 
number of times the surface textures have changed.
This sequence number, along with a pointer to the surface, is stored in 
egl_g3d_buffer and is passed to ->validate.

->validate for DRI2 updates an internal sequence number if the width or height 
changed.
If it did not change, it checks whether it matches the one provided by the 
client and, if so, does not return any texture.
Otherwise, it proceeds as normal.

If context validation is being forced, the sequence numbers are reset to 0 to 
force it.
---
 .../state_trackers/egl_g3d/common/egl_g3d.c        |   32 +++++++---------
 .../state_trackers/egl_g3d/common/egl_g3d.h        |    2 +
 src/gallium/state_trackers/egl_g3d/common/native.h |    4 ++-
 .../state_trackers/egl_g3d/x11/native_dri2.c       |   28 ++++++++++----
 .../state_trackers/egl_g3d/x11/native_ximage.c     |   39 +++++++++++++-------
 5 files changed, 65 insertions(+), 40 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 d68f49e..480f5a7 100644
--- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
@@ -47,11 +47,11 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
    EGLint s, i;
 
    /* validate draw and/or read buffers */
-   num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
-   for (s = 0; s < num_surfaces; s++) {
+   for (s = 0; s < 2; s++) {
       struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
       struct egl_g3d_surface *gsurf;
       struct egl_g3d_buffer *gbuf;
+      int cur_seq_num;
 
       if (s == 0) {
          gsurf = egl_g3d_surface(gctx->base.DrawSurface);
@@ -62,24 +62,20 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
          gbuf = &gctx->read;
       }
 
-      if (!gctx->force_validate) {
-         EGLint cur_w, cur_h;
-
-         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)
-            continue;
-      }
+      if (gctx->force_validate || gsurf != gbuf->surface)
+         gbuf->seq_num = 0;
+      cur_seq_num = gbuf->seq_num;
 
       gsurf->native->validate(gsurf->native,
             gbuf->native_atts, gbuf->num_atts,
             (struct pipe_texture **) textures,
-            &gsurf->base.Width, &gsurf->base.Height);
+            &gsurf->base.Width, &gsurf->base.Height, &gbuf->seq_num);
+
+      if(gbuf->seq_num == cur_seq_num)
+         continue;
+
+      gbuf->surface = gsurf;
+
       for (i = 0; i < gbuf->num_atts; i++) {
          struct pipe_texture *pt = textures[i];
          struct pipe_surface *ps;
@@ -538,7 +534,7 @@ egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay 
*dpy,
    }
 
    if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL,
-            &gsurf->base.Width, &gsurf->base.Height)) {
+            &gsurf->base.Width, &gsurf->base.Height, 0)) {
       gsurf->native->destroy(gsurf->native);
       free(gsurf);
       return NULL;
@@ -579,7 +575,7 @@ egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay 
*dpy,
    }
 
    if (!gsurf->native->validate(gsurf->native, NULL, 0, NULL,
-            &gsurf->base.Width, &gsurf->base.Height)) {
+            &gsurf->base.Width, &gsurf->base.Height, 0)) {
       gsurf->native->destroy(gsurf->native);
       free(gsurf);
       return NULL;
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 7f6823f..223b881 100644
--- a/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
+++ b/src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
@@ -51,6 +51,8 @@ struct egl_g3d_display {
 
 struct egl_g3d_buffer {
    struct st_framebuffer *st_fb;
+   struct egl_g3d_surface* surface;
+   int seq_num;
    EGLint num_atts;
    enum native_attachment native_atts[NUM_NATIVE_ATTACHMENTS];
    uint st_atts[NUM_NATIVE_ATTACHMENTS];
diff --git a/src/gallium/state_trackers/egl_g3d/common/native.h 
b/src/gallium/state_trackers/egl_g3d/common/native.h
index a59ceac..24cc506 100644
--- a/src/gallium/state_trackers/egl_g3d/common/native.h
+++ b/src/gallium/state_trackers/egl_g3d/common/native.h
@@ -67,12 +67,14 @@ struct native_surface {
    /**
     * Validate the buffers of the surface.  Those not listed in the attachments
     * will be destroyed.  The returned textures are owned by the caller.
+    * If *seq_num is not 0, it will do nothing if the surface sequence number
+    * did not change. The current sequence number will be returned.
     */
    boolean (*validate)(struct native_surface *nsurf,
                        const enum native_attachment *natts,
                        unsigned num_natts,
                        struct pipe_texture **textures,
-                       int *width, int *height);
+                       int *width, int *height, int* seq_num);
 
    /**
     * Wait until all native commands affecting the surface has been executed.
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 890e11d..e38695b 100644
--- a/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
@@ -67,6 +67,7 @@ struct dri2_surface {
    unsigned names[NUM_NATIVE_ATTACHMENTS];
    boolean have_back, have_fake;
    int width, height;
+   int seq_num;
 };
 
 struct dri2_config {
@@ -140,7 +141,7 @@ dri2_surface_validate(struct native_surface *nsurf,
                              const enum native_attachment *natts,
                              unsigned num_natts,
                              struct pipe_texture **textures,
-                             int *width, int *height)
+                             int *width, int *height, int* seq_num)
 {
    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
@@ -211,18 +212,26 @@ dri2_surface_validate(struct native_surface *nsurf,
       texture_indices[natts[i]] = i;
    }
 
-   dri2surf->have_back = FALSE;
-   dri2surf->have_fake = FALSE;
-
    xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
-                                    &dri2surf->width, &dri2surf->height,
+                                    &templ.width0, &templ.height0,
                                     dri2atts, FALSE, num_ins, &num_outs);
    if (!xbufs)
       return FALSE;
 
-   /* update width and height */
-   templ.width0 = dri2surf->width;
-   templ.height0 = dri2surf->height;
+   if(!dri2surf->seq_num || dri2surf->width != templ.width0 || 
dri2surf->height != templ.height0)
+   {
+      /* update width and height */
+      dri2surf->width = templ.width0;
+      dri2surf->height = templ.height0;
+
+      if(!++dri2surf->seq_num)
+         ++dri2surf->seq_num; /* wrap to 1, not 0 */
+   }
+   else if(seq_num && *seq_num == dri2surf->seq_num)
+      goto out;
+
+   dri2surf->have_back = FALSE;
+   dri2surf->have_fake = FALSE;
 
    for (i = 0; i < num_outs; i++) {
       struct x11_drawable_buffer *xbuf = &xbufs[i];
@@ -309,12 +318,15 @@ dri2_surface_validate(struct native_surface *nsurf,
       }
    }
 
+out:
    free(xbufs);
 
    if (width)
       *width = dri2surf->width;
    if (height)
       *height = dri2surf->height;
+   if(seq_num)
+      *seq_num = dri2surf->seq_num;
 
    return TRUE;
 }
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..70e2ffb 100644
--- a/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
+++ b/src/gallium/state_trackers/egl_g3d/x11/native_ximage.c
@@ -80,6 +80,7 @@ struct ximage_surface {
    struct ximage_display *xdpy;
 
    int width, height;
+   int seq_num;
    GC gc;
 
    struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
@@ -289,10 +290,11 @@ ximage_surface_validate(struct native_surface *nsurf,
                                const enum native_attachment *natts,
                                unsigned num_natts,
                                struct pipe_texture **textures,
-                               int *width, int *height)
+                               int *width, int *height, int* seq_num)
 {
    struct ximage_surface *xsurf = ximage_surface(nsurf);
    boolean error = FALSE;
+   boolean changed = FALSE;
    unsigned i;
 
    ximage_surface_update_geometry(&xsurf->base);
@@ -318,28 +320,39 @@ ximage_surface_validate(struct native_surface *nsurf,
                xbuf->ximage->height = xbuf->transfer->height;
                xbuf->ximage->bytes_per_line = xbuf->transfer->stride;
             }
+
+            changed = TRUE;
          }
-      }
 
-      /* allocation failed */
-      if (!xbuf->texture) {
-         unsigned j;
-         for (j = 0; j < i; j++)
-            pipe_texture_reference(&textures[j], NULL);
-         for (j = i; j < num_natts; j++)
-            textures[j] = NULL;
-         error = TRUE;
-         break;
+         /* allocation failed */
+         if (!xbuf->texture)
+            return FALSE;
       }
+   }
+
+   if(changed)
+   {
+      if(!++xsurf->seq_num)
+         ++xsurf->seq_num; /* wrap to 1 */
+   }
+   else if(seq_num && *seq_num == xsurf->seq_num)
+      return TRUE;
 
-      if (textures)
-         pipe_texture_reference(&textures[i], xbuf->texture);
+   if(textures) {
+      for (i = 0; i < num_natts; i++) {
+         struct ximage_buffer *xbuf = &xsurf->buffers[natts[i]];
+
+         if (xbuf)
+            pipe_texture_reference(&textures[i], xbuf->texture);
+      }
    }
 
    if (width)
       *width = xsurf->width;
    if (height)
       *height = xsurf->height;
+   if(seq_num)
+      *seq_num = xsurf->seq_num;
 
    return !error;
 }
-- 
1.6.3.3


------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
Mesa3d-dev mailing list
Mesa3d-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mesa3d-dev

Reply via email to