softpipe: Properly implement cylindrical wrapping.

This commit is contained in:
Michal Krol
2010-02-05 17:12:48 +01:00
parent 00bd85e574
commit 5fbb62f761
+148 -31
View File
@@ -393,6 +393,52 @@ static boolean setup_sort_vertices( struct setup_context *setup,
}
/* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
* Some combinations of coordinates produce invalid results,
* but this behaviour is acceptable.
*/
static void
tri_apply_cylindrical_wrap(float v0,
float v1,
float v2,
uint cylindrical_wrap,
float output[3])
{
if (cylindrical_wrap) {
float delta;
delta = v1 - v0;
if (delta > 0.5f) {
v0 += 1.0f;
}
else if (delta < -0.5f) {
v1 += 1.0f;
}
delta = v2 - v1;
if (delta > 0.5f) {
v1 += 1.0f;
}
else if (delta < -0.5f) {
v2 += 1.0f;
}
delta = v0 - v2;
if (delta > 0.5f) {
v2 += 1.0f;
}
else if (delta < -0.5f) {
v0 += 1.0f;
}
}
output[0] = v0;
output[1] = v1;
output[2] = v2;
}
/**
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
* The value value comes from vertex[slot][i].
@@ -418,13 +464,16 @@ static void const_coeff( struct setup_context *setup,
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a triangle.
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
static void tri_linear_coeff( struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
static void
tri_linear_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[3])
{
float botda = setup->vmid[vertSlot][i] - setup->vmin[vertSlot][i];
float majda = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
float botda = v[1] - v[0];
float majda = v[2] - v[0];
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
float dadx = a * setup->oneoverarea;
@@ -447,7 +496,7 @@ static void tri_linear_coeff( struct setup_context *setup,
* to define a0 as the sample at a pixel center somewhere near vmin
* instead - i'll switch to this later.
*/
coef->a0[i] = (setup->vmin[vertSlot][i] -
coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
@@ -468,16 +517,19 @@ static void tri_linear_coeff( struct setup_context *setup,
* the plane coefficients (a0, dadx, dady).
* Later, when we compute the value at a particular fragment position we'll
* divide the interpolated value by the interpolated W at that fragment.
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
static void tri_persp_coeff( struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
static void
tri_persp_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[3])
{
/* premultiply by 1/w (v[0][3] is always W):
*/
float mina = setup->vmin[vertSlot][i] * setup->vmin[0][3];
float mida = setup->vmid[vertSlot][i] * setup->vmid[0][3];
float maxa = setup->vmax[vertSlot][i] * setup->vmax[0][3];
float mina = v[0] * setup->vmin[0][3];
float mida = v[1] * setup->vmid[0][3];
float maxa = v[2] * setup->vmax[0][3];
float botda = mida - mina;
float majda = maxa - mina;
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
@@ -544,11 +596,19 @@ static void setup_tri_coefficients( struct setup_context *setup )
const struct sp_fragment_shader *spfs = softpipe->fs;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float v[3];
/* z and w are done by linear interpolation:
*/
tri_linear_coeff(setup, &setup->posCoef, 0, 2);
tri_linear_coeff(setup, &setup->posCoef, 0, 3);
v[0] = setup->vmin[0][2];
v[1] = setup->vmid[0][2];
v[2] = setup->vmax[0][2];
tri_linear_coeff(setup, &setup->posCoef, 2, v);
v[0] = setup->vmin[0][3];
v[1] = setup->vmid[0][3];
v[2] = setup->vmax[0][3];
tri_linear_coeff(setup, &setup->posCoef, 3, v);
/* setup interpolation for all the remaining attributes:
*/
@@ -562,12 +622,24 @@ static void setup_tri_coefficients( struct setup_context *setup )
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
for (j = 0; j < NUM_CHANNELS; j++)
tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
for (j = 0; j < NUM_CHANNELS; j++) {
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < NUM_CHANNELS; j++)
tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
for (j = 0; j < NUM_CHANNELS; j++) {
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
@@ -777,22 +849,49 @@ void sp_setup_tri( struct setup_context *setup,
}
/* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
*/
static void
line_apply_cylindrical_wrap(float v0,
float v1,
uint cylindrical_wrap,
float output[2])
{
if (cylindrical_wrap) {
float delta;
delta = v1 - v0;
if (delta > 0.5f) {
v0 += 1.0f;
}
else if (delta < -0.5f) {
v1 += 1.0f;
}
}
output[0] = v0;
output[1] = v1;
}
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a line.
* v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_linear_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
uint i,
const float v[2])
{
const float da = setup->vmax[vertSlot][i] - setup->vmin[vertSlot][i];
const float da = v[1] - v[0];
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (setup->vmin[vertSlot][i] -
coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
@@ -801,21 +900,23 @@ line_linear_coeff(const struct setup_context *setup,
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a line.
* v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_persp_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
uint i,
const float v[2])
{
/* XXX double-check/verify this arithmetic */
const float a0 = setup->vmin[vertSlot][i] * setup->vmin[0][3];
const float a1 = setup->vmax[vertSlot][i] * setup->vmax[0][3];
const float a0 = v[0] * setup->vmin[0][3];
const float a1 = v[1] * setup->vmax[0][3];
const float da = a1 - a0;
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (setup->vmin[vertSlot][i] -
coef->a0[i] = (v[0] - /* XXX: <-- shouldn't that be a0? */
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
@@ -835,6 +936,7 @@ setup_line_coefficients(struct setup_context *setup,
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float area;
float v[2];
/* use setup->vmin, vmax to point to vertices */
if (softpipe->rasterizer->flatshade_first)
@@ -855,8 +957,13 @@ setup_line_coefficients(struct setup_context *setup,
/* z and w are done by linear interpolation:
*/
line_linear_coeff(setup, &setup->posCoef, 0, 2);
line_linear_coeff(setup, &setup->posCoef, 0, 3);
v[0] = setup->vmin[0][2];
v[1] = setup->vmax[0][2];
line_linear_coeff(setup, &setup->posCoef, 2, v);
v[0] = setup->vmin[0][3];
v[1] = setup->vmax[0][3];
line_linear_coeff(setup, &setup->posCoef, 3, v);
/* setup interpolation for all the remaining attributes:
*/
@@ -870,12 +977,22 @@ setup_line_coefficients(struct setup_context *setup,
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
for (j = 0; j < NUM_CHANNELS; j++)
line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
for (j = 0; j < NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < NUM_CHANNELS; j++)
line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
for (j = 0; j < NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
spfs->info.input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);