Fix TCL_LIGHT_MODEL_CTL setting in radeonColorMaterial.
[mesa.git] / src / mesa / tnl / t_vertex.c
1 /*
2 * Copyright 2003 Tungsten Graphics, inc.
3 * All Rights Reserved.
4 *
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:
11 *
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
14 * Software.
15 *
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.
23 *
24 * Authors:
25 * Keith Whitwell <keithw@tungstengraphics.com>
26 */
27
28
29
30
31
32
33 struct attr {
34 int attrib;
35 int vertoffset;
36 int vertattrsize;
37 int *inputptr;
38 int inputstride;
39 void (*insert)( const struct attr *a, char *v, const GLfloat *input );
40 void (*extract)( const struct attr *a, GLfloat *output, const char *v );
41 const GLfloat *vp;
42 };
43
44
45 static void insert_4f_viewport( const struct attr *a, char *v,
46 const GLfloat *in )
47 {
48 GLfloat *out = (GLfloat *)v;
49 const GLfloat * const vp = a->vp;
50
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];
54 out[3] = in[3];
55 }
56
57 static void insert_3f_viewport( const struct attr *a, char *v,
58 const GLfloat *in )
59 {
60 GLfloat *out = (GLfloat *)v;
61 const GLfloat * const vp = a->vp;
62
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];
66 }
67
68 static void insert_2f_viewport( const struct attr *a, char *v,
69 const GLfloat *in )
70 {
71 GLfloat *out = (GLfloat *)v;
72 const GLfloat * const vp = a->vp;
73
74 out[0] = vp[0] * in[0] + vp[12];
75 out[1] = vp[5] * in[1] + vp[13];
76 }
77
78
79 static void insert_4f( const struct attr *a, char *v, const GLfloat *in )
80 {
81 GLfloat *out = (GLfloat *)(v);
82
83 out[0] = in[0];
84 out[1] = in[1];
85 out[2] = in[2];
86 out[3] = in[3];
87 }
88
89 static void insert_3f_xyw( const struct attr *a, char *v, const GLfloat *in )
90 {
91 GLfloat *out = (GLfloat *)(v);
92
93 out[0] = in[0];
94 out[1] = in[1];
95 out[2] = in[3];
96 }
97
98
99 static void insert_3f( const struct attr *a, char *v, const GLfloat *in )
100 {
101 GLfloat *out = (GLfloat *)(v);
102
103 out[0] = in[0];
104 out[1] = in[1];
105 out[2] = in[2];
106 }
107
108
109 static void insert_2f( const struct attr *a, char *v, const GLfloat *in )
110 {
111 GLfloat *out = (GLfloat *)(v);
112
113 out[0] = in[0];
114 out[1] = in[1];
115 }
116
117 static void insert_1f( const struct attr *a, char *v, const GLfloat *in )
118 {
119 GLfloat *out = (GLfloat *)(v);
120
121 out[0] = in[0];
122 }
123
124 static void insert_4ub_4f_rgba( const struct attr *a, char *v,
125 const GLfloat *in )
126 {
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]);
131 }
132
133 static void insert_4ub_4f_bgra( const struct attr *a, char *v,
134 const GLfloat *in )
135 {
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]);
140 }
141
142 static void insert_3ub_3f_rgb( const struct attr *a, char *v,
143 const GLfloat *in )
144 {
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]);
148 }
149
150 static void insert_3ub_3f_bgr( const struct attr *a, char *v,
151 const GLfloat *in )
152 {
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]);
156 }
157
158 static void insert_1ub_1f( const struct attr *a, char *v,
159 const GLfloat *in )
160 {
161 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
162 }
163
164
165 /***********************************************************************
166 * Functions to perform the reverse operations to the above, for
167 * swrast translation and clip-interpolation.
168 *
169 * Currently always extracts a full 4 floats.
170 */
171
172 static void extract_4f_viewport( const struct attr *a, GLfloat *out,
173 const char *v )
174 {
175 const GLfloat *in = (const GLfloat *)v;
176 const GLfloat * const vp = a->vp;
177
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];
181 out[3] = in[3];
182 }
183
184 static void extract_3f_viewport( const struct attr *a, GLfloat *out,
185 const char *v )
186 {
187 const GLfloat *in = (const GLfloat *)v;
188 const GLfloat * const vp = a->vp;
189
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];
193 out[3] = 1;
194 }
195
196
197 static void extract_2f_viewport( const struct attr *a, GLfloat *out,
198 const char *v )
199 {
200 const GLfloat *in = (const GLfloat *)v;
201 const GLfloat * const vp = a->vp;
202
203 out[0] = (in[0] - vp[12]) / vp[0];
204 out[1] = (in[1] - vp[13]) / vp[5];
205 out[2] = 0;
206 out[3] = 1;
207 }
208
209
210 static void extract_4f( const struct attr *a, GLfloat *out, const char *v )
211 {
212 const GLfloat *in = (const GLfloat *)v;
213
214 out[0] = in[0];
215 out[1] = in[1];
216 out[2] = in[2];
217 out[3] = in[3];
218 }
219
220 static void extract_3f_xyw( const struct attr *a, GLfloat *out, const char *v )
221 {
222 const GLfloat *in = (const GLfloat *)v;
223
224 out[0] = in[0];
225 out[1] = in[1];
226 out[2] = in[3];
227 out[3] = 1;
228 }
229
230
231 static void extract_3f( const struct attr *a, GLfloat *out, const char *v )
232 {
233 const GLfloat *in = (const GLfloat *)v;
234
235 out[0] = in[0];
236 out[1] = in[1];
237 out[2] = in[2];
238 out[3] = 1;
239 }
240
241
242 static void extract_2f( const struct attr *a, GLfloat *out, const char *v )
243 {
244 const GLfloat *in = (const GLfloat *)v;
245
246 out[0] = in[0];
247 out[1] = in[1];
248 out[2] = 0;
249 out[3] = 1;
250 }
251
252 static void extract_1f( const struct attr *a, GLfloat *out, const char *v )
253 {
254 const GLfloat *in = (const GLfloat *)v;
255
256 out[0] = in[0];
257 out[1] = 0;
258 out[2] = 0;
259 out[3] = 1;
260 }
261
262 static void extract_4ub_4f_rgba( const struct attr *a, GLfloat *out,
263 const char *v )
264 {
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]);
269 }
270
271 static void extract_4ub_4f_bgra( const struct attr *a, GLfloat *out,
272 const char *v )
273 {
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]);
278 }
279
280 static void extract_3ub_3f_rgb( const struct attr *a, GLfloat *out,
281 const char *v )
282 {
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]);
286 out[3] = 1;
287 }
288
289 static void extract_3ub_3f_bgr( const struct attr *a, GLfloat *out,
290 const char *v )
291 {
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]);
295 out[3] = 1;
296 }
297
298 static void extract_1ub_1f( const struct attr *a, GLfloat *out, const char *v )
299 {
300 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
301 out[1] = 0;
302 out[2] = 0;
303 out[3] = 1;
304 }
305
306 /***********************************************************************
307 * Generic (non-codegen) functions for whole vertices or groups of
308 * vertices
309 */
310
311 static void generic_emit( GLcontext *ctx,
312 GLuint start, GLuint end,
313 void *dest,
314 GLuint stride )
315 {
316 int i, j;
317 char *v = (char *)dest;
318
319 vtx->vertex_buf = v - start * stride;
320 vtx->vertex_stride = stride;
321
322 end -= start;
323
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);
327 }
328
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 );
334 }
335 }
336 }
337
338
339 static void generic_interp( GLcontext *ctx,
340 GLfloat t,
341 GLuint edst, GLuint eout, GLuint ein,
342 GLboolean force_boundary )
343 {
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;
350 int j;
351
352 for (j = 0; j < attr_count; j++) {
353 GLfloat fin[4], fout[4], fdst[4];
354
355 a[j].extract( &a[j], vin, fin );
356 a[j].extract( &a[j], vout, fout );
357
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] );
362
363 a[j].insert( &a[j], vdst, fdst );
364 }
365 }
366
367
368 /* Extract color attributes from one vertex and insert them into
369 * another. (Shortcircuit extract/insert with memcpy).
370 */
371 static void generic_copy_colors( GLcontext *ctx, GLuint edst, GLuint esrc )
372 {
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;
378 int j;
379
380 for (j = 0; j < attr_count; j++) {
381 if (a[j].attribute == VERT_ATTRIB_COLOR0 ||
382 a[j].attribute == VERT_ATTRIB_COLOR1) {
383
384 memcpy( vdst + a[j].vertoffset,
385 vsrc + a[j].vertoffset,
386 a[j].vertattrsize );
387 }
388 }
389
390 static void generic_get_attr( GLcontext *ctx, const char *vertex,
391 GLenum attr, GLfloat *dest )
392 {
393 struct dri_vertex_state *vtx = GET_VERTEX_STATE(ctx);
394 const struct attr *a = vtx->attr;
395 int attr_count = vtx->attr_count;
396 int j;
397
398 for (j = 0; j < attr_count; j++) {
399 if (a[j].attribute == attr) {
400 a[j].extract( &a[j], vin, dest );
401 return;
402 }
403 }
404
405 /* Else return the value from ctx->Current
406 */
407 memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
408 }
409
410
411
412
413
414
415
416 /***********************************************************************
417 * Build codegen functions or return generic ones:
418 */
419
420
421 static void choose_emit_func( GLcontext *ctx,
422 GLuint start, GLuint end,
423 void *dest,
424 GLuint stride )
425 {
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 );
429 }
430
431
432 static void choose_interp_func( GLcontext *ctx,
433 GLfloat t,
434 GLuint edst, GLuint eout, GLuint ein,
435 GLboolean force_boundary )
436 {
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 );
440 }
441
442
443 static void choose_copy_color_func( GLcontext *ctx, GLuint edst, GLuint esrc )
444 {
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 );
448 }
449
450
451 /***********************************************************************
452 * Public entrypoints, mostly dispatch to the above:
453 */
454
455 void _tnl_emit( GLcontext *ctx,
456 GLuint start, GLuint end,
457 void *dest,
458 GLuint stride )
459 {
460 struct dri_vertex_state *vtx = GET_VERTEX_STATE(ctx);
461 vtx->emit_func( ctx, start, end, dest, stride );
462 }
463
464 /* Interpolate between two vertices to produce a third:
465 */
466 void _tnl_interp( GLcontext *ctx,
467 GLfloat t,
468 GLuint edst, GLuint eout, GLuint ein,
469 GLboolean force_boundary )
470 {
471 struct dri_vertex_state *vtx = GET_VERTEX_STATE(ctx);
472 vtx->interp_func( ctx, t, edst, eout, ein, force_boundary );
473 }
474
475 /* Copy colors from one vertex to another:
476 */
477 void _tnl_copy_colors( GLcontext *ctx, GLuint edst, GLuint esrc )
478 {
479 struct dri_vertex_state *vtx = GET_VERTEX_STATE(ctx);
480 vtx->copy_color_func( ctx, edst, esrc );
481 }
482
483
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:
487 */
488 void _tnl_get_attr( GLcontext *ctx, void *vertex, GLenum attrib,
489 GLfloat *dest )
490 {
491 struct dri_vertex_state *vtx = GET_VERTEX_STATE(ctx);
492 vtx->get_attr_func( ctx, vertex, attrib, dest );
493 }
494
495
496
497 void _tnl_install_attrs( GLcontext *ctx, const struct dri_attr_map *map,
498 GLuint nr, const GLfloat *vp )
499 {
500 struct dri_vertex_state *vtx = GET_VERTEX_STATE(ctx);
501 int i;
502
503 assert(nr < _TNL_ATTR_MAX);
504
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;
510
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;
521 }
522 }
523
524
525
526
527 /* Populate a swrast SWvertex from an attrib-style vertex.
528 */
529 void _tnl_translate( GLcontext *ctx, const void *vertex, SWvertex *dest )
530 {
531 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_POS, dest.win );
532
533 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
534 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_TEX(i), dest.texcoord[i] );
535
536 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_COLOR0, tmp );
537 UNCLAMPED_FLOAT_TO_CHAN_RGBA( dest.color, tmp );
538
539 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_COLOR1, tmp );
540 UNCLAMPED_FLOAT_TO_CHAN_RGB( dest.specular, tmp );
541
542 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_FOG, tmp );
543 dest.fog = tmp[0];
544
545 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_INDEX, tmp );
546 dest.index = (GLuint) tmp[0];
547
548 _tnl_get_attr( ctx, vertex, VERT_ATTRIB_POINTSIZE, tmp );
549 dest.pointSize = tmp[0];
550 }
551
552
553 static void interp_extras( GLcontext *ctx,
554 GLfloat t,
555 GLuint dst, GLuint out, GLuint in,
556 GLboolean force_boundary )
557 {
558 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
559
560 if (VB->ColorPtr[1]) {
561 assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
562
563 INTERP_4F( t,
564 GET_COLOR(VB->ColorPtr[1], dst),
565 GET_COLOR(VB->ColorPtr[1], out),
566 GET_COLOR(VB->ColorPtr[1], in) );
567
568 if (VB->SecondaryColorPtr[1]) {
569 INTERP_3F( t,
570 GET_COLOR(VB->SecondaryColorPtr[1], dst),
571 GET_COLOR(VB->SecondaryColorPtr[1], out),
572 GET_COLOR(VB->SecondaryColorPtr[1], in) );
573 }
574 }
575
576 if (VB->EdgeFlag) {
577 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
578 }
579
580 generic_interp(ctx, t, dst, out, in, force_boundary);
581 }
582
583 static void copy_pv_extras( GLcontext *ctx,
584 GLuint dst, GLuint src )
585 {
586 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
587
588 if (VB->ColorPtr[1]) {
589 COPY_4FV( GET_COLOR(VB->ColorPtr[1], dst),
590 GET_COLOR(VB->ColorPtr[1], src) );
591
592 if (VB->SecondaryColorPtr[1]) {
593 COPY_4FV( GET_COLOR(VB->SecondaryColorPtr[1], dst),
594 GET_COLOR(VB->SecondaryColorPtr[1], src) );
595 }
596 }
597
598 generic_copy_colors(ctx, dst, src);
599 }
600
601 #endif