#include "sp_quad.h"
#include "sp_prim_setup.h"
#include "pipe/draw/draw_private.h"
+#include "pipe/draw/draw_vertex.h"
#include "pipe/p_util.h"
-#ifndef MESA
-#define FRAG_ATTRIB_WPOS 0
-#define FRAG_ATTRIB_MAX 13
-#endif
-
+#define DEBUG_VERTS 0
/**
* Triangle edge info
float oneoverarea;
- struct tgsi_interp_coef coef[FRAG_ATTRIB_MAX];
+ struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
struct quad_header quad;
struct {
quad_clip(struct setup_stage *setup)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
- if (setup->quad.x0 >= cliprect->maxx ||
- setup->quad.y0 >= cliprect->maxy ||
- setup->quad.x0 + 1 < cliprect->minx ||
- setup->quad.y0 + 1 < cliprect->miny) {
+ 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 < cliprect->minx)
+ if (setup->quad.x0 < minx)
setup->quad.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
- if (setup->quad.y0 < cliprect->miny)
+ if (setup->quad.y0 < miny)
setup->quad.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
- if (setup->quad.x0 == cliprect->maxx - 1)
+ if (setup->quad.x0 == maxx - 1)
setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
- if (setup->quad.y0 == cliprect->maxy - 1)
+ if (setup->quad.y0 == maxy - 1)
setup->quad.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
}
setup->span.right[1] = 0;
}
-#if 0
+#if DEBUG_VERTS
static void print_vertex(const struct setup_stage *setup,
const struct vertex_header *v)
{
int i;
- printf("Vertex:\n");
- for (i = 0; i < setup->softpipe->nr_attrs; i++) {
- printf(" %d: %f %f %f\n", i,
- v->data[i][0], v->data[i][1], v->data[i][2]);
+ fprintf(stderr, "Vertex: (%p)\n", v);
+ for (i = 0; i < setup->quad.nr_attrs; i++) {
+ fprintf(stderr, " %d: %f %f %f %f\n", i,
+ v->data[i][0], v->data[i][1], v->data[i][2], v->data[i][3]);
}
}
#endif
const struct vertex_header *v1 = prim->v[1];
const struct vertex_header *v2 = prim->v[2];
-#if 0
- printf("Triangle:\n");
+#if DEBUG_VERTS
+ fprintf(stderr, "Triangle:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
print_vertex(setup, v2);
const float area = (setup->emaj.dx * setup->ebot.dy -
setup->ebot.dx * setup->emaj.dy);
- setup->oneoverarea = 1.0 / area;
+ setup->oneoverarea = 1.0f / area;
/*
_mesa_printf("%s one-over-area %f area %f det %f\n",
__FUNCTION__, setup->oneoverarea, area, prim->det );
* - the GLSL gl_FrontFacing fragment attribute (bool)
* - two-sided stencil test
*/
- setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->setup.front_winding == PIPE_WINDING_CW);
+ setup->quad.facing = (prim->det > 0.0) ^ (setup->softpipe->rasterizer->front_winding == PIPE_WINDING_CW);
return TRUE;
}
unsigned slot,
unsigned i )
{
- assert(slot < FRAG_ATTRIB_MAX);
+ assert(slot < PIPE_MAX_SHADER_INPUTS);
assert(i <= 3);
setup->coef[slot].dadx[i] = 0;
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
- assert(slot < FRAG_ATTRIB_MAX);
+ assert(slot < PIPE_MAX_SHADER_INPUTS);
assert(i <= 3);
setup->coef[slot].dadx[i] = a * setup->oneoverarea;
* instead - i'll switch to this later.
*/
setup->coef[slot].a0[i] = (setup->vmin->data[slot][i] -
- (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) +
- setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
+ (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5f) +
+ setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5f)));
/*
_mesa_printf("attr[%d].%c: %f dx:%f dy:%f\n",
/**
* 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,
unsigned slot,
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
- assert(slot < FRAG_ATTRIB_MAX);
+ /*
+ printf("tri persp %d,%d: %f %f %f\n", slot, i,
+ setup->vmin->data[slot][i],
+ setup->vmid->data[slot][i],
+ setup->vmax->data[slot][i]
+ );
+ */
+
+ assert(slot < PIPE_MAX_SHADER_INPUTS);
assert(i <= 3);
setup->coef[slot].dadx[i] = a * setup->oneoverarea;
setup->coef[slot].dady[i] = b * setup->oneoverarea;
setup->coef[slot].a0[i] = (mina -
- (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5) +
- setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5)));
+ (setup->coef[slot].dadx[i] * (setup->vmin->data[0][0] - 0.5f) +
+ setup->coef[slot].dady[i] * (setup->vmin->data[0][1] - 0.5f)));
}
*/
static void setup_tri_coefficients( struct setup_stage *setup )
{
- const enum interp_mode *interp = setup->softpipe->interp;
+ const interp_mode *interp = setup->softpipe->vertex_info.interp_mode;
unsigned slot, j;
/* z and w are done by linear interpolation:
for (j = 0; j < NUM_CHANNELS; j++)
tri_persp_coeff(setup, slot, j);
break;
+
+ default:
+ /* invalid interp mode */
+ assert(0);
}
}
}
static void setup_tri_edges( struct setup_stage *setup )
{
- float vmin_x = setup->vmin->data[0][0] + 0.5;
- float vmid_x = setup->vmid->data[0][0] + 0.5;
+ float vmin_x = setup->vmin->data[0][0] + 0.5f;
+ float vmid_x = setup->vmid->data[0][0] + 0.5f;
- float vmin_y = setup->vmin->data[0][1] - 0.5;
- float vmid_y = setup->vmid->data[0][1] - 0.5;
- float vmax_y = setup->vmax->data[0][1] - 0.5;
+ float vmin_y = setup->vmin->data[0][1] - 0.5f;
+ float vmid_y = setup->vmid->data[0][1] - 0.5f;
+ float vmax_y = setup->vmax->data[0][1] - 0.5f;
setup->emaj.sy = ceilf(vmin_y);
setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
unsigned lines )
{
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;
int y, start_y, finish_y;
int sy = (int)eleft->sy;
start_y = sy;
finish_y = sy + lines;
- if (start_y < cliprect->miny)
- start_y = cliprect->miny;
+ if (start_y < miny)
+ start_y = miny;
- if (finish_y > cliprect->maxy)
- finish_y = cliprect->maxy;
+ if (finish_y > maxy)
+ finish_y = maxy;
start_y -= sy;
finish_y -= sy;
int right = (int)(eright->sx + y * eright->dxdy);
/* clip left/right */
- if (left < cliprect->minx)
- left = cliprect->minx;
- if (right > cliprect->maxx)
- right = cliprect->maxx;
+ if (left < minx)
+ left = minx;
+ if (right > maxx)
+ right = maxx;
if (left < right) {
- int _y = sy+y;
- if (block(_y) != setup->span.y) {
- flush_spans(setup);
- setup->span.y = block(_y);
- }
-
- setup->span.left[_y&1] = left;
- setup->span.right[_y&1] = right;
- setup->span.y_flags |= 1<<(_y&1);
+ int _y = sy + y;
+ if (block(_y) != setup->span.y) {
+ flush_spans(setup);
+ setup->span.y = block(_y);
+ }
+
+ setup->span.left[_y&1] = left;setup->span.right[_y&1] = right;
+ setup->span.y_flags |= 1<<(_y&1);
}
- }
+ }
/* save the values so that emaj can be restarted:
setup->coef[slot].dady[i] = dady;
setup->coef[slot].a0[i]
= (setup->vmin->data[slot][i] -
- (dadx * (setup->vmin->data[0][0] - 0.5) +
- dady * (setup->vmin->data[0][1] - 0.5)));
+ (dadx * (setup->vmin->data[0][0] - 0.5f) +
+ dady * (setup->vmin->data[0][1] - 0.5f)));
}
static INLINE void
setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
{
- const enum interp_mode *interp = setup->softpipe->interp;
+ const interp_mode *interp = setup->softpipe->vertex_info.interp_mode;
unsigned slot, j;
/* use setup->vmin, vmax to point to vertices */
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];
/* NOTE: this is not really 1/area */
- setup->oneoverarea = 1.0 / (setup->emaj.dx * setup->emaj.dx +
- setup->emaj.dy * setup->emaj.dy);
+ setup->oneoverarea = 1.0f / (setup->emaj.dx * setup->emaj.dx +
+ setup->emaj.dy * setup->emaj.dy);
/* z and w are done by linear interpolation:
*/
for (j = 0; j < NUM_CHANNELS; j++)
line_persp_coeff(setup, slot, j);
break;
+
+ default:
+ /* invalid interp mode */
+ assert(0);
}
}
}
const int errorDec = error - dx;
for (i = 0; i < dx; i++) {
- if (!sp->setup.line_stipple_enable ||
+ if (!sp->rasterizer->line_stipple_enable ||
stipple_test(sp->line_stipple_counter,
- sp->setup.line_stipple_pattern,
- sp->setup.line_stipple_factor + 1)) {
+ sp->rasterizer->line_stipple_pattern,
+ sp->rasterizer->line_stipple_factor + 1)) {
plot(setup, x0, y0);
}
const int errorDec = error - dy;
for (i = 0; i < dy; i++) {
- if (!sp->setup.line_stipple_enable ||
+ if (!sp->rasterizer->line_stipple_enable ||
stipple_test(sp->line_stipple_counter,
- sp->setup.line_stipple_pattern,
- sp->setup.line_stipple_factor + 1)) {
+ sp->rasterizer->line_stipple_pattern,
+ sp->rasterizer->line_stipple_factor + 1)) {
plot(setup, x0, y0);
}
setup_point(struct draw_stage *stage, struct prim_header *prim)
{
struct setup_stage *setup = setup_stage( stage );
- /*XXX this should be a vertex attrib! */
- const float halfSize = 0.5 * setup->softpipe->setup.point_size;
- const boolean round = setup->softpipe->setup.point_smooth;
const struct vertex_header *v0 = prim->v[0];
- const float x = v0->data[FRAG_ATTRIB_WPOS][0];
- const float y = v0->data[FRAG_ATTRIB_WPOS][1];
+ const int sizeAttr = setup->softpipe->psize_slot;
+ const float halfSize
+ = sizeAttr > 0 ? (0.5f * v0->data[sizeAttr][0])
+ : (0.5f * setup->softpipe->rasterizer->point_size);
+ const boolean round = setup->softpipe->rasterizer->point_smooth;
+ const float x = v0->data[0][0]; /* Note: data[0] is always position */
+ const float y = v0->data[0][1];
unsigned slot, j;
/* For points, all interpolants are constant-valued.
/* special case for 1-pixel points */
const int ix = ((int) x) & 1;
const int iy = ((int) y) & 1;
- setup->quad.x0 = x - ix;
- setup->quad.y0 = y - iy;
+ setup->quad.x0 = (int) x - ix;
+ setup->quad.y0 = (int) y - iy;
setup->quad.mask = (1 << ix) << (2 * iy);
clip_emit_quad(setup);
}
setup->quad.mask = 0x0;
- dx = (ix + 0.5) - x;
- dy = (iy + 0.5) - y;
+ dx = (ix + 0.5f) - x;
+ dy = (iy + 0.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
- setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0);
+ setup->quad.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
setup->quad.mask |= MASK_BOTTOM_LEFT;
}
- dx = (ix + 1.5) - x;
- dy = (iy + 0.5) - y;
+ dx = (ix + 1.5f) - x;
+ dy = (iy + 0.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
- setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0);
+ setup->quad.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
setup->quad.mask |= MASK_BOTTOM_RIGHT;
}
- dx = (ix + 0.5) - x;
- dy = (iy + 1.5) - y;
+ dx = (ix + 0.5f) - x;
+ dy = (iy + 1.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
- setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0);
+ setup->quad.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
setup->quad.mask |= MASK_TOP_LEFT;
}
- dx = (ix + 1.5) - x;
- dy = (iy + 1.5) - y;
+ dx = (ix + 1.5f) - x;
+ dy = (iy + 1.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
- setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0);
+ setup->quad.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
setup->quad.mask |= MASK_TOP_RIGHT;
}
return &setup->stage;
}
+
+
+/* Recalculate det. This is only used in the test harness below:
+ */
+static void calc_det( struct prim_header *header )
+{
+ /* Window coords: */
+ const float *v0 = header->v[0]->data[0];
+ const float *v1 = header->v[1]->data[0];
+ const float *v2 = header->v[2]->data[0];
+
+ /* edge vectors e = v0 - v2, f = v1 - v2 */
+ const float ex = v0[0] - v2[0];
+ const float ey = v0[1] - v2[1];
+ const float fx = v1[0] - v2[0];
+ const float fy = v1[1] - v2[1];
+
+ /* det = cross(e,f).z */
+ header->det = ex * fy - ey * fx;
+}
+
+
+
+/* Test harness - feed vertex buffer back into prim pipeline.
+ *
+ * The big issue at this point is that reset_stipple doesn't make it
+ * through the interface. Probably need to split primitives at reset
+ * stipple, perhaps using the ~0 index marker.
+ */
+void sp_vbuf_setup_draw( struct pipe_context *pipe,
+ unsigned primitive,
+ const ushort *elements,
+ unsigned nr_elements,
+ const void *vertex_buffer,
+ unsigned nr_vertices )
+{
+ struct softpipe_context *softpipe = softpipe_context( pipe );
+ struct setup_stage *setup = setup_stage( softpipe->setup );
+ struct prim_header prim;
+ unsigned vertex_size = setup->stage.draw->vertex_info.size * sizeof(float);
+ int i, j;
+
+ prim.det = 0;
+ prim.reset_line_stipple = 0;
+ prim.edgeflags = 0;
+ prim.pad = 0;
+
+ setup->stage.begin( &setup->stage );
+
+ switch (primitive) {
+ case PIPE_PRIM_TRIANGLES:
+ for (i = 0; i < nr_elements; i += 3) {
+ for (j = 0; j < 3; j++)
+ prim.v[j] = (struct vertex_header *)((char *)vertex_buffer +
+ elements[i+j] * vertex_size);
+
+ calc_det(&prim);
+ setup->stage.tri( &setup->stage, &prim );
+ }
+ break;
+
+ case PIPE_PRIM_LINES:
+ for (i = 0; i < nr_elements; i += 2) {
+ for (j = 0; j < 2; j++)
+ prim.v[j] = (struct vertex_header *)((char *)vertex_buffer +
+ elements[i+j] * vertex_size);
+
+ setup->stage.line( &setup->stage, &prim );
+ }
+ break;
+
+ case PIPE_PRIM_POINTS:
+ for (i = 0; i < nr_elements; i += 2) {
+ prim.v[i] = (struct vertex_header *)((char *)vertex_buffer +
+ elements[i] * vertex_size);
+ setup->stage.point( &setup->stage, &prim );
+ }
+ break;
+ }
+
+ setup->stage.end( &setup->stage );
+}