| /* |
| * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. |
| * Copyright 2001-2003 S3 Graphics, Inc. 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, sub license, |
| * 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 NON-INFRINGEMENT. IN NO EVENT SHALL |
| * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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. |
| */ |
| |
| #include <stdio.h> |
| #include <math.h> |
| |
| #include "glheader.h" |
| #include "context.h" |
| #include "mtypes.h" |
| #include "macros.h" |
| #include "colormac.h" |
| #include "enums.h" |
| |
| #include "swrast/swrast.h" |
| #include "swrast_setup/swrast_setup.h" |
| #include "tnl/t_context.h" |
| #include "tnl/t_pipeline.h" |
| |
| #include "via_context.h" |
| #include "via_tris.h" |
| #include "via_state.h" |
| #include "via_span.h" |
| #include "via_ioctl.h" |
| #include "via_3d_reg.h" |
| #include "via_tex.h" |
| |
| /*********************************************************************** |
| * Emit primitives as inline vertices * |
| ***********************************************************************/ |
| #define LINE_FALLBACK (0) |
| #define POINT_FALLBACK (0) |
| #define TRI_FALLBACK (0) |
| #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK) |
| #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED) |
| |
| |
| #if 0 |
| #define COPY_DWORDS(vb, vertsize, v) \ |
| do { \ |
| via_sse_memcpy(vb, v, vertsize * 4); \ |
| vb += vertsize; \ |
| } while (0) |
| #else |
| #if defined( USE_X86_ASM ) |
| #define COPY_DWORDS(vb, vertsize, v) \ |
| do { \ |
| int j; \ |
| int __tmp; \ |
| __asm__ __volatile__("rep ; movsl" \ |
| : "=%c" (j), "=D" (vb), "=S" (__tmp) \ |
| : "0" (vertsize), \ |
| "D" ((long)vb), \ |
| "S" ((long)v)); \ |
| } while (0) |
| #else |
| #define COPY_DWORDS(vb, vertsize, v) \ |
| do { \ |
| int j; \ |
| for (j = 0; j < vertsize; j++) \ |
| vb[j] = ((GLuint *)v)[j]; \ |
| vb += vertsize; \ |
| } while (0) |
| #endif |
| #endif |
| |
| static void via_draw_triangle(struct via_context *vmesa, |
| viaVertexPtr v0, |
| viaVertexPtr v1, |
| viaVertexPtr v2) |
| { |
| GLuint vertsize = vmesa->vertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 3 * 4 * vertsize); |
| |
| COPY_DWORDS(vb, vertsize, v0); |
| COPY_DWORDS(vb, vertsize, v1); |
| COPY_DWORDS(vb, vertsize, v2); |
| } |
| |
| |
| static void via_draw_quad(struct via_context *vmesa, |
| viaVertexPtr v0, |
| viaVertexPtr v1, |
| viaVertexPtr v2, |
| viaVertexPtr v3) |
| { |
| GLuint vertsize = vmesa->vertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 6 * 4 * vertsize); |
| |
| COPY_DWORDS(vb, vertsize, v0); |
| COPY_DWORDS(vb, vertsize, v1); |
| COPY_DWORDS(vb, vertsize, v3); |
| COPY_DWORDS(vb, vertsize, v1); |
| COPY_DWORDS(vb, vertsize, v2); |
| COPY_DWORDS(vb, vertsize, v3); |
| } |
| |
| static void via_draw_line(struct via_context *vmesa, |
| viaVertexPtr v0, |
| viaVertexPtr v1) |
| { |
| GLuint vertsize = vmesa->vertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 2 * 4 * vertsize); |
| COPY_DWORDS(vb, vertsize, v0); |
| COPY_DWORDS(vb, vertsize, v1); |
| } |
| |
| |
| static void via_draw_point(struct via_context *vmesa, |
| viaVertexPtr v0) |
| { |
| GLuint vertsize = vmesa->vertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 4 * vertsize); |
| COPY_DWORDS(vb, vertsize, v0); |
| } |
| |
| |
| /* Fallback drawing functions for the ptex hack. |
| */ |
| #define PTEX_VERTEX( tmp, vertex_size, v) \ |
| do { \ |
| GLuint j; \ |
| GLfloat rhw = 1.0 / v->f[vertex_size]; \ |
| for ( j = 0 ; j < vertex_size ; j++ ) \ |
| tmp.f[j] = v->f[j]; \ |
| tmp.f[3] *= v->f[vertex_size]; \ |
| tmp.f[vertex_size-2] *= rhw; \ |
| tmp.f[vertex_size-1] *= rhw; \ |
| } while (0) |
| |
| static void via_ptex_tri (struct via_context *vmesa, |
| viaVertexPtr v0, |
| viaVertexPtr v1, |
| viaVertexPtr v2) |
| { |
| GLuint vertsize = vmesa->hwVertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 3*4*vertsize); |
| viaVertex tmp; |
| |
| PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp); |
| PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp); |
| PTEX_VERTEX(tmp, vertsize, v2); COPY_DWORDS(vb, vertsize, &tmp); |
| } |
| |
| static void via_ptex_line (struct via_context *vmesa, |
| viaVertexPtr v0, |
| viaVertexPtr v1) |
| { |
| GLuint vertsize = vmesa->hwVertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 2*4*vertsize); |
| viaVertex tmp; |
| |
| PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp); |
| PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp); |
| } |
| |
| static void via_ptex_point (struct via_context *vmesa, |
| viaVertexPtr v0) |
| { |
| GLuint vertsize = vmesa->hwVertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, 1*4*vertsize); |
| viaVertex tmp; |
| |
| PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp); |
| } |
| |
| |
| |
| |
| |
| /*********************************************************************** |
| * Macros for via_dd_tritmp.h to draw basic primitives * |
| ***********************************************************************/ |
| |
| #define TRI(a, b, c) \ |
| do { \ |
| if (DO_FALLBACK) \ |
| vmesa->drawTri(vmesa, a, b, c); \ |
| else \ |
| via_draw_triangle(vmesa, a, b, c); \ |
| } while (0) |
| |
| #define QUAD(a, b, c, d) \ |
| do { \ |
| if (DO_FALLBACK) { \ |
| vmesa->drawTri(vmesa, a, b, d); \ |
| vmesa->drawTri(vmesa, b, c, d); \ |
| } \ |
| else \ |
| via_draw_quad(vmesa, a, b, c, d); \ |
| } while (0) |
| |
| #define LINE(v0, v1) \ |
| do { \ |
| if (DO_FALLBACK) \ |
| vmesa->drawLine(vmesa, v0, v1); \ |
| else \ |
| via_draw_line(vmesa, v0, v1); \ |
| } while (0) |
| |
| #define POINT(v0) \ |
| do { \ |
| if (DO_FALLBACK) \ |
| vmesa->drawPoint(vmesa, v0); \ |
| else \ |
| via_draw_point(vmesa, v0); \ |
| } while (0) |
| |
| |
| /*********************************************************************** |
| * Build render functions from dd templates * |
| ***********************************************************************/ |
| |
| #define VIA_OFFSET_BIT 0x01 |
| #define VIA_TWOSIDE_BIT 0x02 |
| #define VIA_UNFILLED_BIT 0x04 |
| #define VIA_FALLBACK_BIT 0x08 |
| #define VIA_MAX_TRIFUNC 0x10 |
| |
| |
| static struct { |
| tnl_points_func points; |
| tnl_line_func line; |
| tnl_triangle_func triangle; |
| tnl_quad_func quad; |
| } rast_tab[VIA_MAX_TRIFUNC + 1]; |
| |
| |
| #define DO_FALLBACK (IND & VIA_FALLBACK_BIT) |
| #define DO_OFFSET (IND & VIA_OFFSET_BIT) |
| #define DO_UNFILLED (IND & VIA_UNFILLED_BIT) |
| #define DO_TWOSIDE (IND & VIA_TWOSIDE_BIT) |
| #define DO_FLAT 0 |
| #define DO_TRI 1 |
| #define DO_QUAD 1 |
| #define DO_LINE 1 |
| #define DO_POINTS 1 |
| #define DO_FULL_QUAD 1 |
| |
| #define HAVE_RGBA 1 |
| #define HAVE_SPEC 1 |
| #define HAVE_BACK_COLORS 0 |
| #define HAVE_HW_FLATSHADE 1 |
| #define VERTEX viaVertex |
| #define TAB rast_tab |
| |
| /* Only used to pull back colors into vertices (ie, we know color is |
| * floating point). |
| */ |
| #define VIA_COLOR(dst, src) \ |
| do { \ |
| dst[0] = src[2]; \ |
| dst[1] = src[1]; \ |
| dst[2] = src[0]; \ |
| dst[3] = src[3]; \ |
| } while (0) |
| |
| #define VIA_SPEC(dst, src) \ |
| do { \ |
| dst[0] = src[2]; \ |
| dst[1] = src[1]; \ |
| dst[2] = src[0]; \ |
| } while (0) |
| |
| |
| #define DEPTH_SCALE vmesa->polygon_offset_scale |
| #define UNFILLED_TRI unfilled_tri |
| #define UNFILLED_QUAD unfilled_quad |
| #define VERT_X(_v) _v->v.x |
| #define VERT_Y(_v) _v->v.y |
| #define VERT_Z(_v) _v->v.z |
| #define AREA_IS_CCW(a) (a > 0) |
| #define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int))) |
| |
| #define VERT_SET_RGBA( v, c ) \ |
| do { \ |
| via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \ |
| } while (0) |
| |
| #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] |
| |
| #define VERT_SET_SPEC( v, c ) \ |
| do { \ |
| if (specoffset) { \ |
| via_color_t *color = (via_color_t *)&((v)->ui[specoffset]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ |
| UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ |
| } \ |
| } while (0) |
| #define VERT_COPY_SPEC( v0, v1 ) \ |
| do { \ |
| if (specoffset) { \ |
| v0->ub4[specoffset][0] = v1->ub4[specoffset][0]; \ |
| v0->ub4[specoffset][1] = v1->ub4[specoffset][1]; \ |
| v0->ub4[specoffset][2] = v1->ub4[specoffset][2]; \ |
| } \ |
| } while (0) |
| |
| |
| #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] |
| #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] |
| #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] |
| #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] |
| |
| |
| #define LOCAL_VARS(n) \ |
| struct via_context *vmesa = VIA_CONTEXT(ctx); \ |
| GLuint color[n], spec[n]; \ |
| GLuint coloroffset = vmesa->coloroffset; \ |
| GLuint specoffset = vmesa->specoffset; \ |
| (void)color; (void)spec; (void)coloroffset; (void)specoffset; |
| |
| |
| /*********************************************************************** |
| * Helpers for rendering unfilled primitives * |
| ***********************************************************************/ |
| |
| static const GLenum hwPrim[GL_POLYGON + 2] = { |
| GL_POINTS, |
| GL_LINES, |
| GL_LINES, |
| GL_LINES, |
| GL_TRIANGLES, |
| GL_TRIANGLES, |
| GL_TRIANGLES, |
| GL_TRIANGLES, |
| GL_TRIANGLES, |
| GL_TRIANGLES, |
| GL_POLYGON+1 |
| }; |
| |
| |
| #define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] ) |
| #define RENDER_PRIMITIVE vmesa->renderPrimitive |
| #define TAG(x) x |
| #define IND VIA_FALLBACK_BIT |
| #include "tnl_dd/t_dd_unfilled.h" |
| #undef IND |
| #undef RASTERIZE |
| |
| /*********************************************************************** |
| * Generate GL render functions * |
| ***********************************************************************/ |
| #define RASTERIZE(x) |
| |
| #define IND (0) |
| #define TAG(x) x |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_OFFSET_BIT) |
| #define TAG(x) x##_offset |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT) |
| #define TAG(x) x##_twoside |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT) |
| #define TAG(x) x##_twoside_offset |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_UNFILLED_BIT) |
| #define TAG(x) x##_unfilled |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT) |
| #define TAG(x) x##_offset_unfilled |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT) |
| #define TAG(x) x##_twoside_unfilled |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT) |
| #define TAG(x) x##_twoside_offset_unfilled |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_FALLBACK_BIT) |
| #define TAG(x) x##_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT) |
| #define TAG(x) x##_offset_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT) |
| #define TAG(x) x##_twoside_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_FALLBACK_BIT) |
| #define TAG(x) x##_twoside_offset_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT) |
| #define TAG(x) x##_unfilled_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT) |
| #define TAG(x) x##_offset_unfilled_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT) |
| #define TAG(x) x##_twoside_unfilled_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \ |
| VIA_FALLBACK_BIT) |
| #define TAG(x) x##_twoside_offset_unfilled_fallback |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| |
| /* Catchall case for flat, separate specular triangles (via has flat |
| * diffuse shading, but always does specular color with gouraud). |
| */ |
| #undef DO_FALLBACK |
| #undef DO_OFFSET |
| #undef DO_UNFILLED |
| #undef DO_TWOSIDE |
| #undef DO_FLAT |
| #define DO_FALLBACK (0) |
| #define DO_OFFSET (ctx->_TriangleCaps & DD_TRI_OFFSET) |
| #define DO_UNFILLED (ctx->_TriangleCaps & DD_TRI_UNFILLED) |
| #define DO_TWOSIDE (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) |
| #define DO_FLAT 1 |
| #define TAG(x) x##_flat_specular |
| #define IND VIA_MAX_TRIFUNC |
| #include "tnl_dd/t_dd_tritmp.h" |
| |
| |
| static void init_rast_tab(void) |
| { |
| init(); |
| init_offset(); |
| init_twoside(); |
| init_twoside_offset(); |
| init_unfilled(); |
| init_offset_unfilled(); |
| init_twoside_unfilled(); |
| init_twoside_offset_unfilled(); |
| init_fallback(); |
| init_offset_fallback(); |
| init_twoside_fallback(); |
| init_twoside_offset_fallback(); |
| init_unfilled_fallback(); |
| init_offset_unfilled_fallback(); |
| init_twoside_unfilled_fallback(); |
| init_twoside_offset_unfilled_fallback(); |
| |
| init_flat_specular(); /* special! */ |
| } |
| |
| |
| /*********************************************************************** |
| * Rasterization fallback helpers * |
| ***********************************************************************/ |
| |
| |
| /* This code is hit only when a mix of accelerated and unaccelerated |
| * primitives are being drawn, and only for the unaccelerated |
| * primitives. |
| */ |
| static void |
| via_fallback_tri(struct via_context *vmesa, |
| viaVertex *v0, |
| viaVertex *v1, |
| viaVertex *v2) |
| { |
| GLcontext *ctx = vmesa->glCtx; |
| SWvertex v[3]; |
| _swsetup_Translate(ctx, v0, &v[0]); |
| _swsetup_Translate(ctx, v1, &v[1]); |
| _swsetup_Translate(ctx, v2, &v[2]); |
| viaSpanRenderStart( ctx ); |
| _swrast_Triangle(ctx, &v[0], &v[1], &v[2]); |
| viaSpanRenderFinish( ctx ); |
| } |
| |
| |
| static void |
| via_fallback_line(struct via_context *vmesa, |
| viaVertex *v0, |
| viaVertex *v1) |
| { |
| GLcontext *ctx = vmesa->glCtx; |
| SWvertex v[2]; |
| _swsetup_Translate(ctx, v0, &v[0]); |
| _swsetup_Translate(ctx, v1, &v[1]); |
| viaSpanRenderStart( ctx ); |
| _swrast_Line(ctx, &v[0], &v[1]); |
| viaSpanRenderFinish( ctx ); |
| } |
| |
| |
| static void |
| via_fallback_point(struct via_context *vmesa, |
| viaVertex *v0) |
| { |
| GLcontext *ctx = vmesa->glCtx; |
| SWvertex v[1]; |
| _swsetup_Translate(ctx, v0, &v[0]); |
| viaSpanRenderStart( ctx ); |
| _swrast_Point(ctx, &v[0]); |
| viaSpanRenderFinish( ctx ); |
| } |
| |
| static void viaResetLineStipple( GLcontext *ctx ) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| vmesa->regCmdB |= HC_HLPrst_MASK; |
| } |
| |
| /**********************************************************************/ |
| /* Render unclipped begin/end objects */ |
| /**********************************************************************/ |
| #define IND 0 |
| #define V(x) (viaVertex *)(vertptr + ((x) * vertsize * sizeof(int))) |
| #define RENDER_POINTS(start, count) \ |
| for (; start < count; start++) POINT(V(ELT(start))); |
| #define RENDER_LINE(v0, v1) LINE(V(v0), V(v1)) |
| #define RENDER_TRI( v0, v1, v2) TRI( V(v0), V(v1), V(v2)) |
| #define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3)) |
| #define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x]) |
| #undef LOCAL_VARS |
| #define LOCAL_VARS \ |
| struct via_context *vmesa = VIA_CONTEXT(ctx); \ |
| GLubyte *vertptr = (GLubyte *)vmesa->verts; \ |
| const GLuint vertsize = vmesa->vertexSize; \ |
| const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ |
| const GLboolean stipple = ctx->Line.StippleFlag; \ |
| (void) elt; (void) stipple; |
| #define RESET_STIPPLE if ( stipple ) viaResetLineStipple( ctx ); |
| #define RESET_OCCLUSION |
| #define PRESERVE_VB_DEFS |
| #define ELT(x) x |
| #define TAG(x) via_##x##_verts |
| #include "tnl/t_vb_rendertmp.h" |
| #undef ELT |
| #undef TAG |
| #define TAG(x) via_##x##_elts |
| #define ELT(x) elt[x] |
| #include "tnl/t_vb_rendertmp.h" |
| #undef ELT |
| #undef TAG |
| #undef NEED_EDGEFLAG_SETUP |
| #undef EDGEFLAG_GET |
| #undef EDGEFLAG_SET |
| #undef RESET_OCCLUSION |
| |
| |
| /**********************************************************************/ |
| /* Render clipped primitives */ |
| /**********************************************************************/ |
| |
| |
| |
| static void viaRenderClippedPoly(GLcontext *ctx, const GLuint *elts, |
| GLuint n) |
| { |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
| GLuint prim = VIA_CONTEXT(ctx)->renderPrimitive; |
| |
| /* Render the new vertices as an unclipped polygon. |
| */ |
| { |
| GLuint *tmp = VB->Elts; |
| VB->Elts = (GLuint *)elts; |
| tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n, |
| PRIM_BEGIN|PRIM_END); |
| VB->Elts = tmp; |
| } |
| |
| /* Restore the render primitive |
| */ |
| if (prim != GL_POLYGON && |
| prim != GL_POLYGON + 1) |
| tnl->Driver.Render.PrimitiveNotify( ctx, prim ); |
| } |
| |
| static void viaRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj) |
| { |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| tnl->Driver.Render.Line(ctx, ii, jj); |
| } |
| |
| static void viaFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts, |
| GLuint n) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| GLuint vertsize = vmesa->vertexSize; |
| GLuint *vb = viaExtendPrimitive(vmesa, (n - 2) * 3 * 4 * vertsize); |
| GLubyte *vertptr = (GLubyte *)vmesa->verts; |
| const GLuint *start = (const GLuint *)V(elts[0]); |
| int i; |
| |
| for (i = 2; i < n; i++) { |
| COPY_DWORDS(vb, vertsize, V(elts[i - 1])); |
| COPY_DWORDS(vb, vertsize, V(elts[i])); |
| COPY_DWORDS(vb, vertsize, start); |
| } |
| } |
| |
| |
| /**********************************************************************/ |
| /* Choose render functions */ |
| /**********************************************************************/ |
| |
| |
| #define _VIA_NEW_VERTEX (_NEW_TEXTURE | \ |
| _DD_NEW_SEPARATE_SPECULAR | \ |
| _DD_NEW_TRI_UNFILLED | \ |
| _DD_NEW_TRI_LIGHT_TWOSIDE | \ |
| _NEW_FOG) |
| |
| #define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \ |
| _DD_NEW_TRI_UNFILLED | \ |
| _DD_NEW_TRI_LIGHT_TWOSIDE | \ |
| _DD_NEW_TRI_OFFSET | \ |
| _DD_NEW_TRI_STIPPLE | \ |
| _NEW_POLYGONSTIPPLE) |
| |
| |
| static void viaChooseRenderState(GLcontext *ctx) |
| { |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| GLuint flags = ctx->_TriangleCaps; |
| GLuint index = 0; |
| |
| if (vmesa->ptexHack) { |
| vmesa->drawPoint = via_ptex_point; |
| vmesa->drawLine = via_ptex_line; |
| vmesa->drawTri = via_ptex_tri; |
| index |= VIA_FALLBACK_BIT; |
| } |
| else { |
| vmesa->drawPoint = via_draw_point; |
| vmesa->drawLine = via_draw_line; |
| vmesa->drawTri = via_draw_triangle; |
| } |
| |
| if (flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) { |
| if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) |
| index |= VIA_TWOSIDE_BIT; |
| if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) |
| index |= VIA_UNFILLED_BIT; |
| if (flags & DD_TRI_OFFSET) |
| index |= VIA_OFFSET_BIT; |
| if (flags & ANY_FALLBACK_FLAGS) |
| index |= VIA_FALLBACK_BIT; |
| |
| /* Hook in fallbacks for specific primitives. */ |
| if (flags & POINT_FALLBACK) |
| vmesa->drawPoint = via_fallback_point; |
| |
| if (flags & LINE_FALLBACK) |
| vmesa->drawLine = via_fallback_line; |
| |
| if (flags & TRI_FALLBACK) |
| vmesa->drawTri = via_fallback_tri; |
| } |
| |
| if ((flags & DD_SEPARATE_SPECULAR) && ctx->Light.ShadeModel == GL_FLAT) |
| index = VIA_MAX_TRIFUNC; /* flat specular */ |
| |
| if (vmesa->renderIndex != index) { |
| vmesa->renderIndex = index; |
| |
| tnl->Driver.Render.Points = rast_tab[index].points; |
| tnl->Driver.Render.Line = rast_tab[index].line; |
| tnl->Driver.Render.Triangle = rast_tab[index].triangle; |
| tnl->Driver.Render.Quad = rast_tab[index].quad; |
| |
| if (index == 0) { |
| tnl->Driver.Render.PrimTabVerts = via_render_tab_verts; |
| tnl->Driver.Render.PrimTabElts = via_render_tab_elts; |
| tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */ |
| tnl->Driver.Render.ClippedPolygon = viaFastRenderClippedPoly; |
| } |
| else { |
| tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; |
| tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; |
| tnl->Driver.Render.ClippedLine = viaRenderClippedLine; |
| tnl->Driver.Render.ClippedPolygon = viaRenderClippedPoly; |
| } |
| } |
| } |
| |
| |
| #define VIA_EMIT_TEX1 0x01 |
| #define VIA_EMIT_TEX0 0x02 |
| #define VIA_EMIT_PTEX0 0x04 |
| #define VIA_EMIT_RGBA 0x08 |
| #define VIA_EMIT_SPEC 0x10 |
| #define VIA_EMIT_FOG 0x20 |
| #define VIA_EMIT_W 0x40 |
| |
| #define EMIT_ATTR( ATTR, STYLE, INDEX, REGB ) \ |
| do { \ |
| vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR); \ |
| vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE); \ |
| vmesa->vertex_attr_count++; \ |
| setupIndex |= (INDEX); \ |
| regCmdB |= (REGB); \ |
| } while (0) |
| |
| #define EMIT_PAD( N ) \ |
| do { \ |
| vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0; \ |
| vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD; \ |
| vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N); \ |
| vmesa->vertex_attr_count++; \ |
| } while (0) |
| |
| |
| |
| static void viaChooseVertexState( GLcontext *ctx ) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| DECLARE_RENDERINPUTS(index_bitset); |
| GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z; |
| GLuint setupIndex = 0; |
| |
| RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); |
| vmesa->vertex_attr_count = 0; |
| |
| /* EMIT_ATTR's must be in order as they tell t_vertex.c how to |
| * build up a hardware vertex. |
| */ |
| if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || |
| RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { |
| EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W ); |
| vmesa->coloroffset = 4; |
| } |
| else { |
| EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 ); |
| vmesa->coloroffset = 3; |
| } |
| |
| /* t_context.c always includes a diffuse color */ |
| EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VIA_EMIT_RGBA, |
| HC_HVPMSK_Cd ); |
| |
| vmesa->specoffset = 0; |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) || |
| RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) { |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) { |
| vmesa->specoffset = vmesa->coloroffset + 1; |
| EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC, |
| HC_HVPMSK_Cs ); |
| } |
| else |
| EMIT_PAD( 3 ); |
| |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) |
| EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs ); |
| else |
| EMIT_PAD( 1 ); |
| } |
| |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) { |
| if (vmesa->ptexHack) |
| EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0, |
| (HC_HVPMSK_S | HC_HVPMSK_T) ); |
| else |
| EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, VIA_EMIT_TEX0, |
| (HC_HVPMSK_S | HC_HVPMSK_T) ); |
| } |
| |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) { |
| EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1, |
| (HC_HVPMSK_S | HC_HVPMSK_T) ); |
| } |
| |
| if (setupIndex != vmesa->setupIndex) { |
| vmesa->vertexSize = _tnl_install_attrs( ctx, |
| vmesa->vertex_attrs, |
| vmesa->vertex_attr_count, |
| vmesa->ViewportMatrix.m, 0 ); |
| vmesa->vertexSize >>= 2; |
| vmesa->setupIndex = setupIndex; |
| vmesa->regCmdB &= ~HC_HVPMSK_MASK; |
| vmesa->regCmdB |= regCmdB; |
| |
| if (vmesa->ptexHack) |
| vmesa->hwVertexSize = vmesa->vertexSize - 1; |
| else |
| vmesa->hwVertexSize = vmesa->vertexSize; |
| } |
| } |
| |
| |
| |
| |
| /* Check if projective texture coordinates are used and if we can fake |
| * them. Fallback to swrast if we can't. Returns GL_TRUE if projective |
| * texture coordinates must be faked, GL_FALSE otherwise. |
| */ |
| static GLboolean viaCheckPTexHack( GLcontext *ctx ) |
| { |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| struct vertex_buffer *VB = &tnl->vb; |
| DECLARE_RENDERINPUTS(index_bitset); |
| GLboolean fallback = GL_FALSE; |
| GLboolean ptexHack = GL_FALSE; |
| |
| RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset ); |
| |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->TexCoordPtr[0]->size == 4) { |
| if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX )) |
| ptexHack = GL_TRUE; |
| else |
| fallback = GL_TRUE; |
| } |
| if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->TexCoordPtr[1]->size == 4) |
| fallback = GL_TRUE; |
| |
| FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback); |
| return ptexHack; |
| } |
| |
| |
| |
| |
| /**********************************************************************/ |
| /* High level hooks for t_vb_render.c */ |
| /**********************************************************************/ |
| |
| |
| static void viaRenderStart(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
| |
| { |
| GLboolean ptexHack = viaCheckPTexHack( ctx ); |
| if (ptexHack != vmesa->ptexHack) { |
| vmesa->ptexHack = ptexHack; |
| vmesa->newRenderState |= _VIA_NEW_RENDERSTATE; |
| } |
| } |
| |
| if (vmesa->newState) { |
| vmesa->newRenderState |= vmesa->newState; |
| viaValidateState( ctx ); |
| } |
| |
| if (vmesa->Fallback) { |
| tnl->Driver.Render.Start(ctx); |
| return; |
| } |
| |
| if (vmesa->newRenderState) { |
| viaChooseVertexState(ctx); |
| viaChooseRenderState(ctx); |
| vmesa->newRenderState = 0; |
| } |
| |
| /* Important: |
| */ |
| VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; |
| } |
| |
| static void viaRenderFinish(GLcontext *ctx) |
| { |
| VIA_FINISH_PRIM(VIA_CONTEXT(ctx)); |
| } |
| |
| |
| /* System to flush dma and emit state changes based on the rasterized |
| * primitive. |
| */ |
| void viaRasterPrimitive(GLcontext *ctx, |
| GLenum glprim, |
| GLenum hwprim) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| GLuint regCmdB; |
| RING_VARS; |
| |
| if (VIA_DEBUG & DEBUG_PRIMS) |
| fprintf(stderr, "%s: %s/%s/%s\n", |
| __FUNCTION__, _mesa_lookup_enum_by_nr(glprim), |
| _mesa_lookup_enum_by_nr(hwprim), |
| _mesa_lookup_enum_by_nr(ctx->Light.ShadeModel)); |
| |
| assert (!vmesa->newState); |
| |
| vmesa->renderPrimitive = glprim; |
| |
| if (hwprim != vmesa->hwPrimitive || |
| ctx->Light.ShadeModel != vmesa->hwShadeModel) { |
| |
| VIA_FINISH_PRIM(vmesa); |
| |
| /* Ensure no wrapping inside this function */ |
| viaCheckDma( vmesa, 1024 ); |
| |
| if (vmesa->newEmitState) { |
| viaEmitState(vmesa); |
| } |
| |
| vmesa->regCmdA_End = HC_ACMD_HCmdA; |
| |
| if (ctx->Light.ShadeModel == GL_SMOOTH) { |
| vmesa->regCmdA_End |= HC_HShading_Gouraud; |
| } |
| |
| vmesa->hwShadeModel = ctx->Light.ShadeModel; |
| regCmdB = vmesa->regCmdB; |
| |
| switch (hwprim) { |
| case GL_POINTS: |
| vmesa->regCmdA_End |= HC_HPMType_Point | HC_HVCycle_Full; |
| vmesa->regCmdA_End |= HC_HShading_Gouraud; /* always Gouraud |
| shade points?!? */ |
| break; |
| case GL_LINES: |
| vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_Full; |
| regCmdB |= HC_HLPrst_MASK; |
| if (ctx->Light.ShadeModel == GL_FLAT) |
| vmesa->regCmdA_End |= HC_HShading_FlatB; |
| break; |
| case GL_LINE_LOOP: |
| case GL_LINE_STRIP: |
| vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_AFP | |
| HC_HVCycle_AB | HC_HVCycle_NewB; |
| regCmdB |= HC_HVCycle_AB | HC_HVCycle_NewB | HC_HLPrst_MASK; |
| if (ctx->Light.ShadeModel == GL_FLAT) |
| vmesa->regCmdA_End |= HC_HShading_FlatB; |
| break; |
| case GL_TRIANGLES: |
| vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_Full; |
| if (ctx->Light.ShadeModel == GL_FLAT) |
| vmesa->regCmdA_End |= HC_HShading_FlatC; |
| break; |
| case GL_TRIANGLE_STRIP: |
| vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP | |
| HC_HVCycle_AC | HC_HVCycle_BB | HC_HVCycle_NewC; |
| regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC; |
| if (ctx->Light.ShadeModel == GL_FLAT) |
| vmesa->regCmdA_End |= HC_HShading_FlatC; |
| break; |
| case GL_TRIANGLE_FAN: |
| vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP | |
| HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC; |
| regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC; |
| if (ctx->Light.ShadeModel == GL_FLAT) |
| vmesa->regCmdA_End |= HC_HShading_FlatC; |
| break; |
| case GL_QUADS: |
| abort(); |
| return; |
| case GL_QUAD_STRIP: |
| abort(); |
| return; |
| case GL_POLYGON: |
| vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP | |
| HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC; |
| regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC; |
| if (ctx->Light.ShadeModel == GL_FLAT) |
| vmesa->regCmdA_End |= HC_HShading_FlatC; |
| break; |
| default: |
| abort(); |
| return; |
| } |
| |
| /* assert((vmesa->dmaLow & 0x4) == 0); */ |
| |
| if (vmesa->dmaCliprectAddr == ~0) { |
| if (VIA_DEBUG & DEBUG_DMA) |
| fprintf(stderr, "reserve cliprect space at %x\n", vmesa->dmaLow); |
| vmesa->dmaCliprectAddr = vmesa->dmaLow; |
| BEGIN_RING(8); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_NotTex << 16) ); |
| OUT_RING( 0xCCCCCCCC ); |
| OUT_RING( 0xCCCCCCCC ); |
| OUT_RING( 0xCCCCCCCC ); |
| OUT_RING( 0xCCCCCCCC ); |
| OUT_RING( 0xCCCCCCCC ); |
| OUT_RING( 0xCCCCCCCC ); |
| ADVANCE_RING(); |
| } |
| |
| assert(vmesa->dmaLastPrim == 0); |
| |
| BEGIN_RING(8); |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_NotTex << 16) ); |
| OUT_RING( 0xCCCCCCCC ); |
| OUT_RING( 0xDDDDDDDD ); |
| |
| OUT_RING( HC_HEADER2 ); |
| OUT_RING( (HC_ParaType_CmdVdata << 16) ); |
| OUT_RING( regCmdB ); |
| OUT_RING( vmesa->regCmdA_End ); |
| ADVANCE_RING(); |
| |
| vmesa->hwPrimitive = hwprim; |
| vmesa->dmaLastPrim = vmesa->dmaLow; |
| } |
| else { |
| assert(!vmesa->newEmitState); |
| } |
| } |
| |
| /* Callback for mesa: |
| */ |
| static void viaRenderPrimitive( GLcontext *ctx, GLuint prim ) |
| { |
| viaRasterPrimitive( ctx, prim, hwPrim[prim] ); |
| } |
| |
| |
| void viaFinishPrimitive(struct via_context *vmesa) |
| { |
| if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS)) |
| fprintf(stderr, "%s\n", __FUNCTION__); |
| |
| if (!vmesa->dmaLastPrim || vmesa->dmaCliprectAddr == ~0) { |
| assert(0); |
| } |
| else if (vmesa->dmaLow != vmesa->dmaLastPrim) { |
| GLuint cmdA = (vmesa->regCmdA_End | HC_HPLEND_MASK | |
| HC_HPMValidN_MASK | HC_HE3Fire_MASK); |
| RING_VARS; |
| |
| vmesa->dmaLastPrim = 0; |
| |
| /* KW: modified 0x1 to 0x4 below: |
| */ |
| if ((vmesa->dmaLow & 0x4) || !vmesa->useAgp) { |
| BEGIN_RING_NOCHECK( 1 ); |
| OUT_RING( cmdA ); |
| ADVANCE_RING(); |
| } |
| else { |
| BEGIN_RING_NOCHECK( 2 ); |
| OUT_RING( cmdA ); |
| OUT_RING( cmdA ); |
| ADVANCE_RING(); |
| } |
| |
| if (vmesa->dmaLow > VIA_DMA_HIGHWATER) |
| viaFlushDma( vmesa ); |
| } |
| else { |
| if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS)) |
| fprintf(stderr, "remove empty primitive\n"); |
| |
| /* Remove the primitive header: |
| */ |
| vmesa->dmaLastPrim = 0; |
| vmesa->dmaLow -= 8 * sizeof(GLuint); |
| |
| /* Maybe remove the cliprect as well: |
| */ |
| if (vmesa->dmaCliprectAddr == vmesa->dmaLow - 8 * sizeof(GLuint)) { |
| vmesa->dmaLow -= 8 * sizeof(GLuint); |
| vmesa->dmaCliprectAddr = ~0; |
| } |
| } |
| |
| vmesa->renderPrimitive = GL_POLYGON + 1; |
| vmesa->hwPrimitive = GL_POLYGON + 1; |
| vmesa->dmaLastPrim = 0; |
| } |
| |
| |
| /**********************************************************************/ |
| /* Transition to/from hardware rasterization. */ |
| /**********************************************************************/ |
| |
| |
| void viaFallback(struct via_context *vmesa, GLuint bit, GLboolean mode) |
| { |
| GLcontext *ctx = vmesa->glCtx; |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| GLuint oldfallback = vmesa->Fallback; |
| |
| if (mode) { |
| vmesa->Fallback |= bit; |
| if (oldfallback == 0) { |
| VIA_FLUSH_DMA(vmesa); |
| |
| if (VIA_DEBUG & DEBUG_FALLBACKS) |
| fprintf(stderr, "ENTER FALLBACK %x\n", bit); |
| |
| _swsetup_Wakeup(ctx); |
| vmesa->renderIndex = ~0; |
| } |
| } |
| else { |
| vmesa->Fallback &= ~bit; |
| if (oldfallback == bit) { |
| _swrast_flush( ctx ); |
| |
| if (VIA_DEBUG & DEBUG_FALLBACKS) |
| fprintf(stderr, "LEAVE FALLBACK %x\n", bit); |
| |
| tnl->Driver.Render.Start = viaRenderStart; |
| tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive; |
| tnl->Driver.Render.Finish = viaRenderFinish; |
| |
| tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
| tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
| tnl->Driver.Render.Interp = _tnl_interp; |
| tnl->Driver.Render.ResetLineStipple = viaResetLineStipple; |
| |
| _tnl_invalidate_vertex_state( ctx, ~0 ); |
| _tnl_invalidate_vertices( ctx, ~0 ); |
| _tnl_install_attrs( ctx, |
| vmesa->vertex_attrs, |
| vmesa->vertex_attr_count, |
| vmesa->ViewportMatrix.m, 0 ); |
| |
| vmesa->newState |= (_VIA_NEW_RENDERSTATE|_VIA_NEW_VERTEX); |
| } |
| } |
| } |
| |
| static void viaRunPipeline( GLcontext *ctx ) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| |
| if (vmesa->newState) { |
| vmesa->newRenderState |= vmesa->newState; |
| viaValidateState( ctx ); |
| } |
| |
| _tnl_run_pipeline( ctx ); |
| } |
| |
| |
| /**********************************************************************/ |
| /* Initialization. */ |
| /**********************************************************************/ |
| |
| |
| void viaInitTriFuncs(GLcontext *ctx) |
| { |
| struct via_context *vmesa = VIA_CONTEXT(ctx); |
| TNLcontext *tnl = TNL_CONTEXT(ctx); |
| static int firsttime = 1; |
| |
| if (firsttime) { |
| init_rast_tab(); |
| firsttime = 0; |
| } |
| |
| tnl->Driver.RunPipeline = viaRunPipeline; |
| tnl->Driver.Render.Start = viaRenderStart; |
| tnl->Driver.Render.Finish = viaRenderFinish; |
| tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive; |
| tnl->Driver.Render.ResetLineStipple = viaResetLineStipple; |
| tnl->Driver.Render.BuildVertices = _tnl_build_vertices; |
| tnl->Driver.Render.CopyPV = _tnl_copy_pv; |
| tnl->Driver.Render.Interp = _tnl_interp; |
| |
| _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, |
| (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) ); |
| |
| vmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf; |
| |
| } |