more macros, still missing the alloc_verts one
[mesa.git] / src / mesa / drivers / dri / nouveau / nv10_swtcl.c
1 /*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2006 Stephane Marchesin. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sub license,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 /* Software TCL for NV10, NV20, NV30, NV40, G70 */
27
28 #include <stdio.h>
29 #include <math.h>
30
31 #include "glheader.h"
32 #include "context.h"
33 #include "mtypes.h"
34 #include "macros.h"
35 #include "colormac.h"
36 #include "enums.h"
37
38 #include "swrast/swrast.h"
39 #include "swrast_setup/swrast_setup.h"
40 #include "tnl/t_context.h"
41 #include "tnl/t_pipeline.h"
42
43 #include "nouveau_tris.h"
44 #include "nv10_swtcl.h"
45 #include "nouveau_context.h"
46 #include "nouveau_span.h"
47 #include "nouveau_ioctl.h"
48 #include "nouveau_reg.h"
49 #include "nouveau_tex.h"
50 #include "nouveau_fifo.h"
51
52 /* XXX hack for now */
53 #define channel 1
54
55 static void nv10RenderPrimitive( GLcontext *ctx, GLenum prim );
56 static void nv10RasterPrimitive( GLcontext *ctx, GLenum rprim, GLuint hwprim );
57
58
59
60 /***********************************************************************
61 * Emit primitives as inline vertices *
62 ***********************************************************************/
63 #define LINE_FALLBACK (0)
64 #define POINT_FALLBACK (0)
65 #define TRI_FALLBACK (0)
66 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
67 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
68
69
70 /* the free room we want before we start a vertex batch. this is a performance-tunable */
71 #define NOUVEAU_MIN_PRIM_SIZE (32/4)
72 /* the size above which we fire the ring. this is a performance-tunable */
73 #define NOUVEAU_FIRE_SIZE (2048/4)
74
75 static inline void nv10StartPrimitive(struct nouveau_context* nmesa)
76 {
77 if (nmesa->screen->card_type==NV_10)
78 BEGIN_RING_SIZE(channel,NV10_PRIMITIVE,1);
79 else if (nmesa->screen->card_type==NV_20)
80 BEGIN_RING_SIZE(channel,NV20_PRIMITIVE,1);
81 else
82 BEGIN_RING_SIZE(channel,NV30_PRIMITIVE,1);
83 OUT_RING(nmesa->current_primitive);
84
85 if (nmesa->screen->card_type==NV_10)
86 BEGIN_RING_PRIM(channel,NV10_BEGIN_VERTICES,NOUVEAU_MIN_PRIM_SIZE);
87 else
88 BEGIN_RING_PRIM(channel,NV20_BEGIN_VERTICES,NOUVEAU_MIN_PRIM_SIZE);
89 }
90
91 inline void nv10FinishPrimitive(struct nouveau_context *nmesa)
92 {
93 FINISH_RING_PRIM();
94 if (nmesa->screen->card_type==NV_10)
95 BEGIN_RING_SIZE(channel,NV10_PRIMITIVE,1);
96 else if (nmesa->screen->card_type==NV_20)
97 BEGIN_RING_SIZE(channel,NV20_PRIMITIVE,1);
98 else
99 BEGIN_RING_SIZE(channel,NV30_PRIMITIVE,1);
100 OUT_RING(0x0);
101 FIRE_RING();
102 }
103
104
105 static inline void nv10ExtendPrimitive(struct nouveau_context* nmesa, int size)
106 {
107 /* when the fifo has enough stuff (2048 bytes) or there is not enough room, fire */
108 if ((RING_AHEAD()>=NOUVEAU_FIRE_SIZE)||(RING_AVAILABLE()<size/4))
109 {
110 nv10FinishPrimitive(nmesa);
111 nv10StartPrimitive(nmesa);
112 }
113
114 /* make sure there's enough room. if not, wait */
115 if (RING_AVAILABLE()<size/4)
116 {
117 WAIT_RING(nmesa,size);
118 }
119 }
120
121 static inline void nv10_draw_quad(nouveauContextPtr nmesa,
122 nouveauVertexPtr v0,
123 nouveauVertexPtr v1,
124 nouveauVertexPtr v2,
125 nouveauVertexPtr v3)
126 {
127 GLuint vertsize = nmesa->vertex_size;
128 nv10ExtendPrimitive(nmesa, 4 * 4 * vertsize);
129
130 OUT_RINGp(v0,vertsize);
131 OUT_RINGp(v1,vertsize);
132 OUT_RINGp(v2,vertsize);
133 OUT_RINGp(v3,vertsize);
134 }
135
136 static inline void nv10_draw_triangle(nouveauContextPtr nmesa,
137 nouveauVertexPtr v0,
138 nouveauVertexPtr v1,
139 nouveauVertexPtr v2)
140 {
141 GLuint vertsize = nmesa->vertex_size;
142 nv10ExtendPrimitive(nmesa, 3 * 4 * vertsize);
143
144 OUT_RINGp(v0,vertsize);
145 OUT_RINGp(v1,vertsize);
146 OUT_RINGp(v2,vertsize);
147 }
148
149 static inline void nv10_draw_line(nouveauContextPtr nmesa,
150 nouveauVertexPtr v0,
151 nouveauVertexPtr v1)
152 {
153 GLuint vertsize = nmesa->vertex_size;
154 nv10ExtendPrimitive(nmesa, 2 * 4 * vertsize);
155 OUT_RINGp(v0,vertsize);
156 OUT_RINGp(v1,vertsize);
157 }
158
159 static inline void nv10_draw_point(nouveauContextPtr nmesa,
160 nouveauVertexPtr v0)
161 {
162 GLuint vertsize = nmesa->vertex_size;
163 nv10ExtendPrimitive(nmesa, 1 * 4 * vertsize);
164 OUT_RINGp(v0,vertsize);
165 }
166
167
168
169 #define CTX_ARG nouveauContextPtr nmesa
170 #define GET_VERTEX_DWORDS() nmesa->vertex_size
171 #define LOCAL_VARS \
172 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \
173 const char *nouveauverts = (char *)nmesa->verts;
174 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
175 #define VERTEX nouveauVertex
176
177 #undef TAG
178 #define TAG(x) nouveau_##x
179 #include "tnl_dd/t_dd_triemit.h"
180
181 /***********************************************************************
182 * Macros for nouveau_dd_tritmp.h to draw basic primitives *
183 ***********************************************************************/
184
185 #define QUAD( a, b, c, d ) nouveau_quad( nmesa, a, b, c, d )
186 #define TRI( a, b, c ) nouveau_triangle( nmesa, a, b, c )
187 #define LINE( a, b ) nouveau_line( nmesa, a, b )
188 #define POINT( a ) nouveau_point( nmesa, a )
189
190 #undef TAG
191
192 /***********************************************************************
193 * Build render functions from dd templates *
194 ***********************************************************************/
195
196 #define NOUVEAU_OFFSET_BIT 0x01
197 #define NOUVEAU_TWOSIDE_BIT 0x02
198 #define NOUVEAU_UNFILLED_BIT 0x04
199 #define NOUVEAU_FALLBACK_BIT 0x08
200 #define NOUVEAU_MAX_TRIFUNC 0x10
201
202
203 static struct {
204 tnl_points_func points;
205 tnl_line_func line;
206 tnl_triangle_func triangle;
207 tnl_quad_func quad;
208 } rast_tab[NOUVEAU_MAX_TRIFUNC + 1];
209
210
211 #define DO_FALLBACK (IND & NOUVEAU_FALLBACK_BIT)
212 #define DO_OFFSET (IND & NOUVEAU_OFFSET_BIT)
213 #define DO_UNFILLED (IND & NOUVEAU_UNFILLED_BIT)
214 #define DO_TWOSIDE (IND & NOUVEAU_TWOSIDE_BIT)
215 #define DO_FLAT 0
216 #define DO_TRI 1
217 #define DO_QUAD 1
218 #define DO_LINE 1
219 #define DO_POINTS 1
220 #define DO_FULL_QUAD 1
221
222 #define HAVE_RGBA 1
223 #define HAVE_SPEC 1
224 #define HAVE_BACK_COLORS 0
225 #define HAVE_HW_FLATSHADE 1
226 #define VERTEX nouveauVertex
227 #define TAB rast_tab
228
229
230 #define DEPTH_SCALE 1.0
231 #define UNFILLED_TRI unfilled_tri
232 #define UNFILLED_QUAD unfilled_quad
233 #define VERT_X(_v) _v->v.x
234 #define VERT_Y(_v) _v->v.y
235 #define VERT_Z(_v) _v->v.z
236 #define AREA_IS_CCW(a) (a > 0)
237 #define GET_VERTEX(e) (nmesa->verts + (e * nmesa->vertex_size * sizeof(int)))
238
239 #define VERT_SET_RGBA( v, c ) \
240 do { \
241 nouveau_color_t *color = (nouveau_color_t *)&((v)->f[coloroffset]); \
242 color->red=(c)[0]; \
243 color->green=(c)[1]; \
244 color->blue=(c)[2]; \
245 color->alpha=(c)[3]; \
246 } while (0)
247
248 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
249
250 #define VERT_SET_SPEC( v, c ) \
251 do { \
252 if (specoffset) { \
253 nouveau_color_t *color = (nouveau_color_t *)&((v)->f[specoffset]); \
254 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
255 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
256 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
257 } \
258 } while (0)
259 #define VERT_COPY_SPEC( v0, v1 ) \
260 do { \
261 if (specoffset) { \
262 nouveau_color_t *spec0 = (nouveau_color_t *)&((v0)->ui[specoffset]); \
263 nouveau_color_t *spec1 = (nouveau_color_t *)&((v1)->ui[specoffset]); \
264 spec0->red = spec1->red; \
265 spec0->green = spec1->green; \
266 spec0->blue = spec1->blue; \
267 } \
268 } while (0)
269
270
271 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->f[coloroffset]
272 #define VERT_RESTORE_RGBA( idx ) v[idx]->f[coloroffset] = color[idx]
273 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->f[specoffset]
274 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->f[specoffset] = spec[idx]
275
276
277 #undef LOCAL_VARS
278 #define LOCAL_VARS(n) \
279 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); \
280 GLuint color[n], spec[n]; \
281 GLuint coloroffset = nmesa->color_offset; \
282 GLuint specoffset = nmesa->specular_offset; \
283 (void)color; (void)spec; (void)coloroffset; (void)specoffset;
284
285
286 /***********************************************************************
287 * Helpers for rendering unfilled primitives *
288 ***********************************************************************/
289
290 static const GLuint hw_prim[GL_POLYGON+1] = {
291 GL_POINTS+1,
292 GL_LINES+1,
293 GL_LINES+1,
294 GL_LINES+1,
295 GL_TRIANGLES+1,
296 GL_TRIANGLES+1,
297 GL_TRIANGLES+1,
298 GL_QUADS+1,
299 GL_QUADS+1,
300 GL_TRIANGLES+1
301 };
302
303 #define RASTERIZE(x) nv10RasterPrimitive( ctx, x, hw_prim[x] )
304 #define RENDER_PRIMITIVE nmesa->current_primitive
305 #define TAG(x) x
306 #define IND NOUVEAU_FALLBACK_BIT
307 #include "tnl_dd/t_dd_unfilled.h"
308 #undef IND
309 #undef RASTERIZE
310
311 /***********************************************************************
312 * Generate GL render functions *
313 ***********************************************************************/
314 #define RASTERIZE(x)
315
316 #define IND (0)
317 #define TAG(x) x
318 #include "tnl_dd/t_dd_tritmp.h"
319
320 #define IND (NOUVEAU_OFFSET_BIT)
321 #define TAG(x) x##_offset
322 #include "tnl_dd/t_dd_tritmp.h"
323
324 #define IND (NOUVEAU_TWOSIDE_BIT)
325 #define TAG(x) x##_twoside
326 #include "tnl_dd/t_dd_tritmp.h"
327
328 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT)
329 #define TAG(x) x##_twoside_offset
330 #include "tnl_dd/t_dd_tritmp.h"
331
332 #define IND (NOUVEAU_UNFILLED_BIT)
333 #define TAG(x) x##_unfilled
334 #include "tnl_dd/t_dd_tritmp.h"
335
336 #define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT)
337 #define TAG(x) x##_offset_unfilled
338 #include "tnl_dd/t_dd_tritmp.h"
339
340 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_UNFILLED_BIT)
341 #define TAG(x) x##_twoside_unfilled
342 #include "tnl_dd/t_dd_tritmp.h"
343
344 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT)
345 #define TAG(x) x##_twoside_offset_unfilled
346 #include "tnl_dd/t_dd_tritmp.h"
347
348 #define IND (NOUVEAU_FALLBACK_BIT)
349 #define TAG(x) x##_fallback
350 #include "tnl_dd/t_dd_tritmp.h"
351
352 #define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_FALLBACK_BIT)
353 #define TAG(x) x##_offset_fallback
354 #include "tnl_dd/t_dd_tritmp.h"
355
356 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_FALLBACK_BIT)
357 #define TAG(x) x##_twoside_fallback
358 #include "tnl_dd/t_dd_tritmp.h"
359
360 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT|NOUVEAU_FALLBACK_BIT)
361 #define TAG(x) x##_twoside_offset_fallback
362 #include "tnl_dd/t_dd_tritmp.h"
363
364 #define IND (NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
365 #define TAG(x) x##_unfilled_fallback
366 #include "tnl_dd/t_dd_tritmp.h"
367
368 #define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
369 #define TAG(x) x##_offset_unfilled_fallback
370 #include "tnl_dd/t_dd_tritmp.h"
371
372 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
373 #define TAG(x) x##_twoside_unfilled_fallback
374 #include "tnl_dd/t_dd_tritmp.h"
375
376 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT| \
377 NOUVEAU_FALLBACK_BIT)
378 #define TAG(x) x##_twoside_offset_unfilled_fallback
379 #include "tnl_dd/t_dd_tritmp.h"
380
381
382 /* Catchall case for flat, separate specular triangles */
383 #undef DO_FALLBACK
384 #undef DO_OFFSET
385 #undef DO_UNFILLED
386 #undef DO_TWOSIDE
387 #undef DO_FLAT
388 #define DO_FALLBACK (0)
389 #define DO_OFFSET (ctx->_TriangleCaps & DD_TRI_OFFSET)
390 #define DO_UNFILLED (ctx->_TriangleCaps & DD_TRI_UNFILLED)
391 #define DO_TWOSIDE (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
392 #define DO_FLAT 1
393 #define TAG(x) x##_flat_specular
394 #define IND NOUVEAU_MAX_TRIFUNC
395 #include "tnl_dd/t_dd_tritmp.h"
396
397
398 static void init_rast_tab(void)
399 {
400 init();
401 init_offset();
402 init_twoside();
403 init_twoside_offset();
404 init_unfilled();
405 init_offset_unfilled();
406 init_twoside_unfilled();
407 init_twoside_offset_unfilled();
408 init_fallback();
409 init_offset_fallback();
410 init_twoside_fallback();
411 init_twoside_offset_fallback();
412 init_unfilled_fallback();
413 init_offset_unfilled_fallback();
414 init_twoside_unfilled_fallback();
415 init_twoside_offset_unfilled_fallback();
416
417 init_flat_specular(); /* special! */
418 }
419
420
421 /**********************************************************************/
422 /* Render unclipped begin/end objects */
423 /**********************************************************************/
424 #define IND 0
425 #define V(x) (nouveauVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
426 #define RENDER_POINTS(start, count) \
427 for (; start < count; start++) POINT(V(ELT(start)));
428 #define RENDER_LINE(v0, v1) LINE(V(v0), V(v1))
429 #define RENDER_TRI( v0, v1, v2) TRI( V(v0), V(v1), V(v2))
430 #define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
431 #define INIT(x) nv10RasterPrimitive(ctx, x, hw_prim[x])
432 #undef LOCAL_VARS
433 #define LOCAL_VARS \
434 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx); \
435 GLubyte *vertptr = (GLubyte *)nmesa->verts; \
436 const GLuint vertsize = nmesa->vertex_size; \
437 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
438 const GLboolean stipple = ctx->Line.StippleFlag; \
439 (void) elt; (void) stipple;
440 #define RESET_STIPPLE if ( stipple ) nouveauResetLineStipple( ctx );
441 #define RESET_OCCLUSION
442 #define PRESERVE_VB_DEFS
443 #define ELT(x) x
444 #define TAG(x) nouveau_##x##_verts
445 #include "tnl/t_vb_rendertmp.h"
446 #undef ELT
447 #undef TAG
448 #define TAG(x) nouveau_##x##_elts
449 #define ELT(x) elt[x]
450 #include "tnl/t_vb_rendertmp.h"
451 #undef ELT
452 #undef TAG
453 #undef NEED_EDGEFLAG_SETUP
454 #undef EDGEFLAG_GET
455 #undef EDGEFLAG_SET
456 #undef RESET_OCCLUSION
457
458
459 /**********************************************************************/
460 /* Render clipped primitives */
461 /**********************************************************************/
462
463
464
465 static void nouveauRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
466 GLuint n)
467 {
468 TNLcontext *tnl = TNL_CONTEXT(ctx);
469 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
470 GLuint prim = NOUVEAU_CONTEXT(ctx)->renderPrimitive;
471
472 /* Render the new vertices as an unclipped polygon.
473 */
474 {
475 GLuint *tmp = VB->Elts;
476 VB->Elts = (GLuint *)elts;
477 tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n,
478 PRIM_BEGIN|PRIM_END);
479 VB->Elts = tmp;
480 }
481
482 /* Restore the render primitive
483 */
484 if (prim != GL_POLYGON &&
485 prim != GL_POLYGON + 1)
486 tnl->Driver.Render.PrimitiveNotify( ctx, prim );
487 }
488
489 static void nouveauRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
490 {
491 TNLcontext *tnl = TNL_CONTEXT(ctx);
492 tnl->Driver.Render.Line(ctx, ii, jj);
493 }
494
495 static void nouveauFastRenderClippedPoly(GLcontext *ctx, const GLuint *elts,
496 GLuint n)
497 {
498 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
499 GLuint vertsize = nmesa->vertex_size;
500 nv10ExtendPrimitive(nmesa, (n - 2) * 3 * 4 * vertsize);
501 GLubyte *vertptr = (GLubyte *)nmesa->verts;
502 const GLuint *start = (const GLuint *)V(elts[0]);
503 int i;
504
505 for (i = 2; i < n; i++) {
506 OUT_RINGp(V(elts[i-1]),vertsize);
507 OUT_RINGp(V(elts[i]),vertsize);
508 OUT_RINGp(start,vertsize);
509 }
510 }
511
512 /**********************************************************************/
513 /* Choose render functions */
514 /**********************************************************************/
515
516
517
518
519 #define _NOUVEAU_NEW_VERTEX (_NEW_TEXTURE | \
520 _DD_NEW_SEPARATE_SPECULAR | \
521 _DD_NEW_TRI_UNFILLED | \
522 _DD_NEW_TRI_LIGHT_TWOSIDE | \
523 _NEW_FOG)
524
525 #define _NOUVEAU_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
526 _DD_NEW_TRI_UNFILLED | \
527 _DD_NEW_TRI_LIGHT_TWOSIDE | \
528 _DD_NEW_TRI_OFFSET | \
529 _DD_NEW_TRI_STIPPLE | \
530 _NEW_POLYGONSTIPPLE)
531
532 #define EMIT_ATTR( ATTR, STYLE ) \
533 do { \
534 nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \
535 nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \
536 nmesa->vertex_attr_count++; \
537 } while (0)
538
539
540 static void nv10ChooseRenderState(GLcontext *ctx)
541 {
542 TNLcontext *tnl = TNL_CONTEXT(ctx);
543 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
544 GLuint flags = ctx->_TriangleCaps;
545 GLuint index = 0;
546
547 nmesa->draw_point = nv10_draw_point;
548 nmesa->draw_line = nv10_draw_line;
549 nmesa->draw_tri = nv10_draw_triangle;
550
551 if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
552 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= NOUVEAU_TWOSIDE_BIT;
553 if (flags & DD_TRI_OFFSET) index |= NOUVEAU_OFFSET_BIT;
554 if (flags & DD_TRI_UNFILLED) index |= NOUVEAU_UNFILLED_BIT;
555 if (flags & ANY_FALLBACK_FLAGS) index |= NOUVEAU_FALLBACK_BIT;
556
557 /* Hook in fallbacks for specific primitives.
558 */
559 if (flags & POINT_FALLBACK)
560 nmesa->draw_point = nouveau_fallback_point;
561
562 if (flags & LINE_FALLBACK)
563 nmesa->draw_line = nouveau_fallback_line;
564
565 if (flags & TRI_FALLBACK)
566 nmesa->draw_tri = nouveau_fallback_tri;
567 }
568
569
570 if ((flags & DD_SEPARATE_SPECULAR) &&
571 ctx->Light.ShadeModel == GL_FLAT) {
572 index = NOUVEAU_MAX_TRIFUNC; /* flat specular */
573 }
574
575 if (nmesa->render_index != index) {
576 nmesa->render_index = index;
577
578 tnl->Driver.Render.Points = rast_tab[index].points;
579 tnl->Driver.Render.Line = rast_tab[index].line;
580 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
581 tnl->Driver.Render.Quad = rast_tab[index].quad;
582
583 if (index == 0) {
584 tnl->Driver.Render.PrimTabVerts = nouveau_render_tab_verts;
585 tnl->Driver.Render.PrimTabElts = nouveau_render_tab_elts;
586 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
587 tnl->Driver.Render.ClippedPolygon = nouveauFastRenderClippedPoly;
588 }
589 else {
590 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
591 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
592 tnl->Driver.Render.ClippedLine = nouveauRenderClippedLine;
593 tnl->Driver.Render.ClippedPolygon = nouveauRenderClippedPoly;
594 }
595 }
596 }
597
598
599
600 static inline void nv10OutputVertexFormat(struct nouveau_context* nmesa, GLuint index)
601 {
602 GLcontext* ctx=nmesa->glCtx;
603 TNLcontext *tnl = TNL_CONTEXT(ctx);
604 struct vertex_buffer *VB = &tnl->vb;
605 int attr_size[16];
606 int default_attr_size[8]={3,3,3,4,3,1,4,4};
607 int i;
608 int slots=0;
609 int total_size=0;
610
611 /*
612 * Determine attribute sizes
613 */
614 for(i=0;i<8;i++)
615 {
616 if (index&(1<<i))
617 attr_size[i]=default_attr_size[i];
618 else
619 attr_size[i]=0;
620 }
621 for(i=8;i<16;i++)
622 {
623 if (index&(1<<i))
624 attr_size[i]=VB->TexCoordPtr[i];
625 else
626 attr_size[i]=0;
627 }
628
629 /*
630 * Tell t_vertex about the vertex format
631 */
632 for(i=0;i<16;i++)
633 {
634 if (index&(1<<i))
635 {
636 slots=i+1;
637 if (i==0)
638 {
639 /* special-case POS */
640 EMIT_ATTR(_TNL_ATTRIB_POS,EMIT_3F_VIEWPORT);
641 }
642 else
643 {
644 switch(attr_size[i])
645 {
646 case 1:
647 EMIT_ATTR(i,EMIT_1F);
648 break;
649 case 2:
650 EMIT_ATTR(i,EMIT_2F);
651 break;
652 case 3:
653 EMIT_ATTR(i,EMIT_3F);
654 break;
655 case 4:
656 EMIT_ATTR(i,EMIT_4F);
657 break;
658 }
659 }
660 if (i==_TNL_ATTRIB_COLOR0)
661 nmesa->color_offset=total_size;
662 if (i==_TNL_ATTRIB_COLOR1)
663 nmesa->specular_offset=total_size;
664 total_size+=attr_size[i];
665 }
666 }
667 nmesa->vertex_size=total_size;
668
669 /*
670 * Tell the hardware about the vertex format
671 */
672 if (nmesa->screen->card_type==NV_10) {
673 // XXX needs some love
674 } else if (nmesa->screen->card_type==NV_20) {
675 for(i=0;i<16;i++)
676 {
677 int size=attr_size[i];
678 BEGIN_RING_SIZE(channel,NV20_VERTEX_ATTRIBUTE(i),1);
679 OUT_RING(NV20_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10));
680 }
681 } else {
682 BEGIN_RING_SIZE(channel,NV30_VERTEX_ATTRIBUTES,slots);
683 for(i=0;i<slots;i++)
684 {
685 int size=attr_size[i];
686 OUT_RING(NV20_VERTEX_ATTRIBUTE_TYPE_FLOAT|(size*0x10));
687 }
688 BEGIN_RING_SIZE(channel,NV30_UNKNOWN_0,1);
689 OUT_RING(0);
690 BEGIN_RING_SIZE(channel,NV30_UNKNOWN_0,1);
691 OUT_RING(0);
692 BEGIN_RING_SIZE(channel,NV30_UNKNOWN_0,1);
693 OUT_RING(0);
694 }
695 }
696
697
698 static void nv10ChooseVertexState( GLcontext *ctx )
699 {
700 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
701 TNLcontext *tnl = TNL_CONTEXT(ctx);
702 GLuint index = tnl->render_inputs;
703
704 if (index!=nmesa->render_inputs)
705 {
706 nmesa->render_inputs=index;
707 nv10OutputVertexFormat(nmesa,index);
708 }
709 }
710
711
712 /**********************************************************************/
713 /* High level hooks for t_vb_render.c */
714 /**********************************************************************/
715
716
717 static void nv10RenderStart(GLcontext *ctx)
718 {
719 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
720
721 if (nmesa->new_state) {
722 nmesa->new_render_state |= nmesa->new_state;
723 }
724
725 if (nmesa->Fallback) {
726 tnl->Driver.Render.Start(ctx);
727 return;
728 }
729
730 if (nmesa->new_render_state) {
731 nv10ChooseVertexState(ctx);
732 nv10ChooseRenderState(ctx);
733 nmesa->new_render_state = 0;
734 }
735 }
736
737 static void nv10RenderFinish(GLcontext *ctx)
738 {
739 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
740 nv10FinishPrimitive(nmesa);
741 }
742
743
744 /* System to flush dma and emit state changes based on the rasterized
745 * primitive.
746 */
747 void nv10RasterPrimitive(GLcontext *ctx,
748 GLenum glprim,
749 GLuint hwprim)
750 {
751 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
752
753 assert (!nmesa->new_state);
754
755 if (hwprim != nmesa->current_primitive)
756 {
757 nmesa->current_primitive=hwprim;
758
759 }
760 }
761
762 /* Callback for mesa:
763 */
764 static void nv10RenderPrimitive( GLcontext *ctx, GLuint prim )
765 {
766 nv10RasterPrimitive( ctx, prim, hw_prim[prim] );
767 }
768
769
770 /**********************************************************************/
771 /* Initialization. */
772 /**********************************************************************/
773
774 void nv10TriInitFunctions(GLcontext *ctx)
775 {
776 struct nouveau_context *nmesa = NOUVEAU_CONTEXT(ctx);
777 TNLcontext *tnl = TNL_CONTEXT(ctx);
778 static int firsttime = 1;
779
780 if (firsttime) {
781 init_rast_tab();
782 firsttime = 0;
783 }
784
785 tnl->Driver.RunPipeline = nouveauRunPipeline;
786 tnl->Driver.Render.Start = nv10RenderStart;
787 tnl->Driver.Render.Finish = nv10RenderFinish;
788 tnl->Driver.Render.PrimitiveNotify = nv10RenderPrimitive;
789 tnl->Driver.Render.ResetLineStipple = nouveauResetLineStipple;
790 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
791 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
792 tnl->Driver.Render.Interp = _tnl_interp;
793
794 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
795 (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
796
797 nmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
798
799 }
800
801