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>
39 void (*insert
)( const struct attr
*a
, char *v
, const GLfloat
*input
);
40 void (*extract
)( const struct attr
*a
, GLfloat
*output
, const char *v
);
45 static void insert_4f_viewport( const struct attr
*a
, char *v
,
48 GLfloat
*out
= (GLfloat
*)v
;
49 const GLfloat
* const vp
= a
->vp
;
51 out
[0] = vp
[0] * in
[0] + vp
[12];
52 out
[1] = vp
[5] * in
[1] + vp
[13];
53 out
[2] = vp
[10] * in
[2] + vp
[14];
57 static void insert_3f_viewport( const struct attr
*a
, char *v
,
60 GLfloat
*out
= (GLfloat
*)v
;
61 const GLfloat
* const vp
= a
->vp
;
63 out
[0] = vp
[0] * in
[0] + vp
[12];
64 out
[1] = vp
[5] * in
[1] + vp
[13];
65 out
[2] = vp
[10] * in
[2] + vp
[14];
68 static void insert_2f_viewport( const struct attr
*a
, char *v
,
71 GLfloat
*out
= (GLfloat
*)v
;
72 const GLfloat
* const vp
= a
->vp
;
74 out
[0] = vp
[0] * in
[0] + vp
[12];
75 out
[1] = vp
[5] * in
[1] + vp
[13];
79 static void insert_4f( const struct attr
*a
, char *v
, const GLfloat
*in
)
81 GLfloat
*out
= (GLfloat
*)(v
);
89 static void insert_3f_xyw( const struct attr
*a
, char *v
, const GLfloat
*in
)
91 GLfloat
*out
= (GLfloat
*)(v
);
99 static void insert_3f( const struct attr
*a
, char *v
, const GLfloat
*in
)
101 GLfloat
*out
= (GLfloat
*)(v
);
109 static void insert_2f( const struct attr
*a
, char *v
, const GLfloat
*in
)
111 GLfloat
*out
= (GLfloat
*)(v
);
117 static void insert_1f( const struct attr
*a
, char *v
, const GLfloat
*in
)
119 GLfloat
*out
= (GLfloat
*)(v
);
124 static void insert_4ub_4f_rgba( const struct attr
*a
, char *v
,
127 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
128 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
129 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
130 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
133 static void insert_4ub_4f_bgra( const struct attr
*a
, char *v
,
136 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
137 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
138 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
139 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
142 static void insert_3ub_3f_rgb( const struct attr
*a
, char *v
,
145 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
146 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
147 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
150 static void insert_3ub_3f_bgr( const struct attr
*a
, char *v
,
153 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
154 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
155 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
158 static void insert_1ub_1f( const struct attr
*a
, char *v
,
161 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
165 /***********************************************************************
166 * Functions to perform the reverse operations to the above, for
167 * swrast translation and clip-interpolation.
169 * Currently always extracts a full 4 floats.
172 static void extract_4f_viewport( const struct attr
*a
, GLfloat
*out
,
175 const GLfloat
*in
= (const GLfloat
*)v
;
176 const GLfloat
* const vp
= a
->vp
;
178 out
[0] = (in
[0] - vp
[12]) / vp
[0];
179 out
[1] = (in
[1] - vp
[13]) / vp
[5];
180 out
[2] = (in
[2] - vp
[14]) / vp
[10];
184 static void extract_3f_viewport( const struct attr
*a
, GLfloat
*out
,
187 const GLfloat
*in
= (const GLfloat
*)v
;
188 const GLfloat
* const vp
= a
->vp
;
190 out
[0] = (in
[0] - vp
[12]) / vp
[0];
191 out
[1] = (in
[1] - vp
[13]) / vp
[5];
192 out
[2] = (in
[2] - vp
[14]) / vp
[10];
197 static void extract_2f_viewport( const struct attr
*a
, GLfloat
*out
,
200 const GLfloat
*in
= (const GLfloat
*)v
;
201 const GLfloat
* const vp
= a
->vp
;
203 out
[0] = (in
[0] - vp
[12]) / vp
[0];
204 out
[1] = (in
[1] - vp
[13]) / vp
[5];
210 static void extract_4f( const struct attr
*a
, GLfloat
*out
, const char *v
)
212 const GLfloat
*in
= (const GLfloat
*)v
;
220 static void extract_3f_xyw( const struct attr
*a
, GLfloat
*out
, const char *v
)
222 const GLfloat
*in
= (const GLfloat
*)v
;
231 static void extract_3f( const struct attr
*a
, GLfloat
*out
, const char *v
)
233 const GLfloat
*in
= (const GLfloat
*)v
;
242 static void extract_2f( const struct attr
*a
, GLfloat
*out
, const char *v
)
244 const GLfloat
*in
= (const GLfloat
*)v
;
252 static void extract_1f( const struct attr
*a
, GLfloat
*out
, const char *v
)
254 const GLfloat
*in
= (const GLfloat
*)v
;
262 static void extract_4ub_4f_rgba( const struct attr
*a
, GLfloat
*out
,
265 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
266 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
267 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
268 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
271 static void extract_4ub_4f_bgra( const struct attr
*a
, GLfloat
*out
,
274 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
275 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
276 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
277 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
280 static void extract_3ub_3f_rgb( const struct attr
*a
, GLfloat
*out
,
283 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
284 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
285 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
289 static void extract_3ub_3f_bgr( const struct attr
*a
, GLfloat
*out
,
292 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
293 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
294 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
298 static void extract_1ub_1f( const struct attr
*a
, GLfloat
*out
, const char *v
)
300 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
306 /***********************************************************************
307 * Generic (non-codegen) functions for whole vertices or groups of
311 static void generic_emit( GLcontext
*ctx
,
312 GLuint start
, GLuint end
,
317 char *v
= (char *)dest
;
319 vtx
->vertex_buf
= v
- start
* stride
;
320 vtx
->vertex_stride
= stride
;
324 for (j
= 0; j
< vtx
->attr_count
; j
++) {
325 GLvector4f
*vptr
= VB
->AttrPtr
[a
[j
].attrib
];
326 a
[j
].inputptr
= STRIDE_4F(vptr
->data
, start
* vptr
->stride
);
329 for (i
= 0 ; i
< end
; i
++, v
+= stride
) {
330 for (j
= 0; j
< vtx
->attr_count
; j
++) {
331 int *in
= a
[j
].inputptr
;
332 (char *)a
[j
].inputptr
+= a
[j
].inputstride
;
333 a
[j
].out( &a
[j
], v
+ a
[j
].vertoffset
, in
);
339 static void generic_interp( GLcontext
*ctx
,
341 GLuint edst
, GLuint eout
, GLuint ein
,
342 GLboolean force_boundary
)
344 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
345 char *vin
= vtx
->vertex_buf
+ ein
* vtx
->vertex_stride
;
346 char *vout
= vtx
->vertex_buf
+ eout
* vtx
->vertex_stride
;
347 char *vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_stride
;
348 const struct attr
*a
= vtx
->attr
;
349 int attr_count
= vtx
->attr_count
;
352 for (j
= 0; j
< attr_count
; j
++) {
353 GLfloat fin
[4], fout
[4], fdst
[4];
355 a
[j
].extract( &a
[j
], vin
, fin
);
356 a
[j
].extract( &a
[j
], vout
, fout
);
358 INTERP_F( t
, fdst
[3], fout
[3], fin
[3] );
359 INTERP_F( t
, fdst
[2], fout
[2], fin
[2] );
360 INTERP_F( t
, fdst
[1], fout
[1], fin
[1] );
361 INTERP_F( t
, fdst
[0], fout
[0], fin
[0] );
363 a
[j
].insert( &a
[j
], vdst
, fdst
);
368 /* Extract color attributes from one vertex and insert them into
369 * another. (Shortcircuit extract/insert with memcpy).
371 static void generic_copy_colors( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
373 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
374 char *vsrc
= vert_start
+ esrc
* vert_stride
;
375 char *vdst
= vert_start
+ edst
* vert_stride
;
376 const struct attr
*a
= vtx
->attr
;
377 int attr_count
= vtx
->attr_count
;
380 for (j
= 0; j
< attr_count
; j
++) {
381 if (a
[j
].attribute
== VERT_ATTRIB_COLOR0
||
382 a
[j
].attribute
== VERT_ATTRIB_COLOR1
) {
384 memcpy( vdst
+ a
[j
].vertoffset
,
385 vsrc
+ a
[j
].vertoffset
,
390 static void generic_get_attr( GLcontext
*ctx
, const char *vertex
,
391 GLenum attr
, GLfloat
*dest
)
393 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
394 const struct attr
*a
= vtx
->attr
;
395 int attr_count
= vtx
->attr_count
;
398 for (j
= 0; j
< attr_count
; j
++) {
399 if (a
[j
].attribute
== attr
) {
400 a
[j
].extract( &a
[j
], vin
, dest
);
405 /* Else return the value from ctx->Current
407 memcpy( dest
, ctx
->Current
.Attrib
[attr
], 4*sizeof(GLfloat
));
416 /***********************************************************************
417 * Build codegen functions or return generic ones:
421 static void choose_emit_func( GLcontext
*ctx
,
422 GLuint start
, GLuint end
,
426 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
427 vtx
->emit_func
= generic_emit_func
;
428 vtx
->emit_func( ctx
, start
, end
, dest
, stride
);
432 static void choose_interp_func( GLcontext
*ctx
,
434 GLuint edst
, GLuint eout
, GLuint ein
,
435 GLboolean force_boundary
)
437 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
438 vtx
->interp_func
= generic_interp_func
;
439 vtx
->interp_func( ctx
, t
, edst
, eout
, ein
, force_boundary
);
443 static void choose_copy_color_func( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
445 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
446 vtx
->copy_color_func
= generic_copy_color_func
;
447 vtx
->copy_color_func( ctx
, edst
, esrc
);
451 /***********************************************************************
452 * Public entrypoints, mostly dispatch to the above:
455 void _tnl_emit( GLcontext
*ctx
,
456 GLuint start
, GLuint end
,
460 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
461 vtx
->emit_func( ctx
, start
, end
, dest
, stride
);
464 /* Interpolate between two vertices to produce a third:
466 void _tnl_interp( GLcontext
*ctx
,
468 GLuint edst
, GLuint eout
, GLuint ein
,
469 GLboolean force_boundary
)
471 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
472 vtx
->interp_func( ctx
, t
, edst
, eout
, ein
, force_boundary
);
475 /* Copy colors from one vertex to another:
477 void _tnl_copy_colors( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
479 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
480 vtx
->copy_color_func( ctx
, edst
, esrc
);
484 /* Extract a named attribute from a hardware vertex. Will have to
485 * reverse any viewport transformation, swizzling or other conversions
486 * which may have been applied:
488 void _tnl_get_attr( GLcontext
*ctx
, void *vertex
, GLenum attrib
,
491 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
492 vtx
->get_attr_func( ctx
, vertex
, attrib
, dest
);
497 void _tnl_install_attrs( GLcontext
*ctx
, const struct dri_attr_map
*map
,
498 GLuint nr
, const GLfloat
*vp
)
500 struct dri_vertex_state
*vtx
= GET_VERTEX_STATE(ctx
);
503 assert(nr
< _TNL_ATTR_MAX
);
505 vtx
->attr_count
= nr
;
506 vtx
->emit_func
= choose_emit_func
;
507 vtx
->interp_func
= choose_interp_func
;
508 vtx
->copy_color_func
= choose_copy_color_func
;
509 vtx
->get_attr_func
= choose_get_attr_func
;
511 for (i
= 0; i
< nr
; i
++) {
512 GLuint attrib
= map
[i
].attrib
;
513 vtx
->attr
[i
].attrib
= map
[i
].attrib
;
514 vtx
->attr
[i
].hw_format
= map
[i
].hw_format
;
515 vtx
->attr
[i
].vp
= vp
;
516 vtx
->attr
[i
].insert
= attrib_info
[attrib
].insert
;
517 vtx
->attr
[i
].extract
= attrib_info
[attrib
].extract
;
518 vtx
->attr
[i
].vertattrsize
= attrib_info
[attrib
].attrsize
;
519 vtx
->attr
[i
].vertoffset
= offset
;
520 offset
+= attrib_info
[attrib
].attrsize
;
527 /* Populate a swrast SWvertex from an attrib-style vertex.
529 void _tnl_translate( GLcontext
*ctx
, const void *vertex
, SWvertex
*dest
)
531 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_POS
, dest
.win
);
533 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
534 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_TEX(i
), dest
.texcoord
[i
] );
536 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_COLOR0
, tmp
);
537 UNCLAMPED_FLOAT_TO_CHAN_RGBA( dest
.color
, tmp
);
539 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_COLOR1
, tmp
);
540 UNCLAMPED_FLOAT_TO_CHAN_RGB( dest
.specular
, tmp
);
542 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_FOG
, tmp
);
545 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_INDEX
, tmp
);
546 dest
.index
= (GLuint
) tmp
[0];
548 _tnl_get_attr( ctx
, vertex
, VERT_ATTRIB_POINTSIZE
, tmp
);
549 dest
.pointSize
= tmp
[0];
553 static void interp_extras( GLcontext
*ctx
,
555 GLuint dst
, GLuint out
, GLuint in
,
556 GLboolean force_boundary
)
558 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
560 if (VB
->ColorPtr
[1]) {
561 assert(VB
->ColorPtr
[1]->stride
== 4 * sizeof(GLfloat
));
564 GET_COLOR(VB
->ColorPtr
[1], dst
),
565 GET_COLOR(VB
->ColorPtr
[1], out
),
566 GET_COLOR(VB
->ColorPtr
[1], in
) );
568 if (VB
->SecondaryColorPtr
[1]) {
570 GET_COLOR(VB
->SecondaryColorPtr
[1], dst
),
571 GET_COLOR(VB
->SecondaryColorPtr
[1], out
),
572 GET_COLOR(VB
->SecondaryColorPtr
[1], in
) );
577 VB
->EdgeFlag
[dst
] = VB
->EdgeFlag
[out
] || force_boundary
;
580 generic_interp(ctx
, t
, dst
, out
, in
, force_boundary
);
583 static void copy_pv_extras( GLcontext
*ctx
,
584 GLuint dst
, GLuint src
)
586 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
588 if (VB
->ColorPtr
[1]) {
589 COPY_4FV( GET_COLOR(VB
->ColorPtr
[1], dst
),
590 GET_COLOR(VB
->ColorPtr
[1], src
) );
592 if (VB
->SecondaryColorPtr
[1]) {
593 COPY_4FV( GET_COLOR(VB
->SecondaryColorPtr
[1], dst
),
594 GET_COLOR(VB
->SecondaryColorPtr
[1], src
) );
598 generic_copy_colors(ctx
, dst
, src
);