diff options
Diffstat (limited to 'mesalib/src/mesa/tnl')
-rw-r--r-- | mesalib/src/mesa/tnl/NOTES | 102 | ||||
-rw-r--r-- | mesalib/src/mesa/tnl/t_context.c | 2 | ||||
-rw-r--r-- | mesalib/src/mesa/tnl/t_context.h | 4 | ||||
-rw-r--r-- | mesalib/src/mesa/tnl/t_draw.c | 58 | ||||
-rw-r--r-- | mesalib/src/mesa/tnl/t_rasterpos.c | 25 | ||||
-rw-r--r-- | mesalib/src/mesa/tnl/t_vb_program.c | 16 | ||||
-rw-r--r-- | mesalib/src/mesa/tnl/t_vb_vertex.c | 24 |
7 files changed, 94 insertions, 137 deletions
diff --git a/mesalib/src/mesa/tnl/NOTES b/mesalib/src/mesa/tnl/NOTES deleted file mode 100644 index c39b43485..000000000 --- a/mesalib/src/mesa/tnl/NOTES +++ /dev/null @@ -1,102 +0,0 @@ -INTRODUCTION - -A generic, configurable software implementation of GL transformation & -lighting. - -This module provides an implementation of the routines required by the -'vtxfmt' mechanism of core mesa for tnl functionality in all -combinations of compile and execute modes. - -Most current drivers use the tnl module exclusively to provide this -functionality, though there is an experimental alternate -implementation provided by the tnl_dd/t_dd_imm_* files which can -handle a small subset of GL states in execute mode only. - - -STATE - -To create and destroy the module: - - GLboolean _tnl_CreateContext( GLcontext *ctx ); - void _tnl_DestroyContext( GLcontext *ctx ); - -The module is not active by default, and must be installed by calling -_tnl_Wakeup(). This function installs internal tnl functions into all -the vtxfmt dispatch hooks, thus taking over the task of transformation -and lighting entirely: - - void _tnl_wakeup_exec( GLcontext *ctx ); - void _tnl_wakeup_save_exec( GLcontext *ctx ); - - -This module tracks state changes internally and maintains derived -values based on the current state. For this to work, the driver -ensure the following funciton is called whenever the state changes and -the swsetup module is 'awake': - - void _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ); - -There is no explicit call to put the tnl module to sleep. Simply -install other function pointers into all the vtxfmt dispatch slots, -and (optionally) cease calling _tnl_InvalidateState(). - -CUSTOMIZATION - -The module provides customizability through several mechanisms. The -most important is by allowing drivers to specify the pipeline through -which vertex data is passed, including its eventual transfer to -rasterization hardware (or software). - -The default pipeline is specified in t_pipeline.c, and is usually a -starting point for driver pipelines. Some drivers will remove a stage -where hardware provides support for the implemented operation (for -instance fog where per-pixel hardware fog is available, as in the dri -tdfx driver), or add stages to shortcircuit latter operations (for -example taking advantage of hardware support for strips and other -higher-level primitives (for example the radeon driver). - -In addition, the following functions provide further tweaks: - -extern void -_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag ); - - - Direct the default vertex transformation stage to - produce/not produce projected clip coordinates. - -extern void -_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean flag ); - - - Direct the display list component of the tnl module to - replay display lists as 'glVertex' type calls, rather than - passing the display list data directly into the tnl pipeline - mechanism. - - This allows display lists to be replayed by the tnl module - even when the module is not strictly active. - - -extern void -_tnl_need_dlist_norm_lengths( GLcontext *ctx, GLboolean flag ); - - - Direct the display list component to enable/disable caching - 1/length values for display list normals. Doing so is - ususally helpful when lighting is performed in software, but - wasteful otherwise. - - -DRIVER INTERFACE - -The module itself offers a minimal driver interface: - - void (*RunPipeline)( GLcontext *ctx ); - -Normally this is set to _tnl_RunPipeline(), however the driver can use -this hook to wrap checks or other code around this call. - -In addition, the driver interface for the default render pipeline -stage is housed in the tnl context struct (this could be cleaner). - - -RENDER DRIVER INTERFACE - -See t_context.h for the definition and explanation of this.
\ No newline at end of file diff --git a/mesalib/src/mesa/tnl/t_context.c b/mesalib/src/mesa/tnl/t_context.c index f2771cde0..db21b4589 100644 --- a/mesalib/src/mesa/tnl/t_context.c +++ b/mesalib/src/mesa/tnl/t_context.c @@ -171,7 +171,7 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) if (vp) { GLuint i; for (i = 0; i < MAX_VARYING; i++) { - if (vp->Base.OutputsWritten & (1 << (VERT_RESULT_VAR0 + i))) { + if (vp->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) { RENDERINPUTS_SET(tnl->render_inputs_bitset, _TNL_ATTRIB_GENERIC(i)); } diff --git a/mesalib/src/mesa/tnl/t_context.h b/mesalib/src/mesa/tnl/t_context.h index c19eb3df3..6137c2d2f 100644 --- a/mesalib/src/mesa/tnl/t_context.h +++ b/mesalib/src/mesa/tnl/t_context.h @@ -548,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/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index c64c2c207..04fa10630 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -316,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; } } } @@ -390,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, @@ -410,7 +419,7 @@ void _tnl_draw_prims( GLcontext *ctx, _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. @@ -424,7 +433,7 @@ void _tnl_draw_prims( GLcontext *ctx, * recursively call back into this function. */ vbo_split_prims( ctx, arrays, prim, nr_prims, ib, - 0, max_index, + 0, max_index + prim->basevertex, _tnl_vbo_draw_prims, &limits ); } @@ -435,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/mesalib/src/mesa/tnl/t_rasterpos.c b/mesalib/src/mesa/tnl/t_rasterpos.c index f1fdddf0f..99b678745 100644 --- a/mesalib/src/mesa/tnl/t_rasterpos.c +++ b/mesalib/src/mesa/tnl/t_rasterpos.c @@ -46,11 +46,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 { @@ -408,18 +407,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 +442,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]; diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c index dc954bcba..e69f7d576 100644 --- a/mesalib/src/mesa/tnl/t_vb_program.c +++ b/mesalib/src/mesa/tnl/t_vb_program.c @@ -131,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; @@ -145,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) { @@ -325,7 +329,7 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) /* make list of outputs to save some time below */ numOutputs = 0; for (i = 0; i < VERT_RESULT_MAX; i++) { - if (program->Base.OutputsWritten & (1 << i)) { + if (program->Base.OutputsWritten & BITFIELD64_BIT(i)) { outputs[numOutputs++] = i; } } @@ -403,14 +407,14 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) /* Fixup fog and point size results if needed */ if (program->IsNVProgram) { if (ctx->Fog.Enabled && - (program->Base.OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) { + (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) == 0) { for (i = 0; i < VB->Count; i++) { store->results[VERT_RESULT_FOGC].data[i][0] = 1.0; } } if (ctx->VertexProgram.PointSizeEnabled && - (program->Base.OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) { + (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) == 0) { for (i = 0; i < VB->Count; i++) { store->results[VERT_RESULT_PSIZ].data[i][0] = ctx->Point.Size; } @@ -468,7 +472,7 @@ run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) } for (i = 0; i < ctx->Const.MaxVarying; i++) { - if (program->Base.OutputsWritten & (1 << (VERT_RESULT_VAR0 + i))) { + if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) { /* Note: varying results get put into the generic attributes */ VB->AttribPtr[VERT_ATTRIB_GENERIC0+i] = &store->results[VERT_RESULT_VAR0 + i]; diff --git a/mesalib/src/mesa/tnl/t_vb_vertex.c b/mesalib/src/mesa/tnl/t_vb_vertex.c index 30aa7c408..4734754ea 100644 --- a/mesalib/src/mesa/tnl/t_vb_vertex.c +++ b/mesalib/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) |