softpipe: Properly implement cylindrical wrapping.
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user