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