2 * Copyright 2007 Stephane Marchesin. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 /* Software TCL for NV04, NV05, NV06 */
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
38 #include "tnl/t_context.h"
39 #include "tnl/t_pipeline.h"
41 #include "nouveau_swtcl.h"
42 #include "nv04_swtcl.h"
43 #include "nouveau_context.h"
44 #include "nouveau_span.h"
45 #include "nouveau_reg.h"
46 #include "nouveau_tex.h"
47 #include "nouveau_fifo.h"
48 #include "nouveau_msg.h"
49 #include "nouveau_object.h"
51 static void nv04RasterPrimitive( GLcontext
*ctx
, GLenum rprim
, GLuint hwprim
);
52 static void nv04RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
53 static void nv04ResetLineStipple( GLcontext
*ctx
);
56 static inline void nv04_2triangles(struct nouveau_context
*nmesa
,nouveauVertex
* v0
,nouveauVertex
* v1
,nouveauVertex
* v2
,nouveauVertex
* v3
,nouveauVertex
* v4
,nouveauVertex
* v5
)
58 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xA),49);
68 static inline void nv04_1triangle(struct nouveau_context
*nmesa
,nouveauVertex
* v0
,nouveauVertex
* v1
,nouveauVertex
* v2
)
70 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xD),25);
77 static inline void nv04_1quad(struct nouveau_context
*nmesa
,nouveauVertex
* v0
,nouveauVertex
* v1
,nouveauVertex
* v2
,nouveauVertex
* v3
)
79 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0xC),33);
87 /**********************************************************************/
88 /* Render unclipped begin/end objects */
89 /**********************************************************************/
91 static void nv04_render_points_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
96 static void nv04_render_lines_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
101 static void nv04_render_line_strip_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
106 static void nv04_render_line_loop_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
111 static void nv04_render_triangles_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
113 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
114 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
115 GLuint vertsize
= nmesa
->vertex_size
;
118 for(i
=start
;i
<count
-5;i
+=6)
119 nv04_2triangles(nmesa
,
120 (nouveauVertex
*)(vertptr
+(i
+0)*vertsize
),
121 (nouveauVertex
*)(vertptr
+(i
+1)*vertsize
),
122 (nouveauVertex
*)(vertptr
+(i
+2)*vertsize
),
123 (nouveauVertex
*)(vertptr
+(i
+3)*vertsize
),
124 (nouveauVertex
*)(vertptr
+(i
+4)*vertsize
),
125 (nouveauVertex
*)(vertptr
+(i
+5)*vertsize
)
129 nv04_1triangle(nmesa
,
130 (nouveauVertex
*)(vertptr
+(i
+0)*vertsize
),
131 (nouveauVertex
*)(vertptr
+(i
+1)*vertsize
),
132 (nouveauVertex
*)(vertptr
+(i
+2)*vertsize
)
140 static void nv04_render_tri_strip_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
142 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
143 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
144 GLuint vertsize
= nmesa
->vertex_size
;
145 uint32_t striptbl
[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
148 for(i
=start
;i
<count
;i
+=14)
150 int numvert
=MIN2(16,count
-i
);
151 int numtri
=numvert
-2;
155 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert
*8);
156 for(j
=0;j
<numvert
;j
++)
157 OUT_RINGp((nouveauVertex
*)(vertptr
+(i
+j
)*vertsize
),8);
159 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_DRAW
|NONINC_METHOD
,(numtri
+1)/2);
160 for(j
=0;j
<numtri
/2;j
++)
161 OUT_RING(striptbl
[j
]);
163 OUT_RING(striptbl
[numtri
/2]&0xFFF);
167 static void nv04_render_tri_fan_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
169 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
170 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
171 GLuint vertsize
= nmesa
->vertex_size
;
172 uint32_t fantbl
[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
175 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
176 OUT_RINGp((nouveauVertex
*)(vertptr
+start
*vertsize
),8);
178 for(i
=start
+1;i
<count
;i
+=14)
180 int numvert
=MIN2(15,count
-i
);
181 int numtri
=numvert
-1;
185 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert
*8);
187 for(j
=0;j
<numvert
;j
++)
188 OUT_RINGp((nouveauVertex
*)(vertptr
+(i
+j
)*vertsize
),8);
190 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_DRAW
|NONINC_METHOD
,(numtri
+1)/2);
191 for(j
=0;j
<numtri
/2;j
++)
194 OUT_RING(fantbl
[numtri
/2]&0xFFF);
198 static void nv04_render_quads_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
200 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
201 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
202 GLuint vertsize
= nmesa
->vertex_size
;
205 for(i
=start
;i
<count
;i
+=4)
207 (nouveauVertex
*)(vertptr
+(i
+0)*vertsize
),
208 (nouveauVertex
*)(vertptr
+(i
+1)*vertsize
),
209 (nouveauVertex
*)(vertptr
+(i
+2)*vertsize
),
210 (nouveauVertex
*)(vertptr
+(i
+3)*vertsize
)
214 static void nv04_render_noop_verts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
218 static void (*nv04_render_tab_verts
[GL_POLYGON
+2])(GLcontext
*,
223 nv04_render_points_verts
,
224 nv04_render_lines_verts
,
225 nv04_render_line_loop_verts
,
226 nv04_render_line_strip_verts
,
227 nv04_render_triangles_verts
,
228 nv04_render_tri_strip_verts
,
229 nv04_render_tri_fan_verts
,
230 nv04_render_quads_verts
,
231 nv04_render_tri_strip_verts
, //nv04_render_quad_strip_verts
232 nv04_render_tri_fan_verts
, //nv04_render_poly_verts
233 nv04_render_noop_verts
,
237 static void nv04_render_points_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
242 static void nv04_render_lines_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
247 static void nv04_render_line_strip_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
252 static void nv04_render_line_loop_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
257 static void nv04_render_triangles_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
259 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
260 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
261 GLuint vertsize
= nmesa
->vertex_size
;
262 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
265 for(i
=start
;i
<count
-5;i
+=6)
266 nv04_2triangles(nmesa
,
267 (nouveauVertex
*)(vertptr
+elt
[i
+0]*vertsize
),
268 (nouveauVertex
*)(vertptr
+elt
[i
+1]*vertsize
),
269 (nouveauVertex
*)(vertptr
+elt
[i
+2]*vertsize
),
270 (nouveauVertex
*)(vertptr
+elt
[i
+3]*vertsize
),
271 (nouveauVertex
*)(vertptr
+elt
[i
+4]*vertsize
),
272 (nouveauVertex
*)(vertptr
+elt
[i
+5]*vertsize
)
276 nv04_1triangle(nmesa
,
277 (nouveauVertex
*)(vertptr
+elt
[i
+0]*vertsize
),
278 (nouveauVertex
*)(vertptr
+elt
[i
+1]*vertsize
),
279 (nouveauVertex
*)(vertptr
+elt
[i
+2]*vertsize
)
287 static void nv04_render_tri_strip_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
289 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
290 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
291 GLuint vertsize
= nmesa
->vertex_size
;
292 uint32_t striptbl
[]={0x321210,0x543432,0x765654,0x987876,0xBA9A98,0xDCBCBA,0xFEDEDC};
293 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
296 for(i
=start
;i
<count
;i
+=14)
298 int numvert
=MIN2(16,count
-i
);
299 int numtri
=numvert
-2;
303 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),numvert
*8);
304 for(j
=0;j
<numvert
;j
++)
305 OUT_RINGp((nouveauVertex
*)(vertptr
+elt
[i
+j
]*vertsize
),8);
307 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_DRAW
|NONINC_METHOD
,(numtri
+1)/2);
308 for(j
=0;j
<numtri
/2;j
++)
309 OUT_RING(striptbl
[j
]);
311 OUT_RING(striptbl
[numtri
/2]&0xFFF);
315 static void nv04_render_tri_fan_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
317 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
318 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
319 GLuint vertsize
= nmesa
->vertex_size
;
320 uint32_t fantbl
[]={0x320210,0x540430,0x760650,0x980870,0xBA0A90,0xDC0CB0,0xFE0ED0};
321 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
324 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x0),8);
325 OUT_RINGp((nouveauVertex
*)(vertptr
+elt
[start
]*vertsize
),8);
327 for(i
=start
+1;i
<count
;i
+=14)
329 int numvert
=MIN2(15,count
-i
);
330 int numtri
=numvert
-2;
334 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_TLVERTEX_SX(0x1),numvert
*8);
336 for(j
=0;j
<numvert
;j
++)
337 OUT_RINGp((nouveauVertex
*)(vertptr
+elt
[i
+j
]*vertsize
),8);
339 BEGIN_RING_SIZE(NvSub3D
,NV04_DX5_TEXTURED_TRIANGLE_DRAW
|NONINC_METHOD
,(numtri
+1)/2);
340 for(j
=0;j
<numtri
/2;j
++)
343 OUT_RING(fantbl
[numtri
/2]&0xFFF);
347 static void nv04_render_quads_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
349 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
350 GLubyte
*vertptr
= (GLubyte
*)nmesa
->verts
;
351 GLuint vertsize
= nmesa
->vertex_size
;
352 const GLuint
* const elt
= TNL_CONTEXT(ctx
)->vb
.Elts
;
355 for(i
=start
;i
<count
;i
+=4)
357 (nouveauVertex
*)(vertptr
+elt
[i
+0]*vertsize
),
358 (nouveauVertex
*)(vertptr
+elt
[i
+1]*vertsize
),
359 (nouveauVertex
*)(vertptr
+elt
[i
+2]*vertsize
),
360 (nouveauVertex
*)(vertptr
+elt
[i
+3]*vertsize
)
364 static void nv04_render_noop_elts(GLcontext
*ctx
,GLuint start
,GLuint count
,GLuint flags
)
368 static void (*nv04_render_tab_elts
[GL_POLYGON
+2])(GLcontext
*,
373 nv04_render_points_elts
,
374 nv04_render_lines_elts
,
375 nv04_render_line_loop_elts
,
376 nv04_render_line_strip_elts
,
377 nv04_render_triangles_elts
,
378 nv04_render_tri_strip_elts
,
379 nv04_render_tri_fan_elts
,
380 nv04_render_quads_elts
,
381 nv04_render_tri_strip_elts
, // nv04_render_quad_strip_elts,
382 nv04_render_tri_fan_elts
, // nv04_render_poly_elts,
383 nv04_render_noop_elts
,
387 /**********************************************************************/
388 /* Choose render functions */
389 /**********************************************************************/
392 #define EMIT_ATTR( ATTR, STYLE ) \
394 nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = (ATTR); \
395 nmesa->vertex_attrs[nmesa->vertex_attr_count].format = (STYLE); \
396 nmesa->vertex_attr_count++; \
399 #define EMIT_PAD( N ) \
401 nmesa->vertex_attrs[nmesa->vertex_attr_count].attrib = 0; \
402 nmesa->vertex_attrs[nmesa->vertex_attr_count].format = EMIT_PAD; \
403 nmesa->vertex_attrs[nmesa->vertex_attr_count].offset = (N); \
404 nmesa->vertex_attr_count++; \
408 static void nv04ChooseRenderState(GLcontext
*ctx
)
410 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
412 tnl
->Driver
.Render
.PrimTabVerts
= nv04_render_tab_verts
;
413 tnl
->Driver
.Render
.PrimTabElts
= nv04_render_tab_elts
;
414 tnl
->Driver
.Render
.ClippedLine
= NULL
;
415 tnl
->Driver
.Render
.ClippedPolygon
= NULL
;
420 static inline void nv04OutputVertexFormat(struct nouveau_context
* nmesa
)
422 GLcontext
* ctx
=nmesa
->glCtx
;
423 DECLARE_RENDERINPUTS(index
);
426 * Tell t_vertex about the vertex format
428 RENDERINPUTS_COPY(index
, nmesa
->render_inputs_bitset
);
431 // FIXME : we use W instead of INVW, but since W=1 it doesn't matter
432 if (RENDERINPUTS_TEST(index
, _TNL_ATTRIB_POS
))
433 EMIT_ATTR(_TNL_ATTRIB_POS
,EMIT_4F_VIEWPORT
);
435 EMIT_PAD(4*sizeof(float));
438 if (RENDERINPUTS_TEST(index
, _TNL_ATTRIB_COLOR0
))
439 EMIT_ATTR(_TNL_ATTRIB_COLOR0
,EMIT_4UB_4F_ABGR
);
444 if (RENDERINPUTS_TEST(index
, _TNL_ATTRIB_COLOR1
))
445 EMIT_ATTR(_TNL_ATTRIB_COLOR1
,EMIT_4UB_4F_ABGR
);
450 if (RENDERINPUTS_TEST(index
, _TNL_ATTRIB_TEX0
))
451 EMIT_ATTR(_TNL_ATTRIB_TEX0
,EMIT_2F
);
453 EMIT_PAD(2*sizeof(float));
455 nmesa
->vertex_size
=_tnl_install_attrs( ctx
,
457 nmesa
->vertex_attr_count
,
458 ctx
->Viewport
._WindowMap
.m
, 0 );
462 static void nv04ChooseVertexState( GLcontext
*ctx
)
464 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
465 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
466 DECLARE_RENDERINPUTS(index
);
468 RENDERINPUTS_COPY(index
, tnl
->render_inputs_bitset
);
469 if (!RENDERINPUTS_EQUAL(index
, nmesa
->render_inputs_bitset
))
471 RENDERINPUTS_COPY(nmesa
->render_inputs_bitset
, index
);
472 nv04OutputVertexFormat(nmesa
);
477 /**********************************************************************/
478 /* High level hooks for t_vb_render.c */
479 /**********************************************************************/
482 static void nv04RenderStart(GLcontext
*ctx
)
484 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
486 if (nmesa
->new_state
) {
487 nmesa
->new_render_state
|= nmesa
->new_state
;
490 if (nmesa
->new_render_state
) {
491 nv04ChooseVertexState(ctx
);
492 nv04ChooseRenderState(ctx
);
493 nmesa
->new_render_state
= 0;
497 static void nv04RenderFinish(GLcontext
*ctx
)
502 /* System to flush dma and emit state changes based on the rasterized
505 void nv04RasterPrimitive(GLcontext
*ctx
,
509 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
511 assert (!nmesa
->new_state
);
513 if (hwprim
!= nmesa
->current_primitive
)
515 nmesa
->current_primitive
=hwprim
;
520 static const GLuint hw_prim
[GL_POLYGON
+1] = {
533 /* Callback for mesa:
535 static void nv04RenderPrimitive( GLcontext
*ctx
, GLuint prim
)
537 nv04RasterPrimitive( ctx
, prim
, hw_prim
[prim
] );
540 static void nv04ResetLineStipple( GLcontext
*ctx
)
542 /* FIXME do something here */
543 WARN_ONCE("Unimplemented nv04ResetLineStipple\n");
547 /**********************************************************************/
548 /* Initialization. */
549 /**********************************************************************/
551 void nv04TriInitFunctions(GLcontext
*ctx
)
553 struct nouveau_context
*nmesa
= NOUVEAU_CONTEXT(ctx
);
554 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
556 tnl
->Driver
.RunPipeline
= nouveauRunPipeline
;
557 tnl
->Driver
.Render
.Start
= nv04RenderStart
;
558 tnl
->Driver
.Render
.Finish
= nv04RenderFinish
;
559 tnl
->Driver
.Render
.PrimitiveNotify
= nv04RenderPrimitive
;
560 tnl
->Driver
.Render
.ResetLineStipple
= nv04ResetLineStipple
;
561 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
562 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
563 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
565 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12, 32 );
567 nmesa
->verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;