st/egl_g3d: Use a sequence number to decide if validation is required.
authorChia-I Wu <olvaffe@gmail.com>
Tue, 12 Jan 2010 10:08:02 +0000 (18:08 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Thu, 14 Jan 2010 09:25:19 +0000 (17:25 +0800)
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.

src/gallium/state_trackers/egl_g3d/common/egl_g3d.c
src/gallium/state_trackers/egl_g3d/common/egl_g3d.h
src/gallium/state_trackers/egl_g3d/common/native.h
src/gallium/state_trackers/egl_g3d/kms/native_kms.c
src/gallium/state_trackers/egl_g3d/kms/native_kms.h
src/gallium/state_trackers/egl_g3d/x11/native_dri2.c
src/gallium/state_trackers/egl_g3d/x11/native_ximage.c

index 741e5b465938ea1bf6911f2dd0f0f96b94689c63..9d5734d46f9c6788a73bb88af47fc973c91ee38c 100644 (file)
@@ -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;
 
index 33894b614f971c5a8bcce6f6e5fdbf2ad330b366..4c8b8dfe9e035cbb5d63e071bb4568c5bbd0f994 100644 (file)
@@ -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 {
index 5ddcf673607b16e0e577821f2eda1fe0139f90cb..4714e24b5c6a9716b1c86191c9e6f1de5a7e4ecf 100644 (file)
@@ -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);
 
    /**
index 0e0babdb14f7aa0222c6218968237f815bdb85ab..a44b9b9ae5cc3ec3836c643087be901edb1806eb 100644 (file)
@@ -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;
 }
 
index 3f869b25acf5b053850553d63298c25ce5a87686..095186e3cf367cab95e0cef8f26de6e0249d9bb1 100644 (file)
@@ -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;
index 0dda786bbdb210460289761fcedd205c5486ed8d..2192a1366d293d88a5636549ccf5d35fbe13e5a8 100644 (file)
@@ -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)
index e02faa9b7bac12effa8f2e097bfb858ec1c810f9..1a1844ec49a113ea1da11621c9dc991f343f0891 100644 (file)
@@ -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)