/* $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 * Jim Duchek -- Utah GLX 6326 code * Alan Cox -- 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