Big-endian fixes for R200 sw TCL path.
[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
176
177 if ( rmesa->tnl_index != index ||
178 (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
179 (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
180 R200_NEWPRIM(rmesa);
181 R200_STATECHANGE( rmesa, vtx );
182 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
183 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
184
185 rmesa->swtcl.vertex_size =
186 _tnl_install_attrs( ctx,
187 rmesa->swtcl.vertex_attrs,
188 rmesa->swtcl.vertex_attr_count,
189 NULL, 0 );
190 rmesa->swtcl.vertex_size /= 4;
191 rmesa->tnl_index = index;
192 }
193 }
194
195
196 static void r200RenderStart( GLcontext *ctx )
197 {
198 r200ContextPtr rmesa = R200_CONTEXT( ctx );
199
200 r200SetVertexFormat( ctx );
201
202 if (rmesa->dma.flush != 0 &&
203 rmesa->dma.flush != flush_last_swtcl_prim)
204 rmesa->dma.flush( rmesa );
205 }
206
207
208 /**
209 * Set vertex state for SW TCL. The primary purpose of this function is to
210 * determine in advance whether or not the hardware can / should do the
211 * projection divide or Mesa should do it.
212 */
213 void r200ChooseVertexState( GLcontext *ctx )
214 {
215 r200ContextPtr rmesa = R200_CONTEXT( ctx );
216 TNLcontext *tnl = TNL_CONTEXT(ctx);
217
218 GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
219 GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
220
221 /* HW perspective divide is a win, but tiny vertex formats are a
222 * bigger one.
223 */
224 if ( ((tnl->render_inputs & _TNL_BITS_TEX_ANY) == 0)
225 || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
226 rmesa->swtcl.needproj = GL_TRUE;
227 vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
228 vap |= R200_VAP_FORCE_W_TO_ONE;
229 }
230 else {
231 rmesa->swtcl.needproj = GL_FALSE;
232 vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
233 vap &= ~R200_VAP_FORCE_W_TO_ONE;
234 }
235
236 _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj );
237
238 if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
239 R200_STATECHANGE( rmesa, vte );
240 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
241 }
242
243 if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
244 R200_STATECHANGE( rmesa, vap );
245 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
246 }
247 }
248
249
250 /* Flush vertices in the current dma region.
251 */
252 static void flush_last_swtcl_prim( r200ContextPtr rmesa )
253 {
254 if (R200_DEBUG & DEBUG_IOCTL)
255 fprintf(stderr, "%s\n", __FUNCTION__);
256
257 rmesa->dma.flush = 0;
258
259 if (rmesa->dma.current.buf) {
260 struct r200_dma_region *current = &rmesa->dma.current;
261 GLuint current_offset = (rmesa->r200Screen->gart_buffer_offset +
262 current->buf->buf->idx * RADEON_BUFFER_SIZE +
263 current->start);
264
265 assert (!(rmesa->swtcl.hw_primitive & R200_VF_PRIM_WALK_IND));
266
267 assert (current->start +
268 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
269 current->ptr);
270
271 if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
272 r200EnsureCmdBufSpace( rmesa, VERT_AOS_BUFSZ +
273 rmesa->hw.max_state_size + VBUF_BUFSZ );
274 r200EmitVertexAOS( rmesa,
275 rmesa->swtcl.vertex_size,
276 current_offset);
277
278 r200EmitVbufPrim( rmesa,
279 rmesa->swtcl.hw_primitive,
280 rmesa->swtcl.numverts);
281 }
282
283 rmesa->swtcl.numverts = 0;
284 current->start = current->ptr;
285 }
286 }
287
288
289 /* Alloc space in the current dma region.
290 */
291 static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
292 int nverts, int vsize )
293 {
294 GLuint bytes = vsize * nverts;
295
296 if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
297 r200RefillCurrentDmaRegion( rmesa );
298
299 if (!rmesa->dma.flush) {
300 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
301 rmesa->dma.flush = flush_last_swtcl_prim;
302 }
303
304 ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
305 ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
306 ASSERT( rmesa->dma.current.start +
307 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
308 rmesa->dma.current.ptr );
309
310
311 {
312 GLubyte *head = (GLubyte *) (rmesa->dma.current.address + rmesa->dma.current.ptr);
313 rmesa->dma.current.ptr += bytes;
314 rmesa->swtcl.numverts += nverts;
315 return head;
316 }
317
318 }
319
320
321 /**************************************************************************/
322
323
324 static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
325 R200_VF_PRIM_POINTS,
326 R200_VF_PRIM_LINES,
327 R200_VF_PRIM_LINES,
328 R200_VF_PRIM_LINES,
329 R200_VF_PRIM_TRIANGLES,
330 R200_VF_PRIM_TRIANGLES,
331 R200_VF_PRIM_TRIANGLES,
332 R200_VF_PRIM_TRIANGLES,
333 R200_VF_PRIM_TRIANGLES,
334 R200_VF_PRIM_TRIANGLES
335 };
336
337 static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
338 static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
339 static void r200ResetLineStipple( GLcontext *ctx );
340
341 /***********************************************************************
342 * Emit primitives as inline vertices *
343 ***********************************************************************/
344
345 #define HAVE_POINTS 1
346 #define HAVE_LINES 1
347 #define HAVE_LINE_STRIPS 1
348 #define HAVE_TRIANGLES 1
349 #define HAVE_TRI_STRIPS 1
350 #define HAVE_TRI_STRIP_1 0
351 #define HAVE_TRI_FANS 1
352 #define HAVE_QUADS 0
353 #define HAVE_QUAD_STRIPS 0
354 #define HAVE_POLYGONS 1
355 #define HAVE_ELTS 0
356
357 #undef LOCAL_VARS
358 #undef ALLOC_VERTS
359 #define CTX_ARG r200ContextPtr rmesa
360 #define CTX_ARG2 rmesa
361 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
362 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
363 #define LOCAL_VARS \
364 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
365 const char *r200verts = (char *)rmesa->swtcl.verts;
366 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
367 #define VERTEX r200Vertex
368 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
369
370 #undef TAG
371 #define TAG(x) r200_##x
372 #include "tnl_dd/t_dd_triemit.h"
373
374
375 /***********************************************************************
376 * Macros for t_dd_tritmp.h to draw basic primitives *
377 ***********************************************************************/
378
379 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
380 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
381 #define LINE( a, b ) r200_line( rmesa, a, b )
382 #define POINT( a ) r200_point( rmesa, a )
383
384 /***********************************************************************
385 * Build render functions from dd templates *
386 ***********************************************************************/
387
388 #define R200_TWOSIDE_BIT 0x01
389 #define R200_UNFILLED_BIT 0x02
390 #define R200_MAX_TRIFUNC 0x04
391
392
393 static struct {
394 tnl_points_func points;
395 tnl_line_func line;
396 tnl_triangle_func triangle;
397 tnl_quad_func quad;
398 } rast_tab[R200_MAX_TRIFUNC];
399
400
401 #define DO_FALLBACK 0
402 #define DO_UNFILLED (IND & R200_UNFILLED_BIT)
403 #define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
404 #define DO_FLAT 0
405 #define DO_OFFSET 0
406 #define DO_TRI 1
407 #define DO_QUAD 1
408 #define DO_LINE 1
409 #define DO_POINTS 1
410 #define DO_FULL_QUAD 1
411
412 #define HAVE_RGBA 1
413 #define HAVE_SPEC 1
414 #define HAVE_BACK_COLORS 0
415 #define HAVE_HW_FLATSHADE 1
416 #define TAB rast_tab
417
418 #define DEPTH_SCALE 1.0
419 #define UNFILLED_TRI unfilled_tri
420 #define UNFILLED_QUAD unfilled_quad
421 #define VERT_X(_v) _v->v.x
422 #define VERT_Y(_v) _v->v.y
423 #define VERT_Z(_v) _v->v.z
424 #define AREA_IS_CCW( a ) (a < 0)
425 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
426
427 #define VERT_SET_RGBA( v, c ) \
428 do { \
429 r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
430 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
431 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
432 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
433 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
434 } while (0)
435
436 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
437
438 #define VERT_SET_SPEC( v, c ) \
439 do { \
440 if (specoffset) { \
441 r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
442 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
443 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
444 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
445 } \
446 } while (0)
447 #define VERT_COPY_SPEC( v0, v1 ) \
448 do { \
449 if (specoffset) { \
450 r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
451 r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
452 spec0->red = spec1->red; \
453 spec0->green = spec1->green; \
454 spec0->blue = spec1->blue; \
455 } \
456 } while (0)
457
458 /* These don't need LE32_TO_CPU() as they used to save and restore
459 * colors which are already in the correct format.
460 */
461 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
462 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
463 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
464 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
465
466 #undef LOCAL_VARS
467 #undef TAG
468 #undef INIT
469
470 #define LOCAL_VARS(n) \
471 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
472 GLuint color[n], spec[n]; \
473 GLuint coloroffset = rmesa->swtcl.coloroffset; \
474 GLuint specoffset = rmesa->swtcl.specoffset; \
475 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
476
477 /***********************************************************************
478 * Helpers for rendering unfilled primitives *
479 ***********************************************************************/
480
481 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
482 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
483 #undef TAG
484 #define TAG(x) x
485 #include "tnl_dd/t_dd_unfilled.h"
486 #undef IND
487
488
489 /***********************************************************************
490 * Generate GL render functions *
491 ***********************************************************************/
492
493
494 #define IND (0)
495 #define TAG(x) x
496 #include "tnl_dd/t_dd_tritmp.h"
497
498 #define IND (R200_TWOSIDE_BIT)
499 #define TAG(x) x##_twoside
500 #include "tnl_dd/t_dd_tritmp.h"
501
502 #define IND (R200_UNFILLED_BIT)
503 #define TAG(x) x##_unfilled
504 #include "tnl_dd/t_dd_tritmp.h"
505
506 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
507 #define TAG(x) x##_twoside_unfilled
508 #include "tnl_dd/t_dd_tritmp.h"
509
510
511 static void init_rast_tab( void )
512 {
513 init();
514 init_twoside();
515 init_unfilled();
516 init_twoside_unfilled();
517 }
518
519 /**********************************************************************/
520 /* Render unclipped begin/end objects */
521 /**********************************************************************/
522
523 #define RENDER_POINTS( start, count ) \
524 for ( ; start < count ; start++) \
525 r200_point( rmesa, VERT(start) )
526 #define RENDER_LINE( v0, v1 ) \
527 r200_line( rmesa, VERT(v0), VERT(v1) )
528 #define RENDER_TRI( v0, v1, v2 ) \
529 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
530 #define RENDER_QUAD( v0, v1, v2, v3 ) \
531 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
532 #define INIT(x) do { \
533 r200RenderPrimitive( ctx, x ); \
534 } while (0)
535 #undef LOCAL_VARS
536 #define LOCAL_VARS \
537 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
538 const GLuint vertsize = rmesa->swtcl.vertex_size; \
539 const char *r200verts = (char *)rmesa->swtcl.verts; \
540 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
541 const GLboolean stipple = ctx->Line.StippleFlag; \
542 (void) elt; (void) stipple;
543 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
544 #define RESET_OCCLUSION
545 #define PRESERVE_VB_DEFS
546 #define ELT(x) (x)
547 #define TAG(x) r200_##x##_verts
548 #include "tnl/t_vb_rendertmp.h"
549 #undef ELT
550 #undef TAG
551 #define TAG(x) r200_##x##_elts
552 #define ELT(x) elt[x]
553 #include "tnl/t_vb_rendertmp.h"
554
555
556
557 /**********************************************************************/
558 /* Choose render functions */
559 /**********************************************************************/
560
561 void r200ChooseRenderState( GLcontext *ctx )
562 {
563 TNLcontext *tnl = TNL_CONTEXT(ctx);
564 r200ContextPtr rmesa = R200_CONTEXT(ctx);
565 GLuint index = 0;
566 GLuint flags = ctx->_TriangleCaps;
567
568 if (!rmesa->TclFallback || rmesa->Fallback)
569 return;
570
571 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R200_TWOSIDE_BIT;
572 if (flags & DD_TRI_UNFILLED) index |= R200_UNFILLED_BIT;
573
574 if (index != rmesa->swtcl.RenderIndex) {
575 tnl->Driver.Render.Points = rast_tab[index].points;
576 tnl->Driver.Render.Line = rast_tab[index].line;
577 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
578 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
579 tnl->Driver.Render.Quad = rast_tab[index].quad;
580
581 if (index == 0) {
582 tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts;
583 tnl->Driver.Render.PrimTabElts = r200_render_tab_elts;
584 tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly;
585 } else {
586 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
587 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
588 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
589 }
590
591 rmesa->swtcl.RenderIndex = index;
592 }
593 }
594
595
596 /**********************************************************************/
597 /* High level hooks for t_vb_render.c */
598 /**********************************************************************/
599
600
601 static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
602 {
603 r200ContextPtr rmesa = R200_CONTEXT(ctx);
604
605 if (rmesa->swtcl.hw_primitive != hwprim) {
606 R200_NEWPRIM( rmesa );
607 rmesa->swtcl.hw_primitive = hwprim;
608 }
609 }
610
611 static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
612 {
613 r200ContextPtr rmesa = R200_CONTEXT(ctx);
614 rmesa->swtcl.render_primitive = prim;
615 if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
616 r200RasterPrimitive( ctx, reduced_hw_prim[prim] );
617 }
618
619 static void r200RenderFinish( GLcontext *ctx )
620 {
621 }
622
623 static void r200ResetLineStipple( GLcontext *ctx )
624 {
625 r200ContextPtr rmesa = R200_CONTEXT(ctx);
626 R200_STATECHANGE( rmesa, lin );
627 }
628
629
630 /**********************************************************************/
631 /* Transition to/from hardware rasterization. */
632 /**********************************************************************/
633
634 static const char * const fallbackStrings[] = {
635 "Texture mode",
636 "glDrawBuffer(GL_FRONT_AND_BACK)",
637 "glEnable(GL_STENCIL) without hw stencil buffer",
638 "glRenderMode(selection or feedback)",
639 "glBlendEquation",
640 "glBlendFunc(mode != ADD)",
641 "R200_NO_RAST",
642 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
643 };
644
645
646 static const char *getFallbackString(GLuint bit)
647 {
648 int i = 0;
649 while (bit > 1) {
650 i++;
651 bit >>= 1;
652 }
653 return fallbackStrings[i];
654 }
655
656
657 void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
658 {
659 r200ContextPtr rmesa = R200_CONTEXT(ctx);
660 TNLcontext *tnl = TNL_CONTEXT(ctx);
661 GLuint oldfallback = rmesa->Fallback;
662
663 if (mode) {
664 rmesa->Fallback |= bit;
665 if (oldfallback == 0) {
666 R200_FIREVERTICES( rmesa );
667 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
668 _swsetup_Wakeup( ctx );
669 _tnl_need_projected_coords( ctx, GL_TRUE );
670 rmesa->swtcl.RenderIndex = ~0;
671 if (R200_DEBUG & DEBUG_FALLBACKS) {
672 fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
673 bit, getFallbackString(bit));
674 }
675 }
676 }
677 else {
678 rmesa->Fallback &= ~bit;
679 if (oldfallback == bit) {
680
681 _swrast_flush( ctx );
682 tnl->Driver.Render.Start = r200RenderStart;
683 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
684 tnl->Driver.Render.Finish = r200RenderFinish;
685
686 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
687 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
688 tnl->Driver.Render.Interp = _tnl_interp;
689
690 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
691 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
692 if (rmesa->TclFallback) {
693 /* These are already done if rmesa->TclFallback goes to
694 * zero above. But not if it doesn't (R200_NO_TCL for
695 * example?)
696 */
697 r200ChooseVertexState( ctx );
698 r200ChooseRenderState( ctx );
699 }
700 if (R200_DEBUG & DEBUG_FALLBACKS) {
701 fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
702 bit, getFallbackString(bit));
703 }
704 }
705 }
706 }
707
708
709
710
711 /**
712 * Cope with depth operations by drawing individual pixels as points.
713 *
714 * \todo
715 * The way the vertex state is set in this routine is hokey. It seems to
716 * work, but it's very hackish. This whole routine is pretty hackish. If
717 * the bitmap is small enough, it seems like it would be faster to copy it
718 * to AGP memory and use it as a non-power-of-two texture (i.e.,
719 * NV_texture_rectangle).
720 */
721 void
722 r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
723 GLsizei width, GLsizei height,
724 const struct gl_pixelstore_attrib *unpack,
725 const GLubyte *bitmap )
726 {
727 r200ContextPtr rmesa = R200_CONTEXT(ctx);
728 const GLfloat *rc = ctx->Current.RasterColor;
729 GLint row, col;
730 r200Vertex vert;
731 GLuint orig_vte;
732 GLuint h;
733
734
735 /* Turn off tcl.
736 */
737 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
738
739 /* Choose tiny vertex format
740 */
741 {
742 const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0
743 | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT);
744 const GLuint fmt_1 = 0;
745 GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
746 GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
747
748 vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
749 vap &= ~R200_VAP_FORCE_W_TO_ONE;
750
751 rmesa->swtcl.vertex_size = 5;
752
753 if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
754 || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
755 R200_NEWPRIM(rmesa);
756 R200_STATECHANGE( rmesa, vtx );
757 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
758 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
759 }
760
761 if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
762 R200_STATECHANGE( rmesa, vte );
763 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
764 }
765
766 if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
767 R200_STATECHANGE( rmesa, vap );
768 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
769 }
770 }
771
772 /* Ready for point primitives:
773 */
774 r200RenderPrimitive( ctx, GL_POINTS );
775
776 /* Turn off the hw viewport transformation:
777 */
778 R200_STATECHANGE( rmesa, vte );
779 orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
780 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA |
781 R200_VPORT_Y_SCALE_ENA |
782 R200_VPORT_Z_SCALE_ENA |
783 R200_VPORT_X_OFFSET_ENA |
784 R200_VPORT_Y_OFFSET_ENA |
785 R200_VPORT_Z_OFFSET_ENA);
786
787 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
788 */
789
790
791 /* Populate the vertex
792 *
793 * Incorporate FOG into RGBA
794 */
795 if (ctx->Fog.Enabled) {
796 const GLfloat *fc = ctx->Fog.Color;
797 GLfloat color[4];
798 GLfloat f;
799
800 if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
801 f = _swrast_z_to_fogfactor(ctx, ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
802 else
803 f = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
804
805 color[0] = f * rc[0] + (1.F - f) * fc[0];
806 color[1] = f * rc[1] + (1.F - f) * fc[1];
807 color[2] = f * rc[2] + (1.F - f) * fc[2];
808 color[3] = rc[3];
809
810 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, color[0]);
811 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]);
812 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, color[2]);
813 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]);
814 }
815 else {
816 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, rc[0]);
817 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]);
818 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, rc[2]);
819 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]);
820 }
821
822
823 vert.tv.z = ctx->Current.RasterPos[2];
824
825
826 /* Update window height
827 */
828 LOCK_HARDWARE( rmesa );
829 UNLOCK_HARDWARE( rmesa );
830 h = rmesa->dri.drawable->h + rmesa->dri.drawable->y;
831 px += rmesa->dri.drawable->x;
832
833 /* Clipping handled by existing mechansims in r200_ioctl.c?
834 */
835 for (row=0; row<height; row++) {
836 const GLubyte *src = (const GLubyte *)
837 _mesa_image_address( unpack, bitmap, width, height,
838 GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
839
840 if (unpack->LsbFirst) {
841 /* Lsb first */
842 GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
843 for (col=0; col<width; col++) {
844 if (*src & mask) {
845 vert.tv.x = px+col;
846 vert.tv.y = h - (py+row) - 1;
847 r200_point( rmesa, &vert );
848 }
849 src += (mask >> 7);
850 mask = ((mask << 1) & 0xff) | (mask >> 7);
851 }
852
853 /* get ready for next row */
854 if (mask != 1)
855 src++;
856 }
857 else {
858 /* Msb first */
859 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
860 for (col=0; col<width; col++) {
861 if (*src & mask) {
862 vert.tv.x = px+col;
863 vert.tv.y = h - (py+row) - 1;
864 r200_point( rmesa, &vert );
865 }
866 src += mask & 1;
867 mask = ((mask << 7) & 0xff) | (mask >> 1);
868 }
869 /* get ready for next row */
870 if (mask != 128)
871 src++;
872 }
873 }
874
875 /* Fire outstanding vertices, restore state
876 */
877 R200_STATECHANGE( rmesa, vte );
878 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte;
879
880 /* Unfallback
881 */
882 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 );
883
884 /* Need to restore vertexformat?
885 */
886 if (rmesa->TclFallback)
887 r200ChooseVertexState( ctx );
888 }
889
890
891 void r200FlushVertices( GLcontext *ctx, GLuint flags )
892 {
893 _tnl_FlushVertices( ctx, flags );
894
895 if (flags & FLUSH_STORED_VERTICES)
896 R200_NEWPRIM( R200_CONTEXT( ctx ) );
897 }
898
899 /**********************************************************************/
900 /* Initialization. */
901 /**********************************************************************/
902
903 void r200InitSwtcl( GLcontext *ctx )
904 {
905 TNLcontext *tnl = TNL_CONTEXT(ctx);
906 r200ContextPtr rmesa = R200_CONTEXT(ctx);
907 static int firsttime = 1;
908
909 if (firsttime) {
910 init_rast_tab();
911 firsttime = 0;
912 }
913
914 tnl->Driver.Render.Start = r200RenderStart;
915 tnl->Driver.Render.Finish = r200RenderFinish;
916 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
917 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
918 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
919 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
920 tnl->Driver.Render.Interp = _tnl_interp;
921
922 /* FIXME: what are these numbers? */
923 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
924 36 * sizeof(GLfloat) );
925
926 rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
927 rmesa->swtcl.RenderIndex = ~0;
928 rmesa->swtcl.render_primitive = GL_TRIANGLES;
929 rmesa->swtcl.hw_primitive = 0;
930 }
931
932
933 void r200DestroySwtcl( GLcontext *ctx )
934 {
935 r200ContextPtr rmesa = R200_CONTEXT(ctx);
936
937 if (rmesa->swtcl.indexed_verts.buf)
938 r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ );
939 }