summaryrefslogtreecommitdiff
path: root/src/mesa/tnl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r--src/mesa/tnl/t_context.c33
-rw-r--r--src/mesa/tnl/t_context.h5
-rw-r--r--src/mesa/tnl/t_draw.c107
-rw-r--r--src/mesa/tnl/t_rasterpos.c64
-rw-r--r--src/mesa/tnl/t_vb_cliptmp.h35
-rw-r--r--src/mesa/tnl/t_vb_lighttmp.h6
-rw-r--r--src/mesa/tnl/t_vb_points.c2
-rw-r--r--src/mesa/tnl/t_vb_program.c47
-rw-r--r--src/mesa/tnl/t_vb_rendertmp.h101
-rw-r--r--src/mesa/tnl/t_vb_texgen.c24
-rw-r--r--src/mesa/tnl/t_vb_vertex.c24
-rw-r--r--src/mesa/tnl/t_vertex.c45
-rw-r--r--src/mesa/tnl/t_vp_build.c1
-rw-r--r--src/mesa/tnl/t_vp_build.h7
-rw-r--r--src/mesa/tnl/tnl.h13
-rw-r--r--src/mesa/tnl/tnl_features.h13
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 */