7fb91a0730bc6eb7d3be20e51fd9be2e5cbe6c39
[mesa.git] / src / mesa / drivers / dri / r200 / r200_swtcl.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c,v 1.5 2003/05/06 23:52:08 daenzer Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "mtypes.h"
38 #include "colormac.h"
39 #include "enums.h"
40 #include "image.h"
41 #include "imports.h"
42 #include "macros.h"
43
44 #include "swrast/s_context.h"
45 #include "swrast/s_fog.h"
46 #include "swrast_setup/swrast_setup.h"
47 #include "math/m_translate.h"
48 #include "tnl/tnl.h"
49 #include "tnl/t_context.h"
50 #include "tnl/t_pipeline.h"
51 #include "tnl/t_vtx_api.h"
52
53 #include "r200_context.h"
54 #include "r200_ioctl.h"
55 #include "r200_state.h"
56 #include "r200_swtcl.h"
57 #include "r200_tcl.h"
58
59
60 static void flush_last_swtcl_prim( r200ContextPtr rmesa );
61
62
63 /***********************************************************************
64 * Initialization
65 ***********************************************************************/
66
67 #define EMIT_ATTR( ATTR, STYLE, F0 ) \
68 do { \
69 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \
70 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
71 rmesa->swtcl.vertex_attr_count++; \
72 fmt_0 |= F0; \
73 } while (0)
74
75 #define EMIT_PAD( N ) \
76 do { \
77 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
78 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
79 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
80 rmesa->swtcl.vertex_attr_count++; \
81 } while (0)
82
83 static void r200SetVertexFormat( GLcontext *ctx )
84 {
85 r200ContextPtr rmesa = R200_CONTEXT( ctx );
86 TNLcontext *tnl = TNL_CONTEXT(ctx);
87 struct vertex_buffer *VB = &tnl->vb;
88 GLuint index = tnl->render_inputs;
89 int fmt_0 = 0;
90 int fmt_1 = 0;
91 int offset = 0;
92
93
94 /* Important:
95 */
96 if ( VB->NdcPtr != NULL ) {
97 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
98 }
99 else {
100 VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
101 }
102
103 assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
104 rmesa->swtcl.vertex_attr_count = 0;
105
106 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
107 * build up a hardware vertex.
108 */
109 if ( !rmesa->swtcl.needproj ) {
110 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 );
111 offset = 4;
112 }
113 else {
114 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 );
115 offset = 3;
116 }
117
118 rmesa->swtcl.coloroffset = offset;
119 #if MESA_LITTLE_ENDIAN
120 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
121 #else
122 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
123 #endif
124 offset += 1;
125
126 rmesa->swtcl.specoffset = 0;
127 if (index & (_TNL_BIT_COLOR1|_TNL_BIT_FOG)) {
128
129 #if MESA_LITTLE_ENDIAN
130 if (index & _TNL_BIT_COLOR1) {
131 rmesa->swtcl.specoffset = offset;
132 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
133 }
134 else {
135 EMIT_PAD( 3 );
136 }
137
138 if (index & _TNL_BIT_FOG) {
139 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
140 }
141 else {
142 EMIT_PAD( 1 );
143 }
144 #else
145 if (index & _TNL_BIT_FOG) {
146 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
147 }
148 else {
149 EMIT_PAD( 1 );
150 }
151
152 if (index & _TNL_BIT_COLOR1) {
153 rmesa->swtcl.specoffset = offset;
154 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
155 }
156 else {
157 EMIT_PAD( 3 );
158 }
159 #endif
160 }
161
162 if (index & _TNL_BITS_TEX_ANY) {
163 int i;
164
165 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
166 if (index & _TNL_BIT_TEX(i)) {
167 GLuint sz = VB->TexCoordPtr[i]->size;
168
169 fmt_1 |= sz << (3 * i);
170 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1, 0 );
171 }
172 }
173 }
174
175 if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
176 != R200_FOG_USE_SPEC_ALPHA ) {
177 R200_STATECHANGE( rmesa, ctx );
178 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
179 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
180 }
181
182 if ( rmesa->tnl_index != index ||
183 (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
184 (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
185 R200_NEWPRIM(rmesa);
186 R200_STATECHANGE( rmesa, vtx );
187 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
188 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
189
190 rmesa->swtcl.vertex_size =
191 _tnl_install_attrs( ctx,
192 rmesa->swtcl.vertex_attrs,
193 rmesa->swtcl.vertex_attr_count,
194 NULL, 0 );
195 rmesa->swtcl.vertex_size /= 4;
196 rmesa->tnl_index = index;
197 }
198 }
199
200
201 static void r200RenderStart( GLcontext *ctx )
202 {
203 r200ContextPtr rmesa = R200_CONTEXT( ctx );
204
205 r200SetVertexFormat( ctx );
206
207 if (rmesa->dma.flush != 0 &&
208 rmesa->dma.flush != flush_last_swtcl_prim)
209 rmesa->dma.flush( rmesa );
210 }
211
212
213 /**
214 * Set vertex state for SW TCL. The primary purpose of this function is to
215 * determine in advance whether or not the hardware can / should do the
216 * projection divide or Mesa should do it.
217 */
218 void r200ChooseVertexState( GLcontext *ctx )
219 {
220 r200ContextPtr rmesa = R200_CONTEXT( ctx );
221 TNLcontext *tnl = TNL_CONTEXT(ctx);
222
223 GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
224 GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
225
226 /* HW perspective divide is a win, but tiny vertex formats are a
227 * bigger one.
228 */
229 if ( ((tnl->render_inputs & _TNL_BITS_TEX_ANY) == 0)
230 || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
231 rmesa->swtcl.needproj = GL_TRUE;
232 vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
233 vap |= R200_VAP_FORCE_W_TO_ONE;
234 }
235 else {
236 rmesa->swtcl.needproj = GL_FALSE;
237 vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
238 vap &= ~R200_VAP_FORCE_W_TO_ONE;
239 }
240
241 _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj );
242
243 if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
244 R200_STATECHANGE( rmesa, vte );
245 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
246 }
247
248 if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
249 R200_STATECHANGE( rmesa, vap );
250 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
251 }
252 }
253
254
255 /* Flush vertices in the current dma region.
256 */
257 static void flush_last_swtcl_prim( r200ContextPtr rmesa )
258 {
259 if (R200_DEBUG & DEBUG_IOCTL)
260 fprintf(stderr, "%s\n", __FUNCTION__);
261
262 rmesa->dma.flush = 0;
263
264 if (rmesa->dma.current.buf) {
265 struct r200_dma_region *current = &rmesa->dma.current;
266 GLuint current_offset = (rmesa->r200Screen->gart_buffer_offset +
267 current->buf->buf->idx * RADEON_BUFFER_SIZE +
268 current->start);
269
270 assert (!(rmesa->swtcl.hw_primitive & R200_VF_PRIM_WALK_IND));
271
272 assert (current->start +
273 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
274 current->ptr);
275
276 if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
277 r200EnsureCmdBufSpace( rmesa, VERT_AOS_BUFSZ +
278 rmesa->hw.max_state_size + VBUF_BUFSZ );
279 r200EmitVertexAOS( rmesa,
280 rmesa->swtcl.vertex_size,
281 current_offset);
282
283 r200EmitVbufPrim( rmesa,
284 rmesa->swtcl.hw_primitive,
285 rmesa->swtcl.numverts);
286 }
287
288 rmesa->swtcl.numverts = 0;
289 current->start = current->ptr;
290 }
291 }
292
293
294 /* Alloc space in the current dma region.
295 */
296 static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
297 int nverts, int vsize )
298 {
299 GLuint bytes = vsize * nverts;
300
301 if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
302 r200RefillCurrentDmaRegion( rmesa );
303
304 if (!rmesa->dma.flush) {
305 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
306 rmesa->dma.flush = flush_last_swtcl_prim;
307 }
308
309 ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
310 ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
311 ASSERT( rmesa->dma.current.start +
312 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
313 rmesa->dma.current.ptr );
314
315
316 {
317 GLubyte *head = (GLubyte *) (rmesa->dma.current.address + rmesa->dma.current.ptr);
318 rmesa->dma.current.ptr += bytes;
319 rmesa->swtcl.numverts += nverts;
320 return head;
321 }
322
323 }
324
325
326 /**************************************************************************/
327
328
329 static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
330 R200_VF_PRIM_POINTS,
331 R200_VF_PRIM_LINES,
332 R200_VF_PRIM_LINES,
333 R200_VF_PRIM_LINES,
334 R200_VF_PRIM_TRIANGLES,
335 R200_VF_PRIM_TRIANGLES,
336 R200_VF_PRIM_TRIANGLES,
337 R200_VF_PRIM_TRIANGLES,
338 R200_VF_PRIM_TRIANGLES,
339 R200_VF_PRIM_TRIANGLES
340 };
341
342 static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
343 static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
344 static void r200ResetLineStipple( GLcontext *ctx );
345
346 /***********************************************************************
347 * Emit primitives as inline vertices *
348 ***********************************************************************/
349
350 #define HAVE_POINTS 1
351 #define HAVE_LINES 1
352 #define HAVE_LINE_STRIPS 1
353 #define HAVE_TRIANGLES 1
354 #define HAVE_TRI_STRIPS 1
355 #define HAVE_TRI_STRIP_1 0
356 #define HAVE_TRI_FANS 1
357 #define HAVE_QUADS 0
358 #define HAVE_QUAD_STRIPS 0
359 #define HAVE_POLYGONS 1
360 #define HAVE_ELTS 0
361
362 #undef LOCAL_VARS
363 #undef ALLOC_VERTS
364 #define CTX_ARG r200ContextPtr rmesa
365 #define CTX_ARG2 rmesa
366 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
367 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
368 #define LOCAL_VARS \
369 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
370 const char *r200verts = (char *)rmesa->swtcl.verts;
371 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
372 #define VERTEX r200Vertex
373 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
374
375 #undef TAG
376 #define TAG(x) r200_##x
377 #include "tnl_dd/t_dd_triemit.h"
378
379
380 /***********************************************************************
381 * Macros for t_dd_tritmp.h to draw basic primitives *
382 ***********************************************************************/
383
384 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
385 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
386 #define LINE( a, b ) r200_line( rmesa, a, b )
387 #define POINT( a ) r200_point( rmesa, a )
388
389 /***********************************************************************
390 * Build render functions from dd templates *
391 ***********************************************************************/
392
393 #define R200_TWOSIDE_BIT 0x01
394 #define R200_UNFILLED_BIT 0x02
395 #define R200_MAX_TRIFUNC 0x04
396
397
398 static struct {
399 tnl_points_func points;
400 tnl_line_func line;
401 tnl_triangle_func triangle;
402 tnl_quad_func quad;
403 } rast_tab[R200_MAX_TRIFUNC];
404
405
406 #define DO_FALLBACK 0
407 #define DO_UNFILLED (IND & R200_UNFILLED_BIT)
408 #define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
409 #define DO_FLAT 0
410 #define DO_OFFSET 0
411 #define DO_TRI 1
412 #define DO_QUAD 1
413 #define DO_LINE 1
414 #define DO_POINTS 1
415 #define DO_FULL_QUAD 1
416
417 #define HAVE_RGBA 1
418 #define HAVE_SPEC 1
419 #define HAVE_BACK_COLORS 0
420 #define HAVE_HW_FLATSHADE 1
421 #define TAB rast_tab
422
423 #define DEPTH_SCALE 1.0
424 #define UNFILLED_TRI unfilled_tri
425 #define UNFILLED_QUAD unfilled_quad
426 #define VERT_X(_v) _v->v.x
427 #define VERT_Y(_v) _v->v.y
428 #define VERT_Z(_v) _v->v.z
429 #define AREA_IS_CCW( a ) (a < 0)
430 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
431
432 #define VERT_SET_RGBA( v, c ) \
433 do { \
434 r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
435 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
436 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
437 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
438 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
439 } while (0)
440
441 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
442
443 #define VERT_SET_SPEC( v, c ) \
444 do { \
445 if (specoffset) { \
446 r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
447 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
448 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
449 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
450 } \
451 } while (0)
452 #define VERT_COPY_SPEC( v0, v1 ) \
453 do { \
454 if (specoffset) { \
455 r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
456 r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
457 spec0->red = spec1->red; \
458 spec0->green = spec1->green; \
459 spec0->blue = spec1->blue; \
460 } \
461 } while (0)
462
463 /* These don't need LE32_TO_CPU() as they used to save and restore
464 * colors which are already in the correct format.
465 */
466 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
467 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
468 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
469 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
470
471 #undef LOCAL_VARS
472 #undef TAG
473 #undef INIT
474
475 #define LOCAL_VARS(n) \
476 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
477 GLuint color[n], spec[n]; \
478 GLuint coloroffset = rmesa->swtcl.coloroffset; \
479 GLuint specoffset = rmesa->swtcl.specoffset; \
480 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
481
482 /***********************************************************************
483 * Helpers for rendering unfilled primitives *
484 ***********************************************************************/
485
486 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
487 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
488 #undef TAG
489 #define TAG(x) x
490 #include "tnl_dd/t_dd_unfilled.h"
491 #undef IND
492
493
494 /***********************************************************************
495 * Generate GL render functions *
496 ***********************************************************************/
497
498
499 #define IND (0)
500 #define TAG(x) x
501 #include "tnl_dd/t_dd_tritmp.h"
502
503 #define IND (R200_TWOSIDE_BIT)
504 #define TAG(x) x##_twoside
505 #include "tnl_dd/t_dd_tritmp.h"
506
507 #define IND (R200_UNFILLED_BIT)
508 #define TAG(x) x##_unfilled
509 #include "tnl_dd/t_dd_tritmp.h"
510
511 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
512 #define TAG(x) x##_twoside_unfilled
513 #include "tnl_dd/t_dd_tritmp.h"
514
515
516 static void init_rast_tab( void )
517 {
518 init();
519 init_twoside();
520 init_unfilled();
521 init_twoside_unfilled();
522 }
523
524 /**********************************************************************/
525 /* Render unclipped begin/end objects */
526 /**********************************************************************/
527
528 #define RENDER_POINTS( start, count ) \
529 for ( ; start < count ; start++) \
530 r200_point( rmesa, VERT(start) )
531 #define RENDER_LINE( v0, v1 ) \
532 r200_line( rmesa, VERT(v0), VERT(v1) )
533 #define RENDER_TRI( v0, v1, v2 ) \
534 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
535 #define RENDER_QUAD( v0, v1, v2, v3 ) \
536 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
537 #define INIT(x) do { \
538 r200RenderPrimitive( ctx, x ); \
539 } while (0)
540 #undef LOCAL_VARS
541 #define LOCAL_VARS \
542 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
543 const GLuint vertsize = rmesa->swtcl.vertex_size; \
544 const char *r200verts = (char *)rmesa->swtcl.verts; \
545 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
546 const GLboolean stipple = ctx->Line.StippleFlag; \
547 (void) elt; (void) stipple;
548 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
549 #define RESET_OCCLUSION
550 #define PRESERVE_VB_DEFS
551 #define ELT(x) (x)
552 #define TAG(x) r200_##x##_verts
553 #include "tnl/t_vb_rendertmp.h"
554 #undef ELT
555 #undef TAG
556 #define TAG(x) r200_##x##_elts
557 #define ELT(x) elt[x]
558 #include "tnl/t_vb_rendertmp.h"
559
560
561
562 /**********************************************************************/
563 /* Choose render functions */
564 /**********************************************************************/
565
566 void r200ChooseRenderState( GLcontext *ctx )
567 {
568 TNLcontext *tnl = TNL_CONTEXT(ctx);
569 r200ContextPtr rmesa = R200_CONTEXT(ctx);
570 GLuint index = 0;
571 GLuint flags = ctx->_TriangleCaps;
572
573 if (!rmesa->TclFallback || rmesa->Fallback)
574 return;
575
576 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R200_TWOSIDE_BIT;
577 if (flags & DD_TRI_UNFILLED) index |= R200_UNFILLED_BIT;
578
579 if (index != rmesa->swtcl.RenderIndex) {
580 tnl->Driver.Render.Points = rast_tab[index].points;
581 tnl->Driver.Render.Line = rast_tab[index].line;
582 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
583 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
584 tnl->Driver.Render.Quad = rast_tab[index].quad;
585
586 if (index == 0) {
587 tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts;
588 tnl->Driver.Render.PrimTabElts = r200_render_tab_elts;
589 tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly;
590 } else {
591 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
592 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
593 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
594 }
595
596 rmesa->swtcl.RenderIndex = index;
597 }
598 }
599
600
601 /**********************************************************************/
602 /* High level hooks for t_vb_render.c */
603 /**********************************************************************/
604
605
606 static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
607 {
608 r200ContextPtr rmesa = R200_CONTEXT(ctx);
609
610 if (rmesa->swtcl.hw_primitive != hwprim) {
611 R200_NEWPRIM( rmesa );
612 rmesa->swtcl.hw_primitive = hwprim;
613 }
614 }
615
616 static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
617 {
618 r200ContextPtr rmesa = R200_CONTEXT(ctx);
619 rmesa->swtcl.render_primitive = prim;
620 if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
621 r200RasterPrimitive( ctx, reduced_hw_prim[prim] );
622 }
623
624 static void r200RenderFinish( GLcontext *ctx )
625 {
626 }
627
628 static void r200ResetLineStipple( GLcontext *ctx )
629 {
630 r200ContextPtr rmesa = R200_CONTEXT(ctx);
631 R200_STATECHANGE( rmesa, lin );
632 }
633
634
635 /**********************************************************************/
636 /* Transition to/from hardware rasterization. */
637 /**********************************************************************/
638
639 static const char * const fallbackStrings[] = {
640 "Texture mode",
641 "glDrawBuffer(GL_FRONT_AND_BACK)",
642 "glEnable(GL_STENCIL) without hw stencil buffer",
643 "glRenderMode(selection or feedback)",
644 "glBlendEquation",
645 "glBlendFunc(mode != ADD)",
646 "R200_NO_RAST",
647 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
648 };
649
650
651 static const char *getFallbackString(GLuint bit)
652 {
653 int i = 0;
654 while (bit > 1) {
655 i++;
656 bit >>= 1;
657 }
658 return fallbackStrings[i];
659 }
660
661
662 void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
663 {
664 r200ContextPtr rmesa = R200_CONTEXT(ctx);
665 TNLcontext *tnl = TNL_CONTEXT(ctx);
666 GLuint oldfallback = rmesa->Fallback;
667
668 if (mode) {
669 rmesa->Fallback |= bit;
670 if (oldfallback == 0) {
671 R200_FIREVERTICES( rmesa );
672 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
673 _swsetup_Wakeup( ctx );
674 _tnl_need_projected_coords( ctx, GL_TRUE );
675 rmesa->swtcl.RenderIndex = ~0;
676 if (R200_DEBUG & DEBUG_FALLBACKS) {
677 fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
678 bit, getFallbackString(bit));
679 }
680 }
681 }
682 else {
683 rmesa->Fallback &= ~bit;
684 if (oldfallback == bit) {
685
686 _swrast_flush( ctx );
687 tnl->Driver.Render.Start = r200RenderStart;
688 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
689 tnl->Driver.Render.Finish = r200RenderFinish;
690
691 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
692 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
693 tnl->Driver.Render.Interp = _tnl_interp;
694
695 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
696 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
697 if (rmesa->TclFallback) {
698 /* These are already done if rmesa->TclFallback goes to
699 * zero above. But not if it doesn't (R200_NO_TCL for
700 * example?)
701 */
702 r200ChooseVertexState( ctx );
703 r200ChooseRenderState( ctx );
704 }
705 if (R200_DEBUG & DEBUG_FALLBACKS) {
706 fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
707 bit, getFallbackString(bit));
708 }
709 }
710 }
711 }
712
713
714
715
716 /**
717 * Cope with depth operations by drawing individual pixels as points.
718 *
719 * \todo
720 * The way the vertex state is set in this routine is hokey. It seems to
721 * work, but it's very hackish. This whole routine is pretty hackish. If
722 * the bitmap is small enough, it seems like it would be faster to copy it
723 * to AGP memory and use it as a non-power-of-two texture (i.e.,
724 * NV_texture_rectangle).
725 */
726 void
727 r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
728 GLsizei width, GLsizei height,
729 const struct gl_pixelstore_attrib *unpack,
730 const GLubyte *bitmap )
731 {
732 r200ContextPtr rmesa = R200_CONTEXT(ctx);
733 const GLfloat *rc = ctx->Current.RasterColor;
734 GLint row, col;
735 r200Vertex vert;
736 GLuint orig_vte;
737 GLuint h;
738
739
740 /* Turn off tcl.
741 */
742 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
743
744 /* Choose tiny vertex format
745 */
746 {
747 const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0
748 | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT);
749 const GLuint fmt_1 = 0;
750 GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
751 GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
752
753 vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
754 vap &= ~R200_VAP_FORCE_W_TO_ONE;
755
756 rmesa->swtcl.vertex_size = 5;
757
758 if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
759 || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
760 R200_NEWPRIM(rmesa);
761 R200_STATECHANGE( rmesa, vtx );
762 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
763 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
764 }
765
766 if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
767 R200_STATECHANGE( rmesa, vte );
768 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
769 }
770
771 if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
772 R200_STATECHANGE( rmesa, vap );
773 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
774 }
775 }
776
777 /* Ready for point primitives:
778 */
779 r200RenderPrimitive( ctx, GL_POINTS );
780
781 /* Turn off the hw viewport transformation:
782 */
783 R200_STATECHANGE( rmesa, vte );
784 orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
785 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA |
786 R200_VPORT_Y_SCALE_ENA |
787 R200_VPORT_Z_SCALE_ENA |
788 R200_VPORT_X_OFFSET_ENA |
789 R200_VPORT_Y_OFFSET_ENA |
790 R200_VPORT_Z_OFFSET_ENA);
791
792 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
793 */
794
795
796 /* Populate the vertex
797 *
798 * Incorporate FOG into RGBA
799 */
800 if (ctx->Fog.Enabled) {
801 const GLfloat *fc = ctx->Fog.Color;
802 GLfloat color[4];
803 GLfloat f;
804
805 if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
806 f = _swrast_z_to_fogfactor(ctx, ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
807 else
808 f = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
809
810 color[0] = f * rc[0] + (1.F - f) * fc[0];
811 color[1] = f * rc[1] + (1.F - f) * fc[1];
812 color[2] = f * rc[2] + (1.F - f) * fc[2];
813 color[3] = rc[3];
814
815 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, color[0]);
816 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]);
817 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, color[2]);
818 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]);
819 }
820 else {
821 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, rc[0]);
822 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]);
823 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, rc[2]);
824 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]);
825 }
826
827
828 vert.tv.z = ctx->Current.RasterPos[2];
829
830
831 /* Update window height
832 */
833 LOCK_HARDWARE( rmesa );
834 UNLOCK_HARDWARE( rmesa );
835 h = rmesa->dri.drawable->h + rmesa->dri.drawable->y;
836 px += rmesa->dri.drawable->x;
837
838 /* Clipping handled by existing mechansims in r200_ioctl.c?
839 */
840 for (row=0; row<height; row++) {
841 const GLubyte *src = (const GLubyte *)
842 _mesa_image_address( unpack, bitmap, width, height,
843 GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
844
845 if (unpack->LsbFirst) {
846 /* Lsb first */
847 GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
848 for (col=0; col<width; col++) {
849 if (*src & mask) {
850 vert.tv.x = px+col;
851 vert.tv.y = h - (py+row) - 1;
852 r200_point( rmesa, &vert );
853 }
854 src += (mask >> 7);
855 mask = ((mask << 1) & 0xff) | (mask >> 7);
856 }
857
858 /* get ready for next row */
859 if (mask != 1)
860 src++;
861 }
862 else {
863 /* Msb first */
864 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
865 for (col=0; col<width; col++) {
866 if (*src & mask) {
867 vert.tv.x = px+col;
868 vert.tv.y = h - (py+row) - 1;
869 r200_point( rmesa, &vert );
870 }
871 src += mask & 1;
872 mask = ((mask << 7) & 0xff) | (mask >> 1);
873 }
874 /* get ready for next row */
875 if (mask != 128)
876 src++;
877 }
878 }
879
880 /* Fire outstanding vertices, restore state
881 */
882 R200_STATECHANGE( rmesa, vte );
883 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte;
884
885 /* Unfallback
886 */
887 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 );
888
889 /* Need to restore vertexformat?
890 */
891 if (rmesa->TclFallback)
892 r200ChooseVertexState( ctx );
893 }
894
895
896 void r200FlushVertices( GLcontext *ctx, GLuint flags )
897 {
898 _tnl_FlushVertices( ctx, flags );
899
900 if (flags & FLUSH_STORED_VERTICES)
901 R200_NEWPRIM( R200_CONTEXT( ctx ) );
902 }
903
904 /**********************************************************************/
905 /* Initialization. */
906 /**********************************************************************/
907
908 void r200InitSwtcl( GLcontext *ctx )
909 {
910 TNLcontext *tnl = TNL_CONTEXT(ctx);
911 r200ContextPtr rmesa = R200_CONTEXT(ctx);
912 static int firsttime = 1;
913
914 if (firsttime) {
915 init_rast_tab();
916 firsttime = 0;
917 }
918
919 tnl->Driver.Render.Start = r200RenderStart;
920 tnl->Driver.Render.Finish = r200RenderFinish;
921 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
922 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
923 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
924 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
925 tnl->Driver.Render.Interp = _tnl_interp;
926
927 /* FIXME: what are these numbers? */
928 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
929 36 * sizeof(GLfloat) );
930
931 rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
932 rmesa->swtcl.RenderIndex = ~0;
933 rmesa->swtcl.render_primitive = GL_TRIANGLES;
934 rmesa->swtcl.hw_primitive = 0;
935 }
936
937
938 void r200DestroySwtcl( GLcontext *ctx )
939 {
940 r200ContextPtr rmesa = R200_CONTEXT(ctx);
941
942 if (rmesa->swtcl.indexed_verts.buf)
943 r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ );
944 }