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.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
26 /* Software TCL for NV10, NV20, NV30, NV40, G70 */
38 #include "swrast/swrast.h"
39 #include "swrast_setup/swrast_setup.h"
40 #include "tnl/t_context.h"
41 #include "tnl/t_pipeline.h"
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"
52 /* XXX hack for now */
55 static void nv10RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
56 static void nv10RasterPrimitive( GLcontext
*ctx
, GLenum rprim
, GLuint hwprim
);
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)
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)
74 static inline void nv10StartPrimitive(struct nouveau_context
* nmesa
)
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);
81 BEGIN_RING_SIZE(channel
,NV30_PRIMITIVE
,1);
82 OUT_RING(nmesa
->current_primitive
);
84 if (nmesa
->screen
->card_type
==NV_10
)
85 BEGIN_RING_PRIM(channel
,NV10_BEGIN_VERTICES
,NOUVEAU_MIN_PRIM_SIZE
);
87 BEGIN_RING_PRIM(channel
,NV20_BEGIN_VERTICES
,NOUVEAU_MIN_PRIM_SIZE
);
90 static inline void nv10FinishPrimitive(struct nouveau_context
*nmesa
)
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);
98 BEGIN_RING_SIZE(channel
,NV30_PRIMITIVE
,1);
104 static inline void nv10ExtendPrimitive(struct nouveau_context
* nmesa
, int size
)
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))
109 nv10FinishPrimitive(nmesa
);
110 nv10StartPrimitive(nmesa
);
113 /* make sure there's enough room. if not, wait */
114 if (RING_AVAILABLE()<size
/4)
116 WAIT_RING(nmesa
,size
);
120 static inline void nv10_draw_quad(nouveauContextPtr nmesa
,
126 GLuint vertsize
= nmesa
->vertex_size
;
127 nv10ExtendPrimitive(nmesa
, 4 * 4 * vertsize
);
129 OUT_RINGp(v0
,vertsize
);
130 OUT_RINGp(v1
,vertsize
);
131 OUT_RINGp(v2
,vertsize
);
132 OUT_RINGp(v3
,vertsize
);
135 static inline void nv10_draw_triangle(nouveauContextPtr nmesa
,
140 GLuint vertsize
= nmesa
->vertex_size
;
141 nv10ExtendPrimitive(nmesa
, 3 * 4 * vertsize
);
143 OUT_RINGp(v0
,vertsize
);
144 OUT_RINGp(v1
,vertsize
);
145 OUT_RINGp(v2
,vertsize
);
148 static inline void nv10_draw_line(nouveauContextPtr nmesa
,
152 GLuint vertsize
= nmesa
->vertex_size
;
153 nv10ExtendPrimitive(nmesa
, 2 * 4 * vertsize
);
154 OUT_RINGp(v0
,vertsize
);
155 OUT_RINGp(v1
,vertsize
);
158 static inline void nv10_draw_point(nouveauContextPtr nmesa
,
161 GLuint vertsize
= nmesa
->vertex_size
;
162 nv10ExtendPrimitive(nmesa
, 1 * 4 * vertsize
);
163 OUT_RINGp(v0
,vertsize
);
168 /***********************************************************************
169 * Macros for nouveau_dd_tritmp.h to draw basic primitives *
170 ***********************************************************************/
172 #define TRI(a, b, c) \
175 nmesa->draw_tri(nmesa, a, b, c); \
177 nv10_draw_triangle(nmesa, a, b, c); \
180 #define QUAD(a, b, c, d) \
183 nmesa->draw_tri(nmesa, a, b, d); \
184 nmesa->draw_tri(nmesa, b, c, d); \
187 nv10_draw_quad(nmesa, a, b, c, d); \
190 #define LINE(v0, v1) \
193 nmesa->draw_line(nmesa, v0, v1); \
195 nv10_draw_line(nmesa, v0, v1); \
201 nmesa->draw_point(nmesa, v0); \
203 nv10_draw_point(nmesa, v0); \
207 /***********************************************************************
208 * Build render functions from dd templates *
209 ***********************************************************************/
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
219 tnl_points_func points
;
221 tnl_triangle_func triangle
;
223 } rast_tab
[NOUVEAU_MAX_TRIFUNC
+ 1];
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)
235 #define DO_FULL_QUAD 1
239 #define HAVE_BACK_COLORS 0
240 #define HAVE_HW_FLATSHADE 1
241 #define VERTEX nouveauVertex
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)))
254 #define VERT_SET_RGBA( v, c ) \
256 nouveau_color_t *color = (nouveau_color_t *)&((v)->f[coloroffset]); \
258 color->green=(c)[1]; \
259 color->blue=(c)[2]; \
260 color->alpha=(c)[3]; \
263 #define VERT_COPY_RGBA( v0, v1 ) \
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]; \
273 #define VERT_SET_SPEC( v, c ) \
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]); \
282 #define VERT_COPY_SPEC( v0, v1 ) \
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]; \
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]
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;
306 /***********************************************************************
307 * Helpers for rendering unfilled primitives *
308 ***********************************************************************/
310 static const GLuint hw_prim
[GL_POLYGON
+1] = {
323 #define RASTERIZE(x) nv10RasterPrimitive( ctx, x, hw_prim[x] )
324 #define RENDER_PRIMITIVE nmesa->renderPrimitive
326 #define IND NOUVEAU_FALLBACK_BIT
327 #include "tnl_dd/t_dd_unfilled.h"
331 /***********************************************************************
332 * Generate GL render functions *
333 ***********************************************************************/
338 #include "tnl_dd/t_dd_tritmp.h"
340 #define IND (NOUVEAU_OFFSET_BIT)
341 #define TAG(x) x##_offset
342 #include "tnl_dd/t_dd_tritmp.h"
344 #define IND (NOUVEAU_TWOSIDE_BIT)
345 #define TAG(x) x##_twoside
346 #include "tnl_dd/t_dd_tritmp.h"
348 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_OFFSET_BIT)
349 #define TAG(x) x##_twoside_offset
350 #include "tnl_dd/t_dd_tritmp.h"
352 #define IND (NOUVEAU_UNFILLED_BIT)
353 #define TAG(x) x##_unfilled
354 #include "tnl_dd/t_dd_tritmp.h"
356 #define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_UNFILLED_BIT)
357 #define TAG(x) x##_offset_unfilled
358 #include "tnl_dd/t_dd_tritmp.h"
360 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_UNFILLED_BIT)
361 #define TAG(x) x##_twoside_unfilled
362 #include "tnl_dd/t_dd_tritmp.h"
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"
368 #define IND (NOUVEAU_FALLBACK_BIT)
369 #define TAG(x) x##_fallback
370 #include "tnl_dd/t_dd_tritmp.h"
372 #define IND (NOUVEAU_OFFSET_BIT|NOUVEAU_FALLBACK_BIT)
373 #define TAG(x) x##_offset_fallback
374 #include "tnl_dd/t_dd_tritmp.h"
376 #define IND (NOUVEAU_TWOSIDE_BIT|NOUVEAU_FALLBACK_BIT)
377 #define TAG(x) x##_twoside_fallback
378 #include "tnl_dd/t_dd_tritmp.h"
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"
384 #define IND (NOUVEAU_UNFILLED_BIT|NOUVEAU_FALLBACK_BIT)
385 #define TAG(x) x##_unfilled_fallback
386 #include "tnl_dd/t_dd_tritmp.h"
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"
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"
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"
402 /* Catchall case for flat, separate specular triangles */
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)
413 #define TAG(x) x##_flat_specular
414 #define IND NOUVEAU_MAX_TRIFUNC
415 #include "tnl_dd/t_dd_tritmp.h"
418 static void init_rast_tab(void)
423 init_twoside_offset();
425 init_offset_unfilled();
426 init_twoside_unfilled();
427 init_twoside_offset_unfilled();
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();
437 init_flat_specular(); /* special! */
441 /**********************************************************************/
442 /* Render unclipped begin/end objects */
443 /**********************************************************************/
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])
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
464 #define TAG(x) nouveau_##x##_verts
465 #include "tnl/t_vb_rendertmp.h"
468 #define TAG(x) nouveau_##x##_elts
469 #define ELT(x) elt[x]
470 #include "tnl/t_vb_rendertmp.h"
473 #undef NEED_EDGEFLAG_SETUP
476 #undef RESET_OCCLUSION
479 /**********************************************************************/
480 /* Render clipped primitives */
481 /**********************************************************************/
485 static void nouveauRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
488 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
489 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
490 GLuint prim
= NOUVEAU_CONTEXT(ctx
)->renderPrimitive
;
492 /* Render the new vertices as an unclipped polygon.
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
);
502 /* Restore the render primitive
504 if (prim
!= GL_POLYGON
&&
505 prim
!= GL_POLYGON
+ 1)
506 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
509 static void nouveauRenderClippedLine(GLcontext
*ctx
, GLuint ii
, GLuint jj
)
511 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
512 tnl
->Driver
.Render
.Line(ctx
, ii
, jj
);
515 static void nouveauFastRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
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]);
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
);
532 /**********************************************************************/
533 /* Choose render functions */
534 /**********************************************************************/
539 #define _NOUVEAU_NEW_VERTEX (_NEW_TEXTURE | \
540 _DD_NEW_SEPARATE_SPECULAR | \
541 _DD_NEW_TRI_UNFILLED | \
542 _DD_NEW_TRI_LIGHT_TWOSIDE | \
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 | \
552 #define EMIT_ATTR( ATTR, STYLE ) \
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++; \
560 static void nv10ChooseRenderState(GLcontext
*ctx
)
562 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
563 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
564 GLuint flags
= ctx
->_TriangleCaps
;
567 nmesa
->draw_point
= nv10_draw_point
;
568 nmesa
->draw_line
= nv10_draw_line
;
569 nmesa
->draw_tri
= nv10_draw_triangle
;
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
;
577 /* Hook in fallbacks for specific primitives.
579 if (flags
& POINT_FALLBACK
)
580 nmesa
->draw_point
= nouveau_fallback_point
;
582 if (flags
& LINE_FALLBACK
)
583 nmesa
->draw_line
= nouveau_fallback_line
;
585 if (flags
& TRI_FALLBACK
)
586 nmesa
->draw_tri
= nouveau_fallback_tri
;
590 if ((flags
& DD_SEPARATE_SPECULAR
) &&
591 ctx
->Light
.ShadeModel
== GL_FLAT
) {
592 index
= NOUVEAU_MAX_TRIFUNC
; /* flat specular */
595 if (nmesa
->renderIndex
!= index
) {
596 nmesa
->renderIndex
= index
;
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
;
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
;
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
;
620 static inline void nv10OutputVertexFormat(struct nouveau_context
* nmesa
, GLuint index
)
622 GLcontext
* ctx
=nmesa
->glCtx
;
623 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
624 struct vertex_buffer
*VB
= &tnl
->vb
;
626 int default_attr_size
[8]={3,3,3,4,3,1,4,4};
632 * Determine attribute sizes
637 attr_size
[i
]=default_attr_size
[i
];
644 attr_size
[i
]=VB
->TexCoordPtr
[i
];
650 * Tell t_vertex about the vertex format
659 /* special-case POS */
660 EMIT_ATTR(_TNL_ATTRIB_POS
,EMIT_3F_VIEWPORT
);
667 EMIT_ATTR(i
,EMIT_1F
);
670 EMIT_ATTR(i
,EMIT_2F
);
673 EMIT_ATTR(i
,EMIT_3F
);
676 EMIT_ATTR(i
,EMIT_4F
);
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
];
687 nmesa
->vertex_size
=total_size
;
690 * Tell the hardware about the vertex format
692 if (nmesa
->screen
->card_type
==NV_10
) {
693 // XXX needs some love
694 } else if (nmesa
->screen
->card_type
==NV_20
) {
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));
702 BEGIN_RING_SIZE(channel
,NV30_VERTEX_ATTRIBUTES
,slots
);
705 int size
=attr_size
[i
];
706 OUT_RING(NV20_VERTEX_ATTRIBUTE_TYPE_FLOAT
|(size
*0x10));
708 BEGIN_RING_SIZE(channel
,NV30_UNKNOWN_0
,1);
710 BEGIN_RING_SIZE(channel
,NV30_UNKNOWN_0
,1);
712 BEGIN_RING_SIZE(channel
,NV30_UNKNOWN_0
,1);
718 static void nv10ChooseVertexState( GLcontext
*ctx
)
720 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
721 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
722 GLuint index
= tnl
->render_inputs
;
724 if (index
!=nmesa
->render_inputs
)
726 nmesa
->render_inputs
=index
;
727 nv10OutputVertexFormat(nmesa
,index
);
732 /**********************************************************************/
733 /* High level hooks for t_vb_render.c */
734 /**********************************************************************/
737 static void nv10RenderStart(GLcontext
*ctx
)
739 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
741 if (nmesa
->newState
) {
742 nmesa
->newRenderState
|= nmesa
->newState
;
745 if (nmesa
->Fallback
) {
746 tnl
->Driver
.Render
.Start(ctx
);
750 if (nmesa
->newRenderState
) {
751 nv10ChooseVertexState(ctx
);
752 nv10ChooseRenderState(ctx
);
753 nmesa
->newRenderState
= 0;
757 static void nv10RenderFinish(GLcontext
*ctx
)
759 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
760 nv10FinishPrimitive(nmesa
);
764 /* System to flush dma and emit state changes based on the rasterized
767 void nv10RasterPrimitive(GLcontext
*ctx
,
771 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
773 assert (!nmesa
->newState
);
775 if (hwprim
!= nmesa
->current_primitive
)
777 nmesa
->current_primitive
=hwprim
;
782 /* Callback for mesa:
784 static void nv10RenderPrimitive( GLcontext
*ctx
, GLuint prim
)
786 nv10RasterPrimitive( ctx
, prim
, hw_prim
[prim
] );
791 /**********************************************************************/
792 /* Initialization. */
793 /**********************************************************************/
796 void nouveauInitTriFuncs(GLcontext
*ctx
)
798 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
799 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
800 static int firsttime
= 1;
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
;
816 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
817 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
819 nmesa
->verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;