st/egl_g3d: Update validate to use an attachment mask.
authorChia-I Wu <olvaffe@gmail.com>
Mon, 18 Jan 2010 04:11:15 +0000 (12:11 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 18 Jan 2010 06:28:13 +0000 (14:28 +0800)
A validate call asks for the buffers of a native surface.  Using a mask
to represent the interested buffers is more intuitive.  It also rules
out corner cases such as a single attachment being listed multiple
times.

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/x11/native_dri2.c
src/gallium/state_trackers/egl_g3d/x11/native_ximage.c

index 51da8e19f5ef233ab094ce56519e7ab297602a9e..08f796d0836ecc22f25ba053892ae091931602a8 100644 (file)
@@ -44,8 +44,13 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
    struct egl_g3d_display *gdpy = egl_g3d_display(dpy);
    struct pipe_screen *screen = gdpy->native->screen;
    struct egl_g3d_context *gctx = egl_g3d_context(ctx);
-   EGLint num_surfaces;
-   EGLint s, i;
+   const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
+      ST_SURFACE_FRONT_LEFT,
+      ST_SURFACE_BACK_LEFT,
+      ST_SURFACE_FRONT_RIGHT,
+      ST_SURFACE_BACK_RIGHT,
+   };
+   EGLint num_surfaces, s;
 
    /* validate draw and/or read buffers */
    num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2;
@@ -53,6 +58,7 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
       struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS];
       struct egl_g3d_surface *gsurf;
       struct egl_g3d_buffer *gbuf;
+      EGLint att;
 
       if (s == 0) {
          gsurf = egl_g3d_surface(gctx->base.DrawSurface);
@@ -66,30 +72,31 @@ egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx)
       if (!gctx->force_validate) {
          unsigned int seq_num;
 
-         gsurf->native->validate(gsurf->native,
-               gbuf->native_atts, gbuf->num_atts,
+         gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
                &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,
+      pipe_surface_reference(&gsurf->render_surface, NULL);
+      memset(textures, 0, sizeof(textures));
+
+      gsurf->native->validate(gsurf->native, gbuf->attachment_mask,
             &gsurf->sequence_number, textures,
             &gsurf->base.Width, &gsurf->base.Height);
-      for (i = 0; i < gbuf->num_atts; i++) {
-         struct pipe_texture *pt = textures[i];
+      for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+         struct pipe_texture *pt = textures[att];
          struct pipe_surface *ps;
 
-         if (pt) {
+         if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) {
             ps = screen->get_tex_surface(screen, pt, 0, 0, 0,
                   PIPE_BUFFER_USAGE_GPU_READ |
                   PIPE_BUFFER_USAGE_GPU_WRITE);
             gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb,
-                  gbuf->st_atts[i], ps);
+                  st_att_map[att], ps);
 
-            if (gbuf->native_atts[i] == gsurf->render_att)
+            if (gsurf->render_att == att)
                pipe_surface_reference(&gsurf->render_surface, ps);
 
             pipe_surface_reference(&ps, NULL);
@@ -128,13 +135,7 @@ static void
 egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
 {
    struct egl_g3d_context *gctx = egl_g3d_context(ctx);
-   const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = {
-      ST_SURFACE_FRONT_LEFT,
-      ST_SURFACE_BACK_LEFT,
-      ST_SURFACE_FRONT_RIGHT,
-      ST_SURFACE_BACK_RIGHT,
-   };
-   EGLint s, i;
+   EGLint s;
 
    /* route draw and read buffers' attachments */
    for (s = 0; s < 2; s++) {
@@ -150,11 +151,7 @@ egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx)
          gbuf = &gctx->read;
       }
 
-      gbuf->native_atts[0] = gsurf->render_att;
-      gbuf->num_atts = 1;
-
-      for (i = 0; i < gbuf->num_atts; i++)
-         gbuf->st_atts[i] = st_att_map[gbuf->native_atts[i]];
+      gbuf->attachment_mask = (1 << gsurf->render_att);
 
       /* FIXME OpenGL defaults to draw the front or back buffer when the
        * context is single-buffered or double-buffered respectively.  In EGL,
@@ -196,19 +193,19 @@ egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx)
       if (!gdraw || priv != (void *) &gdraw->base) {
          gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb);
          gctx->draw.st_fb = NULL;
-         gctx->draw.num_atts = 0;
+         gctx->draw.attachment_mask = 0x0;
       }
 
       if (is_equal) {
          gctx->read.st_fb = NULL;
-         gctx->draw.num_atts = 0;
+         gctx->draw.attachment_mask = 0x0;
       }
       else {
          priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb);
          if (!gread || priv != (void *) &gread->base) {
             gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb);
             gctx->read.st_fb = NULL;
-            gctx->draw.num_atts = 0;
+            gctx->draw.attachment_mask = 0x0;
          }
       }
    }
@@ -628,7 +625,7 @@ init_surface_geometry(_EGLSurface *surf)
 {
    struct egl_g3d_surface *gsurf = egl_g3d_surface(surf);
 
-   return gsurf->native->validate(gsurf->native, NULL, 0,
+   return gsurf->native->validate(gsurf->native, 0x0,
          &gsurf->sequence_number, NULL,
          &gsurf->base.Width, &gsurf->base.Height);
 }
index 4c8b8dfe9e035cbb5d63e071bb4568c5bbd0f994..1da8af495b14d84a3b332ecefc3d72daf8e3a840 100644 (file)
@@ -52,9 +52,7 @@ struct egl_g3d_display {
 
 struct egl_g3d_buffer {
    struct st_framebuffer *st_fb;
-   EGLint num_atts;
-   enum native_attachment native_atts[NUM_NATIVE_ATTACHMENTS];
-   uint st_atts[NUM_NATIVE_ATTACHMENTS];
+   uint attachment_mask;
 };
 
 struct egl_g3d_context {
index 76f0e0c78acdb69b8d7ef2b5b3df0ac60d0d6604..6cd161bdf6cb5cc7fcce09d52a0b0e0d9f32d8e7 100644 (file)
@@ -64,18 +64,18 @@ struct native_surface {
    boolean (*flush_frontbuffer)(struct native_surface *nsurf);
 
    /**
-    * Validate the buffers of the surface.  The returned textures are owned by
-    * 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.
+    * Validate the buffers of the surface.  textures, if not NULL, points to an
+    * array of size NUM_NATIVE_ATTACHMENTS and the returned textures are owned
+    * by 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
-    * might change in the future.
+    * If this function is called multiple times with different attachment
+    * masks, those not listed in the latest call might be destroyed.  This
+    * behavior might change in the future.
     */
-   boolean (*validate)(struct native_surface *nsurf,
-                       const enum native_attachment *natts,
-                       unsigned num_natts,
+   boolean (*validate)(struct native_surface *nsurf, uint attachment_mask,
                        unsigned int *seq_num, struct pipe_texture **textures,
                        int *width, int *height);
 
@@ -211,6 +211,15 @@ struct native_display_modeset {
                       const struct native_mode *nmode);
 };
 
+/**
+ * Test whether an attachment is set in the mask.
+ */
+static INLINE boolean
+native_attachment_mask_test(uint mask, enum native_attachment att)
+{
+   return !!(mask & (1 << att));
+}
+
 const char *
 native_get_name(void);
 
index 65829fc7b3d0da055ab2c267f94b384c1af8daa2..dc664366305bb39526798bdd1bc9d6ce2719cb38 100644 (file)
@@ -33,9 +33,7 @@
 #include "native_kms.h"
 
 static boolean
-kms_surface_validate(struct native_surface *nsurf,
-                     const enum native_attachment *natts,
-                     unsigned num_natts,
+kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
                      unsigned int *seq_num, struct pipe_texture **textures,
                      int *width, int *height)
 {
@@ -43,12 +41,9 @@ kms_surface_validate(struct native_surface *nsurf,
    struct kms_display *kdpy = ksurf->kdpy;
    struct pipe_screen *screen = kdpy->base.screen;
    struct pipe_texture templ, *ptex;
-   int i;
-
-   if (num_natts) {
-      if (textures)
-         memset(textures, 0, sizeof(*textures) * num_natts);
+   int att;
 
+   if (attachment_mask) {
       memset(&templ, 0, sizeof(templ));
       templ.target = PIPE_TEXTURE_2D;
       templ.last_level = 0;
@@ -62,17 +57,21 @@ kms_surface_validate(struct native_surface *nsurf,
    }
 
    /* create textures */
-   for (i = 0; i < num_natts; i++) {
-      enum native_attachment natt = natts[i];
+   for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+      /* delay the allocation */
+      if (!native_attachment_mask_test(attachment_mask, att))
+         continue;
 
-      ptex = ksurf->textures[natt];
+      ptex = ksurf->textures[att];
       if (!ptex) {
          ptex = screen->texture_create(screen, &templ);
-         ksurf->textures[natt] = ptex;
+         ksurf->textures[att] = ptex;
       }
 
-      if (textures)
-         pipe_texture_reference(&textures[i], ptex);
+      if (textures) {
+         textures[att] = NULL;
+         pipe_texture_reference(&textures[att], ptex);
+      }
    }
 
    if (seq_num)
@@ -113,7 +112,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, NULL);
+         kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL);
          if (!ksurf->textures[natt])
             return FALSE;
 
index f497d8c1c77daafc36e65e4d4e94ca26a5a73dd5..f675a8e6861e979c75ff19cbb094119649146ef3 100644 (file)
@@ -134,22 +134,18 @@ dri2_surface_swap_buffers(struct native_surface *nsurf)
 }
 
 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)
+dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+                      unsigned int *seq_num, struct pipe_texture **textures,
+                      int *width, int *height)
 {
    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS];
-   EGLint texture_indices[NUM_NATIVE_ATTACHMENTS];
    struct pipe_texture templ;
    struct x11_drawable_buffer *xbufs;
-   int num_ins, num_outs, i;
+   int num_ins, num_outs, att, i;
 
-   if (num_natts) {
+   if (attachment_mask) {
       memset(&templ, 0, sizeof(templ));
       templ.target = PIPE_TEXTURE_2D;
       templ.last_level = 0;
@@ -160,24 +156,27 @@ dri2_surface_validate(struct native_surface *nsurf,
       templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
 
       if (textures)
-         memset(textures, 0, sizeof(*textures) * num_natts);
+         memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS);
    }
 
    /* create textures for pbuffer */
    if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) {
       struct pipe_screen *screen = dri2dpy->base.screen;
 
-      for (i = 0; i < num_natts; i++) {
-         enum native_attachment natt = natts[i];
-         struct pipe_texture *ptex = dri2surf->pbuffer_textures[natt];
+      for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+         struct pipe_texture *ptex = dri2surf->pbuffer_textures[att];
+
+         /* delay the allocation */
+         if (!native_attachment_mask_test(attachment_mask, att))
+            continue;
 
          if (!ptex) {
             ptex = screen->texture_create(screen, &templ);
-            dri2surf->pbuffer_textures[natt] = ptex;
+            dri2surf->pbuffer_textures[att] = ptex;
          }
 
          if (textures)
-            pipe_texture_reference(&textures[i], ptex);
+            pipe_texture_reference(&textures[att], ptex);
       }
 
       if (seq_num)
@@ -190,34 +189,34 @@ dri2_surface_validate(struct native_surface *nsurf,
       return TRUE;
    }
 
-   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
-      texture_indices[i] = -1;
-
    /* prepare the attachments */
-   num_ins = num_natts;
-   for (i = 0; i < num_natts; i++) {
-      unsigned int dri2att;
+   num_ins = 0;
+   for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+      if (native_attachment_mask_test(attachment_mask, att)) {
+         unsigned int dri2att;
+
+         switch (att) {
+         case NATIVE_ATTACHMENT_FRONT_LEFT:
+            dri2att = DRI2BufferFrontLeft;
+            break;
+         case NATIVE_ATTACHMENT_BACK_LEFT:
+            dri2att = DRI2BufferBackLeft;
+            break;
+         case NATIVE_ATTACHMENT_FRONT_RIGHT:
+            dri2att = DRI2BufferFrontRight;
+            break;
+         case NATIVE_ATTACHMENT_BACK_RIGHT:
+            dri2att = DRI2BufferBackRight;
+            break;
+         default:
+            assert(0);
+            dri2att = 0;
+            break;
+         }
 
-      switch (natts[i]) {
-      case NATIVE_ATTACHMENT_FRONT_LEFT:
-         dri2att = DRI2BufferFrontLeft;
-         break;
-      case NATIVE_ATTACHMENT_BACK_LEFT:
-         dri2att = DRI2BufferBackLeft;
-         break;
-      case NATIVE_ATTACHMENT_FRONT_RIGHT:
-         dri2att = DRI2BufferFrontRight;
-         break;
-      case NATIVE_ATTACHMENT_BACK_RIGHT:
-         dri2att = DRI2BufferBackRight;
-         break;
-      default:
-         assert(0);
-         dri2att = 0;
-         break;
+         dri2atts[num_ins] = dri2att;
+         num_ins++;
       }
-      dri2atts[i] = dri2att;
-      texture_indices[natts[i]] = i;
    }
 
    dri2surf->have_back = FALSE;
@@ -266,13 +265,13 @@ dri2_surface_validate(struct native_surface *nsurf,
          break;
       }
 
-      if (!desc || texture_indices[natt] < 0 ||
-          (textures && textures[texture_indices[natt]])) {
+      if (!desc || !native_attachment_mask_test(attachment_mask, natt) ||
+          (textures && textures[natt])) {
          if (!desc)
             _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
-         else if (texture_indices[natt] < 0)
+         else if (!native_attachment_mask_test(attachment_mask, natt))
             _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment);
-         else if (textures && textures[texture_indices[natt]])
+         else
             _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
          continue;
       }
@@ -284,7 +283,7 @@ dri2_surface_validate(struct native_surface *nsurf,
                   desc, xbuf->pitch, xbuf->name);
          if (ptex) {
             /* the caller owns the textures */
-            textures[texture_indices[natt]] = ptex;
+            textures[natt] = ptex;
          }
       }
    }
index 24a50df7a0a5c726716d8180cc935da69d152691..1f136235c0c6cda8c01cebe33367d1a42e439df5 100644 (file)
@@ -289,27 +289,21 @@ ximage_surface_update_geometry(struct native_surface *nsurf)
 }
 
 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)
+ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask,
+                        unsigned int *seq_num, struct pipe_texture **textures,
+                        int *width, int *height)
 {
    struct ximage_surface *xsurf = ximage_surface(nsurf);
-   boolean new_buffers = FALSE, error = FALSE;
-   unsigned i;
+   boolean new_buffers = FALSE;
+   int att;
 
    ximage_surface_update_geometry(&xsurf->base);
 
-   if (textures)
-      memset(textures, 0, sizeof(*textures) * num_natts);
+   for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
+      struct ximage_buffer *xbuf = &xsurf->buffers[att];
 
-   for (i = 0; i < num_natts; i++) {
-      enum native_attachment natt = natts[i];
-      struct ximage_buffer *xbuf = &xsurf->buffers[natt];
-
-      if (!xbuf)
+      /* delay the allocation */
+      if (!native_attachment_mask_test(attachment_mask, att))
          continue;
 
       /* reallocate the texture */
@@ -317,7 +311,7 @@ ximage_surface_validate(struct native_surface *nsurf,
           xsurf->width != xbuf->texture->width0 ||
           xsurf->height != xbuf->texture->height0) {
          new_buffers = TRUE;
-         if (ximage_surface_alloc_buffer(&xsurf->base, natt)) {
+         if (ximage_surface_alloc_buffer(&xsurf->base, att)) {
             /* update ximage */
             if (xbuf->ximage) {
                xbuf->ximage->width = xbuf->transfer->width;
@@ -327,19 +321,10 @@ ximage_surface_validate(struct native_surface *nsurf,
          }
       }
 
-      /* 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;
+      if (textures) {
+         textures[att] = NULL;
+         pipe_texture_reference(&textures[att], xbuf->texture);
       }
-
-      if (textures)
-         pipe_texture_reference(&textures[i], xbuf->texture);
    }
 
    /* increase the sequence number so that caller knows */
@@ -353,7 +338,7 @@ ximage_surface_validate(struct native_surface *nsurf,
    if (height)
       *height = xsurf->height;
 
-   return !error;
+   return TRUE;
 }
 
 static void