tgsi_sampler->get_samples() now operates on a quad (returns 4 colors).

Lambda/level-of-detail is also computed in get_samples() now.
This commit is contained in:
Brian 2007-08-14 11:00:35 -06:00
parent 9f51e181b1
commit b4480285ed
5 changed files with 287 additions and 229 deletions

View file

@ -322,7 +322,7 @@ static void shade_begin(struct quad_stage *qs)
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
qss->samplers[i].state = &softpipe->sampler[i];
qss->samplers[i].texture = softpipe->texture[i];
qss->samplers[i].get_sample = sp_get_sample;
qss->samplers[i].get_samples = sp_get_samples;
qss->samplers[i].pipe = &softpipe->pipe;
/* init cache info here */
qss->samplers[i].cache_x =

View file

@ -66,12 +66,12 @@
* optimization! If we find that's not true on some systems, convert
* to a macro.
*/
static INLINE GLfloat
lerp_2d(GLfloat a, GLfloat b,
GLfloat v00, GLfloat v10, GLfloat v01, GLfloat v11)
static INLINE float
lerp_2d(float a, float b,
float v00, float v10, float v01, float v11)
{
const GLfloat temp0 = LERP(a, v00, v10);
const GLfloat temp1 = LERP(a, v01, v11);
const float temp0 = LERP(a, v00, v10);
const float temp1 = LERP(a, v01, v11);
return LERP(b, temp0, temp1);
}
@ -98,7 +98,7 @@ repeat_remainder(GLint a, GLint b)
* \return integer texture index
*/
static INLINE GLint
nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
nearest_texcoord(GLuint wrapMode, float s, GLuint size)
{
GLint i;
switch (wrapMode) {
@ -122,8 +122,8 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const GLfloat min = 1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s < min)
i = 0;
else if (s > max)
@ -136,8 +136,8 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
{
/* s limited to [min,max] */
/* i limited to [-1, size] */
const GLfloat min = -1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s <= min)
i = -1;
else if (s >= max)
@ -148,14 +148,14 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
return i;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
{
const GLfloat min = 1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
const GLint flr = IFLOOR(s);
GLfloat u;
float u;
if (flr & 1)
u = 1.0F - (s - (GLfloat) flr);
u = 1.0F - (s - (float) flr);
else
u = s - (GLfloat) flr;
u = s - (float) flr;
if (u < min)
i = 0;
else if (u > max)
@ -168,7 +168,7 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
{
/* s limited to [0,1] */
/* i limited to [0,size-1] */
const GLfloat u = FABSF(s);
const float u = FABSF(s);
if (u <= 0.0F)
i = 0;
else if (u >= 1.0F)
@ -181,9 +181,9 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const GLfloat min = 1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const GLfloat u = FABSF(s);
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
const float u = FABSF(s);
if (u < min)
i = 0;
else if (u > max)
@ -196,9 +196,9 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const GLfloat min = -1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const GLfloat u = FABSF(s);
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
const float u = FABSF(s);
if (u < min)
i = -1;
else if (u > max)
@ -224,10 +224,10 @@ nearest_texcoord(GLuint wrapMode, GLfloat s, GLuint size)
* \param a returns blend factor/weight between texture indexes
*/
static INLINE void
linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
GLint *i0, GLint *i1, GLfloat *a)
linear_texcoord(GLuint wrapMode, float s, GLuint size,
GLint *i0, GLint *i1, float *a)
{
GLfloat u;
float u;
switch (wrapMode) {
case PIPE_TEX_WRAP_REPEAT:
u = s * size - 0.5F;
@ -238,7 +238,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
if (s <= 0.0F)
u = 0.0F;
else if (s >= 1.0F)
u = (GLfloat) size;
u = (float) size;
else
u = s * size;
u -= 0.5F;
@ -249,7 +249,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
if (s <= 0.0F)
u = 0.0F;
else if (s >= 1.0F)
u = (GLfloat) size;
u = (float) size;
else
u = s * size;
u -= 0.5F;
@ -262,8 +262,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
break;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
{
const GLfloat min = -1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s <= min)
u = min * size;
else if (s >= max)
@ -279,9 +279,9 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
{
const GLint flr = IFLOOR(s);
if (flr & 1)
u = 1.0F - (s - (GLfloat) flr);
u = 1.0F - (s - (float) flr);
else
u = s - (GLfloat) flr;
u = s - (float) flr;
u = (u * size) - 0.5F;
*i0 = IFLOOR(u);
*i1 = *i0 + 1;
@ -294,7 +294,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
case PIPE_TEX_WRAP_MIRROR_CLAMP:
u = FABSF(s);
if (u >= 1.0F)
u = (GLfloat) size;
u = (float) size;
else
u *= size;
u -= 0.5F;
@ -304,7 +304,7 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
u = FABSF(s);
if (u >= 1.0F)
u = (GLfloat) size;
u = (float) size;
else
u *= size;
u -= 0.5F;
@ -317,8 +317,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
break;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
{
const GLfloat min = -1.0F / (2.0F * size);
const GLfloat max = 1.0F - min;
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
u = FABSF(s);
if (u <= min)
u = min * size;
@ -339,7 +339,8 @@ linear_texcoord(GLuint wrapMode, GLfloat s, GLuint size,
static GLuint
choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4])
choose_cube_face(float rx, float ry, float rz,
float newCoord[4])
{
/*
major axis
@ -352,12 +353,9 @@ choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4])
+rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
-rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
*/
const GLfloat rx = texcoord[0];
const GLfloat ry = texcoord[1];
const GLfloat rz = texcoord[2];
const GLfloat arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
const float arx = FABSF(rx), ary = FABSF(ry), arz = FABSF(rz);
GLuint face;
GLfloat sc, tc, ma;
float sc, tc, ma;
if (arx > ary && arx > arz) {
if (rx >= 0.0F) {
@ -409,9 +407,62 @@ choose_cube_face(const GLfloat texcoord[4], GLfloat newCoord[4])
}
/**
* Examine the quad's texture coordinates to compute the partial
* derivatives w.r.t X and Y, then compute lambda (level of detail).
*
* This is only done for fragment shaders, not vertex shaders.
*/
static float
compute_lambda(struct tgsi_sampler *sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE])
{
float rho, lambda;
assert(s);
{
float dsdx = s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT];
float dsdy = s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT];
dsdx = FABSF(dsdx);
dsdy = FABSF(dsdy);
rho = MAX2(dsdx, dsdy) * sampler->texture->width0;
}
if (t) {
float dtdx = t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT];
float dtdy = t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT];
float max;
dtdx = FABSF(dtdx);
dtdy = FABSF(dtdy);
max = MAX2(dtdx, dtdy) * sampler->texture->height0;
rho = MAX2(rho, max);
}
if (p) {
float dpdx = p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT];
float dpdy = p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT];
float max;
dpdx = FABSF(dpdx);
dpdy = FABSF(dpdy);
max = MAX2(dpdx, dpdy) * sampler->texture->depth0;
rho = MAX2(rho, max);
}
lambda = LOG2(rho);
lambda += sampler->state->lod_bias;
lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod);
return lambda;
}
static void
sp_get_sample_1d(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
sp_get_samples_1d(struct tgsi_sampler *sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
struct pipe_surface *ps
@ -420,26 +471,40 @@ sp_get_sample_1d(struct tgsi_sampler *sampler,
switch (sampler->state->min_img_filter) {
case PIPE_TEX_FILTER_NEAREST:
{
GLint x;
x = nearest_texcoord(sampler->state->wrap_s, strq[0],
sampler->texture->width0);
ps->get_tile(ps, x, 0, 1, 1, rgba);
GLuint j;
for (j = 0; j < QUAD_SIZE; j++) {
GLint x = nearest_texcoord(sampler->state->wrap_s, s[j],
sampler->texture->width0);
float texel[4];
ps->get_tile(ps, x, 0, 1, 1, texel);
rgba[0][j] = texel[0];
rgba[1][j] = texel[1];
rgba[2][j] = texel[2];
rgba[3][j] = texel[3];
}
}
break;
case PIPE_TEX_FILTER_LINEAR:
{
GLfloat t0[4], t1[4];
GLint x0, x1;
GLfloat a;
linear_texcoord(sampler->state->wrap_s, strq[0],
sampler->texture->width0, &x0, &x1, &a);
ps->get_tile(ps, x0, 0, 1, 1, t0);
ps->get_tile(ps, x1, 0, 1, 1, t1);
GLuint j;
for (j = 0; j < QUAD_SIZE; j++) {
float t0[4], t1[4], texel[4];
GLint x0, x1;
float a;
linear_texcoord(sampler->state->wrap_s, s[j],
sampler->texture->width0, &x0, &x1, &a);
ps->get_tile(ps, x0, 0, 1, 1, t0);
ps->get_tile(ps, x1, 0, 1, 1, t1);
rgba[0] = LERP(a, t0[0], t1[0]);
rgba[1] = LERP(a, t0[1], t1[1]);
rgba[2] = LERP(a, t0[2], t1[2]);
rgba[3] = LERP(a, t0[3], t1[3]);
texel[0] = LERP(a, t0[0], t1[0]);
texel[1] = LERP(a, t0[1], t1[1]);
texel[2] = LERP(a, t0[2], t1[2]);
texel[3] = LERP(a, t0[3], t1[3]);
rgba[0][j] = texel[0];
rgba[1][j] = texel[1];
rgba[2][j] = texel[2];
rgba[3][j] = texel[3];
}
}
break;
default:
@ -448,7 +513,7 @@ sp_get_sample_1d(struct tgsi_sampler *sampler,
}
static GLuint
choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda)
choose_mipmap_level(struct tgsi_sampler *sampler, float lambda)
{
if (sampler->state->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
return 0;
@ -463,7 +528,68 @@ choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda)
/**
* Called via tgsi_sampler::get_sample()
* Load the texture cache with a new texture tile.
*/
static void
cache_tex_tile(struct tgsi_sampler *sampler,
unsigned face, unsigned level, unsigned zslice, int cx, int cy)
{
struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
struct pipe_surface *ps
= pipe->get_tex_surface(pipe, sampler->texture, face, level, zslice);
assert(ps->width == sampler->texture->level[level].width);
assert(ps->height == sampler->texture->level[level].height);
sampler->cache_level = level;
sampler->cache_x = cx;
sampler->cache_y = cy;
ps->get_tile(ps,
cx * SAMPLER_CACHE_SIZE,
cy * SAMPLER_CACHE_SIZE,
SAMPLER_CACHE_SIZE, SAMPLER_CACHE_SIZE,
(float *) sampler->cache);
}
/**
* Get a texel from a texture.
* \param face the cube face in 0..5
* \param level the mipmap level
* \param zslize which slice of a 3D texture
* \param x the x coord of texel within 2D image
* \param y the y coord of texel within 2D image
* \param rgba the quad to put the texel/color into
* \param j which element of the rgba quad to write to
*/
static void
get_texel(struct tgsi_sampler *sampler,
unsigned face, unsigned level, unsigned zslice, int x, int y,
float rgba[NUM_CHANNELS][QUAD_SIZE], GLuint j)
{
int cx = x / SAMPLER_CACHE_SIZE;
int cy = y / SAMPLER_CACHE_SIZE;
if (cx != sampler->cache_x || cy != sampler->cache_y ||
level != sampler->cache_level) {
cache_tex_tile(sampler, face, level, zslice, cx, cy);
printf("cache miss (%d, %d)\n", x, y);
}
else {
printf("cache hit (%d, %d)\n", x, y);
}
/* get texel from cache */
cx = x % SAMPLER_CACHE_SIZE;
cy = y % SAMPLER_CACHE_SIZE;
rgba[0][j] = sampler->cache[cy][cx][0];
rgba[1][j] = sampler->cache[cy][cx][1];
rgba[2][j] = sampler->cache[cy][cx][2];
rgba[3][j] = sampler->cache[cy][cx][3];
}
/**
* Called via tgsi_sampler::get_samples()
* Use the sampler's state setting to get a filtered RGBA value
* from the sampler's texture (mipmap tree).
*
@ -475,87 +601,62 @@ choose_mipmap_level(struct tgsi_sampler *sampler, GLfloat lambda)
* a new tgsi_sampler object for each state combo it finds....
*/
static void
sp_get_sample_2d(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
sp_get_samples_2d(struct tgsi_sampler *sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
struct pipe_context *pipe = (struct pipe_context *) sampler->pipe;
GLuint filter;
GLint level0;
if (lambda < 0.0)
filter = sampler->state->mag_img_filter;
else
filter = sampler->state->min_img_filter;
level0 = choose_mipmap_level(sampler, lambda);
assert(sampler->texture->level[level0].width);
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
GLuint j, imgFilter;
int level0, width, height;
/* compute level0 and imgFilter */
switch (sampler->state->min_mip_filter) {
case PIPE_TEX_MIPFILTER_NONE:
imgFilter = sampler->state->mag_img_filter;
level0 = 0;
assert(sampler->state->min_img_filter ==
sampler->state->mag_img_filter);
break;
default:
{
GLint x = nearest_texcoord(sampler->state->wrap_s, strq[0],
sampler->texture->level[level0].width);
GLint y = nearest_texcoord(sampler->state->wrap_t, strq[1],
sampler->texture->level[level0].height);
GLint cx = x / SAMPLER_CACHE_SIZE;
GLint cy = y / SAMPLER_CACHE_SIZE;
if (cx != sampler->cache_x || cy != sampler->cache_y ||
level0 != sampler->cache_level) {
/* cache miss, replace cache with new tile */
struct pipe_surface *ps
= pipe->get_tex_surface(pipe, sampler->texture, 0, level0, 0);
assert(ps->width == sampler->texture->level[level0].width);
assert(ps->height == sampler->texture->level[level0].height);
sampler->cache_level = level0;
sampler->cache_x = cx;
sampler->cache_y = cy;
ps->get_tile(ps,
cx * SAMPLER_CACHE_SIZE,
cy * SAMPLER_CACHE_SIZE,
SAMPLER_CACHE_SIZE, SAMPLER_CACHE_SIZE,
(GLfloat *) sampler->cache);
/*printf("cache miss (%d, %d)\n", x, y);*/
}
else {
/*printf("cache hit (%d, %d)\n", x, y);*/
}
/* get texel from cache */
cx = x % SAMPLER_CACHE_SIZE;
cy = y % SAMPLER_CACHE_SIZE;
COPY_4V(rgba, sampler->cache[cy][cx]);
float lambda = compute_lambda(sampler, s, t, p);
if (lambda < 0.0)
imgFilter = sampler->state->mag_img_filter;
else
imgFilter = sampler->state->min_img_filter;
level0 = choose_mipmap_level(sampler, lambda);
}
}
width = sampler->texture->level[level0].width;
height = sampler->texture->level[level0].height;
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, 0, level0, 0, x, y, rgba, j);
}
break;
case PIPE_TEX_FILTER_LINEAR:
{
GLfloat t00[4], t01[4], t10[4], t11[4];
GLint x0, y0, x1, y1;
GLfloat a, b;
struct pipe_surface *ps
= pipe->get_tex_surface(pipe, sampler->texture, 0, level0, 0);
linear_texcoord(sampler->state->wrap_s, strq[0],
sampler->texture->width0, &x0, &x1, &a);
linear_texcoord(sampler->state->wrap_t, strq[1],
sampler->texture->height0, &y0, &y1, &b);
ps->get_tile(ps, x0, y0, 1, 1, t00);
ps->get_tile(ps, x1, y0, 1, 1, t10);
ps->get_tile(ps, x0, y1, 1, 1, t01);
ps->get_tile(ps, x1, y1, 1, 1, t11);
rgba[0] = lerp_2d(a, b, t00[0], t10[0], t01[0], t11[0]);
rgba[1] = lerp_2d(a, b, t00[1], t10[1], t01[1], t11[1]);
rgba[2] = lerp_2d(a, b, t00[2], t10[2], t01[2], t11[2]);
rgba[3] = lerp_2d(a, b, t00[3], t10[3], t01[3], t11[3]);
for (j = 0; j < QUAD_SIZE; j++) {
float tx[4][4], a, b;
int x0, y0, x1, y1, c;
linear_texcoord(sampler->state->wrap_s, s[j], width, &x0, &x1, &a);
linear_texcoord(sampler->state->wrap_t, t[j], height, &y0, &y1, &b);
get_texel(sampler, 0, level0, 0, x0, y0, tx, 0);
get_texel(sampler, 0, level0, 0, x1, y0, tx, 1);
get_texel(sampler, 0, level0, 0, x0, y1, tx, 2);
get_texel(sampler, 0, level0, 0, x1, y1, tx, 3);
for (c = 0; c < 4; c++) {
rgba[c][j] = lerp_2d(a, b, tx[c][0], tx[c][1], tx[c][2], tx[c][3]);
}
}
break;
/*
{
GLuint level0, level1;
level0 = choose_mipmap_level(sampler, lambda);
}
break;
*/
default:
assert(0);
}
@ -563,40 +664,52 @@ sp_get_sample_2d(struct tgsi_sampler *sampler,
static void
sp_get_sample_3d(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lamba, GLfloat rgba[4])
sp_get_samples_3d(struct tgsi_sampler *sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
/* get/map pipe_surfaces corresponding to 3D tex slices */
}
static void
sp_get_sample_cube(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
sp_get_samples_cube(struct tgsi_sampler *sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
GLfloat st[4];
GLuint face = choose_cube_face(strq, st);
/* get/map surface corresponding to the face */
GLuint j;
for (j = 0; j < QUAD_SIZE; j++) {
float st[4];
GLuint face = choose_cube_face(s[j], t[j], p[j], st);
(void) face;
/* get/map surface corresponding to the face */
}
}
void
sp_get_sample(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4])
sp_get_samples(struct tgsi_sampler *sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float rgba[NUM_CHANNELS][QUAD_SIZE])
{
switch (sampler->texture->target) {
case GL_TEXTURE_1D:
sp_get_sample_1d(sampler, strq, lambda, rgba);
sp_get_samples_1d(sampler, s, t, p, rgba);
break;
case GL_TEXTURE_2D:
sp_get_sample_2d(sampler, strq, lambda, rgba);
sp_get_samples_2d(sampler, s, t, p, rgba);
break;
case GL_TEXTURE_3D:
sp_get_sample_3d(sampler, strq, lambda, rgba);
sp_get_samples_3d(sampler, s, t, p, rgba);
break;
case GL_TEXTURE_CUBE_MAP:
sp_get_sample_cube(sampler, strq, lambda, rgba);
sp_get_samples_cube(sampler, s, t, p, rgba);
break;
default:
assert(0);

View file

@ -6,8 +6,11 @@ struct tgsi_sampler;
extern void
sp_get_sample(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]);
sp_get_samples(struct tgsi_sampler *sampler,
const GLfloat s[QUAD_SIZE],
const GLfloat t[QUAD_SIZE],
const GLfloat p[QUAD_SIZE],
GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]);
#endif /* SP_TEX_SAMPLE_H */

View file

@ -1034,44 +1034,6 @@ exec_kil (struct tgsi_exec_machine *mach,
}
static GLfloat
compute_lambda(struct tgsi_sampler *sampler,
const union tgsi_exec_channel *s,
const union tgsi_exec_channel *t,
const union tgsi_exec_channel *p)
{
GLfloat rho, lambda;
assert(s);
{
GLfloat dsdx = s->f[TILE_BOTTOM_RIGHT] - s->f[TILE_BOTTOM_LEFT];
GLfloat dsdy = s->f[TILE_TOP_LEFT] - s->f[TILE_BOTTOM_LEFT];
dsdx = FABSF(dsdx);
dsdy = FABSF(dsdy);
rho = MAX2(dsdx, dsdy) * sampler->texture->width0;
}
if (t) {
GLfloat dtdx = t->f[TILE_BOTTOM_RIGHT] - t->f[TILE_BOTTOM_LEFT];
GLfloat dtdy = t->f[TILE_TOP_LEFT] - t->f[TILE_BOTTOM_LEFT];
GLfloat max;
dtdx = FABSF(dtdx);
dtdy = FABSF(dtdy);
max = MAX2(dtdx, dtdy) * sampler->texture->height0;
rho = MAX2(rho, max);
}
if (p) {
GLfloat dpdx = p->f[TILE_BOTTOM_RIGHT] - p->f[TILE_BOTTOM_LEFT];
GLfloat dpdy = p->f[TILE_TOP_LEFT] - p->f[TILE_BOTTOM_LEFT];
GLfloat max;
dpdx = FABSF(dpdx);
dpdy = FABSF(dpdy);
max = MAX2(dpdx, dpdy) * sampler->texture->depth0;
rho = MAX2(rho, max);
}
lambda = LOG2(rho);
return lambda;
}
/*
@ -1079,44 +1041,24 @@ compute_lambda(struct tgsi_sampler *sampler,
*/
static void
fetch_texel( struct tgsi_sampler *sampler,
GLfloat lambda,
const union tgsi_exec_channel *s,
const union tgsi_exec_channel *t,
const union tgsi_exec_channel *p,
GLuint unit,
union tgsi_exec_channel *r,
union tgsi_exec_channel *g,
union tgsi_exec_channel *b,
union tgsi_exec_channel *a )
{
GLuint fragment_index;
GLfloat stpq[4][4];
GLuint j;
GLfloat rgba[NUM_CHANNELS][QUAD_SIZE];
for (fragment_index = 0; fragment_index < 4; fragment_index++) {
stpq[fragment_index][0] = s->f[fragment_index];
if (t)
stpq[fragment_index][1] = t->f[fragment_index];
if (p)
stpq[fragment_index][2] = p->f[fragment_index];
}
sampler->get_samples(sampler, s->f, t->f, p->f, rgba);
lambda += sampler->state->lod_bias;
lambda = CLAMP(lambda, sampler->state->min_lod, sampler->state->max_lod);
/* XXX: Use the same lambda value throughout the tile. Could
* end up with four unique values by recalculating partial
* derivs in the other row and column, and calculating lambda
* using the dx and dy values appropriate for each fragment in
* the tile.
*/
for (fragment_index = 0; fragment_index < 4; fragment_index++) {
GLfloat rgba[4];
sampler->get_sample(sampler, stpq[fragment_index], lambda, rgba);
r->f[fragment_index] = rgba[0];
g->f[fragment_index] = rgba[1];
b->f[fragment_index] = rgba[2];
a->f[fragment_index] = rgba[3];
for (j = 0; j < 4; j++) {
r->f[j] = rgba[0][j];
g->f[j] = rgba[1][j];
b->f[j] = rgba[2][j];
a->f[j] = rgba[3][j];
}
}
@ -1647,7 +1589,6 @@ exec_instruction(
case TGSI_OPCODE_TEX:
{
const GLuint unit = inst->FullSrcRegisters[1].SrcRegister.Index;
GLfloat lambda;
switch (inst->InstructionExtTexture.Texture) {
case TGSI_TEXTURE_1D:
@ -1666,10 +1607,8 @@ exec_instruction(
assert (0);
}
lambda = compute_lambda(&mach->Samplers[unit], &r[0], NULL, NULL);
fetch_texel(&mach->Samplers[unit], lambda,
fetch_texel(&mach->Samplers[unit],
&r[0], NULL, NULL,
inst->FullSrcRegisters[1].SrcRegister.Index,
&r[0], &r[1], &r[2], &r[3]);
break;
@ -1693,11 +1632,8 @@ exec_instruction(
assert (0);
}
lambda = compute_lambda(&mach->Samplers[unit], &r[0], &r[1], NULL);
fetch_texel(&mach->Samplers[unit],
lambda,
&r[0], &r[1], NULL,
inst->FullSrcRegisters[1].SrcRegister.Index,
&r[0], &r[1], &r[2], &r[3]);
break;
@ -1723,11 +1659,8 @@ exec_instruction(
assert (0);
}
lambda = compute_lambda(&mach->Samplers[unit], &r[0], &r[1], &r[2]);
fetch_texel(&mach->Samplers[unit],
lambda,
&r[0], &r[1], &r[2],
inst->FullSrcRegisters[1].SrcRegister.Index,
&r[0], &r[1], &r[2], &r[3]);
break;

View file

@ -23,12 +23,21 @@ struct tgsi_exec_vector
#define SAMPLER_CACHE_SIZE 8
#define NUM_CHANNELS 4 /* R,G,B,A */
#ifndef QUAD_SIZE
#define QUAD_SIZE 4 /* 4 pixel/quad */
#endif
struct tgsi_sampler
{
const struct pipe_sampler_state *state;
struct pipe_mipmap_tree *texture;
void (*get_sample)(struct tgsi_sampler *sampler,
const GLfloat strq[4], GLfloat lambda, GLfloat rgba[4]);
/** Get samples for four fragments in a quad */
void (*get_samples)(struct tgsi_sampler *sampler,
const GLfloat s[QUAD_SIZE],
const GLfloat t[QUAD_SIZE],
const GLfloat p[QUAD_SIZE],
GLfloat rgba[NUM_CHANNELS][QUAD_SIZE]);
void *pipe; /*XXX temporary*/
GLint cache_x, cache_y, cache_level;