tgsi_sampler->get_samples() now operates on a quad (returns 4 colors).
authorBrian <brian.paul@tungstengraphics.com>
Tue, 14 Aug 2007 17:00:35 +0000 (11:00 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Tue, 14 Aug 2007 17:00:35 +0000 (11:00 -0600)
Lambda/level-of-detail is also computed in get_samples() now.

src/mesa/pipe/softpipe/sp_quad_fs.c
src/mesa/pipe/softpipe/sp_tex_sample.c
src/mesa/pipe/softpipe/sp_tex_sample.h
src/mesa/pipe/tgsi/core/tgsi_exec.c
src/mesa/pipe/tgsi/core/tgsi_exec.h

index 70a80af..096385d 100644 (file)
@@ -322,7 +322,7 @@ static void shade_begin(struct quad_stage *qs)
    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
       qss->samplers[i].state = &softpipe->sampler[i];
       qss->samplers[i].texture = softpipe->texture[i];
-      qss->samplers[i].get_sample = sp_get_sample;
+      qss->samplers[i].get_samples = sp_get_samples;
       qss->samplers[i].pipe = &softpipe->pipe;
       /* init cache info here */
       qss->samplers[i].cache_x =
index fb4f793..2005a3d 100644 (file)
  * optimization!  If we find that's not true on some systems, convert
  * to a macro.
  */
-static INLINE GLfloat
-lerp_2d(GLfloat a, GLfloat b,
-        GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
+static INLINE float
+lerp_2d(float a, float b,
+        float v00, float v10, float v01, float v11)
 {
-   const GLfloat temp0 = LERP(a, v00, v10);
-   const GLfloat temp1 = LERP(a, v01, v11);
+   const float temp0 = LERP(a, v00, v10);
+   const float temp1 = LERP(a, v01, v11);
    return LERP(b, temp0, temp1);
 }
 
@@ -98,7 +98,7 @@ repeat_remainder(GLint a, GLint b)
  * \return  integer texture index
  */
 static INLINE GLint
-nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
+nearest_texcoord(GLuint wrapMode, float s, GLuint size)
 {
    GLint i;
    switch (wrapMode) {
@@ -122,8 +122,8 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
       {
          /* s limited to [min,max] */
          /* i limited to [0, size-1] */
-         const GLfloat min = 1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
+         const float min = 1.0F / (2.0F * size);
+         const float max = 1.0F - min;
          if (s < min)
             i = 0;
          else if (s > max)
@@ -136,8 +136,8 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
       {
          /* s limited to [min,max] */
          /* i limited to [-1, size] */
-         const GLfloat min = -1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
+         const float min = -1.0F / (2.0F * size);
+         const float max = 1.0F - min;
          if (s <= min)
             i = -1;
          else if (s >= max)
@@ -148,14 +148,14 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
       return i;
    case PIPE_TEX_WRAP_MIRROR_REPEAT:
       {
-         const GLfloat min = 1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
+         const float min = 1.0F / (2.0F * size);
+         const float max = 1.0F - min;
          const GLint flr = IFLOOR(s);
-         GLfloat u;
+         float u;
          if (flr & 1)
-            u = 1.0F - (s - (GLfloat) flr);
+            u = 1.0F - (s - (float) flr);
          else
-            u = s - (GLfloat) flr;
+            u = s - (float) flr;
          if (u < min)
             i = 0;
          else if (u > max)
@@ -168,7 +168,7 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
       {
          /* s limited to [0,1] */
          /* i limited to [0,size-1] */
-         const GLfloat u = FABSF(s);
+         const float u = FABSF(s);
          if (u <= 0.0F)
             i = 0;
          else if (u >= 1.0F)
@@ -181,9 +181,9 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
       {
          /* s limited to [min,max] */
          /* i limited to [0, size-1] */
-         const GLfloat min = 1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
-         const GLfloat u = FABSF(s);
+         const float min = 1.0F / (2.0F * size);
+         const float max = 1.0F - min;
+         const float u = FABSF(s);
          if (u < min)
             i = 0;
          else if (u > max)
@@ -196,9 +196,9 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
       {
          /* s limited to [min,max] */
          /* i limited to [0, size-1] */
-         const GLfloat min = -1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
-         const GLfloat u = FABSF(s);
+         const float min = -1.0F / (2.0F * size);
+         const float max = 1.0F - min;
+         const float u = FABSF(s);
          if (u < min)
             i = -1;
          else if (u > max)
@@ -224,10 +224,10 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
  * \param a  returns blend factor/weight between texture indexes
  */
 static INLINE void
-linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
-                GLint *i0, GLint *i1, GLfloat *a)
+linear_texcoord(GLuint wrapMode, float s, GLuint size,
+                GLint *i0, GLint *i1, float *a)
 {
-   GLfloat u;
+   float u;
    switch (wrapMode) {
    case PIPE_TEX_WRAP_REPEAT:
       u = s * size - 0.5F;
@@ -238,7 +238,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
       if (s <= 0.0F)
          u = 0.0F;
       else if (s >= 1.0F)
-         u = (GLfloat) size;
+         u = (float) size;
       else
          u = s * size;
       u -= 0.5F;
@@ -249,7 +249,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
       if (s <= 0.0F)
          u = 0.0F;
       else if (s >= 1.0F)
-         u = (GLfloat) size;
+         u = (float) size;
       else
          u = s * size;
       u -= 0.5F;
@@ -262,8 +262,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
       break;
    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
       {
-         const GLfloat min = -1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
+         const float min = -1.0F / (2.0F * size);
+         const float max = 1.0F - min;
          if (s <= min)
             u = min * size;
          else if (s >= max)
@@ -279,9 +279,9 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
       {
          const GLint flr = IFLOOR(s);
          if (flr & 1)
-            u = 1.0F - (s - (GLfloat) flr);
+            u = 1.0F - (s - (float) flr);
          else
-            u = s - (GLfloat) flr;
+            u = s - (float) flr;
          u = (u * size) - 0.5F;
          *i0 = IFLOOR(u);
          *i1 = *i0 + 1;
@@ -294,7 +294,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
    case PIPE_TEX_WRAP_MIRROR_CLAMP:
       u = FABSF(s);
       if (u >= 1.0F)
-         u = (GLfloat) size;
+         u = (float) size;
       else
          u *= size;
       u -= 0.5F;
@@ -304,7 +304,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
       u = FABSF(s);
       if (u >= 1.0F)
-         u = (GLfloat) size;
+         u = (float) size;
       else
          u *= size;
       u -= 0.5F;
@@ -317,8 +317,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
       break;
    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
       {
-         const GLfloat min = -1.0F / (2.0F * size);
-         const GLfloat max = 1.0F - min;
+         const float min = -1.0F / (2.0F * size);
+         const float max = 1.0F - min;
          u = FABSF(s);
          if (u <= min)
             u = min * size;
@@ -339,7 +339,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
 
 
 static GLuint
-choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4])
+choose_cube_face(float rx, float ry, float rz,
+                 float newCoord[4])
 {
    /*
       major axis
@@ -352,12 +353,9 @@ choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4])
        +rz          TEXTURE_CUBE_MAP_POSITIVE_Z_EXT    +rx    -ry   rz
        -rz          TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT    -rx    -ry   rz
    */
-   const GLfloat rx = texcoord[0];
-   const GLfloat ry = texcoord[1];
-   const GLfloat rz = texcoord[2];
-   const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
+   const float arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
    GLuint face;
-   GLfloat sc, tc, ma;
+   float sc, tc, ma;
 
    if (arx > ary && arx > arz) {
       if (rx >= 0.0F) {
@@ -409,9 +407,62 @@ choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4])
 }
 
 
+/**
+ * Examine the quad's texture coordinates to compute the partial
+ * derivatives w.r.t X and Y, then compute lambda (level of detail).
+ *
+ * This is only done for fragment shaders, not vertex shaders.
+ */
+static float
+compute_lambda(struct tgsi_sampler *sampler,
+               const float s[QUAD_SIZE],
+               const float t[QUAD_SIZE],
+               const float p[QUAD_SIZE])
+{
+   float rho, lambda;
+
+   assert(s);
+   {
+      float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
+      float dsdy = s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT];
+      dsdx = FABSF(dsdx);
+      dsdy = FABSF(dsdy);
+      rho = MAX2(dsdx, dsdy) * sampler->texture->width0;
+   }
+   if (t) {
+      float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
+      float dtdy = t[QUAD_TOP_LEFT]     - t[QUAD_BOTTOM_LEFT];
+      float max;
+      dtdx = FABSF(dtdx);
+      dtdy = FABSF(dtdy);
+      max = MAX2(dtdx, dtdy) * sampler->texture->height0;
+      rho = MAX2(rho, max);
+   }
+   if (p) {
+      float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT];
+      float dpdy = p[QUAD_TOP_LEFT]     - p[QUAD_BOTTOM_LEFT];
+      float max;
+      dpdx = FABSF(dpdx);
+      dpdy = FABSF(dpdy);
+      max = MAX2(dpdx, dpdy) * sampler->texture->depth0;
+      rho = MAX2(rho, max);
+   }
+
+   lambda = LOG2(rho);
+
+   lambda += sampler->state->lod_bias;
+   lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod);
+
+   return lambda;
+}
+
+
 static void
-sp_get_sample_1d(struct tgsi_sampler *sampler,
-                 const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
+sp_get_samples_1d(struct tgsi_sampler *sampler,
+                  const float s[QUAD_SIZE],
+                  const float t[QUAD_SIZE],
+                  const float p[QUAD_SIZE],
+                  float rgba[NUM_CHANNELS][QUAD_SIZE])
 {
    struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
    struct pipe_surface *ps
@@ -420,26 +471,40 @@ sp_get_sample_1d(struct tgsi_sampler *sampler,
    switch (sampler->state->min_img_filter) {
    case PIPE_TEX_FILTER_NEAREST:
       {
-         GLint x;
-         x = nearest_texcoord(sampler->state->wrap_s, strq[0],
-                              sampler->texture->width0);
-         ps->get_tile(ps, x, 0, 1, 1, rgba);
+         GLuint j;
+         for (j = 0; j < QUAD_SIZE; j++) {
+            GLint x = nearest_texcoord(sampler->state->wrap_s, s[j],
+                                       sampler->texture->width0);
+            float texel[4];
+            ps->get_tile(ps, x, 0, 1, 1, texel);
+            rgba[0][j] = texel[0];
+            rgba[1][j] = texel[1];
+            rgba[2][j] = texel[2];
+            rgba[3][j] = texel[3];
+         }
       }
       break;
    case PIPE_TEX_FILTER_LINEAR:
       {
-         GLfloat t0[4], t1[4];
-         GLint x0, x1;
-         GLfloat a;
-         linear_texcoord(sampler->state->wrap_s, strq[0],
-                         sampler->texture->width0, &x0, &x1, &a);
-         ps->get_tile(ps, x0, 0, 1, 1, t0);
-         ps->get_tile(ps, x1, 0, 1, 1, t1);
-
-         rgba[0] = LERP(a, t0[0], t1[0]);
-         rgba[1] = LERP(a, t0[1], t1[1]);
-         rgba[2] = LERP(a, t0[2], t1[2]);
-         rgba[3] = LERP(a, t0[3], t1[3]);
+         GLuint j;
+         for (j = 0; j < QUAD_SIZE; j++) {
+            float t0[4], t1[4], texel[4];
+            GLint x0, x1;
+            float a;
+            linear_texcoord(sampler->state->wrap_s, s[j],
+                            sampler->texture->width0, &x0, &x1, &a);
+            ps->get_tile(ps, x0, 0, 1, 1, t0);
+            ps->get_tile(ps, x1, 0, 1, 1, t1);
+
+            texel[0] = LERP(a, t0[0], t1[0]);
+            texel[1] = LERP(a, t0[1], t1[1]);
+            texel[2] = LERP(a, t0[2], t1[2]);
+            texel[3] = LERP(a, t0[3], t1[3]);
+            rgba[0][j] = texel[0];
+            rgba[1][j] = texel[1];
+            rgba[2][j] = texel[2];
+            rgba[3][j] = texel[3];
+         }
       }
       break;
    default:
@@ -448,7 +513,7 @@ sp_get_sample_1d(struct tgsi_sampler *sampler,
 }
 
 static GLuint
-choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda)
+choose_mipmap_level(struct tgsi_sampler *sampler, float lambda)
 {
    if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
       return 0;
@@ -463,7 +528,68 @@ choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda)
 
 
 /**
- * Called via tgsi_sampler::get_sample()
+ * Load the texture cache with a new texture tile.
+ */
+static void
+cache_tex_tile(struct tgsi_sampler *sampler,
+               unsigned face, unsigned level, unsigned zslice, int cx, int cy)
+{
+   struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
+   struct pipe_surface *ps
+      = pipe->get_tex_surface(pipe, sampler->texture, face, level, zslice);
+   assert(ps->width == sampler->texture->level[level].width);
+   assert(ps->height == sampler->texture->level[level].height);
+   sampler->cache_level = level;
+   sampler->cache_x = cx;
+   sampler->cache_y = cy;
+   ps->get_tile(ps,
+                cx * SAMPLER_CACHE_SIZE,
+                cy * SAMPLER_CACHE_SIZE,
+                SAMPLER_CACHE_SIZE, SAMPLER_CACHE_SIZE,
+                (float *) sampler->cache);
+}
+
+
+/**
+ * Get a texel from a texture.
+ * \param face  the cube face in 0..5
+ * \param level  the mipmap level
+ * \param zslize  which slice of a 3D texture
+ * \param x  the x coord of texel within 2D image
+ * \param y  the y coord of texel within 2D image
+ * \param rgba  the quad to put the texel/color into
+ * \param j  which element of the rgba quad to write to
+ */
+static void
+get_texel(struct tgsi_sampler *sampler,
+          unsigned face, unsigned level, unsigned zslice, int x, int y,
+          float rgba[NUM_CHANNELS][QUAD_SIZE], GLuint j)
+{
+   int cx = x / SAMPLER_CACHE_SIZE;
+   int cy = y / SAMPLER_CACHE_SIZE;
+
+   if (cx != sampler->cache_x || cy != sampler->cache_y ||
+       level != sampler->cache_level) {
+      cache_tex_tile(sampler, face, level, zslice, cx, cy);
+      printf("cache miss (%d, %d)\n", x, y);
+   }
+   else {
+      printf("cache hit (%d, %d)\n", x, y);
+   }
+
+   /* get texel from cache */
+   cx = x % SAMPLER_CACHE_SIZE;
+   cy = y % SAMPLER_CACHE_SIZE;
+   rgba[0][j] = sampler->cache[cy][cx][0];
+   rgba[1][j] = sampler->cache[cy][cx][1];
+   rgba[2][j] = sampler->cache[cy][cx][2];
+   rgba[3][j] = sampler->cache[cy][cx][3];
+}
+
+
+
+/**
+ * Called via tgsi_sampler::get_samples()
  * Use the sampler's state setting to get a filtered RGBA value
  * from the sampler's texture (mipmap tree).
  *
@@ -475,87 +601,62 @@ choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda)
  * a new tgsi_sampler object for each state combo it finds....
  */
 static void
-sp_get_sample_2d(struct tgsi_sampler *sampler,
-                 const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
+sp_get_samples_2d(struct tgsi_sampler *sampler,
+                  const float s[QUAD_SIZE],
+                  const float t[QUAD_SIZE],
+                  const float p[QUAD_SIZE],
+                  float rgba[NUM_CHANNELS][QUAD_SIZE])
 {
-   struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
-   GLuint filter;
-   GLint level0;
-
-   if (lambda < 0.0)
-      filter = sampler->state->mag_img_filter;
-   else
-      filter = sampler->state->min_img_filter;
+   GLuint j, imgFilter;
+   int level0, width, height;
+   
+   /* compute level0 and imgFilter */
+   switch (sampler->state->min_mip_filter) {
+   case PIPE_TEX_MIPFILTER_NONE:
+      imgFilter = sampler->state->mag_img_filter;
+      level0 = 0;
+      assert(sampler->state->min_img_filter ==
+             sampler->state->mag_img_filter);
+      break;
+   default:
+      {
+         float lambda = compute_lambda(sampler, s, t, p);
+         if (lambda < 0.0)
+            imgFilter = sampler->state->mag_img_filter;
+         else
+            imgFilter = sampler->state->min_img_filter;
+         level0 = choose_mipmap_level(sampler, lambda);
+      }
+   }
 
-   level0 = choose_mipmap_level(sampler, lambda);
+   width = sampler->texture->level[level0].width;
+   height = sampler->texture->level[level0].height;
 
-   assert(sampler->texture->level[level0].width);
+   assert(width > 0);
 
-   switch (filter) {
+   switch (imgFilter) {
    case PIPE_TEX_FILTER_NEAREST:
-      {
-         GLint x = nearest_texcoord(sampler->state->wrap_s, strq[0],
-                                    sampler->texture->level[level0].width);
-         GLint y = nearest_texcoord(sampler->state->wrap_t, strq[1],
-                                    sampler->texture->level[level0].height);
-         GLint cx = x / SAMPLER_CACHE_SIZE;
-         GLint cy = y / SAMPLER_CACHE_SIZE;
-         if (cx != sampler->cache_x || cy != sampler->cache_y ||
-             level0 != sampler->cache_level) {
-            /* cache miss, replace cache with new tile */
-            struct pipe_surface *ps
-               = pipe->get_tex_surface(pipe, sampler->texture, 0, level0, 0);
-            assert(ps->width == sampler->texture->level[level0].width);
-            assert(ps->height == sampler->texture->level[level0].height);
-            sampler->cache_level = level0;
-            sampler->cache_x = cx;
-            sampler->cache_y = cy;
-            ps->get_tile(ps,
-                         cx * SAMPLER_CACHE_SIZE,
-                         cy * SAMPLER_CACHE_SIZE,
-                         SAMPLER_CACHE_SIZE, SAMPLER_CACHE_SIZE,
-                         (GLfloat *) sampler->cache);
-            /*printf("cache miss (%d, %d)\n", x, y);*/
-         }
-         else {
-            /*printf("cache hit (%d, %d)\n", x, y);*/
-         }
-         /* get texel from cache */
-         cx = x % SAMPLER_CACHE_SIZE;
-         cy = y % SAMPLER_CACHE_SIZE;
-         COPY_4V(rgba, sampler->cache[cy][cx]);
+      for (j = 0; j < QUAD_SIZE; j++) {
+         int x = nearest_texcoord(sampler->state->wrap_s, s[j], width);
+         int y = nearest_texcoord(sampler->state->wrap_t, t[j], height);
+         get_texel(sampler, 0, level0, 0, x, y, rgba, j);
       }
       break;
    case PIPE_TEX_FILTER_LINEAR:
-      {
-         GLfloat t00[4], t01[4], t10[4], t11[4];
-         GLint x0, y0, x1, y1;
-         GLfloat a, b;
-         struct pipe_surface *ps
-            = pipe->get_tex_surface(pipe, sampler->texture, 0, level0, 0);
-
-         linear_texcoord(sampler->state->wrap_s, strq[0],
-                         sampler->texture->width0, &x0, &x1, &a);
-         linear_texcoord(sampler->state->wrap_t, strq[1],
-                         sampler->texture->height0, &y0, &y1, &b);
-         ps->get_tile(ps, x0, y0, 1, 1, t00);
-         ps->get_tile(ps, x1, y0, 1, 1, t10);
-         ps->get_tile(ps, x0, y1, 1, 1, t01);
-         ps->get_tile(ps, x1, y1, 1, 1, t11);
-
-         rgba[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
-         rgba[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
-         rgba[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
-         rgba[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
-      }
-      break;
-      /*
-      {
-        GLuint level0, level1;
-        level0 = choose_mipmap_level(sampler, lambda);
+      for (j = 0; j < QUAD_SIZE; j++) {
+         float tx[4][4], a, b;
+         int x0, y0, x1, y1, c;
+         linear_texcoord(sampler->state->wrap_s, s[j], width,  &x0, &x1, &a);
+         linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &b);
+         get_texel(sampler, 0, level0, 0, x0, y0, tx, 0);
+         get_texel(sampler, 0, level0, 0, x1, y0, tx, 1);
+         get_texel(sampler, 0, level0, 0, x0, y1, tx, 2);
+         get_texel(sampler, 0, level0, 0, x1, y1, tx, 3);
+         for (c = 0; c < 4; c++) {
+            rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
+         }
       }
       break;
-      */
    default:
       assert(0);
    }
@@ -563,40 +664,52 @@ sp_get_sample_2d(struct tgsi_sampler *sampler,
 
 
 static void
-sp_get_sample_3d(struct tgsi_sampler *sampler,
-                 const GLfloat strq[4], GLfloat lamba, GLfloat rgba[4])
+sp_get_samples_3d(struct tgsi_sampler *sampler,
+                  const float s[QUAD_SIZE],
+                  const float t[QUAD_SIZE],
+                  const float p[QUAD_SIZE],
+                  float rgba[NUM_CHANNELS][QUAD_SIZE])
 {
    /* get/map pipe_surfaces corresponding to 3D tex slices */
 }
 
 
 static void
-sp_get_sample_cube(struct tgsi_sampler *sampler,
-                   const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
+sp_get_samples_cube(struct tgsi_sampler *sampler,
+                    const float s[QUAD_SIZE],
+                    const float t[QUAD_SIZE],
+                    const float p[QUAD_SIZE],
+                    float rgba[NUM_CHANNELS][QUAD_SIZE])
 {
-   GLfloat st[4];
-   GLuint face = choose_cube_face(strq, st);
-
-   /* get/map surface corresponding to the face */
+   GLuint j;
+   for (j = 0; j < QUAD_SIZE; j++) {
+      float st[4];
+      GLuint face = choose_cube_face(s[j], t[j], p[j], st);
+      (void) face;
+      /* get/map surface corresponding to the face */
+   }
 }
 
 
 void
-sp_get_sample(struct tgsi_sampler *sampler,
-              const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
+sp_get_samples(struct tgsi_sampler *sampler,
+               const float s[QUAD_SIZE],
+               const float t[QUAD_SIZE],
+               const float p[QUAD_SIZE],
+               float rgba[NUM_CHANNELS][QUAD_SIZE])
 {
    switch (sampler->texture->target) {
    case GL_TEXTURE_1D:
-      sp_get_sample_1d(sampler, strq, lambda, rgba);
+      sp_get_samples_1d(sampler, s, t, p, rgba);
       break;
    case GL_TEXTURE_2D:
-      sp_get_sample_2d(sampler, strq, lambda, rgba);
+      sp_get_samples_2d(sampler, s, t, p, rgba);
       break;
    case GL_TEXTURE_3D:
-      sp_get_sample_3d(sampler, strq, lambda, rgba);
+      sp_get_samples_3d(sampler, s, t, p, rgba);
       break;
    case GL_TEXTURE_CUBE_MAP:
-      sp_get_sample_cube(sampler, strq, lambda, rgba);
+      sp_get_samples_cube(sampler, s, t, p, rgba);
       break;
    default:
       assert(0);
index 55ae490..417752d 100644 (file)
@@ -6,8 +6,11 @@ struct tgsi_sampler;
 
 
 extern void
-sp_get_sample(struct tgsi_sampler *sampler,
-              const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]);
+sp_get_samples(struct tgsi_sampler *sampler,
+               const GLfloat s[QUAD_SIZE],
+               const GLfloat t[QUAD_SIZE],
+               const GLfloat p[QUAD_SIZE],
+               GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]);
 
 
 #endif /* SP_TEX_SAMPLE_H */
index 64d413b..03b3b49 100644 (file)
@@ -1034,44 +1034,6 @@ exec_kil (struct tgsi_exec_machine *mach,
 }
 
 
-static GLfloat
-compute_lambda(struct tgsi_sampler *sampler,
-               const union tgsi_exec_channel *s,
-               const union tgsi_exec_channel *t,
-               const union tgsi_exec_channel *p)
-{
-   GLfloat rho, lambda;
-
-   assert(s);
-   {
-      GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT];
-      GLfloat dsdy = s->f[TILE_TOP_LEFT]     - s->f[TILE_BOTTOM_LEFT];
-      dsdx = FABSF(dsdx);
-      dsdy = FABSF(dsdy);
-      rho = MAX2(dsdx, dsdy) * sampler->texture->width0;
-   }
-   if (t) {
-      GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT];
-      GLfloat dtdy = t->f[TILE_TOP_LEFT]     - t->f[TILE_BOTTOM_LEFT];
-      GLfloat max;
-      dtdx = FABSF(dtdx);
-      dtdy = FABSF(dtdy);
-      max = MAX2(dtdx, dtdy) * sampler->texture->height0;
-      rho = MAX2(rho, max);
-   }
-   if (p) {
-      GLfloat dpdx = p->f[TILE_BOTTOM_RIGHT] - p->f[TILE_BOTTOM_LEFT];
-      GLfloat dpdy = p->f[TILE_TOP_LEFT]     - p->f[TILE_BOTTOM_LEFT];
-      GLfloat max;
-      dpdx = FABSF(dpdx);
-      dpdy = FABSF(dpdy);
-      max = MAX2(dpdx, dpdy) * sampler->texture->depth0;
-      rho = MAX2(rho, max);
-   }
-
-   lambda = LOG2(rho);
-   return lambda;
-}
 
 
 /*
@@ -1079,44 +1041,24 @@ compute_lambda(struct tgsi_sampler *sampler,
  */
 static void
 fetch_texel( struct tgsi_sampler *sampler,
-             GLfloat lambda,
              const union tgsi_exec_channel *s,
              const union tgsi_exec_channel *t,
              const union tgsi_exec_channel *p,
-             GLuint unit,
              union tgsi_exec_channel *r,
              union tgsi_exec_channel *g,
              union tgsi_exec_channel *b,
              union tgsi_exec_channel *a )
 {
-   GLuint fragment_index;
-   GLfloat stpq[4][4];
-
-   for (fragment_index = 0; fragment_index < 4; fragment_index++) {
-      stpq[fragment_index][0] = s->f[fragment_index];
-      if (t)
-         stpq[fragment_index][1] = t->f[fragment_index];
-      if (p)
-         stpq[fragment_index][2] = p->f[fragment_index];
-   }
+   GLuint j;
+   GLfloat rgba[NUM_CHANNELS][QUAD_SIZE];
 
-   lambda += sampler->state->lod_bias;
-   lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod);
-
-   /* XXX: Use the same lambda value throughout the tile.  Could
-    * end up with four unique values by recalculating partial
-    * derivs in the other row and column, and calculating lambda
-    * using the dx and dy values appropriate for each fragment in
-    * the tile.
-    */
-
-   for (fragment_index = 0; fragment_index < 4; fragment_index++) {
-      GLfloat rgba[4];
-      sampler->get_sample(sampler, stpq[fragment_index], lambda, rgba);
-      r->f[fragment_index] = rgba[0];
-      g->f[fragment_index] = rgba[1];
-      b->f[fragment_index] = rgba[2];
-      a->f[fragment_index] = rgba[3];
+   sampler->get_samples(sampler, s->f, t->f, p->f, rgba);
+
+   for (j = 0; j < 4; j++) {
+      r->f[j] = rgba[0][j];
+      g->f[j] = rgba[1][j];
+      b->f[j] = rgba[2][j];
+      a->f[j] = rgba[3][j];
    }
 }
 
@@ -1647,7 +1589,6 @@ exec_instruction(
    case TGSI_OPCODE_TEX:
       {
          const GLuint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
-         GLfloat lambda;
          switch (inst->InstructionExtTexture.Texture) {
          case TGSI_TEXTURE_1D:
 
@@ -1666,10 +1607,8 @@ exec_instruction(
                assert (0);
             }
 
-            lambda = compute_lambda(&mach->Samplers[unit], &r[0], NULL, NULL);
-            fetch_texel(&mach->Samplers[unit], lambda,
+            fetch_texel(&mach->Samplers[unit],
                         &r[0], NULL, NULL,
-                        inst->FullSrcRegisters[1].SrcRegister.Index,
                         &r[0], &r[1], &r[2], &r[3]);
             break;
 
@@ -1693,11 +1632,8 @@ exec_instruction(
                assert (0);
             }
 
-            lambda = compute_lambda(&mach->Samplers[unit], &r[0], &r[1], NULL);
             fetch_texel(&mach->Samplers[unit],
-                        lambda,
                         &r[0], &r[1], NULL,
-                        inst->FullSrcRegisters[1].SrcRegister.Index,
                         &r[0], &r[1], &r[2], &r[3]);
             break;
 
@@ -1723,11 +1659,8 @@ exec_instruction(
                assert (0);
             }
 
-            lambda = compute_lambda(&mach->Samplers[unit], &r[0], &r[1], &r[2]);
             fetch_texel(&mach->Samplers[unit],
-                        lambda,
                         &r[0], &r[1], &r[2],
-                        inst->FullSrcRegisters[1].SrcRegister.Index,
                         &r[0], &r[1], &r[2], &r[3]);
             break;
 
index 01dd7f1..4e6fef5 100644 (file)
@@ -23,12 +23,21 @@ struct tgsi_exec_vector
 
 #define SAMPLER_CACHE_SIZE 8
 
+#define NUM_CHANNELS 4  /* R,G,B,A */
+#ifndef QUAD_SIZE
+#define QUAD_SIZE 4     /* 4 pixel/quad */
+#endif
+
 struct tgsi_sampler
 {
    const struct pipe_sampler_state *state;
    struct pipe_mipmap_tree *texture;
-   void (*get_sample)(struct tgsi_sampler *sampler,
-                      const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]);
+   /** Get samples for four fragments in a quad */
+   void (*get_samples)(struct tgsi_sampler *sampler,
+                       const GLfloat s[QUAD_SIZE],
+                       const GLfloat t[QUAD_SIZE],
+                       const GLfloat p[QUAD_SIZE],
+                       GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]);
    void *pipe; /*XXX temporary*/
 
    GLint cache_x, cache_y, cache_level;