1
/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c,v 1.3 2002/12/23 15:29:26 tsi Exp $ */
3
Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
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.
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:
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.
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.
32
* Keith Whitwell <keith@tungstengraphics.com>
44
#include "swrast_setup/swrast_setup.h"
45
#include "swrast/s_fog.h"
46
#include "math/m_translate.h"
48
#include "tnl/t_context.h"
49
#include "tnl/t_pipeline.h"
51
#include "r200_context.h"
52
#include "r200_ioctl.h"
53
#include "r200_state.h"
54
#include "r200_swtcl.h"
57
/***********************************************************************
58
* Build render functions from dd templates *
59
***********************************************************************/
62
#define R200_XYZW_BIT 0x01
63
#define R200_RGBA_BIT 0x02
64
#define R200_SPEC_BIT 0x04
65
#define R200_TEX0_BIT 0x08
66
#define R200_TEX1_BIT 0x10
67
#define R200_PTEX_BIT 0x20
68
#define R200_MAX_SETUP 0x40
70
static void flush_last_swtcl_prim( r200ContextPtr rmesa );
73
void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
76
GLboolean (*check_tex_sizes)( GLcontext *ctx );
78
GLuint vertex_stride_shift;
80
} setup_tab[R200_MAX_SETUP];
83
static int se_vtx_fmt_0[] = {
88
(R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT)),
93
(R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
94
(R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
99
(R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
100
(R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
105
(R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
106
(R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
111
(R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
112
(R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT))
115
static int se_vtx_fmt_1[] = {
119
((2 << R200_VTX_TEX0_COMP_CNT_SHIFT)),
120
((2 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
121
(2 << R200_VTX_TEX1_COMP_CNT_SHIFT)),
122
((3 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
123
(3 << R200_VTX_TEX1_COMP_CNT_SHIFT)),
126
#define TINY_VERTEX_FORMAT 1
127
#define NOTEX_VERTEX_FORMAT 2
128
#define TEX0_VERTEX_FORMAT 3
129
#define TEX1_VERTEX_FORMAT 4
130
#define PROJ_TEX1_VERTEX_FORMAT 5
131
#define TEX2_VERTEX_FORMAT 0
132
#define TEX3_VERTEX_FORMAT 0
133
#define PROJ_TEX3_VERTEX_FORMAT 0
135
#define DO_XYZW (IND & R200_XYZW_BIT)
136
#define DO_RGBA (IND & R200_RGBA_BIT)
137
#define DO_SPEC (IND & R200_SPEC_BIT)
138
#define DO_FOG (IND & R200_SPEC_BIT)
139
#define DO_TEX0 (IND & R200_TEX0_BIT)
140
#define DO_TEX1 (IND & R200_TEX1_BIT)
143
#define DO_PTEX (IND & R200_PTEX_BIT)
145
#define VERTEX r200Vertex
146
#define VERTEX_COLOR r200_color_t
147
#define GET_VIEWPORT_MAT() 0
148
#define GET_TEXSOURCE(n) n
149
#define GET_VERTEX_FORMAT() R200_CONTEXT(ctx)->swtcl.vertex_format
150
#define GET_VERTEX_STORE() R200_CONTEXT(ctx)->swtcl.verts
151
#define GET_VERTEX_STRIDE_SHIFT() R200_CONTEXT(ctx)->swtcl.vertex_stride_shift
152
#define GET_UBYTE_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteColor
153
#define GET_UBYTE_SPEC_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteSecondaryColor
155
#define HAVE_HW_VIEWPORT 1
156
#define HAVE_HW_DIVIDE (IND & ~(R200_XYZW_BIT|R200_RGBA_BIT))
157
#define HAVE_TINY_VERTICES 1
158
#define HAVE_RGBA_COLOR 1
159
#define HAVE_NOTEX_VERTICES 1
160
#define HAVE_TEX0_VERTICES 1
161
#define HAVE_TEX1_VERTICES 1
162
#define HAVE_TEX2_VERTICES 0
163
#define HAVE_TEX3_VERTICES 0
164
#define HAVE_PTEX_VERTICES 1
166
#define CHECK_HW_DIVIDE (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \
169
#define IMPORT_QUALIFIER
170
#define IMPORT_FLOAT_COLORS r200_import_float_colors
171
#define IMPORT_FLOAT_SPEC_COLORS r200_import_float_spec_colors
173
#define INTERP_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].interp
174
#define COPY_PV_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv
177
/***********************************************************************
178
* Generate pv-copying and translation functions *
179
***********************************************************************/
181
#define TAG(x) r200_##x
183
#include "tnl_dd/t_dd_vb.c"
187
/***********************************************************************
188
* Generate vertex emit and interp functions *
189
***********************************************************************/
191
#define IND (R200_XYZW_BIT|R200_RGBA_BIT)
192
#define TAG(x) x##_wg
193
#include "tnl_dd/t_dd_vbtmp.h"
195
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT)
196
#define TAG(x) x##_wgt0
197
#include "tnl_dd/t_dd_vbtmp.h"
199
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_PTEX_BIT)
200
#define TAG(x) x##_wgpt0
201
#include "tnl_dd/t_dd_vbtmp.h"
203
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT)
204
#define TAG(x) x##_wgt0t1
205
#include "tnl_dd/t_dd_vbtmp.h"
207
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT|\
209
#define TAG(x) x##_wgpt0t1
210
#include "tnl_dd/t_dd_vbtmp.h"
212
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT)
213
#define TAG(x) x##_wgfs
214
#include "tnl_dd/t_dd_vbtmp.h"
216
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
218
#define TAG(x) x##_wgfst0
219
#include "tnl_dd/t_dd_vbtmp.h"
221
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
222
R200_TEX0_BIT|R200_PTEX_BIT)
223
#define TAG(x) x##_wgfspt0
224
#include "tnl_dd/t_dd_vbtmp.h"
226
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
227
R200_TEX0_BIT|R200_TEX1_BIT)
228
#define TAG(x) x##_wgfst0t1
229
#include "tnl_dd/t_dd_vbtmp.h"
231
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
232
R200_TEX0_BIT|R200_TEX1_BIT|R200_PTEX_BIT)
233
#define TAG(x) x##_wgfspt0t1
234
#include "tnl_dd/t_dd_vbtmp.h"
237
/***********************************************************************
239
***********************************************************************/
241
static void init_setup_tab( void )
257
void r200PrintSetupFlags(char *msg, GLuint flags )
259
fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
262
(flags & R200_XYZW_BIT) ? " xyzw," : "",
263
(flags & R200_RGBA_BIT) ? " rgba," : "",
264
(flags & R200_SPEC_BIT) ? " spec/fog," : "",
265
(flags & R200_TEX0_BIT) ? " tex-0," : "",
266
(flags & R200_TEX1_BIT) ? " tex-1," : "",
267
(flags & R200_PTEX_BIT) ? " proj-tex," : "");
272
static void r200SetVertexFormat( GLcontext *ctx, GLuint ind )
274
r200ContextPtr rmesa = R200_CONTEXT( ctx );
275
TNLcontext *tnl = TNL_CONTEXT(ctx);
277
rmesa->swtcl.SetupIndex = ind;
279
if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
280
tnl->Driver.Render.Interp = r200_interp_extras;
281
tnl->Driver.Render.CopyPV = r200_copy_pv_extras;
284
tnl->Driver.Render.Interp = setup_tab[ind].interp;
285
tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
288
if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
291
i = rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
292
rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
293
rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
295
R200_STATECHANGE( rmesa, vtx );
296
rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = se_vtx_fmt_0[i];
297
rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = se_vtx_fmt_1[i];
301
GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
302
GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
305
/* HW perspective divide is a win, but tiny vertex formats are a
308
if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT ||
309
(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
311
vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
312
vte &= ~R200_VTX_W0_FMT;
313
vap |= R200_VAP_FORCE_W_TO_ONE;
317
vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
318
vte |= R200_VTX_W0_FMT;
319
vap &= ~R200_VAP_FORCE_W_TO_ONE;
322
_tnl_need_projected_coords( ctx, needproj );
323
if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
324
R200_STATECHANGE( rmesa, vte );
325
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
327
if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
328
R200_STATECHANGE( rmesa, vap );
329
rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
334
static void r200RenderStart( GLcontext *ctx )
336
r200ContextPtr rmesa = R200_CONTEXT( ctx );
338
if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) {
339
r200SetVertexFormat( ctx, rmesa->swtcl.SetupIndex | R200_PTEX_BIT);
342
if (rmesa->dma.flush != 0 &&
343
rmesa->dma.flush != flush_last_swtcl_prim)
344
rmesa->dma.flush( rmesa );
348
void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
351
r200ContextPtr rmesa = R200_CONTEXT( ctx );
352
GLubyte *v = ((GLubyte *)rmesa->swtcl.verts +
353
(start << rmesa->swtcl.vertex_stride_shift));
354
GLuint stride = 1 << rmesa->swtcl.vertex_stride_shift;
356
newinputs |= rmesa->swtcl.SetupNewInputs;
357
rmesa->swtcl.SetupNewInputs = 0;
362
setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride );
366
void r200ChooseVertexState( GLcontext *ctx )
368
r200ContextPtr rmesa = R200_CONTEXT( ctx );
369
GLuint ind = (R200_XYZW_BIT | R200_RGBA_BIT);
371
if (!rmesa->TclFallback || rmesa->Fallback)
374
if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
375
ind |= R200_SPEC_BIT;
377
if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY)
378
ind |= R200_TEX0_BIT|R200_TEX1_BIT;
379
else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY)
380
ind |= R200_TEX0_BIT;
382
r200SetVertexFormat( ctx, ind );
386
/* Flush vertices in the current dma region.
388
static void flush_last_swtcl_prim( r200ContextPtr rmesa )
390
if (R200_DEBUG & DEBUG_IOCTL)
391
fprintf(stderr, "%s\n", __FUNCTION__);
393
if (rmesa->dma.current.buf) {
394
struct r200_dma_region *current = &rmesa->dma.current;
395
GLuint current_offset = (rmesa->r200Screen->agp_buffer_offset +
396
current->buf->buf->idx * RADEON_BUFFER_SIZE +
399
assert (!(rmesa->swtcl.hw_primitive & R200_VF_PRIM_WALK_IND));
401
assert (current->start +
402
rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
405
if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
406
r200EmitVertexAOS( rmesa,
407
rmesa->swtcl.vertex_size,
410
r200EmitVbufPrim( rmesa,
411
rmesa->swtcl.hw_primitive,
412
rmesa->swtcl.numverts);
415
rmesa->swtcl.numverts = 0;
416
current->start = current->ptr;
418
rmesa->dma.flush = 0;
423
/* Alloc space in the current dma region.
425
static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
426
int nverts, int vsize )
428
GLuint bytes = vsize * nverts;
430
if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end )
431
r200RefillCurrentDmaRegion( rmesa );
433
if (!rmesa->dma.flush) {
434
rmesa->dma.flush = flush_last_swtcl_prim;
437
ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
438
ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
439
ASSERT( rmesa->dma.current.start +
440
rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
441
rmesa->dma.current.ptr );
445
GLubyte *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
446
rmesa->dma.current.ptr += bytes;
447
rmesa->swtcl.numverts += nverts;
456
void r200_emit_contiguous_verts( GLcontext *ctx, GLuint start, GLuint count )
458
r200ContextPtr rmesa = R200_CONTEXT(ctx);
459
GLuint vertex_size = rmesa->swtcl.vertex_size * 4;
460
CARD32 *dest = r200AllocDmaLowVerts( rmesa, count-start, vertex_size );
461
setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest,
467
void r200_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
469
r200ContextPtr rmesa = R200_CONTEXT(ctx);
471
r200AllocDmaRegionVerts( rmesa,
472
&rmesa->swtcl.indexed_verts,
474
rmesa->swtcl.vertex_size * 4,
477
setup_tab[rmesa->swtcl.SetupIndex].emit(
479
rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start,
480
rmesa->swtcl.vertex_size * 4 );
485
* Render unclipped vertex buffers by emitting vertices directly to
486
* dma buffers. Use strip/fan hardware primitives where possible.
487
* Try to simulate missing primitives with indexed vertices.
489
#define HAVE_POINTS 1
491
#define HAVE_LINE_STRIPS 1
492
#define HAVE_TRIANGLES 1
493
#define HAVE_TRI_STRIPS 1
494
#define HAVE_TRI_STRIP_1 0
495
#define HAVE_TRI_FANS 1
497
#define HAVE_QUAD_STRIPS 1
498
#define HAVE_POLYGONS 1
501
static const GLuint hw_prim[GL_POLYGON+1] = {
505
R200_VF_PRIM_LINE_STRIP,
506
R200_VF_PRIM_TRIANGLES,
507
R200_VF_PRIM_TRIANGLE_STRIP,
508
R200_VF_PRIM_TRIANGLE_FAN,
510
R200_VF_PRIM_QUAD_STRIP,
514
static __inline void r200DmaPrimitive( r200ContextPtr rmesa, GLenum prim )
516
R200_NEWPRIM( rmesa );
517
rmesa->swtcl.hw_primitive = hw_prim[prim];
518
assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
521
static __inline void r200EltPrimitive( r200ContextPtr rmesa, GLenum prim )
523
R200_NEWPRIM( rmesa );
524
rmesa->swtcl.hw_primitive = hw_prim[prim] | R200_VF_PRIM_WALK_IND;
528
static void VERT_FALLBACK( GLcontext *ctx,
533
TNLcontext *tnl = TNL_CONTEXT(ctx);
534
tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
535
tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
536
tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
537
R200_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_CLIP;
540
static void ELT_FALLBACK( GLcontext *ctx,
545
TNLcontext *tnl = TNL_CONTEXT(ctx);
546
tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
547
tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
548
tnl->Driver.Render.PrimTabElts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
549
R200_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_CLIP;
553
#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
554
#define ELTS_VARS GLushort *dest
555
#define INIT( prim ) r200DmaPrimitive( rmesa, prim )
556
#define ELT_INIT(prim) r200EltPrimitive( rmesa, prim )
557
#define NEW_PRIMITIVE() R200_NEWPRIM( rmesa )
558
#define NEW_BUFFER() r200RefillCurrentDmaRegion( rmesa )
559
#define GET_CURRENT_VB_MAX_VERTS() \
560
(((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
561
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
562
((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
564
#define GET_CURRENT_VB_MAX_ELTS() \
565
((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
566
#define GET_SUBSEQUENT_VB_MAX_ELTS() \
567
((R200_CMD_BUF_SZ - 1024) / 2)
571
/* How do you extend an existing primitive?
573
#define ALLOC_ELTS(nr) \
575
if (rmesa->dma.flush == r200FlushElts && \
576
rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) { \
578
dest = (GLushort *)(rmesa->store.cmd_buf + \
579
rmesa->store.cmd_used); \
580
rmesa->store.cmd_used += nr*2; \
583
if (rmesa->dma.flush) { \
584
rmesa->dma.flush( rmesa ); \
587
r200EmitVertexAOS( rmesa, \
588
rmesa->swtcl.vertex_size, \
589
(rmesa->r200Screen->agp_buffer_offset + \
590
rmesa->swtcl.indexed_verts.buf->buf->idx * \
591
RADEON_BUFFER_SIZE + \
592
rmesa->swtcl.indexed_verts.start)); \
594
dest = r200AllocEltsOpenEnded( rmesa, \
595
rmesa->swtcl.hw_primitive, \
600
#define ALLOC_ELTS_NEW_PRIMITIVE(nr) ALLOC_ELTS( nr )
602
#ifdef MESA_BIG_ENDIAN
603
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
604
#define EMIT_ELT(offset, x) do { \
605
int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
606
GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
607
(des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
609
#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
611
#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
612
#define INCR_ELTS( nr ) dest += nr
613
#define RELEASE_ELT_VERTS() \
614
r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ )
615
#define EMIT_VERTS( ctx, j, nr ) \
616
r200_emit_contiguous_verts(ctx, j, (j)+(nr))
617
#define EMIT_INDEXED_VERTS( ctx, start, count ) \
618
r200_emit_indexed_verts( ctx, start, count )
621
#define TAG(x) r200_dma_##x
622
#include "tnl_dd/t_dd_dmatmp.h"
625
/**********************************************************************/
626
/* Render pipeline stage */
627
/**********************************************************************/
630
static GLboolean r200_run_render( GLcontext *ctx,
631
struct gl_pipeline_stage *stage )
633
r200ContextPtr rmesa = R200_CONTEXT(ctx);
634
TNLcontext *tnl = TNL_CONTEXT(ctx);
635
struct vertex_buffer *VB = &tnl->vb;
636
GLuint i, length, flags = 0;
637
render_func *tab = TAG(render_tab_verts);
639
if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs))
644
if ((R200_DEBUG & DEBUG_VERTS) || /* No debug */
645
VB->ClipOrMask || /* No clipping */
646
rmesa->swtcl.RenderIndex != 0 || /* No per-vertex manipulations */
647
ctx->Line.StippleFlag) /* No stipple -- fix me? */
651
tab = TAG(render_tab_elts);
652
if (!rmesa->swtcl.indexed_verts.buf)
653
if (!TAG(emit_elt_verts)(ctx, 0, VB->Count))
654
return GL_TRUE; /* too many vertices */
657
tnl->Driver.Render.Start( ctx );
659
for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
661
flags = VB->Primitive[i];
662
length = VB->PrimitiveLength[i];
664
if (R200_DEBUG & DEBUG_PRIMS)
665
fprintf(stderr, "r200_render.c: prim %s %d..%d\n",
666
_mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
670
tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
673
tnl->Driver.Render.Finish( ctx );
675
return GL_FALSE; /* finished the pipe */
680
static void r200_check_render( GLcontext *ctx,
681
struct gl_pipeline_stage *stage )
683
GLuint inputs = VERT_OBJ|VERT_CLIP|VERT_RGBA;
685
if (ctx->RenderMode == GL_RENDER) {
686
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
687
inputs |= VERT_SPEC_RGB;
689
if (ctx->Texture.Unit[0]._ReallyEnabled)
690
inputs |= VERT_TEX(0);
692
if (ctx->Texture.Unit[1]._ReallyEnabled)
693
inputs |= VERT_TEX(1);
695
if (ctx->Fog.Enabled)
696
inputs |= VERT_FOG_COORD;
699
stage->inputs = inputs;
703
static void dtr( struct gl_pipeline_stage *stage )
709
const struct gl_pipeline_stage _r200_render_stage =
712
(_DD_NEW_SEPARATE_SPECULAR |
715
_NEW_RENDERMODE), /* re-check (new inputs) */
716
0, /* re-run (always runs) */
717
GL_TRUE, /* active */
718
0, 0, /* inputs (set in check_render), outputs */
719
0, 0, /* changed_inputs, private */
720
dtr, /* destructor */
721
r200_check_render, /* check - initially set to alloc data */
722
r200_run_render /* run */
727
/**************************************************************************/
730
static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
735
R200_VF_PRIM_TRIANGLES,
736
R200_VF_PRIM_TRIANGLES,
737
R200_VF_PRIM_TRIANGLES,
738
R200_VF_PRIM_TRIANGLES,
739
R200_VF_PRIM_TRIANGLES,
740
R200_VF_PRIM_TRIANGLES
743
static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
744
static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
745
static void r200ResetLineStipple( GLcontext *ctx );
750
#undef HAVE_QUAD_STRIPS
751
#define HAVE_QUAD_STRIPS 0
753
/***********************************************************************
754
* Emit primitives as inline vertices *
755
***********************************************************************/
758
#define CTX_ARG r200ContextPtr rmesa
759
#define CTX_ARG2 rmesa
760
#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
761
#define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
763
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
764
const GLuint shift = rmesa->swtcl.vertex_stride_shift; \
765
const char *r200verts = (char *)rmesa->swtcl.verts;
766
#define VERT(x) (r200Vertex *)(r200verts + (x << shift))
767
#define VERTEX r200Vertex
768
#define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
769
#define PRINT_VERTEX(v) r200_print_vertex(rmesa->glCtx, v)
771
#define TAG(x) r200_##x
772
#include "tnl_dd/t_dd_triemit.h"
775
/***********************************************************************
776
* Macros for t_dd_tritmp.h to draw basic primitives *
777
***********************************************************************/
779
#define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
780
#define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
781
#define LINE( a, b ) r200_line( rmesa, a, b )
782
#define POINT( a ) r200_point( rmesa, a )
784
/***********************************************************************
785
* Build render functions from dd templates *
786
***********************************************************************/
788
#define R200_TWOSIDE_BIT 0x01
789
#define R200_UNFILLED_BIT 0x02
790
#define R200_MAX_TRIFUNC 0x04
796
triangle_func triangle;
798
} rast_tab[R200_MAX_TRIFUNC];
801
#define DO_FALLBACK 0
802
#define DO_UNFILLED (IND & R200_UNFILLED_BIT)
803
#define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
810
#define DO_FULL_QUAD 1
815
#define HAVE_BACK_COLORS 0
816
#define HAVE_HW_FLATSHADE 1
819
#define DEPTH_SCALE 1.0
820
#define UNFILLED_TRI unfilled_tri
821
#define UNFILLED_QUAD unfilled_quad
822
#define VERT_X(_v) _v->v.x
823
#define VERT_Y(_v) _v->v.y
824
#define VERT_Z(_v) _v->v.z
825
#define AREA_IS_CCW( a ) (a < 0)
826
#define GET_VERTEX(e) (rmesa->swtcl.verts + (e<<rmesa->swtcl.vertex_stride_shift))
828
#define VERT_SET_RGBA( v, c ) v->ui[coloroffset] = LE32_TO_CPU(*(GLuint *)c)
829
#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
830
#define VERT_SAVE_RGBA( idx ) color[idx] = CPU_TO_LE32(v[idx]->ui[coloroffset])
831
#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = LE32_TO_CPU(color[idx])
833
#define VERT_SET_SPEC( v0, c ) if (havespec) { \
834
v0->v.specular.red = (c)[0]; \
835
v0->v.specular.green = (c)[1]; \
836
v0->v.specular.blue = (c)[2]; }
837
#define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \
838
v0->v.specular.red = v1->v.specular.red; \
839
v0->v.specular.green = v1->v.specular.green; \
840
v0->v.specular.blue = v1->v.specular.blue; }
841
#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = CPU_TO_LE32(v[idx]->ui[5])
842
#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = LE32_TO_CPU(spec[idx])
848
#define LOCAL_VARS(n) \
849
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
850
GLuint color[n], spec[n]; \
851
GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4); \
852
GLboolean havespec = (rmesa->swtcl.vertex_size > 4); \
853
(void) color; (void) spec; (void) coloroffset; (void) havespec;
855
/***********************************************************************
856
* Helpers for rendering unfilled primitives *
857
***********************************************************************/
859
#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
860
#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
862
#include "tnl_dd/t_dd_unfilled.h"
866
/***********************************************************************
867
* Generate GL render functions *
868
***********************************************************************/
873
#include "tnl_dd/t_dd_tritmp.h"
875
#define IND (R200_TWOSIDE_BIT)
876
#define TAG(x) x##_twoside
877
#include "tnl_dd/t_dd_tritmp.h"
879
#define IND (R200_UNFILLED_BIT)
880
#define TAG(x) x##_unfilled
881
#include "tnl_dd/t_dd_tritmp.h"
883
#define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
884
#define TAG(x) x##_twoside_unfilled
885
#include "tnl_dd/t_dd_tritmp.h"
888
static void init_rast_tab( void )
893
init_twoside_unfilled();
896
/**********************************************************************/
897
/* Render unclipped begin/end objects */
898
/**********************************************************************/
900
#define VERT(x) (r200Vertex *)(r200verts + (x << shift))
901
#define RENDER_POINTS( start, count ) \
902
for ( ; start < count ; start++) \
903
r200_point( rmesa, VERT(start) )
904
#define RENDER_LINE( v0, v1 ) \
905
r200_line( rmesa, VERT(v0), VERT(v1) )
906
#define RENDER_TRI( v0, v1, v2 ) \
907
r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
908
#define RENDER_QUAD( v0, v1, v2, v3 ) \
909
r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
910
#define INIT(x) do { \
911
r200RenderPrimitive( ctx, x ); \
915
r200ContextPtr rmesa = R200_CONTEXT(ctx); \
916
const GLuint shift = rmesa->swtcl.vertex_stride_shift; \
917
const char *r200verts = (char *)rmesa->swtcl.verts; \
918
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
919
const GLboolean stipple = ctx->Line.StippleFlag; \
920
(void) elt; (void) stipple;
921
#define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
922
#define RESET_OCCLUSION
923
#define PRESERVE_VB_DEFS
925
#define TAG(x) r200_##x##_verts
926
#include "tnl/t_vb_rendertmp.h"
929
#define TAG(x) r200_##x##_elts
930
#define ELT(x) elt[x]
931
#include "tnl/t_vb_rendertmp.h"
935
/**********************************************************************/
936
/* Choose render functions */
937
/**********************************************************************/
939
void r200ChooseRenderState( GLcontext *ctx )
941
TNLcontext *tnl = TNL_CONTEXT(ctx);
942
r200ContextPtr rmesa = R200_CONTEXT(ctx);
944
GLuint flags = ctx->_TriangleCaps;
946
if (!rmesa->TclFallback || rmesa->Fallback)
949
if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R200_TWOSIDE_BIT;
950
if (flags & DD_TRI_UNFILLED) index |= R200_UNFILLED_BIT;
952
if (index != rmesa->swtcl.RenderIndex) {
953
tnl->Driver.Render.Points = rast_tab[index].points;
954
tnl->Driver.Render.Line = rast_tab[index].line;
955
tnl->Driver.Render.ClippedLine = rast_tab[index].line;
956
tnl->Driver.Render.Triangle = rast_tab[index].triangle;
957
tnl->Driver.Render.Quad = rast_tab[index].quad;
960
tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts;
961
tnl->Driver.Render.PrimTabElts = r200_render_tab_elts;
962
tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly;
964
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
965
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
966
tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
969
rmesa->swtcl.RenderIndex = index;
974
/**********************************************************************/
975
/* High level hooks for t_vb_render.c */
976
/**********************************************************************/
979
static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
981
r200ContextPtr rmesa = R200_CONTEXT(ctx);
983
if (rmesa->swtcl.hw_primitive != hwprim) {
984
R200_NEWPRIM( rmesa );
985
rmesa->swtcl.hw_primitive = hwprim;
989
static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
991
r200ContextPtr rmesa = R200_CONTEXT(ctx);
992
rmesa->swtcl.render_primitive = prim;
993
if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED))
994
r200RasterPrimitive( ctx, reduced_hw_prim[prim] );
997
static void r200RenderFinish( GLcontext *ctx )
1001
static void r200ResetLineStipple( GLcontext *ctx )
1003
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1004
R200_STATECHANGE( rmesa, lin );
1008
/**********************************************************************/
1009
/* Transition to/from hardware rasterization. */
1010
/**********************************************************************/
1012
static char *fallbackStrings[] = {
1014
"glDrawBuffer(GL_FRONT_AND_BACK)",
1015
"glEnable(GL_STENCIL) without hw stencil buffer",
1016
"glRenderMode(selection or feedback)",
1018
"glBlendFunc(mode != ADD)"
1023
static char *getFallbackString(GLuint bit)
1030
return fallbackStrings[i];
1034
void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
1036
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1037
TNLcontext *tnl = TNL_CONTEXT(ctx);
1038
GLuint oldfallback = rmesa->Fallback;
1041
rmesa->Fallback |= bit;
1042
if (oldfallback == 0) {
1043
R200_FIREVERTICES( rmesa );
1044
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
1045
_swsetup_Wakeup( ctx );
1046
_tnl_need_projected_coords( ctx, GL_TRUE );
1047
rmesa->swtcl.RenderIndex = ~0;
1048
if (R200_DEBUG & DEBUG_FALLBACKS) {
1049
fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
1050
bit, getFallbackString(bit));
1055
rmesa->Fallback &= ~bit;
1056
if (oldfallback == bit) {
1057
_swrast_flush( ctx );
1058
tnl->Driver.Render.Start = r200RenderStart;
1059
tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
1060
tnl->Driver.Render.Finish = r200RenderFinish;
1061
tnl->Driver.Render.BuildVertices = r200BuildVertices;
1062
tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
1063
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
1064
if (rmesa->TclFallback) {
1065
/* These are already done if rmesa->TclFallback goes to
1066
* zero above. But not if it doesn't (R200_NO_TCL for
1069
r200ChooseVertexState( ctx );
1070
r200ChooseRenderState( ctx );
1072
if (R200_DEBUG & DEBUG_FALLBACKS) {
1073
fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
1074
bit, getFallbackString(bit));
1083
/* Cope with depth operations by drawing individual pixels as points???
1086
r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
1087
GLsizei width, GLsizei height,
1088
const struct gl_pixelstore_attrib *unpack,
1089
const GLubyte *bitmap )
1091
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1092
const GLfloat *rc = ctx->Current.RasterColor;
1101
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
1103
/* Choose tiny vertex format
1105
r200SetVertexFormat( ctx, R200_XYZW_BIT | R200_RGBA_BIT );
1107
/* Ready for point primitives:
1109
r200RenderPrimitive( ctx, GL_POINTS );
1111
/* Turn off the hw viewport transformation:
1113
R200_STATECHANGE( rmesa, vte );
1114
orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
1115
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA |
1116
R200_VPORT_Y_SCALE_ENA |
1117
R200_VPORT_Z_SCALE_ENA |
1118
R200_VPORT_X_OFFSET_ENA |
1119
R200_VPORT_Y_OFFSET_ENA |
1120
R200_VPORT_Z_OFFSET_ENA);
1122
/* Turn off other stuff: Stipple?, texture?, blending?, etc.
1126
/* Populate the vertex
1128
* Incorporate FOG into RGBA
1130
if (ctx->Fog.Enabled) {
1131
const GLfloat *fc = ctx->Fog.Color;
1135
if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
1136
f = _mesa_z_to_fogfactor(ctx, ctx->Current.FogCoord);
1138
f = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
1140
color[0] = f * rc[0] + (1.F - f) * fc[0];
1141
color[1] = f * rc[1] + (1.F - f) * fc[1];
1142
color[2] = f * rc[2] + (1.F - f) * fc[2];
1145
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, color[0]);
1146
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]);
1147
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, color[2]);
1148
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]);
1151
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, rc[0]);
1152
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]);
1153
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, rc[2]);
1154
UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]);
1158
vert.tv.z = ctx->Current.RasterPos[2];
1161
/* Update window height
1163
LOCK_HARDWARE( rmesa );
1164
UNLOCK_HARDWARE( rmesa );
1165
h = rmesa->dri.drawable->h + rmesa->dri.drawable->y;
1166
px += rmesa->dri.drawable->x;
1168
/* Clipping handled by existing mechansims in r200_ioctl.c?
1170
for (row=0; row<height; row++) {
1171
const GLubyte *src = (const GLubyte *)
1172
_mesa_image_address( unpack, bitmap, width, height,
1173
GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
1175
if (unpack->LsbFirst) {
1177
GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
1178
for (col=0; col<width; col++) {
1181
vert.tv.y = h - (py+row) - 1;
1182
r200_point( rmesa, &vert );
1185
mask = ((mask << 1) & 0xff) | (mask >> 7);
1188
/* get ready for next row */
1194
GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
1195
for (col=0; col<width; col++) {
1198
vert.tv.y = h - (py+row) - 1;
1199
r200_point( rmesa, &vert );
1202
mask = ((mask << 7) & 0xff) | (mask >> 1);
1204
/* get ready for next row */
1210
/* Fire outstanding vertices, restore state
1212
R200_STATECHANGE( rmesa, vte );
1213
rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte;
1217
TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 );
1219
/* Need to restore vertexformat?
1221
if (rmesa->TclFallback)
1222
r200ChooseVertexState( ctx );
1226
/**********************************************************************/
1227
/* Initialization. */
1228
/**********************************************************************/
1230
void r200InitSwtcl( GLcontext *ctx )
1232
TNLcontext *tnl = TNL_CONTEXT(ctx);
1233
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1234
GLuint size = TNL_CONTEXT(ctx)->vb.Size;
1235
static int firsttime = 1;
1243
tnl->Driver.Render.Start = r200RenderStart;
1244
tnl->Driver.Render.Finish = r200RenderFinish;
1245
tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
1246
tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
1247
tnl->Driver.Render.BuildVertices = r200BuildVertices;
1249
rmesa->swtcl.verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 );
1250
rmesa->swtcl.RenderIndex = ~0;
1251
rmesa->swtcl.render_primitive = GL_TRIANGLES;
1252
rmesa->swtcl.hw_primitive = 0;
1256
void r200DestroySwtcl( GLcontext *ctx )
1258
r200ContextPtr rmesa = R200_CONTEXT(ctx);
1260
if (rmesa->swtcl.indexed_verts.buf)
1261
r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ );
1263
if (rmesa->swtcl.verts) {
1264
ALIGN_FREE(rmesa->swtcl.verts);
1265
rmesa->swtcl.verts = 0;
1268
if (rmesa->UbyteSecondaryColor.Ptr) {
1269
ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
1270
rmesa->UbyteSecondaryColor.Ptr = 0;
1273
if (rmesa->UbyteColor.Ptr) {
1274
ALIGN_FREE(rmesa->UbyteColor.Ptr);
1275
rmesa->UbyteColor.Ptr = 0;