diff options
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r-- | src/mesa/tnl/t_context.c | 33 | ||||
-rw-r--r-- | src/mesa/tnl/t_context.h | 5 | ||||
-rw-r--r-- | src/mesa/tnl/t_draw.c | 107 | ||||
-rw-r--r-- | src/mesa/tnl/t_rasterpos.c | 64 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_cliptmp.h | 35 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_lighttmp.h | 6 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_points.c | 2 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_program.c | 47 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_rendertmp.h | 101 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_texgen.c | 24 | ||||
-rw-r--r-- | src/mesa/tnl/t_vb_vertex.c | 24 | ||||
-rw-r--r-- | src/mesa/tnl/t_vertex.c | 45 | ||||
-rw-r--r-- | src/mesa/tnl/t_vp_build.c | 1 | ||||
-rw-r--r-- | src/mesa/tnl/t_vp_build.h | 7 | ||||
-rw-r--r-- | src/mesa/tnl/tnl.h | 13 | ||||
-rw-r--r-- | src/mesa/tnl/tnl_features.h | 13 |
16 files changed, 392 insertions, 135 deletions
diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index 5e2a58249e..f2771cde09 100644 --- a/src/mesa/tnl/t_context.c +++ b/src/mesa/tnl/t_context.c @@ -32,6 +32,8 @@ #include "main/macros.h" #include "main/mtypes.h" #include "main/light.h" +#include "math/m_translate.h" +#include "math/m_xform.h" #include "tnl.h" #include "t_context.h" @@ -78,6 +80,12 @@ _tnl_CreateContext( GLcontext *ctx ) tnl->nr_blocks = 0; + /* plug in the VBO drawing function */ + vbo_set_draw_func(ctx, _tnl_vbo_draw_prims); + + _math_init_transformation(); + _math_init_translate(); + return GL_TRUE; } @@ -109,24 +117,28 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) tnl->pipeline.new_state |= new_state; - /* Calculate tnl->render_inputs: + /* Calculate tnl->render_inputs. This bitmask indicates which vertex + * attributes need to be emitted to the rasterizer. */ if (ctx->Visual.rgbMode) { GLuint i; RENDERINPUTS_ZERO( tnl->render_inputs_bitset ); RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS ); + if (!fp || (fp->Base.InputsRead & FRAG_BIT_COL0)) { RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR0 ); } + + if (NEED_SECONDARY_COLOR(ctx)) + RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 ); + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { - if (ctx->Texture._EnabledCoordUnits & (1 << i)) { + if (ctx->Texture._EnabledCoordUnits & (1 << i) || + (fp && fp->Base.InputsRead & FRAG_BIT_TEX(i))) { RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX(i) ); } } - - if (NEED_SECONDARY_COLOR(ctx)) - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 ); } else { RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS ); @@ -137,13 +149,10 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) /* fixed-function fog */ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG ); } - else if (ctx->FragmentProgram._Current) { - struct gl_fragment_program *fp = ctx->FragmentProgram._Current; - if (fp) { - if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) { - /* fragment program needs fog coord */ - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG ); - } + else if (fp) { + if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) { + /* fragment program needs fog coord */ + RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG ); } } diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index 0a6ce04614..6137c2d2fe 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -50,6 +50,7 @@ #define _T_CONTEXT_H #include "main/glheader.h" +#include "main/bitset.h" #include "main/mtypes.h" #include "math/m_matrix.h" @@ -547,4 +548,8 @@ typedef struct #define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */ +extern void +tnl_clip_prepare(GLcontext *ctx); + + #endif diff --git a/src/mesa/tnl/t_draw.c b/src/mesa/tnl/t_draw.c index fd647c1f4a..04fa106300 100644 --- a/src/mesa/tnl/t_draw.c +++ b/src/mesa/tnl/t_draw.c @@ -88,6 +88,29 @@ static void free_space(GLcontext *ctx) } while (0) +/** + * Convert array of BGRA/GLubyte[4] values to RGBA/float[4] + * \param ptr input/ubyte array + * \param fptr output/float array + */ +static void +convert_bgra_to_float(const struct gl_client_array *input, + const GLubyte *ptr, GLfloat *fptr, + GLuint count ) +{ + GLuint i; + assert(input->Normalized); + assert(input->Size == 4); + for (i = 0; i < count; i++) { + const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */ + *fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */ + *fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */ + *fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */ + *fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */ + ptr += input->StrideB; + } +} + /* Adjust pointer to point at first requested element, convert to * floating point, populate VB->AttribPtr[]. @@ -112,7 +135,13 @@ static void _tnl_import_array( GLcontext *ctx, CONVERT(GLbyte, BYTE_TO_FLOAT); break; case GL_UNSIGNED_BYTE: - CONVERT(GLubyte, UBYTE_TO_FLOAT); + if (input->Format == GL_BGRA) { + /* See GL_EXT_vertex_array_bgra */ + convert_bgra_to_float(input, ptr, fptr, count); + } + else { + CONVERT(GLubyte, UBYTE_TO_FLOAT); + } break; case GL_SHORT: CONVERT(GLshort, SHORT_TO_FLOAT); @@ -287,22 +316,27 @@ static void bind_indices( GLcontext *ctx, ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); - if (ib->type == GL_UNSIGNED_INT) { + if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) { VB->Elts = (GLuint *) ptr; } else { GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); VB->Elts = elts; - if (ib->type == GL_UNSIGNED_SHORT) { + if (ib->type == GL_UNSIGNED_INT) { + const GLuint *in = (GLuint *)ptr; + for (i = 0; i < ib->count; i++) + *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex; + } + else if (ib->type == GL_UNSIGNED_SHORT) { const GLushort *in = (GLushort *)ptr; for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++); + *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex; } else { const GLubyte *in = (GLubyte *)ptr; for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++); + *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex; } } } @@ -331,6 +365,20 @@ static void unmap_vbos( GLcontext *ctx, } +void _tnl_vbo_draw_prims(GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index) +{ + if (!index_bounds_valid) + vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); + + _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); +} /* This is the main entrypoint into the slimmed-down software tnl * module. In a regular swtnl driver, this can be plugged straight @@ -347,10 +395,14 @@ void _tnl_draw_prims( GLcontext *ctx, TNLcontext *tnl = TNL_CONTEXT(ctx); const GLuint TEST_SPLIT = 0; const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; + GLuint max_basevertex = prim->basevertex; + GLuint i; + + for (i = 1; i < nr_prims; i++) + max_basevertex = MAX2(max_basevertex, prim[i].basevertex); if (0) { - GLuint i; _mesa_printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); for (i = 0; i < nr_prims; i++) _mesa_printf("prim %d: %s start %d count %d\n", i, @@ -364,10 +416,10 @@ void _tnl_draw_prims( GLcontext *ctx, */ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, min_index, max_index, - _tnl_draw_prims ); + _tnl_vbo_draw_prims ); return; } - else if (max_index > max) { + else if (max_index + max_basevertex > max) { /* The software TNL pipeline has a fixed amount of storage for * vertices and it is necessary to split incoming drawing commands * if they exceed that limit. @@ -381,8 +433,8 @@ void _tnl_draw_prims( GLcontext *ctx, * recursively call back into this function. */ vbo_split_prims( ctx, arrays, prim, nr_prims, ib, - 0, max_index, - _tnl_draw_prims, + 0, max_index + prim->basevertex, + _tnl_vbo_draw_prims, &limits ); } else { @@ -392,17 +444,34 @@ void _tnl_draw_prims( GLcontext *ctx, struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1]; GLuint nr_bo = 0; - /* Binding inputs may imply mapping some vertex buffer objects. - * They will need to be unmapped below. - */ - bind_inputs(ctx, arrays, max_index+1, bo, &nr_bo); - bind_indices(ctx, ib, bo, &nr_bo); - bind_prims(ctx, prim, nr_prims ); + for (i = 0; i < nr_prims;) { + GLuint this_nr_prims; + + /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices + * will rebase the elements to the basevertex, and we'll only + * emit strings of prims with the same basevertex in one draw call. + */ + for (this_nr_prims = 1; i + this_nr_prims < nr_prims; + this_nr_prims++) { + if (prim[i].basevertex != prim[i + this_nr_prims].basevertex) + break; + } + + /* Binding inputs may imply mapping some vertex buffer objects. + * They will need to be unmapped below. + */ + bind_prims(ctx, &prim[i], this_nr_prims); + bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1, + bo, &nr_bo); + bind_indices(ctx, ib, bo, &nr_bo); - TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); + TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); - unmap_vbos(ctx, bo, nr_bo); - free_space(ctx); + unmap_vbos(ctx, bo, nr_bo); + free_space(ctx); + + i += this_nr_prims; + } } } diff --git a/src/mesa/tnl/t_rasterpos.c b/src/mesa/tnl/t_rasterpos.c index dfbe0f1806..a8cf86060f 100644 --- a/src/mesa/tnl/t_rasterpos.c +++ b/src/mesa/tnl/t_rasterpos.c @@ -26,17 +26,19 @@ #include "main/glheader.h" #include "main/colormac.h" #include "main/context.h" -#include "feedback.h" -#include "light.h" +#include "main/feedback.h" +#include "main/light.h" #include "main/macros.h" -#include "rastpos.h" -#include "simple_list.h" +#include "main/rastpos.h" +#include "main/simple_list.h" #include "main/mtypes.h" #include "math/m_matrix.h" #include "tnl/tnl.h" +#if FEATURE_rastpos + /** * Clip a point against the view volume. @@ -46,11 +48,10 @@ * \return zero if outside view volume, or one if inside. */ static GLuint -viewclip_point( const GLfloat v[] ) +viewclip_point_xy( const GLfloat v[] ) { if ( v[0] > v[3] || v[0] < -v[3] - || v[1] > v[3] || v[1] < -v[3] - || v[2] > v[3] || v[2] < -v[3] ) { + || v[1] > v[3] || v[1] < -v[3] ) { return 0; } else { @@ -167,7 +168,7 @@ shade_rastpos(GLcontext *ctx, light->QuadraticAttenuation)); if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); + GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); if (PV_dot_dir<light->_CosCutoff) { continue; @@ -301,12 +302,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4], mInv = 0.0F; if (texUnit->TexGenEnabled & S_BIT) { - switch (texUnit->GenModeS) { + switch (texUnit->GenS.Mode) { case GL_OBJECT_LINEAR: - texcoord[0] = DOT4(vObj, texUnit->ObjectPlaneS); + texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane); break; case GL_EYE_LINEAR: - texcoord[0] = DOT4(vEye, texUnit->EyePlaneS); + texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane); break; case GL_SPHERE_MAP: texcoord[0] = rx * mInv + 0.5F; @@ -324,12 +325,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4], } if (texUnit->TexGenEnabled & T_BIT) { - switch (texUnit->GenModeT) { + switch (texUnit->GenT.Mode) { case GL_OBJECT_LINEAR: - texcoord[1] = DOT4(vObj, texUnit->ObjectPlaneT); + texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane); break; case GL_EYE_LINEAR: - texcoord[1] = DOT4(vEye, texUnit->EyePlaneT); + texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane); break; case GL_SPHERE_MAP: texcoord[1] = ry * mInv + 0.5F; @@ -347,12 +348,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4], } if (texUnit->TexGenEnabled & R_BIT) { - switch (texUnit->GenModeR) { + switch (texUnit->GenR.Mode) { case GL_OBJECT_LINEAR: - texcoord[2] = DOT4(vObj, texUnit->ObjectPlaneR); + texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane); break; case GL_EYE_LINEAR: - texcoord[2] = DOT4(vEye, texUnit->EyePlaneR); + texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane); break; case GL_REFLECTION_MAP: texcoord[2] = rz; @@ -367,12 +368,12 @@ compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4], } if (texUnit->TexGenEnabled & Q_BIT) { - switch (texUnit->GenModeQ) { + switch (texUnit->GenQ.Mode) { case GL_OBJECT_LINEAR: - texcoord[3] = DOT4(vObj, texUnit->ObjectPlaneQ); + texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane); break; case GL_EYE_LINEAR: - texcoord[3] = DOT4(vEye, texUnit->EyePlaneQ); + texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane); break; default: _mesa_problem(ctx, "Bad Q texgen in compute_texgen()"); @@ -408,18 +409,18 @@ _tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]) /* apply projection matrix: clip = Proj * eye */ TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye ); - /* clip to view volume */ - if (ctx->Transform.RasterPositionUnclipped) { - /* GL_IBM_rasterpos_clip: only clip against Z */ + /* clip to view volume. */ + if (!ctx->Transform.DepthClamp) { if (viewclip_point_z(clip) == 0) { ctx->Current.RasterPosValid = GL_FALSE; return; } } - else if (viewclip_point(clip) == 0) { - /* Normal OpenGL behaviour */ - ctx->Current.RasterPosValid = GL_FALSE; - return; + if (!ctx->Transform.RasterPositionUnclipped) { + if (viewclip_point_xy(clip) == 0) { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } } /* clip to user clipping planes */ @@ -443,6 +444,12 @@ _tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]) / ctx->DrawBuffer->_DepthMaxF; ctx->Current.RasterPos[3] = clip[3]; + if (ctx->Transform.DepthClamp) { + ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3], + ctx->Viewport.Near, + ctx->Viewport.Far); + } + /* compute raster distance */ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; @@ -503,3 +510,6 @@ _tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]) _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); } } + + +#endif /* FEATURE_rastpos */ diff --git a/src/mesa/tnl/t_vb_cliptmp.h b/src/mesa/tnl/t_vb_cliptmp.h index 788fe329ed..618b8b3130 100644 --- a/src/mesa/tnl/t_vb_cliptmp.h +++ b/src/mesa/tnl/t_vb_cliptmp.h @@ -127,7 +127,7 @@ TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask ) GLuint p; const GLuint v0_orig = v0; - if (mask & 0x3f) { + if (mask & CLIP_FRUSTUM_BITS) { LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); @@ -199,7 +199,24 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask ) ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */ - if (mask & 0x3f) { + if (0) { + /* print pre-clip vertex coords */ + GLuint i, j; + _mesa_printf("pre clip:\n"); + for (i = 0; i < n; i++) { + j = inlist[i]; + _mesa_printf(" %u: %u: %f, %f, %f, %f\n", + i, j, + coord[j][0], coord[j][1], coord[j][2], coord[j][3]); + assert(!IS_INF_OR_NAN(coord[j][0])); + assert(!IS_INF_OR_NAN(coord[j][1])); + assert(!IS_INF_OR_NAN(coord[j][2])); + assert(!IS_INF_OR_NAN(coord[j][3])); + } + } + + + if (mask & CLIP_FRUSTUM_BITS) { POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); @@ -227,6 +244,18 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask ) } } + if (0) { + /* print post-clip vertex coords */ + GLuint i, j; + _mesa_printf("post clip:\n"); + for (i = 0; i < n; i++) { + j = inlist[i]; + _mesa_printf(" %u: %u: %f, %f, %f, %f\n", + i, j, + coord[j][0], coord[j][1], coord[j][2], coord[j][3]); + } + } + tnl->Driver.Render.ClippedPolygon( ctx, inlist, n ); } @@ -250,7 +279,7 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3, ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */ - if (mask & 0x3f) { + if (mask & CLIP_FRUSTUM_BITS) { POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); diff --git a/src/mesa/tnl/t_vb_lighttmp.h b/src/mesa/tnl/t_vb_lighttmp.h index a78f27761f..124ca3c74f 100644 --- a/src/mesa/tnl/t_vb_lighttmp.h +++ b/src/mesa/tnl/t_vb_lighttmp.h @@ -141,7 +141,7 @@ static void TAG(light_rgba_spec)( GLcontext *ctx, /* spotlight attenuation */ if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); + GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); if (PV_dot_dir<light->_CosCutoff) { continue; /* this light makes no contribution */ @@ -325,7 +325,7 @@ static void TAG(light_rgba)( GLcontext *ctx, /* spotlight attenuation */ if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); + GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); if (PV_dot_dir<light->_CosCutoff) { continue; /* this light makes no contribution */ @@ -721,7 +721,7 @@ static void TAG(light_ci)( GLcontext *ctx, /* spotlight attenuation */ if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection); + GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); if (PV_dot_dir < light->_CosCutoff) { continue; /* this light makes no contribution */ } diff --git a/src/mesa/tnl/t_vb_points.c b/src/mesa/tnl/t_vb_points.c index 01d055c1dd..a52505b4b8 100644 --- a/src/mesa/tnl/t_vb_points.c +++ b/src/mesa/tnl/t_vb_points.c @@ -25,7 +25,9 @@ * Brian Paul */ +#include "main/glheader.h" #include "main/mtypes.h" +#include "main/dd.h" #include "main/imports.h" #include "t_context.h" #include "t_pipeline.h" diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index f99401ca6d..c10a27614f 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -1,8 +1,9 @@ /* * Mesa 3-D graphics library - * Version: 7.1 + * Version: 7.6 * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. + * Copyright (C) 2009 VMware, 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"), @@ -46,6 +47,16 @@ #include "tnl/t_pipeline.h" +#ifdef NAN_CHECK +/** Check for NaNs and very large values */ +static INLINE void +check_float(float x) +{ + assert(!IS_INF_OR_NAN(x)); + assert(1.0e-15 <= x && x <= 1.0e15); +} +#endif + /*! * Private storage for the vertex program pipeline stage. @@ -120,13 +131,16 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store) store->ormask = 0; store->andmask = CLIP_FRUSTUM_BITS; + tnl_clip_prepare(ctx); + if (tnl->NeedNdcCoords) { VB->NdcPtr = _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, &store->ndcCoords, store->clipmask, &store->ormask, - &store->andmask ); + &store->andmask, + !ctx->Transform.DepthClamp ); } else { VB->NdcPtr = NULL; @@ -134,7 +148,8 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store) NULL, store->clipmask, &store->ormask, - &store->andmask ); + &store->andmask, + !ctx->Transform.DepthClamp ); } if (store->andmask) { @@ -176,17 +191,12 @@ static void vp_fetch_texel(GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda, GLuint unit, GLfloat color[4]) { - GLchan rgba[4]; SWcontext *swrast = SWRAST_CONTEXT(ctx); /* XXX use a float-valued TextureSample routine here!!! */ swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current, 1, (const GLfloat (*)[4]) texcoord, - &lambda, &rgba); - color[0] = CHAN_TO_FLOAT(rgba[0]); - color[1] = CHAN_TO_FLOAT(rgba[1]); - color[2] = CHAN_TO_FLOAT(rgba[2]); - color[3] = CHAN_TO_FLOAT(rgba[3]); + &lambda, (GLfloat (*)[4]) color); } @@ -212,7 +222,7 @@ init_machine(GLcontext *ctx, struct gl_program_machine *machine) { /* Input registers get initialized from the current vertex attribs */ MEMCPY(machine->VertAttribs, ctx->Current.Attrib, - MAX_VERTEX_PROGRAM_ATTRIBS * 4 * sizeof(GLfloat)); + MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat)); if (ctx->VertexProgram._Current->IsNVProgram) { GLuint i; @@ -356,6 +366,12 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) const GLuint size = VB->AttribPtr[attr]->size; const GLuint stride = VB->AttribPtr[attr]->stride; const GLfloat *data = (GLfloat *) (ptr + stride * i); +#ifdef NAN_CHECK + check_float(data[0]); + check_float(data[1]); + check_float(data[2]); + check_float(data[3]); +#endif COPY_CLEAN_4V(machine.VertAttribs[attr], size, data); } } @@ -366,8 +382,17 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) /* copy the output registers into the VB->attribs arrays */ for (j = 0; j < numOutputs; j++) { const GLuint attr = outputs[j]; +#ifdef NAN_CHECK + check_float(machine.Outputs[attr][0]); + check_float(machine.Outputs[attr][1]); + check_float(machine.Outputs[attr][2]); + check_float(machine.Outputs[attr][3]); +#endif COPY_4V(store->results[attr].data[i], machine.Outputs[attr]); } +#ifdef NAN_CHECK + ASSERT(machine.Outputs[0][3] != 0.0F); +#endif #if 0 printf("HPOS: %f %f %f %f\n", machine.Outputs[0][0], diff --git a/src/mesa/tnl/t_vb_rendertmp.h b/src/mesa/tnl/t_vb_rendertmp.h index 2b5f4e93b2..75f6f55bdc 100644 --- a/src/mesa/tnl/t_vb_rendertmp.h +++ b/src/mesa/tnl/t_vb_rendertmp.h @@ -82,7 +82,10 @@ static void TAG(render_lines)( GLcontext *ctx, INIT(GL_LINES); for (j=start+1; j<count; j+=2 ) { RESET_STIPPLE; - RENDER_LINE( ELT(j-1), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_LINE( ELT(j-1), ELT(j) ); + else + RENDER_LINE( ELT(j), ELT(j-1) ); } POSTFIX; } @@ -103,9 +106,12 @@ static void TAG(render_line_strip)( GLcontext *ctx, RESET_STIPPLE; } - for (j=start+1; j<count; j++ ) - RENDER_LINE( ELT(j-1), ELT(j) ); - + for (j=start+1; j<count; j++ ) { + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_LINE( ELT(j-1), ELT(j) ); + else + RENDER_LINE( ELT(j), ELT(j-1) ); + } POSTFIX; } @@ -125,15 +131,24 @@ static void TAG(render_line_loop)( GLcontext *ctx, if (start+1 < count) { if (TEST_PRIM_BEGIN(flags)) { RESET_STIPPLE; - RENDER_LINE( ELT(start), ELT(start+1) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_LINE( ELT(start), ELT(start+1) ); + else + RENDER_LINE( ELT(start+1), ELT(start) ); } for ( i = start+2 ; i < count ; i++) { - RENDER_LINE( ELT(i-1), ELT(i) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_LINE( ELT(i-1), ELT(i) ); + else + RENDER_LINE( ELT(i), ELT(i-1) ); } if ( TEST_PRIM_END(flags)) { - RENDER_LINE( ELT(count-1), ELT(start) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_LINE( ELT(count-1), ELT(start) ); + else + RENDER_LINE( ELT(start), ELT(count-1) ); } } @@ -156,11 +171,17 @@ static void TAG(render_triangles)( GLcontext *ctx, /* Leave the edgeflags as supplied by the user. */ RESET_STIPPLE; - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); + else + RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) ); } } else { for (j=start+2; j<count; j+=3) { - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); + else + RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) ); } } POSTFIX; @@ -180,26 +201,38 @@ static void TAG(render_tri_strip)( GLcontext *ctx, INIT(GL_TRIANGLE_STRIP); if (NEED_EDGEFLAG_SETUP) { for (j=start+2;j<count;j++,parity^=1) { - GLuint ej2 = ELT(j-2+parity); - GLuint ej1 = ELT(j-1-parity); - GLuint ej = ELT(j); - GLboolean ef2 = EDGEFLAG_GET( ej2 ); - GLboolean ef1 = EDGEFLAG_GET( ej1 ); - GLboolean ef = EDGEFLAG_GET( ej ); + GLuint ej2, ej1, ej; + GLboolean ef2, ef1, ef; + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) { + ej2 = ELT(j-2+parity); + ej1 = ELT(j-1-parity); + ej = ELT(j); + } + else { + ej2 = ELT(j-1+parity); + ej1 = ELT(j-parity); + ej = ELT(j-2); + } + ef2 = EDGEFLAG_GET( ej2 ); + ef1 = EDGEFLAG_GET( ej1 ); + ef = EDGEFLAG_GET( ej ); if (TEST_PRIM_BEGIN(flags)) { RESET_STIPPLE; } EDGEFLAG_SET( ej2, GL_TRUE ); EDGEFLAG_SET( ej1, GL_TRUE ); EDGEFLAG_SET( ej, GL_TRUE ); - RENDER_TRI( ej2, ej1, ej ); + RENDER_TRI( ej2, ej1, ej ); EDGEFLAG_SET( ej2, ef2 ); EDGEFLAG_SET( ej1, ef1 ); EDGEFLAG_SET( ej, ef ); } } else { for (j=start+2; j<count ; j++, parity^=1) { - RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) ); + else + RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) ); } } POSTFIX; @@ -232,14 +265,20 @@ static void TAG(render_tri_fan)( GLcontext *ctx, EDGEFLAG_SET( ejs, GL_TRUE ); EDGEFLAG_SET( ej1, GL_TRUE ); EDGEFLAG_SET( ej, GL_TRUE ); - RENDER_TRI( ejs, ej1, ej); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_TRI( ejs, ej1, ej); + else + RENDER_TRI( ej, ejs, ej1); EDGEFLAG_SET( ejs, efs ); EDGEFLAG_SET( ej1, ef1 ); EDGEFLAG_SET( ej, ef ); } } else { for (j=start+2;j<count;j++) { - RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) + RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); + else + RENDER_TRI( ELT(j), ELT(start), ELT(j-1) ); } } @@ -331,11 +370,19 @@ static void TAG(render_quads)( GLcontext *ctx, /* Use user-specified edgeflags for quads. */ RESET_STIPPLE; - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || + !ctx->Const.QuadsFollowProvokingVertexConvention) + RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); + else + RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) ); } } else { for (j=start+3; j<count; j+=4) { - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || + !ctx->Const.QuadsFollowProvokingVertexConvention) + RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); + else + RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) ); } } POSTFIX; @@ -367,7 +414,11 @@ static void TAG(render_quad_strip)( GLcontext *ctx, EDGEFLAG_SET( ELT(j-2), GL_TRUE ); EDGEFLAG_SET( ELT(j-1), GL_TRUE ); EDGEFLAG_SET( ELT(j), GL_TRUE ); - RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || + !ctx->Const.QuadsFollowProvokingVertexConvention) + RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); + else + RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) ); EDGEFLAG_SET( ELT(j-3), ef3 ); EDGEFLAG_SET( ELT(j-2), ef2 ); EDGEFLAG_SET( ELT(j-1), ef1 ); @@ -375,7 +426,11 @@ static void TAG(render_quad_strip)( GLcontext *ctx, } } else { for (j=start+3;j<count;j+=2) { - RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); + if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || + !ctx->Const.QuadsFollowProvokingVertexConvention) + RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); + else + RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) ); } } POSTFIX; diff --git a/src/mesa/tnl/t_vb_texgen.c b/src/mesa/tnl/t_vb_texgen.c index 14d3876e54..7c1819b223 100644 --- a/src/mesa/tnl/t_vb_texgen.c +++ b/src/mesa/tnl/t_vb_texgen.c @@ -367,16 +367,16 @@ static void texgen( GLcontext *ctx, if (texUnit->TexGenEnabled & S_BIT) { GLuint i; - switch (texUnit->GenModeS) { + switch (texUnit->GenS.Mode) { case GL_OBJECT_LINEAR: _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data, sizeof(out->data[0]), obj, - texUnit->ObjectPlaneS ); + texUnit->GenS.ObjectPlane ); break; case GL_EYE_LINEAR: _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data, sizeof(out->data[0]), eye, - texUnit->EyePlaneS ); + texUnit->GenS.EyePlane ); break; case GL_SPHERE_MAP: for (i = 0; i < count; i++) @@ -400,16 +400,16 @@ static void texgen( GLcontext *ctx, if (texUnit->TexGenEnabled & T_BIT) { GLuint i; - switch (texUnit->GenModeT) { + switch (texUnit->GenT.Mode) { case GL_OBJECT_LINEAR: _mesa_dotprod_tab[obj->size]( &(out->data[0][1]), sizeof(out->data[0]), obj, - texUnit->ObjectPlaneT ); + texUnit->GenT.ObjectPlane ); break; case GL_EYE_LINEAR: _mesa_dotprod_tab[eye->size]( &(out->data[0][1]), sizeof(out->data[0]), eye, - texUnit->EyePlaneT ); + texUnit->GenT.EyePlane ); break; case GL_SPHERE_MAP: for (i = 0; i < count; i++) @@ -433,16 +433,16 @@ static void texgen( GLcontext *ctx, if (texUnit->TexGenEnabled & R_BIT) { GLuint i; - switch (texUnit->GenModeR) { + switch (texUnit->GenR.Mode) { case GL_OBJECT_LINEAR: _mesa_dotprod_tab[obj->size]( &(out->data[0][2]), sizeof(out->data[0]), obj, - texUnit->ObjectPlaneR ); + texUnit->GenR.ObjectPlane ); break; case GL_EYE_LINEAR: _mesa_dotprod_tab[eye->size]( &(out->data[0][2]), sizeof(out->data[0]), eye, - texUnit->EyePlaneR ); + texUnit->GenR.EyePlane ); break; case GL_REFLECTION_MAP_NV: for (i=0;i<count;i++) @@ -461,16 +461,16 @@ static void texgen( GLcontext *ctx, } if (texUnit->TexGenEnabled & Q_BIT) { - switch (texUnit->GenModeQ) { + switch (texUnit->GenQ.Mode) { case GL_OBJECT_LINEAR: _mesa_dotprod_tab[obj->size]( &(out->data[0][3]), sizeof(out->data[0]), obj, - texUnit->ObjectPlaneQ ); + texUnit->GenQ.ObjectPlane ); break; case GL_EYE_LINEAR: _mesa_dotprod_tab[eye->size]( &(out->data[0][3]), sizeof(out->data[0]), eye, - texUnit->EyePlaneQ ); + texUnit->GenQ.EyePlane ); break; default: _mesa_problem(ctx, "Bad Q texgen"); diff --git a/src/mesa/tnl/t_vb_vertex.c b/src/mesa/tnl/t_vb_vertex.c index 30aa7c4086..4734754ea4 100644 --- a/src/mesa/tnl/t_vb_vertex.c +++ b/src/mesa/tnl/t_vb_vertex.c @@ -118,6 +118,22 @@ static void (*(usercliptab[5]))( GLcontext *, }; +void +tnl_clip_prepare(GLcontext *ctx) +{ + /* Neither the x86 nor sparc asm cliptest functions have been updated + * for ARB_depth_clamp, so force the C paths. + */ + if (ctx->Transform.DepthClamp) { + static GLboolean c_funcs_installed = GL_FALSE; + if (!c_funcs_installed) { + init_c_cliptest(); + c_funcs_installed = GL_TRUE; + } + } +} + + static GLboolean run_vertex_stage( GLcontext *ctx, struct tnl_pipeline_stage *stage ) @@ -129,6 +145,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx, if (ctx->VertexProgram._Current) return GL_TRUE; + tnl_clip_prepare(ctx); + if (ctx->_NeedEyeCoords) { /* Separate modelview transformation: * Use combined ModelProject to avoid some depth artifacts @@ -173,7 +191,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx, &store->proj, store->clipmask, &store->ormask, - &store->andmask ); + &store->andmask, + !ctx->Transform.DepthClamp ); } else { VB->NdcPtr = NULL; @@ -181,7 +200,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx, NULL, store->clipmask, &store->ormask, - &store->andmask ); + &store->andmask, + !ctx->Transform.DepthClamp ); } if (store->andmask) diff --git a/src/mesa/tnl/t_vertex.c b/src/mesa/tnl/t_vertex.c index 10b78f820e..fe4209ae57 100644 --- a/src/mesa/tnl/t_vertex.c +++ b/src/mesa/tnl/t_vertex.c @@ -535,27 +535,30 @@ void _tnl_init_vertices( GLcontext *ctx, void _tnl_free_vertices( GLcontext *ctx ) { - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct tnl_clipspace_fastpath *fp, *tmp; + TNLcontext *tnl = TNL_CONTEXT(ctx); + if (tnl) { + struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); + struct tnl_clipspace_fastpath *fp, *tmp; - if (vtx->vertex_buf) { - ALIGN_FREE(vtx->vertex_buf); - vtx->vertex_buf = NULL; - } - - for (fp = vtx->fastpath ; fp ; fp = tmp) { - tmp = fp->next; - FREE(fp->attr); - - /* KW: At the moment, fp->func is constrained to be allocated by - * _mesa_exec_alloc(), as the hardwired fastpaths in - * t_vertex_generic.c are handled specially. It would be nice - * to unify them, but this probably won't change until this - * module gets another overhaul. - */ - _mesa_exec_free((void *) fp->func); - FREE(fp); + if (vtx->vertex_buf) { + ALIGN_FREE(vtx->vertex_buf); + vtx->vertex_buf = NULL; + } + + for (fp = vtx->fastpath ; fp ; fp = tmp) { + tmp = fp->next; + FREE(fp->attr); + + /* KW: At the moment, fp->func is constrained to be allocated by + * _mesa_exec_alloc(), as the hardwired fastpaths in + * t_vertex_generic.c are handled specially. It would be nice + * to unify them, but this probably won't change until this + * module gets another overhaul. + */ + _mesa_exec_free((void *) fp->func); + FREE(fp); + } + + vtx->fastpath = NULL; } - - vtx->fastpath = NULL; } diff --git a/src/mesa/tnl/t_vp_build.c b/src/mesa/tnl/t_vp_build.c index 7be4d95af6..735937bbe2 100644 --- a/src/mesa/tnl/t_vp_build.c +++ b/src/mesa/tnl/t_vp_build.c @@ -32,6 +32,7 @@ #include "main/glheader.h" #include "main/ffvertex_prog.h" +#include "main/dd.h" #include "t_vp_build.h" diff --git a/src/mesa/tnl/t_vp_build.h b/src/mesa/tnl/t_vp_build.h index d1c147ff03..d6ebc66c04 100644 --- a/src/mesa/tnl/t_vp_build.h +++ b/src/mesa/tnl/t_vp_build.h @@ -29,6 +29,13 @@ #include "main/mtypes.h" +#define TNL_FIXED_FUNCTION_STATE_FLAGS (_NEW_PROGRAM | \ + _NEW_LIGHT | \ + _NEW_TEXTURE | \ + _NEW_TEXTURE_MATRIX | \ + _NEW_TRANSFORM | \ + _NEW_FOG | \ + _NEW_POINT) extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ); diff --git a/src/mesa/tnl/tnl.h b/src/mesa/tnl/tnl.h index 9a1717bf89..4736dcff9e 100644 --- a/src/mesa/tnl/tnl.h +++ b/src/mesa/tnl/tnl.h @@ -29,7 +29,7 @@ #define _TNL_H #include "main/mtypes.h" - +#include "tnl_features.h" /* These are the public-access functions exported from tnl. (A few @@ -81,8 +81,17 @@ _tnl_draw_prims( GLcontext *ctx, GLuint min_index, GLuint max_index); +void +_tnl_vbo_draw_prims( GLcontext *ctx, + const struct gl_client_array *arrays[], + const struct _mesa_prim *prim, + GLuint nr_prims, + const struct _mesa_index_buffer *ib, + GLboolean index_bounds_valid, + GLuint min_index, + GLuint max_index); extern void -_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]); +_mesa_load_tracked_matrices(GLcontext *ctx); #endif diff --git a/src/mesa/tnl/tnl_features.h b/src/mesa/tnl/tnl_features.h new file mode 100644 index 0000000000..0c86dd09a4 --- /dev/null +++ b/src/mesa/tnl/tnl_features.h @@ -0,0 +1,13 @@ +#ifndef _TNL_FEATURES_H +#define _TNL_FEATURES_H + +#include "main/mtypes.h" + +#if FEATURE_rastpos + +extern void +_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]); + +#endif + +#endif /* _TNL_FEATURES_H */ |