Commit c95dcc49 authored by Keith Whitwell's avatar Keith Whitwell Committed by Zack Rusin

remove usage of vertex_header

parent 7a8ad75c
......@@ -212,12 +212,6 @@ static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
case EMIT_1F:
feme->fetch[i].emit = emit_R32_FLOAT;
break;
case EMIT_HEADER:
feme->fetch[i].ptr = (const ubyte *)&zero;
feme->fetch[i].pitch = 0;
feme->fetch[i].fetch = fetch_R32_FLOAT;
feme->fetch[i].emit = emit_R32_FLOAT;
break;
case EMIT_1F_PSIZE:
feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
feme->fetch[i].pitch = 0;
......
......@@ -126,13 +126,6 @@ dump_emitted_vertex(const struct vertex_info *vinfo, const uint8_t *data)
case EMIT_OMIT:
debug_printf("EMIT_OMIT:");
break;
case EMIT_ALL:
assert(i == 0);
assert(j == 0);
debug_printf("EMIT_ALL:\t");
for(k = 0; k < vinfo->size*4; ++k)
debug_printf("%02x ", *data++);
break;
case EMIT_1F:
debug_printf("EMIT_1F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
......@@ -217,19 +210,6 @@ emit_vertex( struct vbuf_stage *vbuf,
case EMIT_OMIT:
/* no-op */
break;
case EMIT_ALL:
/* just copy the whole vertex as-is to the vbuf */
assert(i == 0);
assert(j == 0);
memcpy(vbuf->vertex_ptr, vertex, vinfo->size * 4);
vbuf->vertex_ptr += vinfo->size;
count += vinfo->size;
break;
case EMIT_HEADER:
memcpy(vbuf->vertex_ptr, vertex, sizeof(*vertex));
*vbuf->vertex_ptr += sizeof(*vertex) / 4;
count += sizeof(*vertex) / 4;
break;
case EMIT_1F:
*vbuf->vertex_ptr++ = fui(vertex->data[j][0]);
count++;
......
......@@ -52,9 +52,6 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
switch (vinfo->emit[i]) {
case EMIT_OMIT:
break;
case EMIT_HEADER:
vinfo->size += sizeof(struct vertex_header) / 4;
break;
case EMIT_4UB:
/* fall-through */
case EMIT_1F_PSIZE:
......@@ -71,8 +68,6 @@ draw_compute_vertex_size(struct vertex_info *vinfo)
case EMIT_4F:
vinfo->size += 4;
break;
case EMIT_ALL:
/* fall-through */
default:
assert(0);
}
......
......@@ -47,8 +47,6 @@
*/
enum attrib_emit {
EMIT_OMIT, /**< don't emit the attribute */
EMIT_ALL, /**< emit whole post-xform vertex, w/ header */
EMIT_HEADER, /**< emit vertex_header struct (XXX temp?) */
EMIT_1F,
EMIT_1F_PSIZE, /**< insert constant point size */
EMIT_2F,
......
......@@ -205,7 +205,7 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf,
const struct vertex_info *vinfo,
float point_size )
{
unsigned i, j, k;
unsigned i, j;
struct draw_vf_attr *a = vf->attr;
struct draw_vf_attr_map attrs[PIPE_MAX_SHADER_INPUTS];
unsigned count = 0; /* for debug/sanity */
......@@ -217,60 +217,6 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf,
case EMIT_OMIT:
/* no-op */
break;
case EMIT_ALL: {
/* just copy the whole vertex as-is to the vbuf */
unsigned s = vinfo->size;
assert(i == 0);
assert(j == 0);
/* copy the vertex header */
/* XXX: we actually don't copy the header, just pad it */
attrs[nr_attrs].attrib = 0;
attrs[nr_attrs].format = DRAW_EMIT_PAD;
attrs[nr_attrs].offset = offsetof(struct vertex_header, data);
s -= offsetof(struct vertex_header, data)/4;
count += offsetof(struct vertex_header, data)/4;
nr_attrs++;
/* copy the vertex data */
for(k = 0; k < (s & ~0x3); k += 4) {
attrs[nr_attrs].attrib = k/4;
attrs[nr_attrs].format = DRAW_EMIT_4F;
attrs[nr_attrs].offset = 0;
nr_attrs++;
count += 4;
}
/* tail */
/* XXX: actually, this shouldn't be needed */
attrs[nr_attrs].attrib = k/4;
attrs[nr_attrs].offset = 0;
switch(s & 0x3) {
case 0:
break;
case 1:
attrs[nr_attrs].format = DRAW_EMIT_1F;
nr_attrs++;
count += 1;
break;
case 2:
attrs[nr_attrs].format = DRAW_EMIT_2F;
nr_attrs++;
count += 2;
break;
case 3:
attrs[nr_attrs].format = DRAW_EMIT_3F;
nr_attrs++;
count += 3;
break;
}
break;
}
case EMIT_HEADER:
/* XXX emit new DRAW_EMIT_HEADER attribute??? */
attrs[nr_attrs].attrib = 0;
attrs[nr_attrs].format = DRAW_EMIT_PAD;
attrs[nr_attrs].offset = offsetof(struct vertex_header, data);
count += offsetof(struct vertex_header, data)/4;
nr_attrs++;
break;
case EMIT_1F:
attrs[nr_attrs].attrib = j;
attrs[nr_attrs].format = DRAW_EMIT_1F;
......
......@@ -27,6 +27,7 @@ C_SOURCES = \
sp_quad_stencil.c \
sp_quad_stipple.c \
sp_screen.c \
sp_setup.c \
sp_state_blend.c \
sp_state_clip.c \
sp_state_derived.c \
......
......@@ -14,6 +14,7 @@ softpipe = env.ConvenienceLibrary(
'sp_flush.c',
'sp_prim_setup.c',
'sp_prim_vbuf.c',
'sp_setup.c',
'sp_quad_alpha_test.c',
'sp_quad_blend.c',
'sp_quad.c',
......
......@@ -26,7 +26,9 @@
**************************************************************************/
/**
* \brief Primitive rasterization/rendering (points, lines, triangles)
* \brief A draw stage that drives our triangle setup routines from
* within the draw pipeline. One of two ways to drive setup, the
* other being in sp_prim_vbuf.c.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Brian Paul
......@@ -34,29 +36,12 @@
#include "sp_context.h"
#include "sp_headers.h"
#include "sp_quad.h"
#include "sp_setup.h"
#include "sp_state.h"
#include "sp_prim_setup.h"
#include "draw/draw_private.h"
#include "draw/draw_vertex.h"
#include "pipe/p_util.h"
#include "pipe/p_shader_tokens.h"
#define DEBUG_VERTS 0
#define DEBUG_FRAGS 0
/**
* Triangle edge info
*/
struct edge {
float dx; /**< X(v1) - X(v0), used only during setup */
float dy; /**< Y(v1) - Y(v0), used only during setup */
float dxdy; /**< dx/dy */
float sx, sy; /**< first sample point coord */
int lines; /**< number of lines on this edge */
};
/**
* Triangle setup info (derived from draw_stage).
......@@ -65,39 +50,7 @@ struct edge {
struct setup_stage {
struct draw_stage stage; /**< This must be first (base class) */
struct softpipe_context *softpipe;
/* Vertices are just an array of floats making up each attribute in
* turn. Currently fixed at 4 floats, but should change in time.
* Codegen will help cope with this.
*/
const struct vertex_header *vmax;
const struct vertex_header *vmid;
const struct vertex_header *vmin;
const struct vertex_header *vprovoke;
struct edge ebot;
struct edge etop;
struct edge emaj;
float oneoverarea;
struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
struct tgsi_interp_coef posCoef; /* For Z, W */
struct quad_header quad;
struct {
int left[2]; /**< [0] = row0, [1] = row1 */
int right[2];
int y;
unsigned y_flags;
unsigned mask; /**< mask of MASK_BOTTOM/TOP_LEFT/RIGHT bits */
} span;
#if DEBUG_FRAGS
uint numFragsEmitted; /**< per primitive */
uint numFragsWritten; /**< per primitive */
#endif
struct setup_context *setup;
};
......@@ -111,1112 +64,50 @@ static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
}
/**
* Clip setup->quad against the scissor/surface bounds.
*/
static INLINE void
quad_clip(struct setup_stage *setup)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
const int maxx = (int) cliprect->maxx;
const int miny = (int) cliprect->miny;
const int maxy = (int) cliprect->maxy;
if (setup->quad.x0 >= maxx ||
setup->quad.y0 >= maxy ||
setup->quad.x0 + 1 < minx ||
setup->quad.y0 + 1 < miny) {
/* totally clipped */
setup->quad.mask = 0x0;
return;
}
if (setup->quad.x0 < minx)
setup->quad.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
if (setup->quad.y0 < miny)
setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
if (setup->quad.x0 == maxx - 1)
setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
if (setup->quad.y0 == maxy - 1)
setup->quad.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
}
/**
* Emit a quad (pass to next stage) with clipping.
*/
static INLINE void
clip_emit_quad(struct setup_stage *setup)
{
quad_clip(setup);
if (setup->quad.mask) {
struct softpipe_context *sp = setup->softpipe;
sp->quad.first->run(sp->quad.first, &setup->quad);
}
}
/**
* Emit a quad (pass to next stage). No clipping is done.
*/
static INLINE void
emit_quad( struct setup_stage *setup, int x, int y, unsigned mask )
{
struct softpipe_context *sp = setup->softpipe;
setup->quad.x0 = x;
setup->quad.y0 = y;
setup->quad.mask = mask;
#if DEBUG_FRAGS
if (mask & 1) setup->numFragsEmitted++;
if (mask & 2) setup->numFragsEmitted++;
if (mask & 4) setup->numFragsEmitted++;
if (mask & 8) setup->numFragsEmitted++;
#endif
sp->quad.first->run(sp->quad.first, &setup->quad);
#if DEBUG_FRAGS
mask = setup->quad.mask;
if (mask & 1) setup->numFragsWritten++;
if (mask & 2) setup->numFragsWritten++;
if (mask & 4) setup->numFragsWritten++;
if (mask & 8) setup->numFragsWritten++;
#endif
}
/**
* Given an X or Y coordinate, return the block/quad coordinate that it
* belongs to.
*/
static INLINE int block( int x )
{
return x & ~1;
}
/**
* Compute mask which indicates which pixels in the 2x2 quad are actually inside
* the triangle's bounds.
*
* this is pretty nasty... may need to rework flush_spans again to
* fix it, if possible.
*/
static unsigned calculate_mask( struct setup_stage *setup, int x )
{
unsigned mask = 0x0;
if (x >= setup->span.left[0] && x < setup->span.right[0])
mask |= MASK_TOP_LEFT;
if (x >= setup->span.left[1] && x < setup->span.right[1])
mask |= MASK_BOTTOM_LEFT;
if (x+1 >= setup->span.left[0] && x+1 < setup->span.right[0])
mask |= MASK_TOP_RIGHT;
if (x+1 >= setup->span.left[1] && x+1 < setup->span.right[1])
mask |= MASK_BOTTOM_RIGHT;
return mask;
}
/**
* Render a horizontal span of quads
*/
static void flush_spans( struct setup_stage *setup )
{
int minleft, maxright;
int x;
switch (setup->span.y_flags) {
case 0x3:
/* both odd and even lines written (both quad rows) */
minleft = MIN2(setup->span.left[0], setup->span.left[1]);
maxright = MAX2(setup->span.right[0], setup->span.right[1]);
break;
case 0x1:
/* only even line written (quad top row) */
minleft = setup->span.left[0];
maxright = setup->span.right[0];
break;
case 0x2:
/* only odd line written (quad bottom row) */
minleft = setup->span.left[1];
maxright = setup->span.right[1];
break;
default:
return;
}
/* XXX this loop could be moved into the above switch cases and
* calculate_mask() could be simplified a bit...
*/
for (x = block(minleft); x <= block(maxright); x += 2) {
emit_quad( setup, x, setup->span.y,
calculate_mask( setup, x ) );
}
setup->span.y = 0;
setup->span.y_flags = 0;
setup->span.right[0] = 0;
setup->span.right[1] = 0;
}
#if DEBUG_VERTS
static void print_vertex(const struct setup_stage *setup,
const struct vertex_header *v)
{
int i;
debug_printf("Vertex: (%p)\n", v);
for (i = 0; i < setup->quad.nr_attrs; i++) {
debug_printf(" %d: %f %f %f %f\n", i,
v->data[i][0], v->data[i][1], v->data[i][2], v->data[i][3]);
}
}
#endif
static boolean setup_sort_vertices( struct setup_stage *setup,
const struct prim_header *prim )
{
const struct vertex_header *v0 = prim->v[0];
const struct vertex_header *v1 = prim->v[1];
const struct vertex_header *v2 = prim->v[2];
#if DEBUG_VERTS
debug_printf("Triangle:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
print_vertex(setup, v2);
#endif
setup->vprovoke = v2;
/* determine bottom to top order of vertices */
{
float y0 = v0->data[0][1];
float y1 = v1->data[0][1];
float y2 = v2->data[0][1];
if (y0 <= y1) {
if (y1 <= y2) {
/* y0<=y1<=y2 */
setup->vmin = v0;
setup->vmid = v1;
setup->vmax = v2;
}
else if (y2 <= y0) {
/* y2<=y0<=y1 */
setup->vmin = v2;
setup->vmid = v0;
setup->vmax = v1;
}
else {
/* y0<=y2<=y1 */
setup->vmin = v0;
setup->vmid = v2;
setup->vmax = v1;
}
}
else {
if (y0 <= y2) {
/* y1<=y0<=y2 */
setup->vmin = v1;
setup->vmid = v0;
setup->vmax = v2;
}
else if (y2 <= y1) {
/* y2<=y1<=y0 */
setup->vmin = v2;
setup->vmid = v1;
setup->vmax = v0;
}
else {
/* y1<=y2<=y0 */
setup->vmin = v1;
setup->vmid = v2;
setup->vmax = v0;
}
}
}
setup->ebot.dx = setup->vmid->data[0][0] - setup->vmin->data[0][0];
setup->ebot.dy = setup->vmid->data[0][1] - setup->vmin->data[0][1];
setup->emaj.dx = setup->vmax->data[0][0] - setup->vmin->data[0][0];
setup->emaj.dy = setup->vmax->data[0][1] - setup->vmin->data[0][1];
setup->etop.dx = setup->vmax->data[0][0] - setup->vmid->data[0][0];
setup->etop.dy = setup->vmax->data[0][1] - setup->vmid->data[0][1];
/*
* Compute triangle's area. Use 1/area to compute partial
* derivatives of attributes later.
*
* The area will be the same as prim->det, but the sign may be
* different depending on how the vertices get sorted above.
*
* To determine whether the primitive is front or back facing we
* use the prim->det value because its sign is correct.
*/
{
const float area = (setup->emaj.dx * setup->ebot.dy -
setup->ebot.dx * setup->emaj.dy);
setup->oneoverarea = 1.0f / area;
/*
debug_printf("%s one-over-area %f area %f det %f\n",
__FUNCTION__, setup->oneoverarea, area, prim->det );
*/
}
/* We need to know if this is a front or back-facing triangle for:
* - the GLSL gl_FrontFacing fragment attribute (bool)
* - two-sided stencil test
*/
setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW);
return TRUE;
}
/**
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
* The value value comes from vertex->data[slot][i].
* The result will be put into setup->coef[slot].a0[i].
* \param slot which attribute slot
* \param i which component of the slot (0..3)
*/
static void const_coeff( struct setup_stage *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
assert(i <= 3);
coef->dadx[i] = 0;
coef->dady[i] = 0;
/* need provoking vertex info!
*/
coef->a0[i] = setup->vprovoke->data[vertSlot][i];
}
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a triangle.
*/
static void tri_linear_coeff( struct setup_stage *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
float botda = setup->vmid->data[vertSlot][i] - setup->vmin->data[vertSlot][i];
float majda = setup->vmax->data[vertSlot][i] - setup->vmin->data[vertSlot][i];
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;
float dady = b * setup->oneoverarea;
assert(i <= 3);
coef->dadx[i] = dadx;
coef->dady[i] = dady;
/* calculate a0 as the value which would be sampled for the
* fragment at (0,0), taking into account that we want to sample at
* pixel centers, in other words (0.5, 0.5).
*
* this is neat but unfortunately not a good way to do things for
* triangles with very large values of dadx or dady as it will
* result in the subtraction and re-addition from a0 of a very
* large number, which means we'll end up loosing a lot of the
* fractional bits and precision from a0. the way to fix this is
* 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->data[vertSlot][i] -
(dadx * (setup->vmin->data[0][0] - 0.5f) +
dady * (setup->vmin->data[0][1] - 0.5f)));
/*
debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
slot, "xyzw"[i],
setup->coef[slot].a0[i],
setup->coef[slot].dadx[i],
setup->coef[slot].dady[i]);
*/
}
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a triangle.
* We basically multiply the vertex value by 1/w before computing
* 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.
*/
static void tri_persp_coeff( struct setup_stage *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
/* premultiply by 1/w (v->data[0][3] is always W):
*/
float mina = setup->vmin->data[vertSlot][i] * setup->vmin->data[0][3];
float mida = setup->vmid->data[vertSlot][i] * setup->vmid->data[0][3];
float maxa = setup->vmax->data[vertSlot][i] * setup->vmax->data[0][3];
float botda = mida - mina;
float majda = maxa - mina;
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;
float dady = b * setup->oneoverarea;
/*
debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
setup->vmin->data[vertSlot][i],
setup->vmid->data[vertSlot][i],
setup->vmax->data[vertSlot][i]
);
*/
assert(i <= 3);
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (mina -
(dadx * (setup->vmin->data[0][0] - 0.5f) +
dady * (setup->vmin->data[0][1] - 0.5f)));
}
/**
* Special coefficient setup for gl_FragCoord.
* X and Y are trivial, though Y has to be inverted for OpenGL.
* Z and W are copied from posCoef which should have already been computed.
* We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
*/
static void
setup_fragcoord_coeff(struct setup_stage *setup, uint slot)
{
/*X*/
setup->coef[slot].a0[0] = 0;
setup->coef[slot].dadx[0] = 1.0;
setup->coef[slot].dady[0] = 0.0;
/*Y*/
if (setup->softpipe->rasterizer->origin_lower_left) {
/* y=0=bottom */
const int winHeight = setup->softpipe->framebuffer.height;
setup->coef[slot].a0[1] = (float) (winHeight - 1);
setup->coef[slot].dady[1] = -1.0;
}
else {
/* y=0=top */
setup->coef[slot].a0[1] = 0.0;
setup->coef[slot].dady[1] = 1.0;
}
setup->coef[slot].dadx[1] = 0.0;
/*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
setup->coef[slot].dady[2] = setup->posCoef.dady[2];
/*W*/
setup->coef[slot].a0[3] = setup->posCoef.a0[3];
setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
setup->coef[slot].dady[3] = setup->posCoef.dady[3];
}
/**
* Compute the setup->coef[] array dadx, dady, a0 values.
* Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
*/
static void setup_tri_coefficients( struct setup_stage *setup )
{
struct softpipe_context *softpipe = setup->softpipe;
const struct sp_fragment_shader *spfs = softpipe->fs;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
/* z and w are done by linear interpolation:
*/
tri_linear_coeff(setup, &setup->posCoef, 0, 2);
tri_linear_coeff(setup, &setup->posCoef, 0, 3);
/* setup interpolation for all the remaining attributes:
*/
for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) {
const uint vertSlot = vinfo->src_index[fragSlot];
uint j;
switch (vinfo->interp_mode[fragSlot]) {
case INTERP_CONSTANT:
for (j = 0; j < NUM_CHANNELS; j++)
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);
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < NUM_CHANNELS; j++)
tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}