st/egl: Reduce validation round-trips in ximage backend.
authorChia-I Wu <olv@lunarg.com>
Thu, 25 Feb 2010 13:16:56 +0000 (21:16 +0800)
committerChia-I Wu <olv@lunarg.com>
Thu, 25 Feb 2010 13:29:37 +0000 (21:29 +0800)
ximage_surface_validate is called several times per frame.  This commit
adds the client and server stamps to reduce the round-trips to the
server.  The idea is to bump the server stamp when flush_frontbuffer or
swap_buffers is called, and to skip the round-trip when the client stamp
is equal to the server stamp.  This makes sure the client APIs get the
new buffers when a new frame is started while skipping all round-trips
during the drawing.  To make this work, egl_g3d_validate_context is no
longer called after swap_buffers.

src/gallium/state_trackers/egl/common/egl_g3d.c
src/gallium/state_trackers/egl/x11/native_ximage.c

index 13a7487ea835e3ab79f6b14e18319eb7cca5a8aa..086e644e211f6f6ad2bbd74e670a8a5d2b4eafb8 100644 (file)
@@ -931,25 +931,7 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
    if (gctx)
       gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb);
 
-   /*
-    * We drew on the back buffer, unless there was no back buffer.
-    * In that case, we drew on the front buffer.  Either case, we call
-    * swap_buffers.
-    */
-   if (!gsurf->native->swap_buffers(gsurf->native))
-      return EGL_FALSE;
-
-   if (gctx) {
-      struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config);
-
-      /* force validation if the swap method is not copy */
-      if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) {
-         gctx->force_validate = EGL_TRUE;
-         egl_g3d_validate_context(dpy, &gctx->base);
-      }
-   }
-
-   return EGL_TRUE;
+   return gsurf->native->swap_buffers(gsurf->native);
 }
 
 /**
index 78675a199857be137dd11e46c03e214670d5e4cf..8ba73f289dddc98a7b347ceaf9e327adb3c8d7a0 100644 (file)
@@ -81,7 +81,8 @@ struct ximage_surface {
 
    GC gc;
 
-   unsigned int sequence_number;
+   unsigned int server_stamp;
+   unsigned int client_stamp;
    int width, height;
    struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS];
    uint valid_mask;
@@ -216,18 +217,11 @@ ximage_surface_update_geometry(struct native_surface *nsurf)
 
    ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable,
          &root, &x, &y, &w, &h, &border, &depth);
-   if (!ok) {
-      w = xsurf->width;
-      h = xsurf->height;
-   }
-
-   /* all buffers become invalid */
-   if (xsurf->width != w || xsurf->height != h) {
+   if (ok && (xsurf->width != w || xsurf->height != h)) {
       xsurf->width = w;
       xsurf->height = h;
-      xsurf->valid_mask = 0x0;
 
-      xsurf->sequence_number++;
+      xsurf->server_stamp++;
       updated = TRUE;
    }
 
@@ -247,10 +241,18 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
    int att;
 
    updated = ximage_surface_update_geometry(&xsurf->base);
-   buffer_mask &= ~xsurf->valid_mask;
-   /* all requested buffers are valid */
-   if (!buffer_mask)
-      return TRUE;
+   if (updated) {
+      /* all buffers become invalid */
+      xsurf->valid_mask = 0x0;
+   }
+   else {
+      buffer_mask &= ~xsurf->valid_mask;
+      /* all requested buffers are valid */
+      if (!buffer_mask) {
+         xsurf->client_stamp = xsurf->server_stamp;
+         return TRUE;
+      }
+   }
 
    new_valid = 0x0;
    for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
@@ -273,11 +275,8 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
       }
    }
 
-   if (new_valid) {
-      xsurf->valid_mask |= new_valid;
-      if (updated)
-         xsurf->sequence_number++;
-   }
+   xsurf->valid_mask |= new_valid;
+   xsurf->client_stamp = xsurf->server_stamp;
 
    return (new_valid == buffer_mask);
 }
@@ -333,7 +332,15 @@ ximage_surface_draw_buffer(struct native_surface *nsurf,
 static boolean
 ximage_surface_flush_frontbuffer(struct native_surface *nsurf)
 {
-   return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT);
+   struct ximage_surface *xsurf = ximage_surface(nsurf);
+   boolean ret;
+
+   ret = ximage_surface_draw_buffer(&xsurf->base,
+         NATIVE_ATTACHMENT_FRONT_LEFT);
+   /* force buffers to be updated in next validation call */
+   xsurf->server_stamp++;
+
+   return ret;
 }
 
 static boolean
@@ -345,6 +352,8 @@ ximage_surface_swap_buffers(struct native_surface *nsurf)
 
    /* display the back buffer first */
    ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT);
+   /* force buffers to be updated in next validation call */
+   xsurf->server_stamp++;
 
    xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT];
    xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT];
@@ -356,7 +365,6 @@ ximage_surface_swap_buffers(struct native_surface *nsurf)
    xtmp = *xfront;
    *xfront = *xback;
    *xback = xtmp;
-   xsurf->sequence_number++;
 
    return ret;
 }
@@ -368,11 +376,14 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
 {
    struct ximage_surface *xsurf = ximage_surface(nsurf);
 
-   if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask))
-      return FALSE;
+   if (xsurf->client_stamp != xsurf->server_stamp ||
+       (xsurf->valid_mask & attachment_mask) != attachment_mask) {
+      if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask))
+         return FALSE;
+   }
 
    if (seq_num)
-      *seq_num = xsurf->sequence_number;
+      *seq_num = xsurf->client_stamp;
 
    if (textures) {
       int att;
@@ -453,6 +464,9 @@ ximage_display_create_surface(struct native_display *ndpy,
          return NULL;
       }
 
+      /* initialize the geometry */
+      ximage_surface_update_buffers(&xsurf->base, 0x0);
+
       for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
          struct ximage_buffer *xbuf = &xsurf->buffers[i];