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