mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 05:18:08 +02:00
simple line drawing code
This commit is contained in:
parent
c9527eae8e
commit
6378dc3ae3
1 changed files with 240 additions and 32 deletions
|
|
@ -36,6 +36,9 @@
|
|||
#include "g_tile.h"
|
||||
|
||||
|
||||
/**
|
||||
* Triangle edge info
|
||||
*/
|
||||
struct edge {
|
||||
GLfloat dx; /* X(v1) - X(v0), used only during setup */
|
||||
GLfloat dy; /* Y(v1) - Y(v0), used only during setup */
|
||||
|
|
@ -46,9 +49,13 @@ struct edge {
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
* Triangle setup info (derived from prim_stage).
|
||||
* Also used for line drawing (taking some liberties).
|
||||
*/
|
||||
struct setup_stage {
|
||||
struct prim_stage stage;
|
||||
|
||||
struct prim_stage stage; /**< This must be first */
|
||||
|
||||
/* 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.
|
||||
|
|
@ -57,7 +64,7 @@ struct setup_stage {
|
|||
const struct vertex_header *vmid;
|
||||
const struct vertex_header *vmin;
|
||||
const struct vertex_header *vprovoke;
|
||||
|
||||
|
||||
struct edge ebot;
|
||||
struct edge etop;
|
||||
struct edge emaj;
|
||||
|
|
@ -190,20 +197,9 @@ static void flush_spans( struct setup_stage *setup )
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do setup for line rasterization, then render the line.
|
||||
*/
|
||||
static void
|
||||
setup_line( struct prim_stage *stage,
|
||||
struct prim_header *header )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static GLboolean 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];
|
||||
|
|
@ -310,11 +306,12 @@ static void const_coeff( struct setup_stage *setup,
|
|||
|
||||
|
||||
/**
|
||||
* Compute a0, dadx and dady for a linearly interpolated coefficient.
|
||||
* Compute a0, dadx and dady for a linearly interpolated coefficient,
|
||||
* for a triangle.
|
||||
*/
|
||||
static void linear_coeff( struct setup_stage *setup,
|
||||
GLuint slot,
|
||||
GLuint i)
|
||||
static void tri_linear_coeff( struct setup_stage *setup,
|
||||
GLuint slot,
|
||||
GLuint i)
|
||||
{
|
||||
GLfloat botda = setup->vmid->data[slot][i] - setup->vmin->data[slot][i];
|
||||
GLfloat majda = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
|
||||
|
|
@ -349,11 +346,12 @@ static void linear_coeff( struct setup_stage *setup,
|
|||
|
||||
|
||||
/**
|
||||
* Compute a0, dadx and dady for a perspective-corrected interpolant.
|
||||
* Compute a0, dadx and dady for a perspective-corrected interpolant,
|
||||
* for a triangle.
|
||||
*/
|
||||
static void persp_coeff( struct setup_stage *setup,
|
||||
GLuint slot,
|
||||
GLuint i )
|
||||
static void tri_persp_coeff( struct setup_stage *setup,
|
||||
GLuint slot,
|
||||
GLuint i )
|
||||
{
|
||||
/* premultiply by 1/w:
|
||||
*/
|
||||
|
|
@ -379,15 +377,15 @@ static void persp_coeff( struct setup_stage *setup,
|
|||
* Compute the setup->coef[] array dadx, dady, a0 values.
|
||||
* Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
|
||||
*/
|
||||
static void setup_coefficients( struct setup_stage *setup )
|
||||
static void setup_tri_coefficients( struct setup_stage *setup )
|
||||
{
|
||||
const enum interp_mode *interp = setup->stage.generic->interp;
|
||||
GLuint slot, j;
|
||||
|
||||
/* z and w are done by linear interpolation:
|
||||
*/
|
||||
linear_coeff(setup, 0, 2);
|
||||
linear_coeff(setup, 0, 3);
|
||||
tri_linear_coeff(setup, 0, 2);
|
||||
tri_linear_coeff(setup, 0, 3);
|
||||
|
||||
/* setup interpolation for all the remaining attributes:
|
||||
*/
|
||||
|
|
@ -400,12 +398,12 @@ static void setup_coefficients( struct setup_stage *setup )
|
|||
|
||||
case INTERP_LINEAR:
|
||||
for (j = 0; j < NUM_CHANNELS; j++)
|
||||
linear_coeff(setup, slot, j);
|
||||
tri_linear_coeff(setup, slot, j);
|
||||
break;
|
||||
|
||||
case INTERP_PERSPECTIVE:
|
||||
for (j = 0; j < NUM_CHANNELS; j++)
|
||||
persp_coeff(setup, slot, j);
|
||||
tri_persp_coeff(setup, slot, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -413,7 +411,7 @@ static void setup_coefficients( struct setup_stage *setup )
|
|||
|
||||
|
||||
|
||||
static void setup_edges( struct setup_stage *setup )
|
||||
static void setup_tri_edges( struct setup_stage *setup )
|
||||
{
|
||||
GLfloat vmin_x = setup->vmin->data[0][0] + 0.5;
|
||||
GLfloat vmid_x = setup->vmid->data[0][0] + 0.5;
|
||||
|
|
@ -531,8 +529,8 @@ static void setup_tri( struct prim_stage *stage,
|
|||
_mesa_printf("%s\n", __FUNCTION__ );
|
||||
|
||||
setup_sort_vertices( setup, prim );
|
||||
setup_coefficients( setup );
|
||||
setup_edges( setup );
|
||||
setup_tri_coefficients( setup );
|
||||
setup_tri_edges( setup );
|
||||
|
||||
setup->span.y = 0;
|
||||
setup->span.y_flags = 0;
|
||||
|
|
@ -559,14 +557,224 @@ static void setup_tri( struct prim_stage *stage,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Compute a0, dadx and dady for a linearly interpolated coefficient,
|
||||
* for a line.
|
||||
*/
|
||||
static void
|
||||
line_linear_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
|
||||
{
|
||||
const GLfloat dz = setup->vmax->data[slot][i] - setup->vmin->data[slot][i];
|
||||
const GLfloat dadx = dz * setup->emaj.dx * setup->oneoverarea;
|
||||
const GLfloat dady = dz * setup->emaj.dy * setup->oneoverarea;
|
||||
setup->coef[slot].dadx[i] = dadx;
|
||||
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)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute a0, dadx and dady for a perspective-corrected interpolant,
|
||||
* for a line.
|
||||
*/
|
||||
static void
|
||||
line_persp_coeff(struct setup_stage *setup, GLuint slot, GLuint i)
|
||||
{
|
||||
/* XXX to do */
|
||||
line_linear_coeff(setup, slot, i); /* XXX temporary */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute the setup->coef[] array dadx, dady, a0 values.
|
||||
* Must be called after setup->vmin,vmax are initialized.
|
||||
*/
|
||||
static INLINE void
|
||||
setup_line_coefficients(struct setup_stage *setup, struct prim_header *prim)
|
||||
{
|
||||
const enum interp_mode *interp = setup->stage.generic->interp;
|
||||
GLuint slot, j;
|
||||
|
||||
/* use setup->vmin, vmax to point to vertices */
|
||||
setup->vprovoke = prim->v[1];
|
||||
setup->vmin = prim->v[0];
|
||||
setup->vmax = prim->v[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];
|
||||
/* NOTE: this is not really 1/area */
|
||||
setup->oneoverarea = 1.0 / (setup->emaj.dx * setup->emaj.dx +
|
||||
setup->emaj.dy * setup->emaj.dy);
|
||||
|
||||
/* z and w are done by linear interpolation:
|
||||
*/
|
||||
line_linear_coeff(setup, 0, 2);
|
||||
line_linear_coeff(setup, 0, 3);
|
||||
|
||||
/* setup interpolation for all the remaining attributes:
|
||||
*/
|
||||
for (slot = 1; slot < setup->quad.nr_attrs; slot++) {
|
||||
switch (interp[slot]) {
|
||||
case INTERP_CONSTANT:
|
||||
for (j = 0; j < NUM_CHANNELS; j++)
|
||||
const_coeff(setup, slot, j);
|
||||
break;
|
||||
|
||||
case INTERP_LINEAR:
|
||||
for (j = 0; j < NUM_CHANNELS; j++)
|
||||
line_linear_coeff(setup, slot, j);
|
||||
break;
|
||||
|
||||
case INTERP_PERSPECTIVE:
|
||||
for (j = 0; j < NUM_CHANNELS; j++)
|
||||
line_persp_coeff(setup, slot, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Plot a pixel in a line segment.
|
||||
*/
|
||||
static INLINE void
|
||||
plot(struct setup_stage *setup, GLint x, GLint y)
|
||||
{
|
||||
const GLint quadX = block(x);
|
||||
const GLint quadY = block(y);
|
||||
|
||||
if ((quadX != setup->quad.x0 || quadY != setup->quad.y0)
|
||||
&& setup->quad.x0 != -1) {
|
||||
/* flush prev quad, start new quad */
|
||||
quad_shade(setup->stage.generic, &setup->quad);
|
||||
setup->quad.mask = 0x0;
|
||||
}
|
||||
setup->quad.x0 = quadX;
|
||||
setup->quad.y0 = quadY;
|
||||
|
||||
if (x & 1) {
|
||||
if (y & 1)
|
||||
setup->quad.mask |= MASK_TOP_RIGHT;
|
||||
else
|
||||
setup->quad.mask |= MASK_BOTTOM_RIGHT;
|
||||
}
|
||||
else {
|
||||
if (y & 1)
|
||||
setup->quad.mask |= MASK_TOP_LEFT;
|
||||
else
|
||||
setup->quad.mask |= MASK_BOTTOM_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Do setup for line rasterization, then render the line.
|
||||
* XXX single-pixel width, no stipple, etc
|
||||
* XXX no scissoring yet.
|
||||
*/
|
||||
static void
|
||||
setup_line(struct prim_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
const struct vertex_header *v0 = prim->v[0];
|
||||
const struct vertex_header *v1 = prim->v[1];
|
||||
struct setup_stage *setup = setup_stage( stage );
|
||||
|
||||
GLint x0 = (GLint) v0->data[0][0];
|
||||
GLint x1 = (GLint) v1->data[0][0];
|
||||
GLint y0 = (GLint) v0->data[0][1];
|
||||
GLint y1 = (GLint) v1->data[0][1];
|
||||
GLint dx = x1 - x0;
|
||||
GLint dy = y1 - y0;
|
||||
GLint xstep, ystep;
|
||||
|
||||
if (dx == 0 && dy == 0)
|
||||
return;
|
||||
|
||||
setup_line_coefficients(setup, prim);
|
||||
|
||||
if (dx < 0) {
|
||||
dx = -dx; /* make positive */
|
||||
xstep = -1;
|
||||
}
|
||||
else {
|
||||
xstep = 1;
|
||||
}
|
||||
|
||||
if (dy < 0) {
|
||||
dy = -dy; /* make positive */
|
||||
ystep = -1;
|
||||
}
|
||||
else {
|
||||
ystep = 1;
|
||||
}
|
||||
|
||||
assert(dx >= 0);
|
||||
assert(dy >= 0);
|
||||
|
||||
setup->quad.x0 = setup->quad.y0 = -1;
|
||||
setup->quad.mask = 0x0;
|
||||
|
||||
if (dx > dy) {
|
||||
/*** X-major line ***/
|
||||
GLint i;
|
||||
const GLint errorInc = dy + dy;
|
||||
GLint error = errorInc - dx;
|
||||
const GLint errorDec = error - dx;
|
||||
|
||||
for (i = 0; i < dx; i++) {
|
||||
plot(setup, x0, y0);
|
||||
|
||||
x0 += xstep;
|
||||
if (error < 0) {
|
||||
error += errorInc;
|
||||
}
|
||||
else {
|
||||
error += errorDec;
|
||||
y0 += ystep;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*** Y-major line ***/
|
||||
GLint i;
|
||||
const GLint errorInc = dx + dx;
|
||||
GLint error = errorInc - dy;
|
||||
const GLint errorDec = error - dy;
|
||||
|
||||
for (i = 0; i < dy; i++) {
|
||||
plot(setup, x0, y0);
|
||||
|
||||
y0 += ystep;
|
||||
|
||||
if (error < 0) {
|
||||
error += errorInc;
|
||||
}
|
||||
else {
|
||||
error += errorDec;
|
||||
x0 += xstep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* draw final quad */
|
||||
if (setup->quad.mask) {
|
||||
quad_shade(setup->stage.generic, &setup->quad);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do setup for point rasterization, then render the point.
|
||||
* Round or square points...
|
||||
* XXX could optimize a lot for 1-pixel points.
|
||||
*/
|
||||
static void
|
||||
setup_point( struct prim_stage *stage,
|
||||
struct prim_header *prim )
|
||||
setup_point(struct prim_stage *stage, struct prim_header *prim)
|
||||
{
|
||||
struct setup_stage *setup = setup_stage( stage );
|
||||
GLfloat halfSize = 7.3; /*XXX this is a vertex attrib */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue