diff options
Diffstat (limited to 'src/gallium/drivers/softpipe')
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_context.c | 24 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_context.h | 9 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_fs_exec.c | 26 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_fs_sse.c | 4 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_prim_vbuf.c | 29 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_quad_fs.c | 24 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_screen.c | 4 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_state.h | 2 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_sample.c | 979 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_sample.h | 70 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tile_cache.c | 4 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tile_cache.h | 2 | 
12 files changed, 707 insertions, 470 deletions
| diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index cd1e6663d8..800f944838 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -2,6 +2,7 @@   *    * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.   * All Rights Reserved. + * Copyright 2008 VMware, Inc.  All rights reserved.   *    * Permission is hereby granted, free of charge, to any person obtaining a   * copy of this software and associated documentation files (the @@ -221,6 +222,24 @@ softpipe_create( struct pipe_screen *screen,        softpipe->quad[i].output = sp_quad_output_stage(softpipe);     } +   /* vertex shader samplers */ +   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { +      softpipe->tgsi.vert_samplers[i].base.get_samples = sp_get_samples_vertex; +      softpipe->tgsi.vert_samplers[i].unit = i; +      softpipe->tgsi.vert_samplers[i].sp = softpipe; +      softpipe->tgsi.vert_samplers[i].cache = softpipe->tex_cache[i]; +      softpipe->tgsi.vert_samplers_list[i] = &softpipe->tgsi.vert_samplers[i]; +   } + +   /* fragment shader samplers */ +   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { +      softpipe->tgsi.frag_samplers[i].base.get_samples = sp_get_samples_fragment; +      softpipe->tgsi.frag_samplers[i].unit = i; +      softpipe->tgsi.frag_samplers[i].sp = softpipe; +      softpipe->tgsi.frag_samplers[i].cache = softpipe->tex_cache[i]; +      softpipe->tgsi.frag_samplers_list[i] = &softpipe->tgsi.frag_samplers[i]; +   } +     /*      * Create drawing context and plug our rendering stage into it.      */ @@ -228,6 +247,11 @@ softpipe_create( struct pipe_screen *screen,     if (!softpipe->draw)         goto fail; +   draw_texture_samplers(softpipe->draw, +                         PIPE_MAX_SAMPLERS, +                         (struct tgsi_sampler **) +                            softpipe->tgsi.vert_samplers_list); +     softpipe->setup = sp_draw_render_stage(softpipe);     if (!softpipe->setup)        goto fail; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 2b9a2a8ee5..7ab12a6d70 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -37,6 +37,7 @@  #include "draw/draw_vertex.h"  #include "sp_quad.h" +#include "sp_tex_sample.h"  /** @@ -139,6 +140,14 @@ struct softpipe_context {        struct quad_stage *first; /**< points to one of the above stages */     } quad[SP_NUM_QUAD_THREADS]; +   /** TGSI exec things */ +   struct { +      struct sp_shader_sampler vert_samplers[PIPE_MAX_SAMPLERS]; +      struct sp_shader_sampler *vert_samplers_list[PIPE_MAX_SAMPLERS]; +      struct sp_shader_sampler frag_samplers[PIPE_MAX_SAMPLERS]; +      struct sp_shader_sampler *frag_samplers_list[PIPE_MAX_SAMPLERS]; +   } tgsi; +     /** The primitive drawing context */     struct draw_context *draw;     struct draw_stage *setup; diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c index 701ee4c72f..453b0373f0 100644 --- a/src/gallium/drivers/softpipe/sp_fs_exec.c +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c @@ -39,11 +39,19 @@  #include "tgsi/tgsi_exec.h"  #include "tgsi/tgsi_parse.h" -struct sp_exec_fragment_shader { +struct sp_exec_fragment_shader +{     struct sp_fragment_shader base;  }; +/** cast wrapper */ +static INLINE struct sp_exec_fragment_shader * +sp_exec_fragment_shader(const struct sp_fragment_shader *base) +{ +   return (struct sp_exec_fragment_shader *) base; +} +  /**   * Compute quad X,Y,Z,W for the four fragments in a quad. @@ -84,12 +92,18 @@ sp_setup_pos_vector(const struct tgsi_interp_coef *coef,  static void  exec_prepare( const struct sp_fragment_shader *base,  	      struct tgsi_exec_machine *machine, -	      struct tgsi_sampler *samplers ) +	      struct tgsi_sampler **samplers )  { -   tgsi_exec_machine_bind_shader( machine, -				  base->shader.tokens, -				  PIPE_MAX_SAMPLERS, -				  samplers ); +   /* +    * Bind tokens/shader to the interpreter's machine state. +    * Avoid redundant binding. +    */ +   if (machine->Tokens != base->shader.tokens) { +      tgsi_exec_machine_bind_shader( machine, +                                     base->shader.tokens, +                                     PIPE_MAX_SAMPLERS, +                                     samplers ); +   }  } diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index 50eb2c07bc..9a273c8764 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -40,7 +40,7 @@  #include "tgsi/tgsi_sse2.h" -#ifdef PIPE_ARCH_X86 +#if defined(PIPE_ARCH_X86)  #include "rtasm/rtasm_x86sse.h" @@ -69,7 +69,7 @@ struct sp_sse_fragment_shader {  static void  fs_sse_prepare( const struct sp_fragment_shader *base,  		struct tgsi_exec_machine *machine, -		struct tgsi_sampler *samplers ) +		struct tgsi_sampler **samplers )  {  } diff --git a/src/gallium/drivers/softpipe/sp_prim_vbuf.c b/src/gallium/drivers/softpipe/sp_prim_vbuf.c index 425e13cd28..9cd5784e5b 100644 --- a/src/gallium/drivers/softpipe/sp_prim_vbuf.c +++ b/src/gallium/drivers/softpipe/sp_prim_vbuf.c @@ -26,10 +26,10 @@   **************************************************************************/  /** - * Post-transform vertex buffering.  This is an optional part of the - * softpipe rendering pipeline. - * Probably not desired in general, but useful for testing/debuggin. - * Enabled/Disabled with SP_VBUF env var. + * Interface between 'draw' module's output and the softpipe rasterizer/setup + * code.  When the 'draw' module has finished filling a vertex buffer, the + * draw_arrays() functions below will be called.  Loop over the vertices and + * call the point/line/tri setup functions.   *   * Authors   *  Brian Paul @@ -131,21 +131,23 @@ static INLINE cptrf4 get_vert( const void *vertex_buffer,  } +/** + * draw elements / indexed primitives + */  static void  sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)  {     struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);     struct softpipe_context *softpipe = cvbr->softpipe; -   unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); -   unsigned i; +   const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);     const void *vertex_buffer = cvbr->vertex_buffer; +   unsigned i;     /* XXX: break this dependency - make setup_context live under      * softpipe, rename the old "setup" draw stage to something else.      */     struct draw_stage *setup = softpipe->setup; -   struct setup_context *setup_ctx = sp_draw_setup_context(softpipe->setup); - +   struct setup_context *setup_ctx = sp_draw_setup_context(setup);     switch (cvbr->prim) {     case PIPE_PRIM_POINTS: @@ -258,13 +260,16 @@ sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)  {     struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);     struct softpipe_context *softpipe = cvbr->softpipe; -   struct draw_stage *setup = softpipe->setup; -   const void *vertex_buffer = NULL;     const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float); +   const void *vertex_buffer = +      (void *) get_vert(cvbr->vertex_buffer, start, stride);     unsigned i; -   struct setup_context *setup_ctx = sp_draw_setup_context(setup); -   vertex_buffer = (void *)get_vert(cvbr->vertex_buffer, start, stride); +   /* XXX: break this dependency - make setup_context live under +    * softpipe, rename the old "setup" draw stage to something else. +    */ +   struct draw_stage *setup = softpipe->setup; +   struct setup_context *setup_ctx = sp_draw_setup_context(setup);     switch (cvbr->prim) {     case PIPE_PRIM_POINTS: diff --git a/src/gallium/drivers/softpipe/sp_quad_fs.c b/src/gallium/drivers/softpipe/sp_quad_fs.c index 1f0cb3e035..5dacbbe55f 100644 --- a/src/gallium/drivers/softpipe/sp_quad_fs.c +++ b/src/gallium/drivers/softpipe/sp_quad_fs.c @@ -2,6 +2,7 @@   *    * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.   * All Rights Reserved. + * Copyright 2008 VMware, Inc.  All rights reserved.   *    * Permission is hereby granted, free of charge, to any person obtaining a   * copy of this software and associated documentation files (the @@ -50,8 +51,7 @@  struct quad_shade_stage  { -   struct quad_stage stage; -   struct tgsi_sampler samplers[PIPE_MAX_SAMPLERS]; +   struct quad_stage stage;  /**< base class */     struct tgsi_exec_machine machine;     struct tgsi_exec_vector *inputs, *outputs;  }; @@ -147,18 +147,11 @@ static void shade_begin(struct quad_stage *qs)  {     struct quad_shade_stage *qss = quad_shade_stage(qs);     struct softpipe_context *softpipe = qs->softpipe; -   unsigned i; -   unsigned num = MAX2(softpipe->num_textures, softpipe->num_samplers); - -   /* set TGSI sampler state that varies */ -   for (i = 0; i < num; i++) { -      qss->samplers[i].state = softpipe->sampler[i]; -      qss->samplers[i].texture = softpipe->texture[i]; -   }     softpipe->fs->prepare( softpipe->fs,   			  &qss->machine, -			  qss->samplers ); +			  (struct tgsi_sampler **) +                             softpipe->tgsi.frag_samplers_list );     qs->next->begin(qs->next);  } @@ -178,7 +171,6 @@ static void shade_destroy(struct quad_stage *qs)  struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )  {     struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage); -   uint i;     /* allocate storage for program inputs/outputs, aligned to 16 bytes */     qss->inputs = MALLOC(PIPE_MAX_ATTRIBS * sizeof(*qss->inputs) + 16); @@ -191,14 +183,6 @@ struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe )     qss->stage.run = shade_quad;     qss->stage.destroy = shade_destroy; -   /* set TGSI sampler state that's constant */ -   for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { -      assert(softpipe->tex_cache[i]); -      qss->samplers[i].get_samples = sp_get_samples; -      qss->samplers[i].pipe = &softpipe->pipe; -      qss->samplers[i].cache = softpipe->tex_cache[i]; -   } -     tgsi_exec_machine_init( &qss->machine );     return &qss->stage; diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 9644dbd168..11b08b3a82 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -55,7 +55,9 @@ softpipe_get_param(struct pipe_screen *screen, int param)  {     switch (param) {     case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: -      return 8; +      return PIPE_MAX_SAMPLERS; +   case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS: +      return PIPE_MAX_SAMPLERS;     case PIPE_CAP_NPOT_TEXTURES:        return 1;     case PIPE_CAP_TWO_SIDED_STENCIL: diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 476ef3dc8f..3eff41ffa5 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -69,7 +69,7 @@ struct sp_fragment_shader {     void (*prepare)( const struct sp_fragment_shader *shader,  		    struct tgsi_exec_machine *machine, -		    struct tgsi_sampler *samplers); +		    struct tgsi_sampler **samplers);     /* Run the shader - this interface will get cleaned up in the      * future: diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index 49250ec084..32aa5025e4 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -2,6 +2,7 @@   *    * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.   * All Rights Reserved. + * Copyright 2008 VMware, Inc.  All rights reserved.   *   * Permission is hereby granted, free of charge, to any person obtaining a   * copy of this software and associated documentation files (the @@ -35,15 +36,16 @@  #include "sp_context.h"  #include "sp_headers.h"  #include "sp_surface.h" +#include "sp_texture.h"  #include "sp_tex_sample.h"  #include "sp_tile_cache.h"  #include "pipe/p_context.h"  #include "pipe/p_defines.h" -#include "tgsi/tgsi_exec.h"  #include "util/u_math.h"  #include "util/u_memory.h" +  /*   * Note, the FRAC macro has to work perfectly.  Otherwise you'll sometimes   * see 1-pixel bands of improperly weighted linear-filtered textures. @@ -57,7 +59,11 @@  /**   * Linear interpolation macro   */ -#define LERP(T, A, B)  ( (A) + (T) * ((B) - (A)) ) +static INLINE float +lerp(float a, float v0, float v1) +{ +   return v0 + a * (v1 - v0); +}  /** @@ -72,12 +78,27 @@ static INLINE float  lerp_2d(float a, float b,          float v00, float v10, float v01, float v11)  { -   const float temp0 = LERP(a, v00, v10); -   const float temp1 = LERP(a, v01, v11); -   return LERP(b, temp0, temp1); +   const float temp0 = lerp(a, v00, v10); +   const float temp1 = lerp(a, v01, v11); +   return lerp(b, temp0, temp1); +} + + +/** + * As above, but 3D interpolation of 8 values. + */ +static INLINE float +lerp_3d(float a, float b, float c, +        float v000, float v100, float v010, float v110, +        float v001, float v101, float v011, float v111) +{ +   const float temp0 = lerp_2d(a, b, v000, v100, v010, v110); +   const float temp1 = lerp_2d(a, b, v001, v101, v011, v111); +   return lerp(c, temp0, temp1);  } +  /**   * If A is a signed integer, A % B doesn't give the right value for A < 0   * (in terms of texture repeat).  Just casting to unsigned fixes that. @@ -86,250 +107,275 @@ lerp_2d(float a, float b,  /** - * Apply texture coord wrapping mode and return integer texture index. + * Apply texture coord wrapping mode and return integer texture indexes + * for a vector of four texcoords (S or T or P).   * \param wrapMode  PIPE_TEX_WRAP_x - * \param s  the texcoord + * \param s  the incoming texcoords   * \param size  the texture image size + * \param icoord  returns the integer texcoords   * \return  integer texture index   */ -static INLINE int -nearest_texcoord(unsigned wrapMode, float s, unsigned size) +static INLINE void +nearest_texcoord_4(unsigned wrapMode, const float s[4], unsigned size, +                   int icoord[4])  { -   int i; +   uint ch;     switch (wrapMode) {     case PIPE_TEX_WRAP_REPEAT:        /* s limited to [0,1) */        /* i limited to [0,size-1] */ -      i = util_ifloor(s * size); -      i = REMAINDER(i, size); -      return i; +      for (ch = 0; ch < 4; ch++) { +         int i = util_ifloor(s[ch] * size); +         icoord[ch] = REMAINDER(i, size); +      } +      return;     case PIPE_TEX_WRAP_CLAMP:        /* s limited to [0,1] */        /* i limited to [0,size-1] */ -      if (s <= 0.0F) -         i = 0; -      else if (s >= 1.0F) -         i = size - 1; -      else -         i = util_ifloor(s * size); -      return i; +      for (ch = 0; ch < 4; ch++) { +         if (s[ch] <= 0.0F) +            icoord[ch] = 0; +         else if (s[ch] >= 1.0F) +            icoord[ch] = size - 1; +         else +            icoord[ch] = util_ifloor(s[ch] * size); +      } +      return;     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:        {           /* s limited to [min,max] */           /* i limited to [0, size-1] */           const float min = 1.0F / (2.0F * size);           const float max = 1.0F - min; -         if (s < min) -            i = 0; -         else if (s > max) -            i = size - 1; -         else -            i = util_ifloor(s * size); +         for (ch = 0; ch < 4; ch++) { +            if (s[ch] < min) +               icoord[ch] = 0; +            else if (s[ch] > max) +               icoord[ch] = size - 1; +            else +               icoord[ch] = util_ifloor(s[ch] * size); +         }        } -      return i; +      return;     case PIPE_TEX_WRAP_CLAMP_TO_BORDER:        {           /* s limited to [min,max] */           /* i limited to [-1, size] */           const float min = -1.0F / (2.0F * size);           const float max = 1.0F - min; -         if (s <= min) -            i = -1; -         else if (s >= max) -            i = size; -         else -            i = util_ifloor(s * size); +         for (ch = 0; ch < 4; ch++) { +            if (s[ch] <= min) +               icoord[ch] = -1; +            else if (s[ch] >= max) +               icoord[ch] = size; +            else +               icoord[ch] = util_ifloor(s[ch] * size); +         }        } -      return i; +      return;     case PIPE_TEX_WRAP_MIRROR_REPEAT:        {           const float min = 1.0F / (2.0F * size);           const float max = 1.0F - min; -         const int flr = util_ifloor(s); -         float u; -         if (flr & 1) -            u = 1.0F - (s - (float) flr); -         else -            u = s - (float) flr; -         if (u < min) -            i = 0; -         else if (u > max) -            i = size - 1; -         else -            i = util_ifloor(u * size); +         for (ch = 0; ch < 4; ch++) { +            const int flr = util_ifloor(s[ch]); +            float u; +            if (flr & 1) +               u = 1.0F - (s[ch] - (float) flr); +            else +               u = s[ch] - (float) flr; +            if (u < min) +               icoord[ch] = 0; +            else if (u > max) +               icoord[ch] = size - 1; +            else +               icoord[ch] = util_ifloor(u * size); +         }        } -      return i; +      return;     case PIPE_TEX_WRAP_MIRROR_CLAMP: -      { +      for (ch = 0; ch < 4; ch++) {           /* s limited to [0,1] */           /* i limited to [0,size-1] */ -         const float u = fabsf(s); +         const float u = fabsf(s[ch]);           if (u <= 0.0F) -            i = 0; +            icoord[ch] = 0;           else if (u >= 1.0F) -            i = size - 1; +            icoord[ch] = size - 1;           else -            i = util_ifloor(u * size); +            icoord[ch] = util_ifloor(u * size);        } -      return i; +      return;     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:        {           /* s limited to [min,max] */           /* i limited to [0, size-1] */           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) -            i = size - 1; -         else -            i = util_ifloor(u * size); +         for (ch = 0; ch < 4; ch++) { +            const float u = fabsf(s[ch]); +            if (u < min) +               icoord[ch] = 0; +            else if (u > max) +               icoord[ch] = size - 1; +            else +               icoord[ch] = util_ifloor(u * size); +         }        } -      return i; +      return;     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:        {           /* s limited to [min,max] */           /* i limited to [0, size-1] */           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) -            i = size; -         else -            i = util_ifloor(u * size); +         for (ch = 0; ch < 4; ch++) { +            const float u = fabsf(s[ch]); +            if (u < min) +               icoord[ch] = -1; +            else if (u > max) +               icoord[ch] = size; +            else +               icoord[ch] = util_ifloor(u * size); +         }        } -      return i; +      return;     default:        assert(0); -      return 0;     }  }  /** - * Used to compute texel locations for linear sampling. + * Used to compute texel locations for linear sampling for four texcoords.   * \param wrapMode  PIPE_TEX_WRAP_x - * \param s  the texcoord + * \param s  the texcoords   * \param size  the texture image size - * \param i0  returns first texture index - * \param i1  returns second texture index (usually *i0 + 1) - * \param a  returns blend factor/weight between texture indexes + * \param icoord0  returns first texture indexes + * \param icoord1  returns second texture indexes (usually icoord0 + 1) + * \param w  returns blend factor/weight between texture indexes + * \param icoord  returns the computed integer texture coords   */  static INLINE void -linear_texcoord(unsigned wrapMode, float s, unsigned size, -                int *i0, int *i1, float *a) +linear_texcoord_4(unsigned wrapMode, const float s[4], unsigned size, +                  int icoord0[4], int icoord1[4], float w[4])  { -   float u; +   uint ch; +     switch (wrapMode) {     case PIPE_TEX_WRAP_REPEAT: -      u = s * size - 0.5F; -      *i0 = REMAINDER(util_ifloor(u), size); -      *i1 = REMAINDER(*i0 + 1, size); -      break; +      for (ch = 0; ch < 4; ch++) { +         float u = s[ch] * size - 0.5F; +         icoord0[ch] = REMAINDER(util_ifloor(u), size); +         icoord1[ch] = REMAINDER(icoord0[ch] + 1, size); +         w[ch] = FRAC(u); +      } +      break;;     case PIPE_TEX_WRAP_CLAMP: -      if (s <= 0.0F) -         u = 0.0F; -      else if (s >= 1.0F) -         u = (float) size; -      else -         u = s * size; -      u -= 0.5F; -      *i0 = util_ifloor(u); -      *i1 = *i0 + 1; -      break; +      for (ch = 0; ch < 4; ch++) { +         float u = CLAMP(s[ch], 0.0F, 1.0F); +         u = u * size - 0.5f; +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         w[ch] = FRAC(u); +      } +      break;;     case PIPE_TEX_WRAP_CLAMP_TO_EDGE: -      if (s <= 0.0F) -         u = 0.0F; -      else if (s >= 1.0F) -         u = (float) size; -      else -         u = s * size; -      u -= 0.5F; -      *i0 = util_ifloor(u); -      *i1 = *i0 + 1; -      if (*i0 < 0) -         *i0 = 0; -      if (*i1 >= (int) size) -         *i1 = size - 1; -      break; +      for (ch = 0; ch < 4; ch++) { +         float u = CLAMP(s[ch], 0.0F, 1.0F); +         u = u * size - 0.5f; +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         if (icoord0[ch] < 0) +            icoord0[ch] = 0; +         if (icoord1[ch] >= (int) size) +            icoord1[ch] = size - 1; +         w[ch] = FRAC(u); +      } +      break;;     case PIPE_TEX_WRAP_CLAMP_TO_BORDER:        {           const float min = -1.0F / (2.0F * size);           const float max = 1.0F - min; -         if (s <= min) -            u = min * size; -         else if (s >= max) -            u = max * size; -         else -            u = s * size; -         u -= 0.5F; -         *i0 = util_ifloor(u); -         *i1 = *i0 + 1; +         for (ch = 0; ch < 4; ch++) { +            float u = CLAMP(s[ch], min, max); +            u = u * size - 0.5f; +            icoord0[ch] = util_ifloor(u); +            icoord1[ch] = icoord0[ch] + 1; +            w[ch] = FRAC(u); +         }        } -      break; +      break;;     case PIPE_TEX_WRAP_MIRROR_REPEAT: -      { -         const int flr = util_ifloor(s); +      for (ch = 0; ch < 4; ch++) { +         const int flr = util_ifloor(s[ch]); +         float u;           if (flr & 1) -            u = 1.0F - (s - (float) flr); +            u = 1.0F - (s[ch] - (float) flr);           else -            u = s - (float) flr; -         u = (u * size) - 0.5F; -         *i0 = util_ifloor(u); -         *i1 = *i0 + 1; -         if (*i0 < 0) -            *i0 = 0; -         if (*i1 >= (int) size) -            *i1 = size - 1; +            u = s[ch] - (float) flr; +         u = u * size - 0.5F; +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         if (icoord0[ch] < 0) +            icoord0[ch] = 0; +         if (icoord1[ch] >= (int) size) +            icoord1[ch] = size - 1; +         w[ch] = FRAC(u);        } -      break; +      break;;     case PIPE_TEX_WRAP_MIRROR_CLAMP: -      u = fabsf(s); -      if (u >= 1.0F) -         u = (float) size; -      else -         u *= size; -      u -= 0.5F; -      *i0 = util_ifloor(u); -      *i1 = *i0 + 1; -      break; +      for (ch = 0; ch < 4; ch++) { +         float u = fabsf(s[ch]); +         if (u >= 1.0F) +            u = (float) size; +         else +            u *= size; +         u -= 0.5F; +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         w[ch] = FRAC(u); +      } +      break;;     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: -      u = fabsf(s); -      if (u >= 1.0F) -         u = (float) size; -      else -         u *= size; -      u -= 0.5F; -      *i0 = util_ifloor(u); -      *i1 = *i0 + 1; -      if (*i0 < 0) -         *i0 = 0; -      if (*i1 >= (int) size) -         *i1 = size - 1; -      break; +      for (ch = 0; ch < 4; ch++) { +         float u = fabsf(s[ch]); +         if (u >= 1.0F) +            u = (float) size; +         else +            u *= size; +         u -= 0.5F; +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         if (icoord0[ch] < 0) +            icoord0[ch] = 0; +         if (icoord1[ch] >= (int) size) +            icoord1[ch] = size - 1; +         w[ch] = FRAC(u); +      } +      break;;     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:        {           const float min = -1.0F / (2.0F * size);           const float max = 1.0F - min; -         u = fabsf(s); -         if (u <= min) -            u = min * size; -         else if (u >= max) -            u = max * size; -         else -            u *= size; -         u -= 0.5F; -         *i0 = util_ifloor(u); -         *i1 = *i0 + 1; +         for (ch = 0; ch < 4; ch++) { +            float u = fabsf(s[ch]); +            if (u <= min) +               u = min * size; +            else if (u >= max) +               u = max * size; +            else +               u *= size; +            u -= 0.5F; +            icoord0[ch] = util_ifloor(u); +            icoord1[ch] = icoord0[ch] + 1; +            w[ch] = FRAC(u); +         }        } -      break; +      break;;     default:        assert(0);     } -   *a = FRAC(u);  } @@ -337,21 +383,27 @@ linear_texcoord(unsigned wrapMode, float s, unsigned size,   * For RECT textures / unnormalized texcoords   * Only a subset of wrap modes supported.   */ -static INLINE int -nearest_texcoord_unnorm(unsigned wrapMode, float s, unsigned size) +static INLINE void +nearest_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size, +                          int icoord[4])  { -   int i; +   uint ch;     switch (wrapMode) {     case PIPE_TEX_WRAP_CLAMP: -      i = util_ifloor(s); -      return CLAMP(i, 0, (int) size-1); +      for (ch = 0; ch < 4; ch++) { +         int i = util_ifloor(s[ch]); +         icoord[ch]= CLAMP(i, 0, (int) size-1); +      } +      return;     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:        /* fall-through */     case PIPE_TEX_WRAP_CLAMP_TO_BORDER: -      return util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) ); +      for (ch = 0; ch < 4; ch++) { +         icoord[ch]= util_ifloor( CLAMP(s[ch], 0.5F, (float) size - 0.5F) ); +      } +      return;     default:        assert(0); -      return 0;     }  } @@ -361,30 +413,36 @@ nearest_texcoord_unnorm(unsigned wrapMode, float s, unsigned size)   * Only a subset of wrap modes supported.   */  static INLINE void -linear_texcoord_unnorm(unsigned wrapMode, float s, unsigned size, -                       int *i0, int *i1, float *a) +linear_texcoord_unnorm_4(unsigned wrapMode, const float s[4], unsigned size, +                         int icoord0[4], int icoord1[4], float w[4])  { +   uint ch;     switch (wrapMode) {     case PIPE_TEX_WRAP_CLAMP: -      /* Not exactly what the spec says, but it matches NVIDIA output */ -      s = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f); -      *i0 = util_ifloor(s); -      *i1 = *i0 + 1; -      break; +      for (ch = 0; ch < 4; ch++) { +         /* Not exactly what the spec says, but it matches NVIDIA output */ +         float u = CLAMP(s[ch] - 0.5F, 0.0f, (float) size - 1.0f); +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         w[ch] = FRAC(u); +      } +      return;     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:        /* fall-through */     case PIPE_TEX_WRAP_CLAMP_TO_BORDER: -      s = CLAMP(s, 0.5F, (float) size - 0.5F); -      s -= 0.5F; -      *i0 = util_ifloor(s); -      *i1 = *i0 + 1; -      if (*i1 > (int) size - 1) -         *i1 = size - 1; +      for (ch = 0; ch < 4; ch++) { +         float u = CLAMP(s[ch], 0.5F, (float) size - 0.5F); +         u -= 0.5F; +         icoord0[ch] = util_ifloor(u); +         icoord1[ch] = icoord0[ch] + 1; +         if (icoord1[ch] > (int) size - 1) +            icoord1[ch] = size - 1; +         w[ch] = FRAC(u); +      }        break;     default:        assert(0);     } -   *a = FRAC(s);  } @@ -463,7 +521,8 @@ choose_cube_face(float rx, float ry, float rz, float *newS, float *newT)   * This is only done for fragment shaders, not vertex shaders.   */  static float -compute_lambda(struct tgsi_sampler *sampler, +compute_lambda(const struct pipe_texture *tex, +               const struct pipe_sampler_state *sampler,                 const float s[QUAD_SIZE],                 const float t[QUAD_SIZE],                 const float p[QUAD_SIZE], @@ -471,7 +530,7 @@ compute_lambda(struct tgsi_sampler *sampler,  {     float rho, lambda; -   assert(sampler->state->normalized_coords); +   assert(sampler->normalized_coords);     assert(s);     { @@ -479,7 +538,7 @@ compute_lambda(struct tgsi_sampler *sampler,        float dsdy = s[QUAD_TOP_LEFT]     - s[QUAD_BOTTOM_LEFT];        dsdx = fabsf(dsdx);        dsdy = fabsf(dsdy); -      rho = MAX2(dsdx, dsdy) * sampler->texture->width[0]; +      rho = MAX2(dsdx, dsdy) * tex->width[0];     }     if (t) {        float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]; @@ -487,7 +546,7 @@ compute_lambda(struct tgsi_sampler *sampler,        float max;        dtdx = fabsf(dtdx);        dtdy = fabsf(dtdy); -      max = MAX2(dtdx, dtdy) * sampler->texture->height[0]; +      max = MAX2(dtdx, dtdy) * tex->height[0];        rho = MAX2(rho, max);     }     if (p) { @@ -496,13 +555,13 @@ compute_lambda(struct tgsi_sampler *sampler,        float max;        dpdx = fabsf(dpdx);        dpdy = fabsf(dpdy); -      max = MAX2(dpdx, dpdy) * sampler->texture->depth[0]; +      max = MAX2(dpdx, dpdy) * tex->depth[0];        rho = MAX2(rho, max);     }     lambda = util_fast_log2(rho); -   lambda += lodbias + sampler->state->lod_bias; -   lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod); +   lambda += lodbias + sampler->lod_bias; +   lambda = CLAMP(lambda, sampler->min_lod, sampler->max_lod);     return lambda;  } @@ -514,68 +573,74 @@ compute_lambda(struct tgsi_sampler *sampler,   * 2. Determine if we're minifying or magnifying   * 3. If minifying, choose mipmap levels   * 4. Return image filter to use within mipmap images + * \param level0  Returns first mipmap level to sample from + * \param level1  Returns second mipmap level to sample from + * \param levelBlend  Returns blend factor between levels, in [0,1] + * \param imgFilter  Returns either the min or mag filter, depending on lambda   */  static void -choose_mipmap_levels(struct tgsi_sampler *sampler, +choose_mipmap_levels(const struct pipe_texture *texture, +                     const struct pipe_sampler_state *sampler,                       const float s[QUAD_SIZE],                       const float t[QUAD_SIZE],                       const float p[QUAD_SIZE], +                     boolean computeLambda,                       float lodbias,                       unsigned *level0, unsigned *level1, float *levelBlend,                       unsigned *imgFilter)  { -   if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) { +   if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {        /* no mipmap selection needed */ -      *level0 = *level1 = CLAMP((int) sampler->state->min_lod, -                                0, (int) sampler->texture->last_level); +      *level0 = *level1 = CLAMP((int) sampler->min_lod, +                                0, (int) texture->last_level); -      if (sampler->state->min_img_filter != sampler->state->mag_img_filter) { +      if (sampler->min_img_filter != sampler->mag_img_filter) {           /* non-mipmapped texture, but still need to determine if doing            * minification or magnification.            */ -         float lambda = compute_lambda(sampler, s, t, p, lodbias); +         float lambda = compute_lambda(texture, sampler, s, t, p, lodbias);           if (lambda <= 0.0) { -            *imgFilter = sampler->state->mag_img_filter; +            *imgFilter = sampler->mag_img_filter;           }           else { -            *imgFilter = sampler->state->min_img_filter; +            *imgFilter = sampler->min_img_filter;           }        }        else { -         *imgFilter = sampler->state->mag_img_filter; +         *imgFilter = sampler->mag_img_filter;        }     }     else {        float lambda; -      if (1) +      if (computeLambda)           /* fragment shader */ -         lambda = compute_lambda(sampler, s, t, p, lodbias); +         lambda = compute_lambda(texture, sampler, s, t, p, lodbias);        else           /* vertex shader */           lambda = lodbias; /* not really a bias, but absolute LOD */        if (lambda <= 0.0) { /* XXX threshold depends on the filter */           /* magnifying */ -         *imgFilter = sampler->state->mag_img_filter; +         *imgFilter = sampler->mag_img_filter;           *level0 = *level1 = 0;        }        else {           /* minifying */ -         *imgFilter = sampler->state->min_img_filter; +         *imgFilter = sampler->min_img_filter;           /* choose mipmap level(s) and compute the blend factor between them */ -         if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) { +         if (sampler->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST) {              /* Nearest mipmap level */              const int lvl = (int) (lambda + 0.5);              *level0 = -            *level1 = CLAMP(lvl, 0, (int) sampler->texture->last_level); +            *level1 = CLAMP(lvl, 0, (int) texture->last_level);           }           else {              /* Linear interpolation between mipmap levels */              const int lvl = (int) lambda; -            *level0 = CLAMP(lvl,     0, (int) sampler->texture->last_level); -            *level1 = CLAMP(lvl + 1, 0, (int) sampler->texture->last_level); +            *level0 = CLAMP(lvl,     0, (int) texture->last_level); +            *level1 = CLAMP(lvl + 1, 0, (int) texture->last_level);              *levelBlend = FRAC(lambda);  /* blending weight between levels */           }        } @@ -598,23 +663,29 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,   * sp_get_cached_tile_tex() function.  Also, get 4 texels instead of 1...   */  static void -get_texel(struct tgsi_sampler *sampler, +get_texel(const struct tgsi_sampler *tgsi_sampler,            unsigned face, unsigned level, int x, int y, int z,            float rgba[NUM_CHANNELS][QUAD_SIZE], unsigned j)  { -   if (x < 0 || x >= (int) sampler->texture->width[level] || -       y < 0 || y >= (int) sampler->texture->height[level] || -       z < 0 || z >= (int) sampler->texture->depth[level]) { -      rgba[0][j] = sampler->state->border_color[0]; -      rgba[1][j] = sampler->state->border_color[1]; -      rgba[2][j] = sampler->state->border_color[2]; -      rgba[3][j] = sampler->state->border_color[3]; +   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); +   struct softpipe_context *sp = samp->sp; +   const uint unit = samp->unit; +   const struct pipe_texture *texture = sp->texture[unit]; +   const struct pipe_sampler_state *sampler = sp->sampler[unit]; + +   if (x < 0 || x >= (int) texture->width[level] || +       y < 0 || y >= (int) texture->height[level] || +       z < 0 || z >= (int) texture->depth[level]) { +      rgba[0][j] = sampler->border_color[0]; +      rgba[1][j] = sampler->border_color[1]; +      rgba[2][j] = sampler->border_color[2]; +      rgba[3][j] = sampler->border_color[3];     }     else {        const int tx = x % TILE_SIZE;        const int ty = y % TILE_SIZE;        const struct softpipe_cached_tile *tile -         = sp_get_cached_tile_tex(sampler->pipe, sampler->cache, +         = sp_get_cached_tile_tex(sp, samp->cache,                                    x, y, z, face, level);        rgba[0][j] = tile->data.color[ty][tx][0];        rgba[1][j] = tile->data.color[ty][tx][1]; @@ -624,7 +695,7 @@ get_texel(struct tgsi_sampler *sampler,        {           debug_printf("Get texel %f %f %f %f from %s\n",                        rgba[0][j], rgba[1][j], rgba[2][j], rgba[3][j], -                      pf_name(sampler->texture->format)); +                      pf_name(texture->format));        }     }  } @@ -682,103 +753,124 @@ shadow_compare(uint compare_func,   * Could probably extend for 3D...   */  static void -sp_get_samples_2d_common(struct tgsi_sampler *sampler, +sp_get_samples_2d_common(const struct tgsi_sampler *tgsi_sampler,                           const float s[QUAD_SIZE],                           const float t[QUAD_SIZE],                           const float p[QUAD_SIZE], +                         boolean computeLambda,                           float lodbias,                           float rgba[NUM_CHANNELS][QUAD_SIZE],                           const unsigned faces[4])  { -   const uint compare_func = sampler->state->compare_func; +   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); +   const struct softpipe_context *sp = samp->sp; +   const uint unit = samp->unit; +   const struct pipe_texture *texture = sp->texture[unit]; +   const struct pipe_sampler_state *sampler = sp->sampler[unit]; +   const uint compare_func = sampler->compare_func;     unsigned level0, level1, j, imgFilter;     int width, height;     float levelBlend; -   choose_mipmap_levels(sampler, s, t, p, lodbias, +   choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,                          &level0, &level1, &levelBlend, &imgFilter); -   assert(sampler->state->normalized_coords); +   assert(sampler->normalized_coords); -   width = sampler->texture->width[level0]; -   height = sampler->texture->height[level0]; +   width = texture->width[level0]; +   height = texture->height[level0];     assert(width > 0);     switch (imgFilter) {     case PIPE_TEX_FILTER_NEAREST: -      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, faces[j], level0, x, y, 0, rgba, j); -         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { -            shadow_compare(compare_func, rgba, p, j); -         } +      { +         int x[4], y[4]; +         nearest_texcoord_4(sampler->wrap_s, s, width, x); +         nearest_texcoord_4(sampler->wrap_t, t, height, y); -         if (level0 != level1) { -            /* get texels from second mipmap level and blend */ -            float rgba2[4][4]; -            unsigned c; -            x = x / 2; -            y = y / 2; -            get_texel(sampler, faces[j], level1, x, y, 0, rgba2, j); -            if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ -               shadow_compare(compare_func, rgba2, p, j); +         for (j = 0; j < QUAD_SIZE; j++) { +            get_texel(tgsi_sampler, faces[j], level0, x[j], y[j], 0, rgba, j); +            if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +               shadow_compare(compare_func, rgba, p, j);              } -            for (c = 0; c < NUM_CHANNELS; c++) { -               rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]); +            if (level0 != level1) { +               /* get texels from second mipmap level and blend */ +               float rgba2[4][4]; +               unsigned c; +               x[j] /= 2; +               y[j] /= 2; +               get_texel(tgsi_sampler, faces[j], level1, x[j], y[j], 0, +                         rgba2, j); +               if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ +                  shadow_compare(compare_func, rgba2, p, j); +               } + +               for (c = 0; c < NUM_CHANNELS; c++) { +                  rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); +               }              }           }        }        break;     case PIPE_TEX_FILTER_LINEAR:     case PIPE_TEX_FILTER_ANISO: -      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, faces[j], level0, x0, y0, 0, tx, 0); -         get_texel(sampler, faces[j], level0, x1, y0, 0, tx, 1); -         get_texel(sampler, faces[j], level0, x0, y1, 0, tx, 2); -         get_texel(sampler, faces[j], level0, x1, y1, 0, tx, 3); -         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { -            shadow_compare(compare_func, tx, p, 0); -            shadow_compare(compare_func, tx, p, 1); -            shadow_compare(compare_func, tx, p, 2); -            shadow_compare(compare_func, tx, p, 3); -         } +      { +         int x0[4], y0[4], x1[4], y1[4]; +         float xw[4], yw[4]; /* weights */ -         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]); -         } +         linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw); +         linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); -         if (level0 != level1) { -            /* get texels from second mipmap level and blend */ -            float rgba2[4][4]; -            x0 = x0 / 2; -            y0 = y0 / 2; -            x1 = x1 / 2; -            y1 = y1 / 2; -            get_texel(sampler, faces[j], level1, x0, y0, 0, tx, 0); -            get_texel(sampler, faces[j], level1, x1, y0, 0, tx, 1); -            get_texel(sampler, faces[j], level1, x0, y1, 0, tx, 2); -            get_texel(sampler, faces[j], level1, x1, y1, 0, tx, 3); -            if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ +         for (j = 0; j < QUAD_SIZE; j++) { +            float tx[4][4]; /* texels */ +            int c; +            get_texel(tgsi_sampler, faces[j], level0, x0[j], y0[j], 0, tx, 0); +            get_texel(tgsi_sampler, faces[j], level0, x1[j], y0[j], 0, tx, 1); +            get_texel(tgsi_sampler, faces[j], level0, x0[j], y1[j], 0, tx, 2); +            get_texel(tgsi_sampler, faces[j], level0, x1[j], y1[j], 0, tx, 3); +            if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) {                 shadow_compare(compare_func, tx, p, 0);                 shadow_compare(compare_func, tx, p, 1);                 shadow_compare(compare_func, tx, p, 2);                 shadow_compare(compare_func, tx, p, 3);              } +            /* interpolate R, G, B, A */              for (c = 0; c < 4; c++) { -               rgba2[c][j] = lerp_2d(a, b, -                                     tx[c][0], tx[c][1], tx[c][2], tx[c][3]); +               rgba[c][j] = lerp_2d(xw[j], yw[j], +                                    tx[c][0], tx[c][1], +                                    tx[c][2], tx[c][3]);              } -            for (c = 0; c < NUM_CHANNELS; c++) { -               rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]); +            if (level0 != level1) { +               /* get texels from second mipmap level and blend */ +               float rgba2[4][4]; +               x0[j] /= 2; +               y0[j] /= 2; +               x1[j] /= 2; +               y1[j] /= 2; +               get_texel(tgsi_sampler, faces[j], level1, x0[j], y0[j], 0, tx, 0); +               get_texel(tgsi_sampler, faces[j], level1, x1[j], y0[j], 0, tx, 1); +               get_texel(tgsi_sampler, faces[j], level1, x0[j], y1[j], 0, tx, 2); +               get_texel(tgsi_sampler, faces[j], level1, x1[j], y1[j], 0, tx, 3); +               if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE){ +                  shadow_compare(compare_func, tx, p, 0); +                  shadow_compare(compare_func, tx, p, 1); +                  shadow_compare(compare_func, tx, p, 2); +                  shadow_compare(compare_func, tx, p, 3); +               } + +               /* interpolate R, G, B, A */ +               for (c = 0; c < 4; c++) { +                  rgba2[c][j] = lerp_2d(xw[j], yw[j], +                                        tx[c][0], tx[c][1], tx[c][2], tx[c][3]); +               } + +               for (c = 0; c < NUM_CHANNELS; c++) { +                  rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); +               }              }           }        } @@ -789,55 +881,65 @@ sp_get_samples_2d_common(struct tgsi_sampler *sampler,  } -static void -sp_get_samples_1d(struct tgsi_sampler *sampler, +static INLINE void +sp_get_samples_1d(const struct tgsi_sampler *sampler,                    const float s[QUAD_SIZE],                    const float t[QUAD_SIZE],                    const float p[QUAD_SIZE], +                  boolean computeLambda,                    float lodbias,                    float rgba[NUM_CHANNELS][QUAD_SIZE])  {     static const unsigned faces[4] = {0, 0, 0, 0};     static const float tzero[4] = {0, 0, 0, 0}; -   sp_get_samples_2d_common(sampler, s, tzero, NULL, lodbias, rgba, faces); +   sp_get_samples_2d_common(sampler, s, tzero, NULL, +                            computeLambda, lodbias, rgba, faces);  } -static void -sp_get_samples_2d(struct tgsi_sampler *sampler, +static INLINE void +sp_get_samples_2d(const struct tgsi_sampler *sampler,                    const float s[QUAD_SIZE],                    const float t[QUAD_SIZE],                    const float p[QUAD_SIZE], +                  boolean computeLambda,                    float lodbias,                    float rgba[NUM_CHANNELS][QUAD_SIZE])  {     static const unsigned faces[4] = {0, 0, 0, 0}; -   sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces); +   sp_get_samples_2d_common(sampler, s, t, p, +                            computeLambda, lodbias, rgba, faces);  } -static void -sp_get_samples_3d(struct tgsi_sampler *sampler, +static INLINE void +sp_get_samples_3d(const struct tgsi_sampler *tgsi_sampler,                    const float s[QUAD_SIZE],                    const float t[QUAD_SIZE],                    const float p[QUAD_SIZE], +                  boolean computeLambda,                    float lodbias,                    float rgba[NUM_CHANNELS][QUAD_SIZE])  { +   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); +   const struct softpipe_context *sp = samp->sp; +   const uint unit = samp->unit; +   const struct pipe_texture *texture = sp->texture[unit]; +   const struct pipe_sampler_state *sampler = sp->sampler[unit];     /* get/map pipe_surfaces corresponding to 3D tex slices */     unsigned level0, level1, j, imgFilter;     int width, height, depth;     float levelBlend;     const uint face = 0; -   choose_mipmap_levels(sampler, s, t, p, lodbias, +   choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,                          &level0, &level1, &levelBlend, &imgFilter); -   assert(sampler->state->normalized_coords); +   assert(sampler->normalized_coords); -   width = sampler->texture->width[level0]; -   height = sampler->texture->height[level0]; -   depth = sampler->texture->depth[level0]; +   width = texture->width[level0]; +   height = texture->height[level0]; +   depth = texture->depth[level0];     assert(width > 0);     assert(height > 0); @@ -845,89 +947,89 @@ sp_get_samples_3d(struct tgsi_sampler *sampler,     switch (imgFilter) {     case PIPE_TEX_FILTER_NEAREST: -      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); -         int z = nearest_texcoord(sampler->state->wrap_r, p[j], depth); -         get_texel(sampler, face, level0, x, y, z, rgba, j); - -         if (level0 != level1) { -            /* get texels from second mipmap level and blend */ -            float rgba2[4][4]; -            unsigned c; -            x /= 2; -            y /= 2; -            z /= 2; -            get_texel(sampler, face, level1, x, y, z, rgba2, j); -            for (c = 0; c < NUM_CHANNELS; c++) { -               rgba[c][j] = LERP(levelBlend, rgba2[c][j], rgba[c][j]); +      { +         int x[4], y[4], z[4]; +         nearest_texcoord_4(sampler->wrap_s, s, width, x); +         nearest_texcoord_4(sampler->wrap_t, t, height, y); +         nearest_texcoord_4(sampler->wrap_r, p, depth, z); +         for (j = 0; j < QUAD_SIZE; j++) { +            get_texel(tgsi_sampler, face, level0, x[j], y[j], z[j], rgba, j); +            if (level0 != level1) { +               /* get texels from second mipmap level and blend */ +               float rgba2[4][4]; +               unsigned c; +               x[j] /= 2; +               y[j] /= 2; +               z[j] /= 2; +               get_texel(tgsi_sampler, face, level1, x[j], y[j], z[j], rgba2, j); +               for (c = 0; c < NUM_CHANNELS; c++) { +                  rgba[c][j] = lerp(levelBlend, rgba2[c][j], rgba[c][j]); +               }              }           }        }        break;     case PIPE_TEX_FILTER_LINEAR:     case PIPE_TEX_FILTER_ANISO: -      for (j = 0; j < QUAD_SIZE; j++) { -         float texel0[4][4], texel1[4][4]; -         float xw, yw, zw; /* interpolation weights */ -         int x0, x1, y0, y1, z0, z1, c; -         linear_texcoord(sampler->state->wrap_s, s[j], width,  &x0, &x1, &xw); -         linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &yw); -         linear_texcoord(sampler->state->wrap_r, p[j], depth,  &z0, &z1, &zw); -         get_texel(sampler, face, level0, x0, y0, z0, texel0, 0); -         get_texel(sampler, face, level0, x1, y0, z0, texel0, 1); -         get_texel(sampler, face, level0, x0, y1, z0, texel0, 2); -         get_texel(sampler, face, level0, x1, y1, z0, texel0, 3); -         get_texel(sampler, face, level0, x0, y0, z1, texel1, 0); -         get_texel(sampler, face, level0, x1, y0, z1, texel1, 1); -         get_texel(sampler, face, level0, x0, y1, z1, texel1, 2); -         get_texel(sampler, face, level0, x1, y1, z1, texel1, 3); - -         /* 3D lerp */ -         for (c = 0; c < 4; c++) { -            float ctemp0[4][4], ctemp1[4][4]; -            ctemp0[c][j] = lerp_2d(xw, yw, -                                   texel0[c][0], texel0[c][1], -                                   texel0[c][2], texel0[c][3]); -            ctemp1[c][j] = lerp_2d(xw, yw, -                                   texel1[c][0], texel1[c][1], -                                   texel1[c][2], texel1[c][3]); -            rgba[c][j] = LERP(zw, ctemp0[c][j], ctemp1[c][j]); -         } +      { +         int x0[4], x1[4], y0[4], y1[4], z0[4], z1[4]; +         float xw[4], yw[4], zw[4]; /* interpolation weights */ +         linear_texcoord_4(sampler->wrap_s, s, width,  x0, x1, xw); +         linear_texcoord_4(sampler->wrap_t, t, height, y0, y1, yw); +         linear_texcoord_4(sampler->wrap_r, p, depth,  z0, z1, zw); -         if (level0 != level1) { -            /* get texels from second mipmap level and blend */ -            float rgba2[4][4]; -            x0 /= 2; -            y0 /= 2; -            z0 /= 2; -            x1 /= 2; -            y1 /= 2; -            z1 /= 2; -            get_texel(sampler, face, level1, x0, y0, z0, texel0, 0); -            get_texel(sampler, face, level1, x1, y0, z0, texel0, 1); -            get_texel(sampler, face, level1, x0, y1, z0, texel0, 2); -            get_texel(sampler, face, level1, x1, y1, z0, texel0, 3); -            get_texel(sampler, face, level1, x0, y0, z1, texel1, 0); -            get_texel(sampler, face, level1, x1, y0, z1, texel1, 1); -            get_texel(sampler, face, level1, x0, y1, z1, texel1, 2); -            get_texel(sampler, face, level1, x1, y1, z1, texel1, 3); +         for (j = 0; j < QUAD_SIZE; j++) { +            int c; +            float tx0[4][4], tx1[4][4]; +            get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z0[j], tx0, 0); +            get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z0[j], tx0, 1); +            get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z0[j], tx0, 2); +            get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z0[j], tx0, 3); +            get_texel(tgsi_sampler, face, level0, x0[j], y0[j], z1[j], tx1, 0); +            get_texel(tgsi_sampler, face, level0, x1[j], y0[j], z1[j], tx1, 1); +            get_texel(tgsi_sampler, face, level0, x0[j], y1[j], z1[j], tx1, 2); +            get_texel(tgsi_sampler, face, level0, x1[j], y1[j], z1[j], tx1, 3); -            /* 3D lerp */ +            /* interpolate R, G, B, A */              for (c = 0; c < 4; c++) { -               float ctemp0[4][4], ctemp1[4][4]; -               ctemp0[c][j] = lerp_2d(xw, yw, -                                      texel0[c][0], texel0[c][1], -                                      texel0[c][2], texel0[c][3]); -               ctemp1[c][j] = lerp_2d(xw, yw, -                                      texel1[c][0], texel1[c][1], -                                      texel1[c][2], texel1[c][3]); -               rgba2[c][j] = LERP(zw, ctemp0[c][j], ctemp1[c][j]); +               rgba[c][j] = lerp_3d(xw[j], yw[j], zw[j], +                                    tx0[c][0], tx0[c][1], +                                    tx0[c][2], tx0[c][3], +                                    tx1[c][0], tx1[c][1], +                                    tx1[c][2], tx1[c][3]);              } -            /* blend mipmap levels */ -            for (c = 0; c < NUM_CHANNELS; c++) { -               rgba[c][j] = LERP(levelBlend, rgba[c][j], rgba2[c][j]); +            if (level0 != level1) { +               /* get texels from second mipmap level and blend */ +               float rgba2[4][4]; +               x0[j] /= 2; +               y0[j] /= 2; +               z0[j] /= 2; +               x1[j] /= 2; +               y1[j] /= 2; +               z1[j] /= 2; +               get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z0[j], tx0, 0); +               get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z0[j], tx0, 1); +               get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z0[j], tx0, 2); +               get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z0[j], tx0, 3); +               get_texel(tgsi_sampler, face, level1, x0[j], y0[j], z1[j], tx1, 0); +               get_texel(tgsi_sampler, face, level1, x1[j], y0[j], z1[j], tx1, 1); +               get_texel(tgsi_sampler, face, level1, x0[j], y1[j], z1[j], tx1, 2); +               get_texel(tgsi_sampler, face, level1, x1[j], y1[j], z1[j], tx1, 3); + +               /* interpolate R, G, B, A */ +               for (c = 0; c < 4; c++) { +                  rgba2[c][j] = lerp_3d(xw[j], yw[j], zw[j], +                                        tx0[c][0], tx0[c][1], +                                        tx0[c][2], tx0[c][3], +                                        tx1[c][0], tx1[c][1], +                                        tx1[c][2], tx1[c][3]); +               } + +               /* blend mipmap levels */ +               for (c = 0; c < NUM_CHANNELS; c++) { +                  rgba[c][j] = lerp(levelBlend, rgba[c][j], rgba2[c][j]); +               }              }           }        } @@ -939,10 +1041,11 @@ sp_get_samples_3d(struct tgsi_sampler *sampler,  static void -sp_get_samples_cube(struct tgsi_sampler *sampler, +sp_get_samples_cube(const struct tgsi_sampler *sampler,                      const float s[QUAD_SIZE],                      const float t[QUAD_SIZE],                      const float p[QUAD_SIZE], +                    boolean computeLambda,                      float lodbias,                      float rgba[NUM_CHANNELS][QUAD_SIZE])  { @@ -951,67 +1054,80 @@ sp_get_samples_cube(struct tgsi_sampler *sampler,     for (j = 0; j < QUAD_SIZE; j++) {        faces[j] = choose_cube_face(s[j], t[j], p[j], ssss + j, tttt + j);     } -   sp_get_samples_2d_common(sampler, ssss, tttt, NULL, lodbias, rgba, faces); +   sp_get_samples_2d_common(sampler, ssss, tttt, NULL, +                            computeLambda, lodbias, rgba, faces);  }  static void -sp_get_samples_rect(struct tgsi_sampler *sampler, +sp_get_samples_rect(const struct tgsi_sampler *tgsi_sampler,                      const float s[QUAD_SIZE],                      const float t[QUAD_SIZE],                      const float p[QUAD_SIZE], +                    boolean computeLambda,                      float lodbias,                      float rgba[NUM_CHANNELS][QUAD_SIZE])  { -   //sp_get_samples_2d_common(sampler, s, t, p, lodbias, rgba, faces); -   static const uint face = 0; -   const uint compare_func = sampler->state->compare_func; +   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); +   const struct softpipe_context *sp = samp->sp; +   const uint unit = samp->unit; +   const struct pipe_texture *texture = sp->texture[unit]; +   const struct pipe_sampler_state *sampler = sp->sampler[unit]; +   const uint face = 0; +   const uint compare_func = sampler->compare_func;     unsigned level0, level1, j, imgFilter;     int width, height;     float levelBlend; -   choose_mipmap_levels(sampler, s, t, p, lodbias, +   choose_mipmap_levels(texture, sampler, s, t, p, computeLambda, lodbias,                          &level0, &level1, &levelBlend, &imgFilter);     /* texture RECTS cannot be mipmapped */     assert(level0 == level1); -   width = sampler->texture->width[level0]; -   height = sampler->texture->height[level0]; +   width = texture->width[level0]; +   height = texture->height[level0];     assert(width > 0);     switch (imgFilter) {     case PIPE_TEX_FILTER_NEAREST: -      for (j = 0; j < QUAD_SIZE; j++) { -         int x = nearest_texcoord_unnorm(sampler->state->wrap_s, s[j], width); -         int y = nearest_texcoord_unnorm(sampler->state->wrap_t, t[j], height); -         get_texel(sampler, face, level0, x, y, 0, rgba, j); -         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { -            shadow_compare(compare_func, rgba, p, j); +      { +         int x[4], y[4]; +         nearest_texcoord_unnorm_4(sampler->wrap_s, s, width, x); +         nearest_texcoord_unnorm_4(sampler->wrap_t, t, height, y); +         for (j = 0; j < QUAD_SIZE; j++) { +            get_texel(tgsi_sampler, face, level0, x[j], y[j], 0, rgba, j); +            if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +               shadow_compare(compare_func, rgba, p, j); +            }           }        }        break;     case PIPE_TEX_FILTER_LINEAR:     case PIPE_TEX_FILTER_ANISO: -      for (j = 0; j < QUAD_SIZE; j++) { -         float tx[4][4], a, b; -         int x0, y0, x1, y1, c; -         linear_texcoord_unnorm(sampler->state->wrap_s, s[j], width,  &x0, &x1, &a); -         linear_texcoord_unnorm(sampler->state->wrap_t, t[j], height, &y0, &y1, &b); -         get_texel(sampler, face, level0, x0, y0, 0, tx, 0); -         get_texel(sampler, face, level0, x1, y0, 0, tx, 1); -         get_texel(sampler, face, level0, x0, y1, 0, tx, 2); -         get_texel(sampler, face, level0, x1, y1, 0, tx, 3); -         if (sampler->state->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { -            shadow_compare(compare_func, tx, p, 0); -            shadow_compare(compare_func, tx, p, 1); -            shadow_compare(compare_func, tx, p, 2); -            shadow_compare(compare_func, tx, p, 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]); +      { +         int x0[4], y0[4], x1[4], y1[4]; +         float xw[4], yw[4]; /* weights */ +         linear_texcoord_unnorm_4(sampler->wrap_s, s, width,  x0, x1, xw); +         linear_texcoord_unnorm_4(sampler->wrap_t, t, height, y0, y1, yw); +         for (j = 0; j < QUAD_SIZE; j++) { +            float tx[4][4]; /* texels */ +            int c; +            get_texel(tgsi_sampler, face, level0, x0[j], y0[j], 0, tx, 0); +            get_texel(tgsi_sampler, face, level0, x1[j], y0[j], 0, tx, 1); +            get_texel(tgsi_sampler, face, level0, x0[j], y1[j], 0, tx, 2); +            get_texel(tgsi_sampler, face, level0, x1[j], y1[j], 0, tx, 3); +            if (sampler->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { +               shadow_compare(compare_func, tx, p, 0); +               shadow_compare(compare_func, tx, p, 1); +               shadow_compare(compare_func, tx, p, 2); +               shadow_compare(compare_func, tx, p, 3); +            } +            for (c = 0; c < 4; c++) { +               rgba[c][j] = lerp_2d(xw[j], yw[j], +                                    tx[c][0], tx[c][1], tx[c][2], tx[c][3]); +            }           }        }        break; @@ -1021,49 +1137,45 @@ sp_get_samples_rect(struct tgsi_sampler *sampler,  } - -  /** - * Called via tgsi_sampler::get_samples() - * Use the sampler's state setting to get a filtered RGBA value - * from the sampler's texture. - * - * XXX we can implement many versions of this function, each - * tightly coded for a specific combination of sampler state - * (nearest + repeat), (bilinear mipmap + clamp), etc. - * - * The update_samplers() function in st_atom_sampler.c could create - * a new tgsi_sampler object for each state combo it finds.... + * Common code for vertex/fragment program texture sampling.   */ -void -sp_get_samples(struct tgsi_sampler *sampler, +static INLINE void +sp_get_samples(struct tgsi_sampler *tgsi_sampler,                 const float s[QUAD_SIZE],                 const float t[QUAD_SIZE],                 const float p[QUAD_SIZE], +               boolean computeLambda,                 float lodbias,                 float rgba[NUM_CHANNELS][QUAD_SIZE])  { -   if (!sampler->texture) +   const struct sp_shader_sampler *samp = sp_shader_sampler(tgsi_sampler); +   const struct softpipe_context *sp = samp->sp; +   const uint unit = samp->unit; +   const struct pipe_texture *texture = sp->texture[unit]; +   const struct pipe_sampler_state *sampler = sp->sampler[unit]; + +   if (!texture)        return; -   switch (sampler->texture->target) { +   switch (texture->target) {     case PIPE_TEXTURE_1D: -      assert(sampler->state->normalized_coords); -      sp_get_samples_1d(sampler, s, t, p, lodbias, rgba); +      assert(sampler->normalized_coords); +      sp_get_samples_1d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);        break;     case PIPE_TEXTURE_2D: -      if (sampler->state->normalized_coords) -         sp_get_samples_2d(sampler, s, t, p, lodbias, rgba); +      if (sampler->normalized_coords) +         sp_get_samples_2d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);        else -         sp_get_samples_rect(sampler, s, t, p, lodbias, rgba); +         sp_get_samples_rect(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);        break;     case PIPE_TEXTURE_3D: -      assert(sampler->state->normalized_coords); -      sp_get_samples_3d(sampler, s, t, p, lodbias, rgba); +      assert(sampler->normalized_coords); +      sp_get_samples_3d(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);        break;     case PIPE_TEXTURE_CUBE: -      assert(sampler->state->normalized_coords); -      sp_get_samples_cube(sampler, s, t, p, lodbias, rgba); +      assert(sampler->normalized_coords); +      sp_get_samples_cube(tgsi_sampler, s, t, p, computeLambda, lodbias, rgba);        break;     default:        assert(0); @@ -1084,3 +1196,34 @@ sp_get_samples(struct tgsi_sampler *sampler,  #endif  } + +/** + * Called via tgsi_sampler::get_samples() when running a fragment shader. + * Get four filtered RGBA values from the sampler's texture. + */ +void +sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler, +                        const float s[QUAD_SIZE], +                        const float t[QUAD_SIZE], +                        const float p[QUAD_SIZE], +                        float lodbias, +                        float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ +   sp_get_samples(tgsi_sampler, s, t, p, TRUE, lodbias, rgba); +} + + +/** + * Called via tgsi_sampler::get_samples() when running a vertex shader. + * Get four filtered RGBA values from the sampler's texture. + */ +void +sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler, +                      const float s[QUAD_SIZE], +                      const float t[QUAD_SIZE], +                      const float p[QUAD_SIZE], +                      float lodbias, +                      float rgba[NUM_CHANNELS][QUAD_SIZE]) +{ +   sp_get_samples(tgsi_sampler, s, t, p, FALSE, lodbias, rgba); +} diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.h b/src/gallium/drivers/softpipe/sp_tex_sample.h index 404bfd0c36..40d8eb2c2a 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.h +++ b/src/gallium/drivers/softpipe/sp_tex_sample.h @@ -1,17 +1,73 @@ +/************************************************************************** + *  + * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + *  + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + *  + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + *  + **************************************************************************/ +  #ifndef SP_TEX_SAMPLE_H  #define SP_TEX_SAMPLE_H -struct tgsi_sampler; +#include "tgsi/tgsi_exec.h" + + +/** + * Subclass of tgsi_sampler + */ +struct sp_shader_sampler +{ +   struct tgsi_sampler base;  /**< base class */ + +   uint unit; +   struct softpipe_context *sp; +   struct softpipe_tile_cache *cache; +}; + +static INLINE const struct sp_shader_sampler * +sp_shader_sampler(const struct tgsi_sampler *sampler) +{ +   return (const struct sp_shader_sampler *) sampler; +} + + +extern void +sp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler, +                        const float s[QUAD_SIZE], +                        const float t[QUAD_SIZE], +                        const float p[QUAD_SIZE], +                        float lodbias, +                        float rgba[NUM_CHANNELS][QUAD_SIZE]); +  extern void -sp_get_samples(struct tgsi_sampler *sampler, -               const float s[QUAD_SIZE], -               const float t[QUAD_SIZE], -               const float p[QUAD_SIZE], -               float lodbias, -               float rgba[NUM_CHANNELS][QUAD_SIZE]); +sp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler, +                      const float s[QUAD_SIZE], +                      const float t[QUAD_SIZE], +                      const float p[QUAD_SIZE], +                      float lodbias, +                      float rgba[NUM_CHANNELS][QUAD_SIZE]);  #endif /* SP_TEX_SAMPLE_H */ diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index b50c984513..78b0efa46d 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -494,11 +494,11 @@ tex_cache_pos(int x, int y, int z, int face, int level)   * Tiles are read-only and indexed with more params.   */  const struct softpipe_cached_tile * -sp_get_cached_tile_tex(struct pipe_context *pipe, +sp_get_cached_tile_tex(struct softpipe_context *sp,                         struct softpipe_tile_cache *tc, int x, int y, int z,                         int face, int level)  { -   struct pipe_screen *screen = pipe->screen; +   struct pipe_screen *screen = sp->pipe.screen;     /* tile pos in framebuffer: */     const int tile_x = x & ~(TILE_SIZE - 1);     const int tile_y = y & ~(TILE_SIZE - 1); diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index bc96c941f6..a66bb50bcc 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -96,7 +96,7 @@ sp_get_cached_tile(struct softpipe_context *softpipe,                     struct softpipe_tile_cache *tc, int x, int y);  extern const struct softpipe_cached_tile * -sp_get_cached_tile_tex(struct pipe_context *pipe, +sp_get_cached_tile_tex(struct softpipe_context *softpipe,                         struct softpipe_tile_cache *tc, int x, int y, int z,                         int face, int level); | 
