Just a few minor things below.

On 12/11/2012 02:52 AM, Dave Airlie wrote:
This adds seamless sampling for cubemap boundaries if requested.

The corner case averaging is messy but seems like it should be spec
compliant.

The face direction stuff is also a bit messy, I've no idea if that could
or should be simpler, or even if all my directions are fully correct!

Signed-off-by: Dave Airlie<airl...@redhat.com>
---
  src/gallium/drivers/softpipe/sp_screen.c     |   2 +-
  src/gallium/drivers/softpipe/sp_tex_sample.c | 143 +++++++++++++++++++++++++--
  2 files changed, 135 insertions(+), 10 deletions(-)

diff --git a/src/gallium/drivers/softpipe/sp_screen.c 
b/src/gallium/drivers/softpipe/sp_screen.c
index 909fa1c..7ca259e 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -127,7 +127,7 @@ softpipe_get_param(struct pipe_screen *screen, enum 
pipe_cap param)
        return 1;
     case PIPE_CAP_SEAMLESS_CUBE_MAP:
     case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
-      return 0;
+      return 1;
     case PIPE_CAP_SCALED_RESOLVE:
        return 0;
     case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c 
b/src/gallium/drivers/softpipe/sp_tex_sample.c
index 7558ef1..9500a03 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -607,6 +607,100 @@ get_texel_2d(const struct sp_sampler_variant *samp,
     }
  }


Maybe add a comment on this array explaining what it's for.


+static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
+   /* pos X first then neg X is Z different, Y the same */
+   /* PIPE_TEX_FACE_POS_X,*/
+   { PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
+     PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
+   /* PIPE_TEX_FACE_NEG_X */
+   { PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
+     PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
+
+   /* pos Y first then neg Y is X different, X the same */
+   /* PIPE_TEX_FACE_POS_Y */
+   { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
+     PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
+
+   /* PIPE_TEX_FACE_NEG_Y */
+   { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
+     PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
+
+   /* pos Z first then neg Y is X different, X the same */
+   /* PIPE_TEX_FACE_POS_Z */
+   { PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
+     PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
+
+   /* PIPE_TEX_FACE_NEG_Z */
+   { PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
+     PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y }
+};
+
+static INLINE unsigned
+get_next_face(unsigned face, int x, int y)
+{
+   int idx = 0;
+
+   if (x == 0&&  y == 0)
+      return face;
+   if (x == -1) idx = 0;
+   else if (x == 1) idx = 1;
+   else if (y == -1) idx = 2;
+   else if (y == 1) idx = 3;

Please put the "idx = ..." assignments on separate lines. The problem with "if (c) expr;" is it's a PITA if you want to set a breakpoint on expr.


+
+   return face_array[face][idx];
+}
+
+static INLINE const float *
+get_texel_cube_seamless(const struct sp_sampler_variant *samp,
+                        union tex_tile_address addr, int x, int y,
+                        float *corner)
+{
+   const struct pipe_resource *texture = samp->view->texture;
+   unsigned level = addr.bits.level;
+   unsigned face = addr.bits.face;
+   int new_x, new_y;
+   int max_x, max_y;
+   int c;
+
+   max_x = (int) u_minify(texture->width0, level);
+   max_y = (int) u_minify(texture->height0, level);
+   new_x = x;
+   new_y = y;
+
+   /* the corner case */
+   if ((x<  0 || x>= max_x)&&
+       (y<  0 || y>= max_y)) {
+      const float *c1, *c2, *c3;
+      int fx = x<  0 ? 0 : max_x - 1;
+      int fy = y<  0 ? 0 : max_y - 1;
+      c1 = get_texel_2d_no_border( samp, addr, fx, fy);
+      addr.bits.face = get_next_face(face, (x<  0) ? -1 : 1, 0);
+      c2 = get_texel_2d_no_border( samp, addr, (x<  0) ? max_x - 1 : 0, fy);
+      addr.bits.face = get_next_face(face, 0, (y<  0) ? -1 : 1);
+      c3 = get_texel_2d_no_border( samp, addr, fx, (y<  0) ?  max_y - 1 : 0);
+      for (c = 0; c<  TGSI_QUAD_SIZE; c++)
+         corner[c] = CLAMP((c1[c] + c2[c] + c3[c]), 0.0F, 1.0F) / 3;
+
+      return corner;
+   }
+   /* change the face */
+   if (x<  0) {
+      new_x = max_x - 1;
+      face = get_next_face(face, -1, 0);
+   } else if (x>= max_x) {
+      new_x = 0;
+      face = get_next_face(face, 1, 0);
+   } else if (y<  0) {
+      new_y = max_y - 1;
+      face = get_next_face(face, 0, -1);
+   } else if (y>= max_y) {
+      new_y = 0;
+      face = get_next_face(face, 0, 1);
+   }
+
+   addr.bits.face = face;
+   return get_texel_2d_no_border( samp, addr, new_x, new_y );
+}

  /* Gather a quad of adjacent texels within a tile:
   */
@@ -1121,6 +1215,7 @@ img_filter_cube_nearest(struct tgsi_sampler *tgsi_sampler,
     union tex_tile_address addr;
     const float *out;
     int c;
+   float corner0[TGSI_QUAD_SIZE];

     width = u_minify(texture->width0, level);
     height = u_minify(texture->height0, level);
@@ -1131,10 +1226,23 @@ img_filter_cube_nearest(struct tgsi_sampler 
*tgsi_sampler,
     addr.value = 0;
     addr.bits.level = level;

-   samp->nearest_texcoord_s(s, width,&x);
-   samp->nearest_texcoord_t(t, height,&y);
+   /*
+    * If NEAREST filtering is done within a miplevel, always apply wrap
+    * mode CLAMP_TO_EDGE.
+    */
+   if (samp->sampler->seamless_cube_map) {
+      wrap_nearest_clamp_to_edge(s, width,&x);
+      wrap_nearest_clamp_to_edge(t, height,&y);
+   } else {
+      samp->nearest_texcoord_s(s, width,&x);
+      samp->nearest_texcoord_t(t, height,&y);
+   }

-   out = get_texel_2d(samp, face(addr, face_id), x, y);
+   if (samp->sampler->seamless_cube_map) {
+      out = get_texel_cube_seamless(samp, face(addr, face_id), x, y, corner0);
+   } else {
+      out = get_texel_2d(samp, face(addr, face_id), x, y);
+   }
     for (c = 0; c<  TGSI_QUAD_SIZE; c++)
        rgba[TGSI_NUM_CHANNELS*c] = out[c];

@@ -1403,6 +1511,7 @@ img_filter_cube_linear(struct tgsi_sampler *tgsi_sampler,
     float xw, yw; /* weights */
     union tex_tile_address addr, addrj;
     const float *tx0, *tx1, *tx2, *tx3;
+   float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE], 
corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
     int c;

     width = u_minify(texture->width0, level);
@@ -1414,15 +1523,31 @@ img_filter_cube_linear(struct tgsi_sampler 
*tgsi_sampler,
     addr.value = 0;
     addr.bits.level = level;

-   samp->linear_texcoord_s(s, width,&x0,&x1,&xw);
-   samp->linear_texcoord_t(t, height,&y0,&y1,&yw);
+   /* For seamless,
+    * if LINEAR filtering is done within a miplevel, always apply wrap mode
+    * CLAMP_TO_BORDER.
+    */

I think that comment could be rewrapped to fit on two lines.


+   if (samp->sampler->seamless_cube_map) {
+      wrap_linear_clamp_to_border(s, width,&x0,&x1,&xw);
+      wrap_linear_clamp_to_border(t, height,&y0,&y1,&yw);
+   } else {
+      samp->linear_texcoord_s(s, width,&x0,&x1,&xw);
+      samp->linear_texcoord_t(t, height,&y0,&y1,&yw);
+   }

     addrj = face(addr, face_id);
-   tx0 = get_texel_2d(samp, addrj, x0, y0);
-   tx1 = get_texel_2d(samp, addrj, x1, y0);
-   tx2 = get_texel_2d(samp, addrj, x0, y1);
-   tx3 = get_texel_2d(samp, addrj, x1, y1);

+   if (samp->sampler->seamless_cube_map) {
+      tx0 = get_texel_cube_seamless(samp, addrj, x0, y0, corner0);
+      tx1 = get_texel_cube_seamless(samp, addrj, x1, y0, corner1);
+      tx2 = get_texel_cube_seamless(samp, addrj, x0, y1, corner2);
+      tx3 = get_texel_cube_seamless(samp, addrj, x1, y1, corner3);
+   } else {
+      tx0 = get_texel_2d(samp, addrj, x0, y0);
+      tx1 = get_texel_2d(samp, addrj, x1, y0);
+      tx2 = get_texel_2d(samp, addrj, x0, y1);
+      tx3 = get_texel_2d(samp, addrj, x1, y1);
+   }
     /* interpolate R, G, B, A */
     for (c = 0; c<  TGSI_QUAD_SIZE; c++)
        rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,


Thanks for working on this, Dave!

Reviewed-by: Brian Paul <bri...@vmware.com>

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to