Make most of the _mesa_noop_*() functions static.
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_swtcl.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c,v 1.6 2003/05/06 23:52:08 daenzer Exp $ */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
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 "imports.h"
41 #include "macros.h"
42
43 #include "swrast_setup/swrast_setup.h"
44 #include "math/m_translate.h"
45 #include "tnl/tnl.h"
46 #include "tnl/t_context.h"
47 #include "tnl/t_pipeline.h"
48 #include "tnl/t_vtx_api.h" /* for _tnl_FlushVertices */
49
50 #include "radeon_context.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_state.h"
53 #include "radeon_swtcl.h"
54 #include "radeon_tcl.h"
55
56
57 static void flush_last_swtcl_prim( radeonContextPtr rmesa );
58
59 /* R100: xyzw, c0, c1/fog, stq[0..2] = 4+1+1+3*3 = 15 right? */
60 /* R200: xyzw, c0, c1/fog, strq[0..5] = 4+1+1+4*6 = 30 */
61 #define RADEON_MAX_TNL_VERTEX_SIZE (15 * sizeof(GLfloat)) /* for mesa _tnl stage */
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 GLuint radeon_cp_vc_frmts[3][2] =
84 {
85 { RADEON_CP_VC_FRMT_ST0, RADEON_CP_VC_FRMT_ST0 | RADEON_CP_VC_FRMT_Q0 },
86 { RADEON_CP_VC_FRMT_ST1, RADEON_CP_VC_FRMT_ST1 | RADEON_CP_VC_FRMT_Q1 },
87 { RADEON_CP_VC_FRMT_ST2, RADEON_CP_VC_FRMT_ST2 | RADEON_CP_VC_FRMT_Q2 },
88 };
89
90 static void radeonSetVertexFormat( GLcontext *ctx )
91 {
92 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
93 TNLcontext *tnl = TNL_CONTEXT(ctx);
94 struct vertex_buffer *VB = &tnl->vb;
95 DECLARE_RENDERINPUTS(index_bitset);
96 int fmt_0 = 0;
97 int offset = 0;
98
99 RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
100
101 /* Important:
102 */
103 if ( VB->NdcPtr != NULL ) {
104 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
105 }
106 else {
107 VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
108 }
109
110 assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
111 rmesa->swtcl.vertex_attr_count = 0;
112
113 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
114 * build up a hardware vertex.
115 */
116 if ( !rmesa->swtcl.needproj ||
117 RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) { /* for projtex */
118 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F,
119 RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z | RADEON_CP_VC_FRMT_W0 );
120 offset = 4;
121 }
122 else {
123 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F,
124 RADEON_CP_VC_FRMT_XY | RADEON_CP_VC_FRMT_Z );
125 offset = 3;
126 }
127
128 rmesa->swtcl.coloroffset = offset;
129 #if MESA_LITTLE_ENDIAN
130 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA,
131 RADEON_CP_VC_FRMT_PKCOLOR );
132 #else
133 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR,
134 RADEON_CP_VC_FRMT_PKCOLOR );
135 #endif
136 offset += 1;
137
138 rmesa->swtcl.specoffset = 0;
139 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
140 RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
141
142 #if MESA_LITTLE_ENDIAN
143 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
144 rmesa->swtcl.specoffset = offset;
145 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB,
146 RADEON_CP_VC_FRMT_PKSPEC );
147 }
148 else {
149 EMIT_PAD( 3 );
150 }
151
152 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
153 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F,
154 RADEON_CP_VC_FRMT_PKSPEC );
155 }
156 else {
157 EMIT_PAD( 1 );
158 }
159 #else
160 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
161 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F,
162 RADEON_CP_VC_FRMT_PKSPEC );
163 }
164 else {
165 EMIT_PAD( 1 );
166 }
167
168 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
169 rmesa->swtcl.specoffset = offset;
170 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR,
171 RADEON_CP_VC_FRMT_PKSPEC );
172 }
173 else {
174 EMIT_PAD( 3 );
175 }
176 #endif
177 }
178
179 if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX )) {
180 int i;
181
182 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
183 if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX(i) )) {
184 GLuint sz = VB->TexCoordPtr[i]->size;
185
186 switch (sz) {
187 case 1:
188 case 2:
189 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_2F,
190 radeon_cp_vc_frmts[i][0] );
191 break;
192 case 3:
193 case 4:
194 if (ctx->Texture.Unit[i]._ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
195 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F,
196 radeon_cp_vc_frmts[i][1] );
197 } else {
198 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_3F_XYW,
199 radeon_cp_vc_frmts[i][1] );
200 }
201 break;
202 default:
203 continue;
204 };
205 }
206 }
207 }
208
209 if (!RENDERINPUTS_EQUAL( rmesa->tnl_index_bitset, index_bitset ) ||
210 fmt_0 != rmesa->swtcl.vertex_format) {
211 RADEON_NEWPRIM(rmesa);
212 rmesa->swtcl.vertex_format = fmt_0;
213 rmesa->swtcl.vertex_size =
214 _tnl_install_attrs( ctx,
215 rmesa->swtcl.vertex_attrs,
216 rmesa->swtcl.vertex_attr_count,
217 NULL, 0 );
218 rmesa->swtcl.vertex_size /= 4;
219 RENDERINPUTS_COPY( rmesa->tnl_index_bitset, index_bitset );
220 if (RADEON_DEBUG & DEBUG_VERTS)
221 fprintf( stderr, "%s: vertex_size= %d floats\n",
222 __FUNCTION__, rmesa->swtcl.vertex_size);
223 }
224 }
225
226
227 static void radeonRenderStart( GLcontext *ctx )
228 {
229 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
230
231 radeonSetVertexFormat( ctx );
232
233 if (rmesa->dma.flush != 0 &&
234 rmesa->dma.flush != flush_last_swtcl_prim)
235 rmesa->dma.flush( rmesa );
236 }
237
238
239 /**
240 * Set vertex state for SW TCL. The primary purpose of this function is to
241 * determine in advance whether or not the hardware can / should do the
242 * projection divide or Mesa should do it.
243 */
244 void radeonChooseVertexState( GLcontext *ctx )
245 {
246 radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
247 TNLcontext *tnl = TNL_CONTEXT(ctx);
248
249 GLuint se_coord_fmt;
250
251 /* We must ensure that we don't do _tnl_need_projected_coords while in a
252 * rasterization fallback. As this function will be called again when we
253 * leave a rasterization fallback, we can just skip it for now.
254 */
255 if (rmesa->Fallback != 0)
256 return;
257
258 /* HW perspective divide is a win, but tiny vertex formats are a
259 * bigger one.
260 */
261
262 if ((!RENDERINPUTS_TEST_RANGE( tnl->render_inputs_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) &&
263 !RENDERINPUTS_TEST( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 ))
264 || (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
265 rmesa->swtcl.needproj = GL_TRUE;
266 se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
267 RADEON_VTX_Z_PRE_MULT_1_OVER_W0 |
268 RADEON_TEX1_W_ROUTING_USE_Q1);
269 }
270 else {
271 rmesa->swtcl.needproj = GL_FALSE;
272 se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
273 RADEON_TEX1_W_ROUTING_USE_Q1);
274 }
275
276 _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj );
277
278 if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
279 RADEON_STATECHANGE( rmesa, set );
280 rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
281 }
282 }
283
284
285 /* Flush vertices in the current dma region.
286 */
287 static void flush_last_swtcl_prim( radeonContextPtr rmesa )
288 {
289 if (RADEON_DEBUG & DEBUG_IOCTL)
290 fprintf(stderr, "%s\n", __FUNCTION__);
291
292 rmesa->dma.flush = NULL;
293
294 if (rmesa->dma.current.buf) {
295 struct radeon_dma_region *current = &rmesa->dma.current;
296 GLuint current_offset = (rmesa->radeonScreen->gart_buffer_offset +
297 current->buf->buf->idx * RADEON_BUFFER_SIZE +
298 current->start);
299
300 assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
301
302 assert (current->start +
303 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
304 current->ptr);
305
306 if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
307 radeonEnsureCmdBufSpace( rmesa, VERT_AOS_BUFSZ +
308 rmesa->hw.max_state_size + VBUF_BUFSZ );
309
310 radeonEmitVertexAOS( rmesa,
311 rmesa->swtcl.vertex_size,
312 current_offset);
313
314 radeonEmitVbufPrim( rmesa,
315 rmesa->swtcl.vertex_format,
316 rmesa->swtcl.hw_primitive,
317 rmesa->swtcl.numverts);
318 }
319
320 rmesa->swtcl.numverts = 0;
321 current->start = current->ptr;
322 }
323 }
324
325
326 /* Alloc space in the current dma region.
327 */
328 static INLINE void *
329 radeonAllocDmaLowVerts( radeonContextPtr rmesa, int nverts, int vsize )
330 {
331 GLuint bytes = vsize * nverts;
332
333 if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
334 radeonRefillCurrentDmaRegion( rmesa );
335
336 if (!rmesa->dma.flush) {
337 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
338 rmesa->dma.flush = flush_last_swtcl_prim;
339 }
340
341 assert( vsize == rmesa->swtcl.vertex_size * 4 );
342 assert( rmesa->dma.flush == flush_last_swtcl_prim );
343 assert (rmesa->dma.current.start +
344 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
345 rmesa->dma.current.ptr);
346
347
348 {
349 GLubyte *head = (GLubyte *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
350 rmesa->dma.current.ptr += bytes;
351 rmesa->swtcl.numverts += nverts;
352 return head;
353 }
354
355 }
356
357
358 /*
359 * Render unclipped vertex buffers by emitting vertices directly to
360 * dma buffers. Use strip/fan hardware primitives where possible.
361 * Try to simulate missing primitives with indexed vertices.
362 */
363 #define HAVE_POINTS 1
364 #define HAVE_LINES 1
365 #define HAVE_LINE_STRIPS 1
366 #define HAVE_TRIANGLES 1
367 #define HAVE_TRI_STRIPS 1
368 #define HAVE_TRI_STRIP_1 0
369 #define HAVE_TRI_FANS 1
370 #define HAVE_QUADS 0
371 #define HAVE_QUAD_STRIPS 0
372 #define HAVE_POLYGONS 0
373 /* \todo: is it possible to make "ELTS" work with t_vertex code ? */
374 #define HAVE_ELTS 0
375
376 static const GLuint hw_prim[GL_POLYGON+1] = {
377 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
378 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
379 0,
380 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
381 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
382 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP,
383 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN,
384 0,
385 0,
386 0
387 };
388
389 static INLINE void
390 radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim )
391 {
392 RADEON_NEWPRIM( rmesa );
393 rmesa->swtcl.hw_primitive = hw_prim[prim];
394 assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
395 }
396
397 #define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
398 #define INIT( prim ) radeonDmaPrimitive( rmesa, prim )
399 #define FLUSH() RADEON_NEWPRIM( rmesa )
400 #define GET_CURRENT_VB_MAX_VERTS() \
401 (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
402 #define GET_SUBSEQUENT_VB_MAX_VERTS() \
403 ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
404 #define ALLOC_VERTS( nr ) \
405 radeonAllocDmaLowVerts( rmesa, nr, rmesa->swtcl.vertex_size * 4 )
406 #define EMIT_VERTS( ctx, j, nr, buf ) \
407 _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf)
408
409 #define TAG(x) radeon_dma_##x
410 #include "tnl_dd/t_dd_dmatmp.h"
411
412
413 /**********************************************************************/
414 /* Render pipeline stage */
415 /**********************************************************************/
416
417
418 static GLboolean radeon_run_render( GLcontext *ctx,
419 struct tnl_pipeline_stage *stage )
420 {
421 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
422 TNLcontext *tnl = TNL_CONTEXT(ctx);
423 struct vertex_buffer *VB = &tnl->vb;
424 tnl_render_func *tab = TAG(render_tab_verts);
425 GLuint i;
426
427 if (rmesa->swtcl.indexed_verts.buf)
428 RELEASE_ELT_VERTS();
429
430 if (rmesa->swtcl.RenderIndex != 0 ||
431 !radeon_dma_validate_render( ctx, VB ))
432 return GL_TRUE;
433
434 tnl->Driver.Render.Start( ctx );
435
436 for (i = 0 ; i < VB->PrimitiveCount ; i++)
437 {
438 GLuint prim = VB->Primitive[i].mode;
439 GLuint start = VB->Primitive[i].start;
440 GLuint length = VB->Primitive[i].count;
441
442 if (!length)
443 continue;
444
445 if (RADEON_DEBUG & DEBUG_PRIMS)
446 fprintf(stderr, "radeon_render.c: prim %s %d..%d\n",
447 _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK),
448 start, start+length);
449
450 if (length)
451 tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim );
452 }
453
454 tnl->Driver.Render.Finish( ctx );
455
456 return GL_FALSE; /* finished the pipe */
457 }
458
459
460
461
462 const struct tnl_pipeline_stage _radeon_render_stage =
463 {
464 "radeon render",
465 NULL,
466 NULL,
467 NULL,
468 NULL,
469 radeon_run_render /* run */
470 };
471
472
473 /**************************************************************************/
474
475 /* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension
476 * as in the extension spec. Need to translate here.
477 *
478 * Note that swrast expects 0..dimension, so if a fallback is active,
479 * don't do anything. (Maybe need to configure swrast to match hw)
480 */
481 struct texrect_stage_data {
482 GLvector4f texcoord[MAX_TEXTURE_UNITS];
483 };
484
485 #define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
486
487
488 static GLboolean run_texrect_stage( GLcontext *ctx,
489 struct tnl_pipeline_stage *stage )
490 {
491 struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
492 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
493 TNLcontext *tnl = TNL_CONTEXT(ctx);
494 struct vertex_buffer *VB = &tnl->vb;
495 GLuint i;
496
497 if (rmesa->Fallback)
498 return GL_TRUE;
499
500 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
501 if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT) {
502 struct gl_texture_object *texObj = ctx->Texture.Unit[i].CurrentRect;
503 struct gl_texture_image *texImage = texObj->Image[0][texObj->BaseLevel];
504 const GLfloat iw = 1.0/texImage->Width;
505 const GLfloat ih = 1.0/texImage->Height;
506 GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data;
507 GLint instride = VB->TexCoordPtr[i]->stride;
508 GLfloat (*out)[4] = store->texcoord[i].data;
509 GLint j;
510
511 store->texcoord[i].size = VB->TexCoordPtr[i]->size;
512 for (j = 0 ; j < VB->Count ; j++) {
513 switch (VB->TexCoordPtr[i]->size) {
514 case 4:
515 out[j][3] = in[3];
516 /* fallthrough */
517 case 3:
518 out[j][2] = in[2];
519 /* fallthrough */
520 default:
521 out[j][0] = in[0] * iw;
522 out[j][1] = in[1] * ih;
523 }
524 in = (GLfloat *)((GLubyte *)in + instride);
525 }
526
527 VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i] = &store->texcoord[i];
528 }
529 }
530
531 return GL_TRUE;
532 }
533
534
535 /* Called the first time stage->run() is invoked.
536 */
537 static GLboolean alloc_texrect_data( GLcontext *ctx,
538 struct tnl_pipeline_stage *stage )
539 {
540 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
541 struct texrect_stage_data *store;
542 GLuint i;
543
544 stage->privatePtr = CALLOC(sizeof(*store));
545 store = TEXRECT_STAGE_DATA(stage);
546 if (!store)
547 return GL_FALSE;
548
549 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
550 _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
551
552 return GL_TRUE;
553 }
554
555 static void free_texrect_data( struct tnl_pipeline_stage *stage )
556 {
557 struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
558 GLuint i;
559
560 if (store) {
561 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
562 if (store->texcoord[i].data)
563 _mesa_vector4f_free( &store->texcoord[i] );
564 FREE( store );
565 stage->privatePtr = NULL;
566 }
567 }
568
569 const struct tnl_pipeline_stage _radeon_texrect_stage =
570 {
571 "radeon texrect stage", /* name */
572 NULL,
573 alloc_texrect_data,
574 free_texrect_data,
575 NULL,
576 run_texrect_stage
577 };
578
579
580 /**************************************************************************/
581
582
583 static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
584 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
585 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
586 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
587 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
588 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
589 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
590 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
591 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
592 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
593 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
594 };
595
596 static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim );
597 static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim );
598 static void radeonResetLineStipple( GLcontext *ctx );
599
600
601 /***********************************************************************
602 * Emit primitives as inline vertices *
603 ***********************************************************************/
604
605 #undef LOCAL_VARS
606 #undef ALLOC_VERTS
607 #define CTX_ARG radeonContextPtr rmesa
608 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
609 #define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, (size) * 4 )
610 #undef LOCAL_VARS
611 #define LOCAL_VARS \
612 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
613 const char *radeonverts = (char *)rmesa->swtcl.verts;
614 #define VERT(x) (radeonVertex *)(radeonverts + ((x) * (vertsize) * sizeof(int)))
615 #define VERTEX radeonVertex
616 #undef TAG
617 #define TAG(x) radeon_##x
618 #include "tnl_dd/t_dd_triemit.h"
619
620
621 /***********************************************************************
622 * Macros for t_dd_tritmp.h to draw basic primitives *
623 ***********************************************************************/
624
625 #define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d )
626 #define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c )
627 #define LINE( a, b ) radeon_line( rmesa, a, b )
628 #define POINT( a ) radeon_point( rmesa, a )
629
630 /***********************************************************************
631 * Build render functions from dd templates *
632 ***********************************************************************/
633
634 #define RADEON_TWOSIDE_BIT 0x01
635 #define RADEON_UNFILLED_BIT 0x02
636 #define RADEON_MAX_TRIFUNC 0x04
637
638
639 static struct {
640 tnl_points_func points;
641 tnl_line_func line;
642 tnl_triangle_func triangle;
643 tnl_quad_func quad;
644 } rast_tab[RADEON_MAX_TRIFUNC];
645
646
647 #define DO_FALLBACK 0
648 #define DO_OFFSET 0
649 #define DO_UNFILLED (IND & RADEON_UNFILLED_BIT)
650 #define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT)
651 #define DO_FLAT 0
652 #define DO_TRI 1
653 #define DO_QUAD 1
654 #define DO_LINE 1
655 #define DO_POINTS 1
656 #define DO_FULL_QUAD 1
657
658 #define HAVE_RGBA 1
659 #define HAVE_SPEC 1
660 #define HAVE_BACK_COLORS 0
661 #define HAVE_HW_FLATSHADE 1
662 #define TAB rast_tab
663
664 #define DEPTH_SCALE 1.0
665 #define UNFILLED_TRI unfilled_tri
666 #define UNFILLED_QUAD unfilled_quad
667 #define VERT_X(_v) _v->v.x
668 #define VERT_Y(_v) _v->v.y
669 #define VERT_Z(_v) _v->v.z
670 #define AREA_IS_CCW( a ) (a < 0)
671 #define GET_VERTEX(e) (rmesa->swtcl.verts + ((e) * rmesa->swtcl.vertex_size * sizeof(int)))
672
673 #define VERT_SET_RGBA( v, c ) \
674 do { \
675 radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \
676 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
677 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
678 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
679 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
680 } while (0)
681
682 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
683
684 #define VERT_SET_SPEC( v, c ) \
685 do { \
686 if (specoffset) { \
687 radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \
688 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
689 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
690 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
691 } \
692 } while (0)
693 #define VERT_COPY_SPEC( v0, v1 ) \
694 do { \
695 if (specoffset) { \
696 radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \
697 radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \
698 spec0->red = spec1->red; \
699 spec0->green = spec1->green; \
700 spec0->blue = spec1->blue; \
701 } \
702 } while (0)
703
704 /* These don't need LE32_TO_CPU() as they used to save and restore
705 * colors which are already in the correct format.
706 */
707 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
708 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
709 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
710 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
711
712 #undef LOCAL_VARS
713 #undef TAG
714 #undef INIT
715
716 #define LOCAL_VARS(n) \
717 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
718 GLuint color[n], spec[n]; \
719 GLuint coloroffset = rmesa->swtcl.coloroffset; \
720 GLuint specoffset = rmesa->swtcl.specoffset; \
721 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
722
723 /***********************************************************************
724 * Helpers for rendering unfilled primitives *
725 ***********************************************************************/
726
727 #define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] )
728 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
729 #undef TAG
730 #define TAG(x) x
731 #include "tnl_dd/t_dd_unfilled.h"
732 #undef IND
733
734
735 /***********************************************************************
736 * Generate GL render functions *
737 ***********************************************************************/
738
739
740 #define IND (0)
741 #define TAG(x) x
742 #include "tnl_dd/t_dd_tritmp.h"
743
744 #define IND (RADEON_TWOSIDE_BIT)
745 #define TAG(x) x##_twoside
746 #include "tnl_dd/t_dd_tritmp.h"
747
748 #define IND (RADEON_UNFILLED_BIT)
749 #define TAG(x) x##_unfilled
750 #include "tnl_dd/t_dd_tritmp.h"
751
752 #define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT)
753 #define TAG(x) x##_twoside_unfilled
754 #include "tnl_dd/t_dd_tritmp.h"
755
756
757 static void init_rast_tab( void )
758 {
759 init();
760 init_twoside();
761 init_unfilled();
762 init_twoside_unfilled();
763 }
764
765 /**********************************************************************/
766 /* Render unclipped begin/end objects */
767 /**********************************************************************/
768
769 #define RENDER_POINTS( start, count ) \
770 for ( ; start < count ; start++) \
771 radeon_point( rmesa, VERT(start) )
772 #define RENDER_LINE( v0, v1 ) \
773 radeon_line( rmesa, VERT(v0), VERT(v1) )
774 #define RENDER_TRI( v0, v1, v2 ) \
775 radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
776 #define RENDER_QUAD( v0, v1, v2, v3 ) \
777 radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
778 #undef INIT
779 #define INIT(x) do { \
780 radeonRenderPrimitive( ctx, x ); \
781 } while (0)
782 #undef LOCAL_VARS
783 #define LOCAL_VARS \
784 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
785 const GLuint vertsize = rmesa->swtcl.vertex_size; \
786 const char *radeonverts = (char *)rmesa->swtcl.verts; \
787 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
788 const GLboolean stipple = ctx->Line.StippleFlag; \
789 (void) elt; (void) stipple;
790 #define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx );
791 #define RESET_OCCLUSION
792 #define PRESERVE_VB_DEFS
793 #define ELT(x) (x)
794 #define TAG(x) radeon_##x##_verts
795 #include "tnl/t_vb_rendertmp.h"
796 #undef ELT
797 #undef TAG
798 #define TAG(x) radeon_##x##_elts
799 #define ELT(x) elt[x]
800 #include "tnl/t_vb_rendertmp.h"
801
802
803
804 /**********************************************************************/
805 /* Choose render functions */
806 /**********************************************************************/
807
808 void radeonChooseRenderState( GLcontext *ctx )
809 {
810 TNLcontext *tnl = TNL_CONTEXT(ctx);
811 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
812 GLuint index = 0;
813 GLuint flags = ctx->_TriangleCaps;
814
815 if (!rmesa->TclFallback || rmesa->Fallback)
816 return;
817
818 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= RADEON_TWOSIDE_BIT;
819 if (flags & DD_TRI_UNFILLED) index |= RADEON_UNFILLED_BIT;
820
821 if (index != rmesa->swtcl.RenderIndex) {
822 tnl->Driver.Render.Points = rast_tab[index].points;
823 tnl->Driver.Render.Line = rast_tab[index].line;
824 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
825 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
826 tnl->Driver.Render.Quad = rast_tab[index].quad;
827
828 if (index == 0) {
829 tnl->Driver.Render.PrimTabVerts = radeon_render_tab_verts;
830 tnl->Driver.Render.PrimTabElts = radeon_render_tab_elts;
831 tnl->Driver.Render.ClippedPolygon = radeon_fast_clipped_poly;
832 } else {
833 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
834 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
835 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
836 }
837
838 rmesa->swtcl.RenderIndex = index;
839 }
840 }
841
842
843 /**********************************************************************/
844 /* High level hooks for t_vb_render.c */
845 /**********************************************************************/
846
847
848 static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim )
849 {
850 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
851
852 if (rmesa->swtcl.hw_primitive != hwprim) {
853 RADEON_NEWPRIM( rmesa );
854 rmesa->swtcl.hw_primitive = hwprim;
855 }
856 }
857
858 static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim )
859 {
860 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
861 rmesa->swtcl.render_primitive = prim;
862 if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
863 radeonRasterPrimitive( ctx, reduced_hw_prim[prim] );
864 }
865
866 static void radeonRenderFinish( GLcontext *ctx )
867 {
868 }
869
870 static void radeonResetLineStipple( GLcontext *ctx )
871 {
872 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
873 RADEON_STATECHANGE( rmesa, lin );
874 }
875
876
877 /**********************************************************************/
878 /* Transition to/from hardware rasterization. */
879 /**********************************************************************/
880
881 static const char * const fallbackStrings[] = {
882 "Texture mode",
883 "glDrawBuffer(GL_FRONT_AND_BACK)",
884 "glEnable(GL_STENCIL) without hw stencil buffer",
885 "glRenderMode(selection or feedback)",
886 "glBlendEquation",
887 "glBlendFunc",
888 "RADEON_NO_RAST",
889 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
890 };
891
892
893 static const char *getFallbackString(GLuint bit)
894 {
895 int i = 0;
896 while (bit > 1) {
897 i++;
898 bit >>= 1;
899 }
900 return fallbackStrings[i];
901 }
902
903
904 void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
905 {
906 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
907 TNLcontext *tnl = TNL_CONTEXT(ctx);
908 GLuint oldfallback = rmesa->Fallback;
909
910 if (mode) {
911 rmesa->Fallback |= bit;
912 if (oldfallback == 0) {
913 RADEON_FIREVERTICES( rmesa );
914 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE );
915 _swsetup_Wakeup( ctx );
916 rmesa->swtcl.RenderIndex = ~0;
917 if (RADEON_DEBUG & DEBUG_FALLBACKS) {
918 fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n",
919 bit, getFallbackString(bit));
920 }
921 }
922 }
923 else {
924 rmesa->Fallback &= ~bit;
925 if (oldfallback == bit) {
926 _swrast_flush( ctx );
927 tnl->Driver.Render.Start = radeonRenderStart;
928 tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive;
929 tnl->Driver.Render.Finish = radeonRenderFinish;
930
931 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
932 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
933 tnl->Driver.Render.Interp = _tnl_interp;
934
935 tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
936 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE );
937 if (rmesa->TclFallback) {
938 /* These are already done if rmesa->TclFallback goes to
939 * zero above. But not if it doesn't (RADEON_NO_TCL for
940 * example?)
941 */
942 _tnl_invalidate_vertex_state( ctx, ~0 );
943 _tnl_invalidate_vertices( ctx, ~0 );
944 RENDERINPUTS_ZERO( rmesa->tnl_index_bitset );
945 radeonChooseVertexState( ctx );
946 radeonChooseRenderState( ctx );
947 }
948 if (RADEON_DEBUG & DEBUG_FALLBACKS) {
949 fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n",
950 bit, getFallbackString(bit));
951 }
952 }
953 }
954 }
955
956
957 void radeonFlushVertices( GLcontext *ctx, GLuint flags )
958 {
959 _tnl_FlushVertices( ctx, flags );
960
961 if (flags & FLUSH_STORED_VERTICES)
962 RADEON_NEWPRIM( RADEON_CONTEXT( ctx ) );
963 }
964
965 /**********************************************************************/
966 /* Initialization. */
967 /**********************************************************************/
968
969 void radeonInitSwtcl( GLcontext *ctx )
970 {
971 TNLcontext *tnl = TNL_CONTEXT(ctx);
972 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
973 static int firsttime = 1;
974
975 if (firsttime) {
976 init_rast_tab();
977 firsttime = 0;
978 }
979
980 tnl->Driver.Render.Start = radeonRenderStart;
981 tnl->Driver.Render.Finish = radeonRenderFinish;
982 tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive;
983 tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
984 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
985 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
986 tnl->Driver.Render.Interp = _tnl_interp;
987
988 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
989 RADEON_MAX_TNL_VERTEX_SIZE);
990
991 rmesa->swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
992 rmesa->swtcl.RenderIndex = ~0;
993 rmesa->swtcl.render_primitive = GL_TRIANGLES;
994 rmesa->swtcl.hw_primitive = 0;
995 }
996
997
998 void radeonDestroySwtcl( GLcontext *ctx )
999 {
1000 radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1001
1002 if (rmesa->swtcl.indexed_verts.buf)
1003 radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts,
1004 __FUNCTION__ );
1005 }