t_vertex.c revision 01e04c3f
1a966c04fSmrg/*
2a966c04fSmrg * Copyright 2003 VMware, Inc.
3a966c04fSmrg * All Rights Reserved.
4a966c04fSmrg *
5a966c04fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
6a966c04fSmrg * copy of this software and associated documentation files (the "Software"),
7a966c04fSmrg * to deal in the Software without restriction, including without limitation
8a966c04fSmrg * on the rights to use, copy, modify, merge, publish, distribute, sub
9a966c04fSmrg * license, and/or sell copies of the Software, and to permit persons to whom
10a966c04fSmrg * the Software is furnished to do so, subject to the following conditions:
11a966c04fSmrg *
12a966c04fSmrg * The above copyright notice and this permission notice (including the next
13a966c04fSmrg * paragraph) shall be included in all copies or substantial portions of the
14a966c04fSmrg * Software.
15a966c04fSmrg *
16a966c04fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17a966c04fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18a966c04fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19a966c04fSmrg * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20a966c04fSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21a966c04fSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22a966c04fSmrg * USE OR OTHER DEALINGS IN THE SOFTWARE.
23a966c04fSmrg *
24a966c04fSmrg * Authors:
25a966c04fSmrg *    Keith Whitwell <keithw@vmware.com>
26a966c04fSmrg */
27a966c04fSmrg
28a966c04fSmrg#include <stdio.h>
29a966c04fSmrg#include "main/glheader.h"
3019569120Smrg#include "main/context.h"
31a966c04fSmrg#include "main/execmem.h"
32a966c04fSmrg#include "swrast/s_chan.h"
33a966c04fSmrg#include "t_context.h"
34a966c04fSmrg#include "t_vertex.h"
35a966c04fSmrg
36a966c04fSmrg#define DBG 0
37a966c04fSmrg
38a966c04fSmrg/* Build and manage clipspace/ndc/window vertices.
39a966c04fSmrg */
40a966c04fSmrg
41a966c04fSmrgstatic GLboolean match_fastpath( struct tnl_clipspace *vtx,
42a966c04fSmrg				 const struct tnl_clipspace_fastpath *fp)
43a966c04fSmrg{
44a966c04fSmrg   GLuint j;
45a966c04fSmrg
46a966c04fSmrg   if (vtx->attr_count != fp->attr_count)
47a966c04fSmrg      return GL_FALSE;
48a966c04fSmrg
49a966c04fSmrg   for (j = 0; j < vtx->attr_count; j++)
50edce3322Smrg      if (vtx->attr[j].format != fp->attr[j].format ||
51edce3322Smrg	  vtx->attr[j].inputsize != fp->attr[j].size ||
52edce3322Smrg	  vtx->attr[j].vertoffset != fp->attr[j].offset)
53edce3322Smrg	 return GL_FALSE;
54edce3322Smrg
55edce3322Smrg   if (fp->match_strides) {
56edce3322Smrg      if (vtx->vertex_size != fp->vertex_size)
57a966c04fSmrg	 return GL_FALSE;
58edce3322Smrg
59a966c04fSmrg      for (j = 0; j < vtx->attr_count; j++)
60edce3322Smrg	 if (vtx->attr[j].inputstride != fp->attr[j].stride)
61edce3322Smrg	    return GL_FALSE;
62edce3322Smrg   }
63edce3322Smrg
64edce3322Smrg   return GL_TRUE;
65edce3322Smrg}
66a966c04fSmrg
67edce3322Smrgstatic GLboolean search_fastpath_emit( struct tnl_clipspace *vtx )
68edce3322Smrg{
69edce3322Smrg   struct tnl_clipspace_fastpath *fp = vtx->fastpath;
70edce3322Smrg
71edce3322Smrg   for ( ; fp ; fp = fp->next) {
72edce3322Smrg      if (match_fastpath(vtx, fp)) {
73edce3322Smrg         vtx->emit = fp->func;
74edce3322Smrg	 return GL_TRUE;
75edce3322Smrg      }
76edce3322Smrg   }
77edce3322Smrg
78edce3322Smrg   return GL_FALSE;
79edce3322Smrg}
80edce3322Smrg
81edce3322Smrgvoid _tnl_register_fastpath( struct tnl_clipspace *vtx,
82edce3322Smrg			     GLboolean match_strides )
83edce3322Smrg{
84edce3322Smrg   struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath);
85edce3322Smrg   GLuint i;
86edce3322Smrg
87a966c04fSmrg   if (fastpath == NULL) {
88a966c04fSmrg      _mesa_error_no_memory(__func__);
89a966c04fSmrg      return;
90a966c04fSmrg   }
91a966c04fSmrg
92a966c04fSmrg   fastpath->vertex_size = vtx->vertex_size;
9397cf2ee2Smrg   fastpath->attr_count = vtx->attr_count;
94a966c04fSmrg   fastpath->match_strides = match_strides;
95a966c04fSmrg   fastpath->func = vtx->emit;
96a966c04fSmrg   fastpath->attr = malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
97a966c04fSmrg
98a966c04fSmrg   if (fastpath->attr == NULL) {
99a966c04fSmrg      free(fastpath);
100a966c04fSmrg      _mesa_error_no_memory(__func__);
101a966c04fSmrg      return;
1022e2dd055Smrg   }
1032e2dd055Smrg
1042e2dd055Smrg   for (i = 0; i < vtx->attr_count; i++) {
1052e2dd055Smrg      fastpath->attr[i].format = vtx->attr[i].format;
1062e2dd055Smrg      fastpath->attr[i].stride = vtx->attr[i].inputstride;
1072e2dd055Smrg      fastpath->attr[i].size = vtx->attr[i].inputsize;
1082e2dd055Smrg      fastpath->attr[i].offset = vtx->attr[i].vertoffset;
1092e2dd055Smrg   }
1102e2dd055Smrg
1112e2dd055Smrg   fastpath->next = vtx->fastpath;
112a966c04fSmrg   vtx->fastpath = fastpath;
113a966c04fSmrg}
114a966c04fSmrg
115a966c04fSmrg
116a966c04fSmrg
117a966c04fSmrg/***********************************************************************
118a966c04fSmrg * Build codegen functions or return generic ones:
119a966c04fSmrg */
120a966c04fSmrgstatic void choose_emit_func( struct gl_context *ctx, GLuint count, GLubyte *dest)
121a966c04fSmrg{
122a966c04fSmrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
123a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
124a966c04fSmrg   struct tnl_clipspace_attr *a = vtx->attr;
125a966c04fSmrg   const GLuint attr_count = vtx->attr_count;
126a966c04fSmrg   GLuint j;
127a966c04fSmrg
128a966c04fSmrg   for (j = 0; j < attr_count; j++) {
129a966c04fSmrg      GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
130a966c04fSmrg      a[j].inputstride = vptr->stride;
131a966c04fSmrg      a[j].inputsize = vptr->size;
132a966c04fSmrg      a[j].emit = a[j].insert[vptr->size - 1]; /* not always used */
133a966c04fSmrg   }
134a966c04fSmrg
135a966c04fSmrg   vtx->emit = NULL;
136a966c04fSmrg
137a966c04fSmrg   /* Does this match an existing (hardwired, codegen or known-bad)
138a966c04fSmrg    * fastpath?
139a966c04fSmrg    */
140a966c04fSmrg   if (search_fastpath_emit(vtx)) {
141a966c04fSmrg      /* Use this result.  If it is null, then it is already known
142a966c04fSmrg       * that the current state will fail for codegen and there is no
143a966c04fSmrg       * point trying again.
144a966c04fSmrg       */
145a966c04fSmrg   }
146a966c04fSmrg   else if (vtx->codegen_emit) {
147a966c04fSmrg      vtx->codegen_emit(ctx);
148a966c04fSmrg   }
149a966c04fSmrg
150a966c04fSmrg   if (!vtx->emit) {
151a966c04fSmrg      _tnl_generate_hardwired_emit(ctx);
152a966c04fSmrg   }
153a966c04fSmrg
154a966c04fSmrg   /* Otherwise use the generic version:
155a966c04fSmrg    */
156a966c04fSmrg   if (!vtx->emit)
157a966c04fSmrg      vtx->emit = _tnl_generic_emit;
158a966c04fSmrg
159a966c04fSmrg   vtx->emit( ctx, count, dest );
160a966c04fSmrg}
161a966c04fSmrg
162a966c04fSmrg
163a966c04fSmrg
164a966c04fSmrgstatic void choose_interp_func( struct gl_context *ctx,
165a966c04fSmrg				GLfloat t,
166a966c04fSmrg				GLuint edst, GLuint eout, GLuint ein,
167a966c04fSmrg				GLboolean force_boundary )
168a966c04fSmrg{
169a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
170a966c04fSmrg   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
171a966c04fSmrg                         ctx->Polygon.BackMode != GL_FILL);
172a966c04fSmrg   GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
173a966c04fSmrg
174a966c04fSmrg   if (vtx->need_extras && (twosided || unfilled)) {
175a966c04fSmrg      vtx->interp = _tnl_generic_interp_extras;
176a966c04fSmrg   } else {
177a966c04fSmrg      vtx->interp = _tnl_generic_interp;
178a966c04fSmrg   }
179a966c04fSmrg
180a966c04fSmrg   vtx->interp( ctx, t, edst, eout, ein, force_boundary );
181a966c04fSmrg}
182a966c04fSmrg
183a966c04fSmrg
184a966c04fSmrgstatic void choose_copy_pv_func(  struct gl_context *ctx, GLuint edst, GLuint esrc )
185a966c04fSmrg{
186a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
187a966c04fSmrg   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
188a966c04fSmrg                         ctx->Polygon.BackMode != GL_FILL);
189a966c04fSmrg
190a966c04fSmrg   GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
191a966c04fSmrg
192a966c04fSmrg   if (vtx->need_extras && (twosided || unfilled)) {
193a966c04fSmrg      vtx->copy_pv = _tnl_generic_copy_pv_extras;
194a966c04fSmrg   } else {
195a966c04fSmrg      vtx->copy_pv = _tnl_generic_copy_pv;
196a966c04fSmrg   }
197a966c04fSmrg
198a966c04fSmrg   vtx->copy_pv( ctx, edst, esrc );
199a966c04fSmrg}
200a966c04fSmrg
201a966c04fSmrg
202a966c04fSmrg/***********************************************************************
203a966c04fSmrg * Public entrypoints, mostly dispatch to the above:
204a966c04fSmrg */
205a966c04fSmrg
206a966c04fSmrg
207a966c04fSmrg/* Interpolate between two vertices to produce a third:
208a966c04fSmrg */
209a966c04fSmrgvoid _tnl_interp( struct gl_context *ctx,
210a966c04fSmrg		  GLfloat t,
211a966c04fSmrg		  GLuint edst, GLuint eout, GLuint ein,
212a966c04fSmrg		  GLboolean force_boundary )
213a966c04fSmrg{
214a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
215a966c04fSmrg   vtx->interp( ctx, t, edst, eout, ein, force_boundary );
2162e2dd055Smrg}
2172e2dd055Smrg
2182e2dd055Smrg/* Copy colors from one vertex to another:
2192e2dd055Smrg */
2202e2dd055Smrgvoid _tnl_copy_pv(  struct gl_context *ctx, GLuint edst, GLuint esrc )
2212e2dd055Smrg{
222a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
223a966c04fSmrg   vtx->copy_pv( ctx, edst, esrc );
224a966c04fSmrg}
225a966c04fSmrg
226a966c04fSmrg
227a966c04fSmrg/* Extract a named attribute from a hardware vertex.  Will have to
22897cf2ee2Smrg * reverse any viewport transformation, swizzling or other conversions
22997cf2ee2Smrg * which may have been applied:
230a966c04fSmrg */
231a966c04fSmrgvoid _tnl_get_attr( struct gl_context *ctx, const void *vin,
232a966c04fSmrg			      GLenum attr, GLfloat *dest )
233a966c04fSmrg{
234a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
235a966c04fSmrg   const struct tnl_clipspace_attr *a = vtx->attr;
236a966c04fSmrg   const GLuint attr_count = vtx->attr_count;
237a966c04fSmrg   GLuint j;
238a966c04fSmrg
239a966c04fSmrg   for (j = 0; j < attr_count; j++) {
240a966c04fSmrg      if (a[j].attrib == attr) {
241a966c04fSmrg	 a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
242a966c04fSmrg	 return;
243a966c04fSmrg      }
244a966c04fSmrg   }
245a966c04fSmrg
246a966c04fSmrg   /* Else return the value from ctx->Current.
247a966c04fSmrg    */
248a966c04fSmrg   if (attr == _TNL_ATTRIB_POINTSIZE) {
249edce3322Smrg      /* If the hardware vertex doesn't have point size then use size from
250edce3322Smrg       * struct gl_context.  XXX this will be wrong if drawing attenuated points!
251a966c04fSmrg       */
252a966c04fSmrg      dest[0] = ctx->Point.Size;
253a966c04fSmrg   }
254edce3322Smrg   else {
255edce3322Smrg      memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
256a966c04fSmrg   }
2579f00f3a1Smrg}
2589f00f3a1Smrg
2599f00f3a1Smrg
260edce3322Smrg/* Complementary operation to the above.
261edce3322Smrg */
2629f00f3a1Smrgvoid _tnl_set_attr( struct gl_context *ctx, void *vout,
2639f00f3a1Smrg		    GLenum attr, const GLfloat *src )
2649f00f3a1Smrg{
265a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
266a966c04fSmrg   const struct tnl_clipspace_attr *a = vtx->attr;
267a966c04fSmrg   const GLuint attr_count = vtx->attr_count;
268a966c04fSmrg   GLuint j;
269a966c04fSmrg
270a966c04fSmrg   for (j = 0; j < attr_count; j++) {
271a966c04fSmrg      if (a[j].attrib == attr) {
272a966c04fSmrg	 a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
273a966c04fSmrg	 return;
274edce3322Smrg      }
275a966c04fSmrg   }
276a966c04fSmrg}
277a966c04fSmrg
278a966c04fSmrg
279a966c04fSmrgvoid *_tnl_get_vertex( struct gl_context *ctx, GLuint nr )
280a966c04fSmrg{
281a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
282a966c04fSmrg
283a966c04fSmrg   return vtx->vertex_buf + nr * vtx->vertex_size;
284a966c04fSmrg}
285a966c04fSmrg
286a966c04fSmrgvoid _tnl_invalidate_vertex_state( struct gl_context *ctx, GLuint new_state )
287a966c04fSmrg{
288a966c04fSmrg   /* if two-sided lighting changes or filled/unfilled polygon state changes */
289a966c04fSmrg   if (new_state & (_NEW_LIGHT | _NEW_POLYGON) ) {
290a966c04fSmrg      struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
291a966c04fSmrg      vtx->new_inputs = ~0;
292a966c04fSmrg      vtx->interp = choose_interp_func;
293a966c04fSmrg      vtx->copy_pv = choose_copy_pv_func;
294a966c04fSmrg   }
295a966c04fSmrg}
296a966c04fSmrg
297edce3322Smrgstatic void invalidate_funcs( struct tnl_clipspace *vtx )
298edce3322Smrg{
299a966c04fSmrg   vtx->emit = choose_emit_func;
300a966c04fSmrg   vtx->interp = choose_interp_func;
301a966c04fSmrg   vtx->copy_pv = choose_copy_pv_func;
302a966c04fSmrg   vtx->new_inputs = ~0;
303a966c04fSmrg}
304a966c04fSmrg
305a966c04fSmrgGLuint _tnl_install_attrs( struct gl_context *ctx, const struct tnl_attr_map *map,
306a966c04fSmrg			   GLuint nr, const GLfloat *vp,
307a966c04fSmrg			   GLuint unpacked_size )
308edce3322Smrg{
309edce3322Smrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
310a966c04fSmrg   GLuint offset = 0;
311edce3322Smrg   GLuint i, j;
312edce3322Smrg
313edce3322Smrg   assert(nr < _TNL_ATTRIB_MAX);
314edce3322Smrg   assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
315edce3322Smrg
316edce3322Smrg   vtx->new_inputs = ~0;
317a966c04fSmrg   vtx->need_viewport = GL_FALSE;
318edce3322Smrg
319edce3322Smrg   if (vp) {
320edce3322Smrg      vtx->need_viewport = GL_TRUE;
321edce3322Smrg   }
322a966c04fSmrg
323a966c04fSmrg   for (j = 0, i = 0; i < nr; i++) {
324a966c04fSmrg      const GLuint format = map[i].format;
325a966c04fSmrg      if (format == EMIT_PAD) {
326edce3322Smrg	 if (DBG)
327edce3322Smrg	    printf("%d: pad %d, offset %d\n", i,
328a966c04fSmrg		   map[i].offset, offset);
329a966c04fSmrg
330a966c04fSmrg	 offset += map[i].offset;
331a966c04fSmrg
332edce3322Smrg      }
333edce3322Smrg      else {
334a966c04fSmrg	 GLuint tmpoffset;
335a966c04fSmrg
336a966c04fSmrg	 if (unpacked_size)
337a966c04fSmrg	    tmpoffset = map[i].offset;
338a966c04fSmrg	 else
339a966c04fSmrg	    tmpoffset = offset;
340a966c04fSmrg
341a966c04fSmrg	 if (vtx->attr_count != j ||
342a966c04fSmrg	     vtx->attr[j].attrib != map[i].attrib ||
343a966c04fSmrg	     vtx->attr[j].format != format ||
344a966c04fSmrg	     vtx->attr[j].vertoffset != tmpoffset) {
345a966c04fSmrg	    invalidate_funcs(vtx);
346a966c04fSmrg
347a966c04fSmrg	    vtx->attr[j].attrib = map[i].attrib;
348a966c04fSmrg	    vtx->attr[j].format = format;
349edce3322Smrg	    vtx->attr[j].vp = vp;
350edce3322Smrg	    vtx->attr[j].insert = _tnl_format_info[format].insert;
351a966c04fSmrg	    vtx->attr[j].extract = _tnl_format_info[format].extract;
352a966c04fSmrg	    vtx->attr[j].vertattrsize = _tnl_format_info[format].attrsize;
353a966c04fSmrg	    vtx->attr[j].vertoffset = tmpoffset;
354edce3322Smrg	 }
355edce3322Smrg
356a966c04fSmrg
3579f00f3a1Smrg	 if (DBG)
3589f00f3a1Smrg	    printf("%d: %s, vp %p, offset %d\n", i,
3599f00f3a1Smrg		   _tnl_format_info[format].name, (void *)vp,
360edce3322Smrg		   vtx->attr[j].vertoffset);
361edce3322Smrg
3629f00f3a1Smrg	 offset += _tnl_format_info[format].attrsize;
3639f00f3a1Smrg	 j++;
3649f00f3a1Smrg      }
365a966c04fSmrg   }
366a966c04fSmrg
367a966c04fSmrg   vtx->attr_count = j;
368a966c04fSmrg
369a966c04fSmrg   if (unpacked_size)
370a966c04fSmrg      vtx->vertex_size = unpacked_size;
371a966c04fSmrg   else
372a966c04fSmrg      vtx->vertex_size = offset;
373a966c04fSmrg
374edce3322Smrg   assert(vtx->vertex_size <= vtx->max_vertex_size);
375a966c04fSmrg   return vtx->vertex_size;
376a966c04fSmrg}
377a966c04fSmrg
378a966c04fSmrg
379a966c04fSmrg
380a966c04fSmrgvoid _tnl_invalidate_vertices( struct gl_context *ctx, GLuint newinputs )
381a966c04fSmrg{
382a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
383a966c04fSmrg   vtx->new_inputs |= newinputs;
384edce3322Smrg}
385edce3322Smrg
386edce3322Smrg
387edce3322Smrg/* This event has broader use beyond this file - will move elsewhere
388edce3322Smrg * and probably invoke a driver callback.
389edce3322Smrg */
390a966c04fSmrgvoid _tnl_notify_pipeline_output_change( struct gl_context *ctx )
391edce3322Smrg{
392edce3322Smrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
393edce3322Smrg   invalidate_funcs(vtx);
394edce3322Smrg}
395a966c04fSmrg
396a966c04fSmrg
397a966c04fSmrgstatic void adjust_input_ptrs( struct gl_context *ctx, GLint diff)
398a966c04fSmrg{
399edce3322Smrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
400edce3322Smrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
401a966c04fSmrg   struct tnl_clipspace_attr *a = vtx->attr;
402a966c04fSmrg   const GLuint count = vtx->attr_count;
403a966c04fSmrg   GLuint j;
404a966c04fSmrg
405a966c04fSmrg   diff -= 1;
406a966c04fSmrg   for (j=0; j<count; ++j) {
407a966c04fSmrg           register GLvector4f *vptr = VB->AttribPtr[a->attrib];
408a966c04fSmrg	   (a++)->inputptr += diff*vptr->stride;
409a966c04fSmrg   }
410a966c04fSmrg}
411edce3322Smrg
412edce3322Smrgstatic void update_input_ptrs( struct gl_context *ctx, GLuint start )
413edce3322Smrg{
414edce3322Smrg   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
415a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
416a966c04fSmrg   struct tnl_clipspace_attr *a = vtx->attr;
417a966c04fSmrg   const GLuint count = vtx->attr_count;
4182e2dd055Smrg   GLuint j;
4192e2dd055Smrg
4202e2dd055Smrg   for (j = 0; j < count; j++) {
4212e2dd055Smrg      GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
4222e2dd055Smrg
4232e2dd055Smrg      if (vtx->emit != choose_emit_func) {
4242e2dd055Smrg	 assert(a[j].inputstride == vptr->stride);
4252e2dd055Smrg	 assert(a[j].inputsize == vptr->size);
4262e2dd055Smrg      }
427a966c04fSmrg
428a966c04fSmrg      a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
429a966c04fSmrg   }
430a966c04fSmrg
431a966c04fSmrg   if (a->vp) {
43297cf2ee2Smrg      vtx->vp_scale[0] = a->vp[MAT_SX];
433a966c04fSmrg      vtx->vp_scale[1] = a->vp[MAT_SY];
434a966c04fSmrg      vtx->vp_scale[2] = a->vp[MAT_SZ];
435a966c04fSmrg      vtx->vp_scale[3] = 1.0;
436a966c04fSmrg      vtx->vp_xlate[0] = a->vp[MAT_TX];
437a966c04fSmrg      vtx->vp_xlate[1] = a->vp[MAT_TY];
438a966c04fSmrg      vtx->vp_xlate[2] = a->vp[MAT_TZ];
439a966c04fSmrg      vtx->vp_xlate[3] = 0.0;
440a966c04fSmrg   }
441a966c04fSmrg}
442a966c04fSmrg
443a966c04fSmrg
444a966c04fSmrgvoid _tnl_build_vertices( struct gl_context *ctx,
445a966c04fSmrg			  GLuint start,
446a966c04fSmrg			  GLuint end,
447a966c04fSmrg			  GLuint newinputs )
448a966c04fSmrg{
449a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
450a966c04fSmrg   update_input_ptrs( ctx, start );
451a966c04fSmrg   vtx->emit( ctx, end - start,
452a966c04fSmrg	      (GLubyte *)(vtx->vertex_buf +
453a966c04fSmrg			  start * vtx->vertex_size));
454a966c04fSmrg}
455a966c04fSmrg
456a966c04fSmrg/* Emit VB vertices start..end to dest.  Note that VB vertex at
457a966c04fSmrg * postion start will be emitted to dest at position zero.
458a966c04fSmrg */
459a966c04fSmrgvoid *_tnl_emit_vertices_to_buffer( struct gl_context *ctx,
460a966c04fSmrg				    GLuint start,
461a966c04fSmrg				    GLuint end,
462a966c04fSmrg				    void *dest )
463a966c04fSmrg{
464a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
465a966c04fSmrg
466a966c04fSmrg   update_input_ptrs(ctx, start);
467a966c04fSmrg   /* Note: dest should not be adjusted for non-zero 'start' values:
468a966c04fSmrg    */
469a966c04fSmrg   vtx->emit( ctx, end - start, (GLubyte*) dest );
470a966c04fSmrg   return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
471a966c04fSmrg}
472a966c04fSmrg
473a966c04fSmrg/* Emit indexed VB vertices start..end to dest.  Note that VB vertex at
474a966c04fSmrg * postion start will be emitted to dest at position zero.
475a966c04fSmrg */
476a966c04fSmrg
477a966c04fSmrgvoid *_tnl_emit_indexed_vertices_to_buffer( struct gl_context *ctx,
478a966c04fSmrg					    const GLuint *elts,
479a966c04fSmrg					    GLuint start,
480a966c04fSmrg					    GLuint end,
481a966c04fSmrg					    void *dest )
482a966c04fSmrg{
483a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
484a966c04fSmrg   GLuint oldIndex;
485a966c04fSmrg   GLubyte *cdest = dest;
486a966c04fSmrg
487a966c04fSmrg   update_input_ptrs(ctx, oldIndex = elts[start++]);
488a966c04fSmrg   vtx->emit( ctx, 1, cdest );
489a966c04fSmrg   cdest += vtx->vertex_size;
490a966c04fSmrg
491a966c04fSmrg   for (; start < end; ++start) {
492a966c04fSmrg      adjust_input_ptrs(ctx, elts[start] - oldIndex);
493a966c04fSmrg      oldIndex = elts[start];
494a966c04fSmrg      vtx->emit( ctx, 1, cdest);
495a966c04fSmrg      cdest += vtx->vertex_size;
496a966c04fSmrg   }
497a966c04fSmrg
498a966c04fSmrg   return (void *) cdest;
499a966c04fSmrg}
500a966c04fSmrg
501a966c04fSmrg
502a966c04fSmrgvoid _tnl_init_vertices( struct gl_context *ctx,
503a966c04fSmrg			GLuint vb_size,
504a966c04fSmrg			GLuint max_vertex_size )
505a966c04fSmrg{
506a966c04fSmrg   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
507a966c04fSmrg
508a966c04fSmrg   _tnl_install_attrs( ctx, NULL, 0, NULL, 0 );
509a966c04fSmrg
510a966c04fSmrg   vtx->need_extras = GL_TRUE;
511a966c04fSmrg   if (max_vertex_size > vtx->max_vertex_size) {
512a966c04fSmrg      _tnl_free_vertices( ctx );
513a966c04fSmrg      vtx->max_vertex_size = max_vertex_size;
514a966c04fSmrg      vtx->vertex_buf = _mesa_align_calloc(vb_size * max_vertex_size, 32 );
515a966c04fSmrg      invalidate_funcs(vtx);
516a966c04fSmrg   }
517a966c04fSmrg
518a966c04fSmrg   switch(CHAN_TYPE) {
519a966c04fSmrg   case GL_UNSIGNED_BYTE:
520a966c04fSmrg      vtx->chan_scale[0] = 255.0;
521a966c04fSmrg      vtx->chan_scale[1] = 255.0;
522a966c04fSmrg      vtx->chan_scale[2] = 255.0;
523a966c04fSmrg      vtx->chan_scale[3] = 255.0;
524a966c04fSmrg      break;
525a966c04fSmrg   case GL_UNSIGNED_SHORT:
526a966c04fSmrg      vtx->chan_scale[0] = 65535.0;
527a966c04fSmrg      vtx->chan_scale[1] = 65535.0;
528a966c04fSmrg      vtx->chan_scale[2] = 65535.0;
529a966c04fSmrg      vtx->chan_scale[3] = 65535.0;
530a966c04fSmrg      break;
531a966c04fSmrg   default:
532a966c04fSmrg      vtx->chan_scale[0] = 1.0;
533a966c04fSmrg      vtx->chan_scale[1] = 1.0;
534a966c04fSmrg      vtx->chan_scale[2] = 1.0;
535a966c04fSmrg      vtx->chan_scale[3] = 1.0;
536a966c04fSmrg      break;
537a966c04fSmrg   }
538a966c04fSmrg
539a966c04fSmrg   vtx->identity[0] = 0.0;
540a966c04fSmrg   vtx->identity[1] = 0.0;
541a966c04fSmrg   vtx->identity[2] = 0.0;
542a966c04fSmrg   vtx->identity[3] = 1.0;
543a966c04fSmrg
544a966c04fSmrg   vtx->codegen_emit = NULL;
545a966c04fSmrg
546a966c04fSmrg#ifdef USE_SSE_ASM
547a966c04fSmrg   if (!getenv("MESA_NO_CODEGEN"))
548a966c04fSmrg      vtx->codegen_emit = _tnl_generate_sse_emit;
549a966c04fSmrg#endif
550a966c04fSmrg}
551a966c04fSmrg
552a966c04fSmrg
553a966c04fSmrgvoid _tnl_free_vertices( struct gl_context *ctx )
554a966c04fSmrg{
555a966c04fSmrg   TNLcontext *tnl = TNL_CONTEXT(ctx);
5569f00f3a1Smrg   if (tnl) {
5579f00f3a1Smrg      struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
5589f00f3a1Smrg      struct tnl_clipspace_fastpath *fp, *tmp;
5599f00f3a1Smrg
5609f00f3a1Smrg      _mesa_align_free(vtx->vertex_buf);
5619f00f3a1Smrg      vtx->vertex_buf = NULL;
5629f00f3a1Smrg
5639f00f3a1Smrg      for (fp = vtx->fastpath ; fp ; fp = tmp) {
564a966c04fSmrg         tmp = fp->next;
565a966c04fSmrg         free(fp->attr);
566a966c04fSmrg
567a966c04fSmrg         /* KW: At the moment, fp->func is constrained to be allocated by
568a966c04fSmrg          * _mesa_exec_alloc(), as the hardwired fastpaths in
569a966c04fSmrg          * t_vertex_generic.c are handled specially.  It would be nice
570a966c04fSmrg          * to unify them, but this probably won't change until this
571a966c04fSmrg          * module gets another overhaul.
572a966c04fSmrg          */
573a966c04fSmrg         _mesa_exec_free((void *) fp->func);
574a966c04fSmrg         free(fp);
575a966c04fSmrg      }
5769f00f3a1Smrg
5779f00f3a1Smrg      vtx->fastpath = NULL;
5789f00f3a1Smrg   }
5799f00f3a1Smrg}
5809f00f3a1Smrg