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