On Tue, Jan 12, 2010 at 5:03 PM, Chia-I Wu <olva...@gmail.com> wrote:
> Semantically, the validate call asks for nothing but the specified textures of
> the native surface _at the moment_.  There are some properties
> * It can be called repeatedly without any ill effect
> * It may return entirely different textures between two calls, without any
>  knowledge in advance
> As such, splitting the call into "get sequence number" and "validate" is not
> possible.
> For optimization, some artifacts are added (and documented)
> * The argument "textures" may be NULL.  Since there will be no way to return
>  the textures to the caller, the native display may skip the creation of the
>  textures.
> * (NEW) A sequence number is returned to indicate which moment the textures
>  belong to (even when the argument "textures" is NULL)
> Using these artifacts, EGL is capable to
> * validate the native surface with "textures" set to NULL to get the sequence
>  number
> * if the sequence number differs from what EGLSurface knows (which rarely
>  happens), validate is called again to retrieve the textures
> The "force_validate" is used to indicate that the first validate call is very
> likely to return a different sequence number, and it may call to retrieve
> the textures directly.
The attached patch is what's on my mind.  I only does a quick test and
it seems to work.
From a276ba00280bfe145f7af962424879e34fc61cba Mon Sep 17 00:00:00 2001
From: Chia-I Wu <olva...@gmail.com>
Date: Tue, 12 Jan 2010 18:08:02 +0800
Subject: [PATCH] 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 so that the native display can notify us.

Signed-off-by: Chia-I Wu <olva...@gmail.com>
---
 .../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..60fce03 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, (struct pipe_texture **) 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)
-- 
1.6.5

------------------------------------------------------------------------------
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