summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/softpipe
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/softpipe')
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c11
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h7
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_exec.c26
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_sse.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_prim_vbuf.c29
-rw-r--r--src/gallium/drivers/softpipe/sp_quad_fs.c23
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h2
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.c933
-rw-r--r--src/gallium/drivers/softpipe/sp_tex_sample.h50
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.c4
-rw-r--r--src/gallium/drivers/softpipe/sp_tile_cache.h2
12 files changed, 638 insertions, 455 deletions
diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c
index cd1e6663d86..99b52748575 100644
--- a/src/gallium/drivers/softpipe/sp_context.c
+++ b/src/gallium/drivers/softpipe/sp_context.c
@@ -221,6 +221,14 @@ softpipe_create( struct pipe_screen *screen,
softpipe->quad[i].output = sp_quad_output_stage(softpipe);
}
+ for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
+ softpipe->tgsi.samplers[i].base.get_samples = sp_get_samples;
+ softpipe->tgsi.samplers[i].unit = i;
+ softpipe->tgsi.samplers[i].sp = softpipe;
+ softpipe->tgsi.samplers[i].cache = softpipe->tex_cache[i];
+ softpipe->tgsi.samplers_list[i] = &softpipe->tgsi.samplers[i];
+ }
+
/*
* Create drawing context and plug our rendering stage into it.
*/
@@ -228,6 +236,9 @@ softpipe_create( struct pipe_screen *screen,
if (!softpipe->draw)
goto fail;
+ draw_texture_samplers(softpipe->draw,
+ PIPE_MAX_SAMPLERS, softpipe->tgsi.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 2b9a2a8ee52..790143aecc9 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,12 @@ 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 samplers[PIPE_MAX_SAMPLERS];
+ struct sp_shader_sampler *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 701ee4c72f2..453b0373f0f 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 50eb2c07bcb..9a273c87643 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 425e13cd283..9cd5784e5bc 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 1f0cb3e0355..963a2b44f55 100644
--- a/src/gallium/drivers/softpipe/sp_quad_fs.c
+++ b/src/gallium/drivers/softpipe/sp_quad_fs.c
@@ -50,8 +50,9 @@
struct quad_shade_stage
{
- struct quad_stage stage;
- struct tgsi_sampler samplers[PIPE_MAX_SAMPLERS];
+ struct quad_stage stage; /**< base class */
+ struct sp_shader_sampler samplers[PIPE_MAX_SAMPLERS];
+ struct sp_shader_sampler *samplers_list[PIPE_MAX_SAMPLERS];
struct tgsi_exec_machine machine;
struct tgsi_exec_vector *inputs, *outputs;
};
@@ -147,18 +148,10 @@ 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 **) qss->samplers_list );
qs->next->begin(qs->next);
}
@@ -191,12 +184,14 @@ 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 */
+ /* setup TGSI sampler state */
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].base.get_samples = sp_get_samples;
+ qss->samplers[i].unit = i;
+ qss->samplers[i].sp = softpipe;
qss->samplers[i].cache = softpipe->tex_cache[i];
+ qss->samplers_list[i] = &qss->samplers[i];
}
tgsi_exec_machine_init( &qss->machine );
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 9644dbd168f..12f98c32f53 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -56,6 +56,8 @@ softpipe_get_param(struct pipe_screen *screen, int param)
switch (param) {
case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
return 8;
+ case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
+ return 8;
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 476ef3dc8fb..3eff41ffa5f 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 49250ec084c..631c60966c2 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.c
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.c
@@ -35,6 +35,7 @@
#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"
@@ -57,7 +58,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,13 +77,28 @@ 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 +106,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 +382,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 +412,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 +520,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 +529,7 @@ compute_lambda(struct tgsi_sampler *sampler,
{
float rho, lambda;
- assert(sampler->state->normalized_coords);
+ assert(sampler->normalized_coords);
assert(s);
{
@@ -479,7 +537,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 +545,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 +554,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,9 +572,14 @@ 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],
@@ -524,25 +587,25 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,
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 {
@@ -550,32 +613,32 @@ choose_mipmap_levels(struct tgsi_sampler *sampler,
if (1)
/* 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 +661,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 +693,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,7 +751,7 @@ 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],
@@ -690,95 +759,115 @@ sp_get_samples_2d_common(struct tgsi_sampler *sampler,
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, 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);
- }
-
- 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);
+ {
+ int x[4], y[4];
+ nearest_texcoord_4(sampler->wrap_s, s, width, x);
+ nearest_texcoord_4(sampler->wrap_t, t, height, y);
+
+ 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);
- }
-
- 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]);
- }
-
- 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){
+ {
+ int x0[4], y0[4], x1[4], y1[4];
+ float xw[4], yw[4]; /* weights */
+
+ linear_texcoord_4(sampler->wrap_s, s, width, x0, x1, xw);
+ linear_texcoord_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, 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,8 +878,8 @@ 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],
@@ -803,8 +892,8 @@ sp_get_samples_1d(struct tgsi_sampler *sampler,
}
-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],
@@ -816,28 +905,33 @@ sp_get_samples_2d(struct tgsi_sampler *sampler,
}
-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],
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, 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 +939,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]);
- }
-
- 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);
-
- /* 3D lerp */
+ {
+ 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);
+
+ 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);
+
+ /* 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,7 +1033,7 @@ 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],
@@ -956,62 +1050,73 @@ sp_get_samples_cube(struct tgsi_sampler *sampler,
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],
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, 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 +1126,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....
+ * Get four filtered RGBA values from the sampler's texture.
*/
void
-sp_get_samples(struct tgsi_sampler *sampler,
+sp_get_samples(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])
{
- 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, 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, lodbias, rgba);
else
- sp_get_samples_rect(sampler, s, t, p, lodbias, rgba);
+ sp_get_samples_rect(tgsi_sampler, s, t, p, 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, 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, lodbias, rgba);
break;
default:
assert(0);
diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.h b/src/gallium/drivers/softpipe/sp_tex_sample.h
index 404bfd0c365..f0a8a787782 100644
--- a/src/gallium/drivers/softpipe/sp_tex_sample.h
+++ b/src/gallium/drivers/softpipe/sp_tex_sample.h
@@ -1,8 +1,56 @@
+/**************************************************************************
+ *
+ * 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
diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c
index b50c9845133..78b0efa46d2 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 bc96c941f61..a66bb50bcc1 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);