blob: f75e17318fc873bf702caa97299bcaa83c5e656d [file] [log] [blame]
/* $XFree86*/ /* -*- c-basic-offset: 3 -*- */
/*
* Copyright 2005 Eric Anholt
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors:
* Eric Anholt <anholt@FreeBSD.org>
* Jim Duchek <jim@linuxpimps.com> -- Utah GLX 6326 code
* Alan Cox <alan@redhat.com> -- 6326 Debugging
*
*/
static void TAG(sis_draw_tri_mmio)(sisContextPtr smesa, char *verts)
{
sisVertexPtr v0 = (sisVertexPtr)verts;
sisVertexPtr v1 = (sisVertexPtr)(verts + smesa->vertex_size * 4);
sisVertexPtr v2 = (sisVertexPtr)(verts + smesa->vertex_size * 4 * 2);
mWait3DCmdQueue (MMIO_VERT_REG_COUNT * 3);
SIS_MMIO_WRITE_VERTEX(v0, 0, 0);
SIS_MMIO_WRITE_VERTEX(v1, 1, 0);
SIS_MMIO_WRITE_VERTEX(v2, 2, 1);
}
static void TAG(sis_draw_line_mmio)(sisContextPtr smesa, char *verts)
{
sisVertexPtr v0 = (sisVertexPtr)verts;
sisVertexPtr v1 = (sisVertexPtr)(verts + smesa->vertex_size * 4);
mWait3DCmdQueue (MMIO_VERT_REG_COUNT * 2);
SIS_MMIO_WRITE_VERTEX(v0, 0, 0);
SIS_MMIO_WRITE_VERTEX(v1, 1, 1);
}
static void TAG(sis_draw_point_mmio)(sisContextPtr smesa, char *verts)
{
sisVertexPtr v0 = (sisVertexPtr)verts;
mWait3DCmdQueue (MMIO_VERT_REG_COUNT * 1);
SIS_MMIO_WRITE_VERTEX(v0, 1, 1);
}
#if !(SIS_STATES & VERT_UV1)
static void TAG(sis6326_draw_tri_mmio)(sisContextPtr smesa, char *verts)
{
sisVertexPtr v0 = (sisVertexPtr)verts;
sisVertexPtr v1 = (sisVertexPtr)(verts + smesa->vertex_size * 4);
sisVertexPtr v2 = (sisVertexPtr)(verts + smesa->vertex_size * 4 * 2);
GLfloat x0, x1, x2;
GLfloat y0, y1, y2;
GLfloat delt02, diffx02, diffy02, diffy12;
GLint dwPrimitiveSet = smesa->dwPrimitiveSet;
sisVertex tv0, tv1, tv2;
/* XXX Culling? */
tv0 = *v0;
tv1 = *v1;
tv2 = *v2;
tv0.v.y = Y_FLIP(tv0.v.y);
tv1.v.y = Y_FLIP(tv1.v.y);
tv2.v.y = Y_FLIP(tv2.v.y);
v0 = &tv0;
v1 = &tv1;
v2 = &tv2;
/* Cull polygons we won't draw. The hardware draws funky things if it
is fed these */
if((((v1->v.x - v0->v.x) * (v0->v.y - v2->v.y)) +
((v1->v.y - v0->v.y) * (v2->v.x - v0->v.x))) < 0)
return;
y0 = v0->v.y;
y1 = v1->v.y;
y2 = v2->v.y;
if (y0 > y1) {
if (y1 > y2) {
x0 = v0->v.x;
x1 = v1->v.x;
x2 = v2->v.x;
dwPrimitiveSet |= OP_6326_3D_ATOP | OP_6326_3D_BMID | OP_6326_3D_CBOT;
if ((SIS_STATES & VERT_SMOOTH) == 0)
dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_BOT;
} else {
if (y0 > y2) {
x0 = v0->v.x;
x1 = v2->v.x;
y1 = v2->v.y;
dwPrimitiveSet |= OP_6326_3D_ATOP | OP_6326_3D_CMID |
OP_6326_3D_BBOT;
if ((SIS_STATES & VERT_SMOOTH) == 0)
dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_MID;
} else {
x0 = v2->v.x;
y0 = v2->v.y;
x1 = v0->v.x;
y1 = v0->v.y;
dwPrimitiveSet |= OP_6326_3D_CTOP | OP_6326_3D_AMID |
OP_6326_3D_BBOT;
if ((SIS_STATES & VERT_SMOOTH) == 0)
dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_TOP;
}
x2 = v1->v.x;
y2 = v1->v.y;
}
} else {
if (y0 > y2) {
x0 = v1->v.x;
y0 = v1->v.y;
x1 = v0->v.x;
y1 = v0->v.y;
x2 = v2->v.x;
dwPrimitiveSet |= OP_6326_3D_BTOP | OP_6326_3D_AMID | OP_6326_3D_CBOT;
if ((SIS_STATES & VERT_SMOOTH) == 0)
dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_BOT;
} else {
if (y1 > y2) {
x0 = v1->v.x;
y0 = v1->v.y;
x1 = v2->v.x;
y1 = v2->v.y;
dwPrimitiveSet |= OP_6326_3D_BTOP | OP_6326_3D_CMID |
OP_6326_3D_ABOT;
if ((SIS_STATES & VERT_SMOOTH) == 0)
dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_MID;
} else {
x0 = v2->v.x;
y0 = v2->v.y;
x1 = v1->v.x;
dwPrimitiveSet |= OP_6326_3D_CTOP | OP_6326_3D_BMID |
OP_6326_3D_ABOT;
if ((SIS_STATES & VERT_SMOOTH) == 0)
dwPrimitiveSet |= OP_6326_3D_SHADE_FLAT_TOP;
}
x2 = v0->v.x;
y2 = v0->v.y;
}
}
if (x1 <= x0 && x1 <= x2) {
dwPrimitiveSet |= OP_3D_DIRECTION_LEFT;
} else if (x1 < x0 || x1 < x2) {
GLfloat tmp;
diffx02 = x0 - x2;
diffy02 = y0 - y2;
diffy12 = y1 - y2;
delt02 = diffx02 / diffy02;
tmp = x1 - (diffy12 * delt02 + x2);
if (tmp <= 0.0)
dwPrimitiveSet |= OP_3D_DIRECTION_LEFT;
}
tv0 = *v0;
tv1 = *v1;
tv2 = *v2;
tv0.v.y = Y_FLIP(tv0.v.y);
tv1.v.y = Y_FLIP(tv1.v.y);
tv2.v.y = Y_FLIP(tv2.v.y);
v0 = &tv0;
v1 = &tv1;
v2 = &tv2;
y0 = v0->v.y;
y1 = v1->v.y;
y2 = v2->v.y;
/* fprintf(stderr, "Vertex0 %f %f %f\n", v0->v.x, v0->v.y, v0->v.z);
fprintf(stderr, "Vertex1 %f %f %f\n", v1->v.x, v1->v.y, v1->v.z);
fprintf(stderr, "Vertex2 %f %f %f\n", v2->v.x, v2->v.y, v2->v.z);*/
mWait3DCmdQueue(MMIO_VERT_REG_COUNT * 3 + 1);
MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
SIS_MMIO_WRITE_VERTEX(v0, 0, 0);
SIS_MMIO_WRITE_VERTEX(v1, 1, 0);
SIS_MMIO_WRITE_VERTEX(v2, 2, 1);
mEndPrimitive();
}
static void TAG(sis6326_draw_line_mmio)(sisContextPtr smesa, char *verts)
{
sisVertexPtr v0 = (sisVertexPtr)verts;
sisVertexPtr v1 = (sisVertexPtr)(verts + smesa->vertex_size * 4);
GLint dwPrimitiveSet = smesa->dwPrimitiveSet;
if (abs(v0->v.y - v1->v.y) > abs(v0->v.x - v1->v.x))
{
dwPrimitiveSet |= OP_3D_DIRECTION_VERTICAL;
if (v0->v.y > v1->v.y)
dwPrimitiveSet |= OP_6326_3D_ATOP | OP_6326_3D_BBOT;
else
dwPrimitiveSet |= OP_6326_3D_BTOP | OP_6326_3D_ABOT;
} else {
if (v0->v.y > v1->v.y)
dwPrimitiveSet |= OP_6326_3D_BTOP | OP_6326_3D_ABOT;
else
dwPrimitiveSet |= OP_6326_3D_ATOP | OP_6326_3D_BBOT;
}
mWait3DCmdQueue (MMIO_VERT_REG_COUNT * 2 + 1);
MMIO(REG_3D_PrimitiveSet, dwPrimitiveSet);
SIS_MMIO_WRITE_VERTEX(v0, 0, 0);
SIS_MMIO_WRITE_VERTEX(v1, 1, 1);
}
static void TAG(sis6326_draw_point_mmio)(sisContextPtr smesa, char *verts)
{
sisVertexPtr v0 = (sisVertexPtr)verts;
mWait3DCmdQueue (MMIO_VERT_REG_COUNT * 1 + 1);
MMIO(REG_3D_PrimitiveSet, smesa->dwPrimitiveSet | OP_6326_3D_ATOP);
SIS_MMIO_WRITE_VERTEX(v0, 1, 1);
}
#endif
static INLINE void TAG(sis_vert_init)( void )
{
sis_tri_func_mmio[SIS_STATES] = TAG(sis_draw_tri_mmio);
sis_line_func_mmio[SIS_STATES] = TAG(sis_draw_line_mmio);
sis_point_func_mmio[SIS_STATES] = TAG(sis_draw_point_mmio);
#if !(SIS_STATES & VERT_UV1)
sis_tri_func_mmio[SIS_STATES | VERT_6326] = TAG(sis6326_draw_tri_mmio);
sis_line_func_mmio[SIS_STATES | VERT_6326] = TAG(sis6326_draw_line_mmio);
sis_point_func_mmio[SIS_STATES | VERT_6326] = TAG(sis6326_draw_point_mmio);
#endif
}
#undef TAG
#undef SIS_STATES