2 * Copyright 2003 Tungsten Graphics, inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keithw@tungstengraphics.com>
32 #include "t_context.h"
36 /* Build and manage clipspace/ndc/window vertices.
38 * Another new mechanism designed and crying out for codegen. Before
39 * that, it would be very interesting to investigate the merger of
40 * these vertices and those built in t_vtx_*.
45 #define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace)
47 static void insert_4f_viewport( const struct tnl_clipspace_attr
*a
, char *v
,
50 GLfloat
*out
= (GLfloat
*)v
;
51 const GLfloat
* const vp
= a
->vp
;
53 out
[0] = vp
[0] * in
[0] + vp
[12];
54 out
[1] = vp
[5] * in
[1] + vp
[13];
55 out
[2] = vp
[10] * in
[2] + vp
[14];
59 static void insert_3f_viewport( const struct tnl_clipspace_attr
*a
, char *v
,
62 GLfloat
*out
= (GLfloat
*)v
;
63 const GLfloat
* const vp
= a
->vp
;
65 out
[0] = vp
[0] * in
[0] + vp
[12];
66 out
[1] = vp
[5] * in
[1] + vp
[13];
67 out
[2] = vp
[10] * in
[2] + vp
[14];
70 static void insert_2f_viewport( const struct tnl_clipspace_attr
*a
, char *v
,
73 GLfloat
*out
= (GLfloat
*)v
;
74 const GLfloat
* const vp
= a
->vp
;
76 out
[0] = vp
[0] * in
[0] + vp
[12];
77 out
[1] = vp
[5] * in
[1] + vp
[13];
81 static void insert_4f( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
83 GLfloat
*out
= (GLfloat
*)(v
);
91 static void insert_3f_xyw( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
93 GLfloat
*out
= (GLfloat
*)(v
);
101 static void insert_3f( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
103 GLfloat
*out
= (GLfloat
*)(v
);
111 static void insert_2f( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
113 GLfloat
*out
= (GLfloat
*)(v
);
119 static void insert_1f( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
121 GLfloat
*out
= (GLfloat
*)(v
);
126 static void insert_3f_pad( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
128 GLfloat
*out
= (GLfloat
*)(v
);
137 static void insert_2f_pad( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
139 GLfloat
*out
= (GLfloat
*)(v
);
147 static void insert_1f_pad( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
)
149 GLfloat
*out
= (GLfloat
*)(v
);
157 static void insert_4chan_4f_rgba( const struct tnl_clipspace_attr
*a
, char *v
,
160 GLchan
*c
= (GLchan
*)v
;
161 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
162 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
163 UNCLAMPED_FLOAT_TO_CHAN(c
[2], in
[2]);
164 UNCLAMPED_FLOAT_TO_CHAN(c
[3], in
[3]);
167 static void insert_4ub_4f_rgba( const struct tnl_clipspace_attr
*a
, char *v
,
170 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
171 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
172 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
173 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
176 static void insert_4ub_4f_bgra( const struct tnl_clipspace_attr
*a
, char *v
,
179 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
180 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
181 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
182 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
185 static void insert_3ub_3f_rgb( const struct tnl_clipspace_attr
*a
, char *v
,
188 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
189 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
190 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
193 static void insert_3ub_3f_bgr( const struct tnl_clipspace_attr
*a
, char *v
,
196 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
197 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
198 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
201 static void insert_1ub_1f( const struct tnl_clipspace_attr
*a
, char *v
,
204 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
208 /***********************************************************************
209 * Functions to perform the reverse operations to the above, for
210 * swrast translation and clip-interpolation.
212 * Currently always extracts a full 4 floats.
215 static void extract_4f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
218 const GLfloat
*in
= (const GLfloat
*)v
;
219 const GLfloat
* const vp
= a
->vp
;
221 out
[0] = (in
[0] - vp
[12]) / vp
[0];
222 out
[1] = (in
[1] - vp
[13]) / vp
[5];
223 out
[2] = (in
[2] - vp
[14]) / vp
[10];
227 static void extract_3f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
230 const GLfloat
*in
= (const GLfloat
*)v
;
231 const GLfloat
* const vp
= a
->vp
;
233 out
[0] = (in
[0] - vp
[12]) / vp
[0];
234 out
[1] = (in
[1] - vp
[13]) / vp
[5];
235 out
[2] = (in
[2] - vp
[14]) / vp
[10];
240 static void extract_2f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
243 const GLfloat
*in
= (const GLfloat
*)v
;
244 const GLfloat
* const vp
= a
->vp
;
246 out
[0] = (in
[0] - vp
[12]) / vp
[0];
247 out
[1] = (in
[1] - vp
[13]) / vp
[5];
253 static void extract_4f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const char *v
)
255 const GLfloat
*in
= (const GLfloat
*)v
;
263 static void extract_3f_xyw( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const char *v
)
265 const GLfloat
*in
= (const GLfloat
*)v
;
274 static void extract_3f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const char *v
)
276 const GLfloat
*in
= (const GLfloat
*)v
;
285 static void extract_2f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const char *v
)
287 const GLfloat
*in
= (const GLfloat
*)v
;
295 static void extract_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const char *v
)
297 const GLfloat
*in
= (const GLfloat
*)v
;
305 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
308 GLchan
*c
= (GLchan
*)v
;
310 out
[0] = CHAN_TO_FLOAT(c
[0]);
311 out
[1] = CHAN_TO_FLOAT(c
[1]);
312 out
[2] = CHAN_TO_FLOAT(c
[2]);
313 out
[3] = CHAN_TO_FLOAT(c
[3]);
316 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
319 out
[0] = UBYTE_TO_FLOAT(v
[0]);
320 out
[1] = UBYTE_TO_FLOAT(v
[1]);
321 out
[2] = UBYTE_TO_FLOAT(v
[2]);
322 out
[3] = UBYTE_TO_FLOAT(v
[3]);
325 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
328 out
[2] = UBYTE_TO_FLOAT(v
[0]);
329 out
[1] = UBYTE_TO_FLOAT(v
[1]);
330 out
[0] = UBYTE_TO_FLOAT(v
[2]);
331 out
[3] = UBYTE_TO_FLOAT(v
[3]);
334 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
337 out
[0] = UBYTE_TO_FLOAT(v
[0]);
338 out
[1] = UBYTE_TO_FLOAT(v
[1]);
339 out
[2] = UBYTE_TO_FLOAT(v
[2]);
343 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
346 out
[2] = UBYTE_TO_FLOAT(v
[0]);
347 out
[1] = UBYTE_TO_FLOAT(v
[1]);
348 out
[0] = UBYTE_TO_FLOAT(v
[2]);
352 static void extract_1ub_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const char *v
)
354 out
[0] = UBYTE_TO_FLOAT(v
[0]);
361 typedef void (*extract_func
)( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
364 typedef void (*insert_func
)( const struct tnl_clipspace_attr
*a
, char *v
, const GLfloat
*in
);
368 extract_func extract
;
371 } format_info
[EMIT_MAX
] = {
379 2 * sizeof(GLfloat
) },
383 3 * sizeof(GLfloat
) },
387 4 * sizeof(GLfloat
) },
389 { extract_2f_viewport
,
391 2 * sizeof(GLfloat
) },
393 { extract_3f_viewport
,
395 3 * sizeof(GLfloat
) },
397 { extract_4f_viewport
,
399 4 * sizeof(GLfloat
) },
403 3 * sizeof(GLfloat
) },
409 { extract_3ub_3f_rgb
,
411 3 * sizeof(GLubyte
) },
413 { extract_3ub_3f_bgr
,
415 3 * sizeof(GLubyte
) },
417 { extract_4ub_4f_rgba
,
419 4 * sizeof(GLubyte
) },
421 { extract_4ub_4f_bgra
,
423 4 * sizeof(GLubyte
) },
425 { extract_4chan_4f_rgba
,
426 insert_4chan_4f_rgba
,
427 4 * sizeof(GLchan
) },
431 4 * sizeof(GLfloat
) },
435 4 * sizeof(GLfloat
) },
439 4 * sizeof(GLfloat
) },
445 /***********************************************************************
446 * Generic (non-codegen) functions for whole vertices or groups of
450 static void generic_emit( GLcontext
*ctx
,
451 GLuint start
, GLuint end
,
454 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
455 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
456 struct tnl_clipspace_attr
*a
= vtx
->attr
;
457 char *v
= (char *)dest
;
459 GLuint count
= vtx
->attr_count
;
462 for (j
= 0; j
< count
; j
++) {
463 GLvector4f
*vptr
= VB
->AttribPtr
[a
[j
].attrib
];
464 a
[j
].inputstride
= vptr
->stride
;
465 a
[j
].inputptr
= (GLfloat
*)STRIDE_4F(vptr
->data
, start
* vptr
->stride
);
469 stride
= vtx
->vertex_size
;
471 for (i
= 0 ; i
< end
; i
++, v
+= stride
) {
472 for (j
= 0; j
< count
; j
++) {
473 GLfloat
*in
= a
[j
].inputptr
;
474 (char *)a
[j
].inputptr
+= a
[j
].inputstride
;
475 a
[j
].insert( &a
[j
], v
+ a
[j
].vertoffset
, in
);
481 static void generic_interp( GLcontext
*ctx
,
483 GLuint edst
, GLuint eout
, GLuint ein
,
484 GLboolean force_boundary
)
486 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
487 struct vertex_buffer
*VB
= &tnl
->vb
;
488 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
489 char *vin
= vtx
->vertex_buf
+ ein
* vtx
->vertex_size
;
490 char *vout
= vtx
->vertex_buf
+ eout
* vtx
->vertex_size
;
491 char *vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_size
;
492 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
493 int attr_count
= vtx
->attr_count
;
496 if (tnl
->NeedNdcCoords
) {
497 const GLfloat
*dstclip
= VB
->ClipPtr
->data
[edst
];
498 const GLfloat w
= 1.0 / dstclip
[3];
501 pos
[0] = dstclip
[0] * w
;
502 pos
[1] = dstclip
[1] * w
;
503 pos
[2] = dstclip
[2] * w
;
506 a
[0].insert( &a
[0], vdst
, pos
);
509 a
[0].insert( &a
[0], vdst
, VB
->ClipPtr
->data
[edst
] );
513 for (j
= 1; j
< attr_count
; j
++) {
514 GLfloat fin
[4], fout
[4], fdst
[4];
516 a
[j
].extract( &a
[j
], fin
, vin
+ a
[j
].vertoffset
);
517 a
[j
].extract( &a
[j
], fout
, vout
+ a
[j
].vertoffset
);
519 INTERP_F( t
, fdst
[3], fout
[3], fin
[3] );
520 INTERP_F( t
, fdst
[2], fout
[2], fin
[2] );
521 INTERP_F( t
, fdst
[1], fout
[1], fin
[1] );
522 INTERP_F( t
, fdst
[0], fout
[0], fin
[0] );
524 a
[j
].insert( &a
[j
], vdst
+ a
[j
].vertoffset
, fdst
);
529 /* Extract color attributes from one vertex and insert them into
530 * another. (Shortcircuit extract/insert with memcpy).
532 static void generic_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
534 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
535 char *vsrc
= vtx
->vertex_buf
+ esrc
* vtx
->vertex_size
;
536 char *vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_size
;
537 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
538 int attr_count
= vtx
->attr_count
;
541 for (j
= 0; j
< attr_count
; j
++) {
542 if (a
[j
].attrib
== VERT_ATTRIB_COLOR0
||
543 a
[j
].attrib
== VERT_ATTRIB_COLOR1
) {
545 memcpy( vdst
+ a
[j
].vertoffset
,
546 vsrc
+ a
[j
].vertoffset
,
553 /* Helper functions for hardware which doesn't put back colors and/or
554 * edgeflags into vertices.
556 static void generic_interp_extras( GLcontext
*ctx
,
558 GLuint dst
, GLuint out
, GLuint in
,
559 GLboolean force_boundary
)
561 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
563 if (VB
->ColorPtr
[1]) {
564 assert(VB
->ColorPtr
[1]->stride
== 4 * sizeof(GLfloat
));
567 VB
->ColorPtr
[1]->data
[dst
],
568 VB
->ColorPtr
[1]->data
[out
],
569 VB
->ColorPtr
[1]->data
[in
] );
571 if (VB
->SecondaryColorPtr
[1]) {
573 VB
->SecondaryColorPtr
[1]->data
[dst
],
574 VB
->SecondaryColorPtr
[1]->data
[out
],
575 VB
->SecondaryColorPtr
[1]->data
[in
] );
580 VB
->EdgeFlag
[dst
] = VB
->EdgeFlag
[out
] || force_boundary
;
583 generic_interp(ctx
, t
, dst
, out
, in
, force_boundary
);
586 static void generic_copy_pv_extras( GLcontext
*ctx
,
587 GLuint dst
, GLuint src
)
589 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
591 if (VB
->ColorPtr
[1]) {
592 COPY_4FV( VB
->ColorPtr
[1]->data
[dst
],
593 VB
->ColorPtr
[1]->data
[src
] );
595 if (VB
->SecondaryColorPtr
[1]) {
596 COPY_4FV( VB
->SecondaryColorPtr
[1]->data
[dst
],
597 VB
->SecondaryColorPtr
[1]->data
[src
] );
601 _tnl_copy_pv(ctx
, dst
, src
);
609 /***********************************************************************
610 * Build codegen functions or return generic ones:
614 static void choose_emit_func( GLcontext
*ctx
,
615 GLuint start
, GLuint end
,
618 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
619 vtx
->emit
= generic_emit
;
620 vtx
->emit( ctx
, start
, end
, dest
);
624 static void choose_interp_func( GLcontext
*ctx
,
626 GLuint edst
, GLuint eout
, GLuint ein
,
627 GLboolean force_boundary
)
629 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
631 if (vtx
->need_extras
&&
632 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
633 vtx
->interp
= generic_interp_extras
;
635 vtx
->interp
= generic_interp
;
638 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
642 static void choose_copy_pv_func( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
644 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
646 if (vtx
->need_extras
&&
647 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
648 vtx
->copy_pv
= generic_copy_pv_extras
;
650 vtx
->copy_pv
= generic_copy_pv
;
653 vtx
->copy_pv( ctx
, edst
, esrc
);
657 /***********************************************************************
658 * Public entrypoints, mostly dispatch to the above:
662 /* Interpolate between two vertices to produce a third:
664 void _tnl_interp( GLcontext
*ctx
,
666 GLuint edst
, GLuint eout
, GLuint ein
,
667 GLboolean force_boundary
)
669 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
670 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
673 /* Copy colors from one vertex to another:
675 void _tnl_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
677 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
678 vtx
->copy_pv( ctx
, edst
, esrc
);
682 /* Extract a named attribute from a hardware vertex. Will have to
683 * reverse any viewport transformation, swizzling or other conversions
684 * which may have been applied:
686 void _tnl_get_attr( GLcontext
*ctx
, const void *vin
,
687 GLenum attr
, GLfloat
*dest
)
689 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
690 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
691 int attr_count
= vtx
->attr_count
;
694 for (j
= 0; j
< attr_count
; j
++) {
695 if (a
[j
].attrib
== attr
) {
696 a
[j
].extract( &a
[j
], dest
, vin
);
701 /* Else return the value from ctx->Current
703 memcpy( dest
, ctx
->Current
.Attrib
[attr
], 4*sizeof(GLfloat
));
706 void *_tnl_get_vertex( GLcontext
*ctx
, GLuint nr
)
708 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
710 return vtx
->vertex_buf
+ nr
* vtx
->vertex_size
;
713 void _tnl_invalidate_vertex_state( GLcontext
*ctx
, GLuint new_state
)
715 if (new_state
& (_DD_NEW_TRI_LIGHT_TWOSIDE
|_DD_NEW_TRI_UNFILLED
) ) {
716 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
717 vtx
->new_inputs
= ~0;
718 vtx
->interp
= choose_interp_func
;
719 vtx
->copy_pv
= choose_copy_pv_func
;
724 GLuint
_tnl_install_attrs( GLcontext
*ctx
, const struct tnl_attr_map
*map
,
725 GLuint nr
, const GLfloat
*vp
)
727 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
731 assert(nr
< _TNL_ATTRIB_MAX
);
732 assert(nr
== 0 || map
[0].attrib
== VERT_ATTRIB_POS
);
734 vtx
->attr_count
= nr
;
735 vtx
->emit
= choose_emit_func
;
736 vtx
->interp
= choose_interp_func
;
737 vtx
->copy_pv
= choose_copy_pv_func
;
738 vtx
->new_inputs
= ~0;
740 for (i
= 0; i
< nr
; i
++) {
741 GLuint format
= map
[i
].format
;
742 vtx
->attr
[i
].attrib
= map
[i
].attrib
;
743 /* vtx->attr[i].format = map[i].format; */
744 vtx
->attr
[i
].vp
= vp
;
745 vtx
->attr
[i
].insert
= format_info
[format
].insert
;
746 vtx
->attr
[i
].extract
= format_info
[format
].extract
;
747 vtx
->attr
[i
].vertattrsize
= format_info
[format
].attrsize
;
748 vtx
->attr
[i
].vertoffset
= offset
;
749 offset
+= format_info
[format
].attrsize
;
752 assert(offset
<= vtx
->max_vertex_size
);
754 vtx
->vertex_size
= offset
;
756 return vtx
->vertex_size
;
761 void _tnl_invalidate_vertices( GLcontext
*ctx
, GLuint newinputs
)
763 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
764 vtx
->new_inputs
|= newinputs
;
769 void _tnl_build_vertices( GLcontext
*ctx
,
774 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
775 GLuint stride
= vtx
->vertex_size
;
776 GLubyte
*v
= ((GLubyte
*)vtx
->vertex_buf
+ (start
*stride
));
778 newinputs
|= vtx
->new_inputs
;
782 vtx
->emit( ctx
, start
, count
, v
);
786 void *_tnl_emit_vertices_to_buffer( GLcontext
*ctx
,
791 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
792 vtx
->emit( ctx
, start
, count
, dest
);
793 return (void *)((char *)dest
+ vtx
->vertex_size
* (count
- start
));
797 void _tnl_init_vertices( GLcontext
*ctx
,
799 GLuint max_vertex_size
)
801 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
803 _tnl_install_attrs( ctx
, 0, 0, 0 );
805 vtx
->need_extras
= GL_TRUE
;
806 vtx
->max_vertex_size
= max_vertex_size
;
807 vtx
->vertex_buf
= (char *)ALIGN_MALLOC(vb_size
* 4 * 18, max_vertex_size
);
811 void _tnl_free_vertices( GLcontext
*ctx
)
813 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
814 if (vtx
->vertex_buf
) {
815 ALIGN_FREE(vtx
->vertex_buf
);