1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c,v 1.6 2003/05/06 23:52:08 daenzer Exp $ */
2 /**************************************************************************
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
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.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
43 #include "swrast_setup/swrast_setup.h"
44 #include "math/m_translate.h"
46 #include "tnl/t_context.h"
47 #include "tnl/t_pipeline.h"
48 #include "tnl/t_vtx_api.h" /* for _tnl_FlushVertices */
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"
56 /***********************************************************************
57 * Build render functions from dd templates *
58 ***********************************************************************/
61 #define RADEON_XYZW_BIT 0x01
62 #define RADEON_RGBA_BIT 0x02
63 #define RADEON_SPEC_BIT 0x04
64 #define RADEON_TEX0_BIT 0x08
65 #define RADEON_TEX1_BIT 0x10
66 #define RADEON_PTEX_BIT 0x20
67 #define RADEON_MAX_SETUP 0x40
69 static void flush_last_swtcl_prim( radeonContextPtr rmesa
);
72 void (*emit
)( GLcontext
*, GLuint
, GLuint
, void *, GLuint
);
73 tnl_interp_func interp
;
74 tnl_copy_pv_func copy_pv
;
75 GLboolean (*check_tex_sizes
)( GLcontext
*ctx
);
78 } setup_tab
[RADEON_MAX_SETUP
];
81 #define TINY_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
82 RADEON_CP_VC_FRMT_Z | \
83 RADEON_CP_VC_FRMT_PKCOLOR)
85 #define NOTEX_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
86 RADEON_CP_VC_FRMT_Z | \
87 RADEON_CP_VC_FRMT_W0 | \
88 RADEON_CP_VC_FRMT_PKCOLOR | \
89 RADEON_CP_VC_FRMT_PKSPEC)
91 #define TEX0_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
92 RADEON_CP_VC_FRMT_Z | \
93 RADEON_CP_VC_FRMT_W0 | \
94 RADEON_CP_VC_FRMT_PKCOLOR | \
95 RADEON_CP_VC_FRMT_PKSPEC | \
96 RADEON_CP_VC_FRMT_ST0)
98 #define TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
99 RADEON_CP_VC_FRMT_Z | \
100 RADEON_CP_VC_FRMT_W0 | \
101 RADEON_CP_VC_FRMT_PKCOLOR | \
102 RADEON_CP_VC_FRMT_PKSPEC | \
103 RADEON_CP_VC_FRMT_ST0 | \
104 RADEON_CP_VC_FRMT_ST1)
106 #define PROJ_TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \
107 RADEON_CP_VC_FRMT_Z | \
108 RADEON_CP_VC_FRMT_W0 | \
109 RADEON_CP_VC_FRMT_PKCOLOR | \
110 RADEON_CP_VC_FRMT_PKSPEC | \
111 RADEON_CP_VC_FRMT_ST0 | \
112 RADEON_CP_VC_FRMT_Q0 | \
113 RADEON_CP_VC_FRMT_ST1 | \
114 RADEON_CP_VC_FRMT_Q1)
116 #define TEX2_VERTEX_FORMAT 0
117 #define TEX3_VERTEX_FORMAT 0
118 #define PROJ_TEX3_VERTEX_FORMAT 0
120 #define DO_XYZW (IND & RADEON_XYZW_BIT)
121 #define DO_RGBA (IND & RADEON_RGBA_BIT)
122 #define DO_SPEC (IND & RADEON_SPEC_BIT)
123 #define DO_FOG (IND & RADEON_SPEC_BIT)
124 #define DO_TEX0 (IND & RADEON_TEX0_BIT)
125 #define DO_TEX1 (IND & RADEON_TEX1_BIT)
128 #define DO_PTEX (IND & RADEON_PTEX_BIT)
130 #define VERTEX radeonVertex
131 #define VERTEX_COLOR radeon_color_t
132 #define GET_VIEWPORT_MAT() 0
133 #define GET_TEXSOURCE(n) n
134 #define GET_VERTEX_FORMAT() RADEON_CONTEXT(ctx)->swtcl.vertex_format
135 #define GET_VERTEX_STORE() RADEON_CONTEXT(ctx)->swtcl.verts
136 #define GET_VERTEX_SIZE() RADEON_CONTEXT(ctx)->swtcl.vertex_size * sizeof(GLuint)
138 #define HAVE_HW_VIEWPORT 1
139 /* Tiny vertices don't seem to work atm - haven't looked into why.
141 #define HAVE_HW_DIVIDE (IND & ~(RADEON_XYZW_BIT|RADEON_RGBA_BIT))
142 #define HAVE_TINY_VERTICES 1
143 #define HAVE_RGBA_COLOR 1
144 #define HAVE_NOTEX_VERTICES 1
145 #define HAVE_TEX0_VERTICES 1
146 #define HAVE_TEX1_VERTICES 1
147 #define HAVE_TEX2_VERTICES 0
148 #define HAVE_TEX3_VERTICES 0
149 #define HAVE_PTEX_VERTICES 1
151 #define CHECK_HW_DIVIDE (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \
154 #define INTERP_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].interp
155 #define COPY_PV_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv
158 /***********************************************************************
159 * Generate pv-copying and translation functions *
160 ***********************************************************************/
162 #define TAG(x) radeon_##x
164 #include "tnl_dd/t_dd_vb.c"
168 /***********************************************************************
169 * Generate vertex emit and interp functions *
170 ***********************************************************************/
172 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT)
173 #define TAG(x) x##_wg
174 #include "tnl_dd/t_dd_vbtmp.h"
176 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT)
177 #define TAG(x) x##_wgt0
178 #include "tnl_dd/t_dd_vbtmp.h"
180 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_PTEX_BIT)
181 #define TAG(x) x##_wgpt0
182 #include "tnl_dd/t_dd_vbtmp.h"
184 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT)
185 #define TAG(x) x##_wgt0t1
186 #include "tnl_dd/t_dd_vbtmp.h"
188 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\
190 #define TAG(x) x##_wgpt0t1
191 #include "tnl_dd/t_dd_vbtmp.h"
193 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT)
194 #define TAG(x) x##_wgfs
195 #include "tnl_dd/t_dd_vbtmp.h"
197 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
199 #define TAG(x) x##_wgfst0
200 #include "tnl_dd/t_dd_vbtmp.h"
202 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
203 RADEON_TEX0_BIT|RADEON_PTEX_BIT)
204 #define TAG(x) x##_wgfspt0
205 #include "tnl_dd/t_dd_vbtmp.h"
207 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
208 RADEON_TEX0_BIT|RADEON_TEX1_BIT)
209 #define TAG(x) x##_wgfst0t1
210 #include "tnl_dd/t_dd_vbtmp.h"
212 #define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
213 RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_PTEX_BIT)
214 #define TAG(x) x##_wgfspt0t1
215 #include "tnl_dd/t_dd_vbtmp.h"
218 /***********************************************************************
220 ***********************************************************************/
222 static void init_setup_tab( void )
238 void radeonPrintSetupFlags(char *msg
, GLuint flags
)
240 fprintf(stderr
, "%s(%x): %s%s%s%s%s%s\n",
243 (flags
& RADEON_XYZW_BIT
) ? " xyzw," : "",
244 (flags
& RADEON_RGBA_BIT
) ? " rgba," : "",
245 (flags
& RADEON_SPEC_BIT
) ? " spec/fog," : "",
246 (flags
& RADEON_TEX0_BIT
) ? " tex-0," : "",
247 (flags
& RADEON_TEX1_BIT
) ? " tex-1," : "",
248 (flags
& RADEON_PTEX_BIT
) ? " proj-tex," : "");
252 static void radeonRenderStart( GLcontext
*ctx
)
254 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
255 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
257 if (!setup_tab
[rmesa
->swtcl
.SetupIndex
].check_tex_sizes(ctx
)) {
258 GLuint ind
= rmesa
->swtcl
.SetupIndex
|= (RADEON_PTEX_BIT
|RADEON_RGBA_BIT
);
260 /* Projective textures are handled nicely; just have to change
261 * up to the new vertex format.
263 if (setup_tab
[ind
].vertex_format
!= rmesa
->swtcl
.vertex_format
) {
264 RADEON_NEWPRIM(rmesa
);
265 rmesa
->swtcl
.vertex_format
= setup_tab
[ind
].vertex_format
;
266 rmesa
->swtcl
.vertex_size
= setup_tab
[ind
].vertex_size
;
269 if (!(ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
270 tnl
->Driver
.Render
.Interp
= setup_tab
[rmesa
->swtcl
.SetupIndex
].interp
;
271 tnl
->Driver
.Render
.CopyPV
= setup_tab
[rmesa
->swtcl
.SetupIndex
].copy_pv
;
275 if (rmesa
->dma
.flush
!= 0 &&
276 rmesa
->dma
.flush
!= flush_last_swtcl_prim
)
277 rmesa
->dma
.flush( rmesa
);
281 void radeonBuildVertices( GLcontext
*ctx
, GLuint start
, GLuint count
,
284 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
285 GLuint stride
= rmesa
->swtcl
.vertex_size
* sizeof(int);
286 GLubyte
*v
= ((GLubyte
*)rmesa
->swtcl
.verts
+ (start
* stride
));
288 newinputs
|= rmesa
->swtcl
.SetupNewInputs
;
289 rmesa
->swtcl
.SetupNewInputs
= 0;
294 setup_tab
[rmesa
->swtcl
.SetupIndex
].emit( ctx
, start
, count
, v
, stride
);
297 void radeonChooseVertexState( GLcontext
*ctx
)
299 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
300 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
301 GLuint ind
= (RADEON_XYZW_BIT
| RADEON_RGBA_BIT
);
303 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
306 if (ctx
->Fog
.Enabled
|| (ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
))
307 ind
|= RADEON_SPEC_BIT
;
309 if (ctx
->Texture
._EnabledUnits
& 0x2)
311 ind
|= RADEON_TEX0_BIT
|RADEON_TEX1_BIT
;
312 else if (ctx
->Texture
._EnabledUnits
& 0x1)
314 ind
|= RADEON_TEX0_BIT
;
316 rmesa
->swtcl
.SetupIndex
= ind
;
318 if (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
)) {
319 tnl
->Driver
.Render
.Interp
= radeon_interp_extras
;
320 tnl
->Driver
.Render
.CopyPV
= radeon_copy_pv_extras
;
323 tnl
->Driver
.Render
.Interp
= setup_tab
[ind
].interp
;
324 tnl
->Driver
.Render
.CopyPV
= setup_tab
[ind
].copy_pv
;
327 if (setup_tab
[ind
].vertex_format
!= rmesa
->swtcl
.vertex_format
) {
328 RADEON_NEWPRIM(rmesa
);
329 rmesa
->swtcl
.vertex_format
= setup_tab
[ind
].vertex_format
;
330 rmesa
->swtcl
.vertex_size
= setup_tab
[ind
].vertex_size
;
334 GLuint se_coord_fmt
, needproj
;
336 /* HW perspective divide is a win, but tiny vertex formats are a
339 if (setup_tab
[ind
].vertex_format
== TINY_VERTEX_FORMAT
||
340 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
342 se_coord_fmt
= (RADEON_VTX_XY_PRE_MULT_1_OVER_W0
|
343 RADEON_VTX_Z_PRE_MULT_1_OVER_W0
|
344 RADEON_TEX1_W_ROUTING_USE_Q1
);
348 se_coord_fmt
= (RADEON_VTX_W0_IS_NOT_1_OVER_W0
|
349 RADEON_TEX1_W_ROUTING_USE_Q1
);
352 if ( se_coord_fmt
!= rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
] ) {
353 RADEON_STATECHANGE( rmesa
, set
);
354 rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
] = se_coord_fmt
;
356 _tnl_need_projected_coords( ctx
, needproj
);
361 /* Flush vertices in the current dma region.
363 static void flush_last_swtcl_prim( radeonContextPtr rmesa
)
365 if (RADEON_DEBUG
& DEBUG_IOCTL
)
366 fprintf(stderr
, "%s\n", __FUNCTION__
);
368 rmesa
->dma
.flush
= 0;
370 if (rmesa
->dma
.current
.buf
) {
371 struct radeon_dma_region
*current
= &rmesa
->dma
.current
;
372 GLuint current_offset
= (rmesa
->radeonScreen
->gart_buffer_offset
+
373 current
->buf
->buf
->idx
* RADEON_BUFFER_SIZE
+
376 assert (!(rmesa
->swtcl
.hw_primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
378 assert (current
->start
+
379 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
382 if (rmesa
->dma
.current
.start
!= rmesa
->dma
.current
.ptr
) {
383 radeonEnsureCmdBufSpace( rmesa
, VERT_AOS_BUFSZ
+
384 rmesa
->hw
.max_state_size
+ VBUF_BUFSZ
);
385 radeonEmitVertexAOS( rmesa
,
386 rmesa
->swtcl
.vertex_size
,
389 radeonEmitVbufPrim( rmesa
,
390 rmesa
->swtcl
.vertex_format
,
391 rmesa
->swtcl
.hw_primitive
,
392 rmesa
->swtcl
.numverts
);
395 rmesa
->swtcl
.numverts
= 0;
396 current
->start
= current
->ptr
;
401 /* Alloc space in the current dma region.
403 static __inline
void *radeonAllocDmaLowVerts( radeonContextPtr rmesa
,
404 int nverts
, int vsize
)
406 GLuint bytes
= vsize
* nverts
;
408 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
409 radeonRefillCurrentDmaRegion( rmesa
);
411 if (!rmesa
->dma
.flush
) {
412 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
413 rmesa
->dma
.flush
= flush_last_swtcl_prim
;
416 assert( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
417 assert( rmesa
->dma
.flush
== flush_last_swtcl_prim
);
418 assert (rmesa
->dma
.current
.start
+
419 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
420 rmesa
->dma
.current
.ptr
);
424 GLubyte
*head
= (GLubyte
*)(rmesa
->dma
.current
.address
+ rmesa
->dma
.current
.ptr
);
425 rmesa
->dma
.current
.ptr
+= bytes
;
426 rmesa
->swtcl
.numverts
+= nverts
;
435 static void *radeon_emit_contiguous_verts( GLcontext
*ctx
,
440 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
441 GLuint stride
= rmesa
->swtcl
.vertex_size
* 4;
442 setup_tab
[rmesa
->swtcl
.SetupIndex
].emit( ctx
, start
, count
, dest
, stride
);
443 return (void *)((char *)dest
+ stride
* (count
- start
));
448 void radeon_emit_indexed_verts( GLcontext
*ctx
, GLuint start
, GLuint count
)
450 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
452 radeonAllocDmaRegionVerts( rmesa
,
453 &rmesa
->swtcl
.indexed_verts
,
455 rmesa
->swtcl
.vertex_size
* 4,
458 setup_tab
[rmesa
->swtcl
.SetupIndex
].emit(
460 rmesa
->swtcl
.indexed_verts
.address
+ rmesa
->swtcl
.indexed_verts
.start
,
461 rmesa
->swtcl
.vertex_size
* 4 );
466 * Render unclipped vertex buffers by emitting vertices directly to
467 * dma buffers. Use strip/fan hardware primitives where possible.
468 * Try to simulate missing primitives with indexed vertices.
470 #define HAVE_POINTS 1
472 #define HAVE_LINE_STRIPS 1
473 #define HAVE_TRIANGLES 1
474 #define HAVE_TRI_STRIPS 1
475 #define HAVE_TRI_STRIP_1 0
476 #define HAVE_TRI_FANS 1
478 #define HAVE_QUAD_STRIPS 0
479 #define HAVE_POLYGONS 0
482 static const GLuint hw_prim
[GL_POLYGON
+1] = {
483 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
,
484 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
486 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
,
487 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
488 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
,
489 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
,
495 static __inline
void radeonDmaPrimitive( radeonContextPtr rmesa
, GLenum prim
)
497 RADEON_NEWPRIM( rmesa
);
498 rmesa
->swtcl
.hw_primitive
= hw_prim
[prim
];
499 assert(rmesa
->dma
.current
.ptr
== rmesa
->dma
.current
.start
);
502 static __inline
void radeonEltPrimitive( radeonContextPtr rmesa
, GLenum prim
)
504 RADEON_NEWPRIM( rmesa
);
505 rmesa
->swtcl
.hw_primitive
= hw_prim
[prim
] | RADEON_CP_VC_CNTL_PRIM_WALK_IND
;
511 #define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx); (void)rmesa
512 #define ELTS_VARS( buf ) GLushort *dest = buf
513 #define INIT( prim ) radeonDmaPrimitive( rmesa, prim )
514 #define ELT_INIT(prim) radeonEltPrimitive( rmesa, prim )
515 #define FLUSH() RADEON_NEWPRIM( rmesa )
516 #define GET_CURRENT_VB_MAX_VERTS() \
517 (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
518 #define GET_SUBSEQUENT_VB_MAX_VERTS() \
519 ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
521 #if RADEON_OLD_PACKETS
522 # define GET_CURRENT_VB_MAX_ELTS() \
523 ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 24)) / 2)
525 # define GET_CURRENT_VB_MAX_ELTS() \
526 ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
528 #define GET_SUBSEQUENT_VB_MAX_ELTS() \
529 ((RADEON_CMD_BUF_SZ - 1024) / 2)
532 static void *radeon_alloc_elts( radeonContextPtr rmesa
, int nr
)
534 if (rmesa
->dma
.flush
== radeonFlushElts
&&
535 rmesa
->store
.cmd_used
+ nr
*2 < RADEON_CMD_BUF_SZ
) {
537 rmesa
->store
.cmd_used
+= nr
*2;
539 return (void *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
);
542 if (rmesa
->dma
.flush
) {
543 rmesa
->dma
.flush( rmesa
);
546 radeonEmitVertexAOS( rmesa
,
547 rmesa
->swtcl
.vertex_size
,
548 (rmesa
->radeonScreen
->gart_buffer_offset
+
549 rmesa
->swtcl
.indexed_verts
.buf
->buf
->idx
*
551 rmesa
->swtcl
.indexed_verts
.start
));
553 return (void *) radeonAllocEltsOpenEnded( rmesa
,
554 rmesa
->swtcl
.vertex_format
,
555 rmesa
->swtcl
.hw_primitive
,
560 #define ALLOC_ELTS(nr) radeon_alloc_elts(rmesa, nr)
562 #ifdef MESA_BIG_ENDIAN
563 /* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
564 #define EMIT_ELT(offset, x) do { \
565 int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \
566 GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \
567 (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); \
568 (void)rmesa; } while (0)
570 #define EMIT_ELT(offset, x) do { \
571 (dest)[offset] = (GLushort) (x); \
572 (void)rmesa; } while (0)
574 #define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x);
575 #define INCR_ELTS( nr ) dest += nr
577 #define RELEASE_ELT_VERTS() \
578 radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ )
579 #define EMIT_INDEXED_VERTS( ctx, start, count ) \
580 radeon_emit_indexed_verts( ctx, start, count )
583 #define ALLOC_VERTS( nr ) \
584 radeonAllocDmaLowVerts( rmesa, nr, rmesa->swtcl.vertex_size * 4 )
585 #define EMIT_VERTS( ctx, j, nr, buf ) \
586 radeon_emit_contiguous_verts(ctx, j, (j)+(nr), buf)
588 #define TAG(x) radeon_dma_##x
589 #include "tnl_dd/t_dd_dmatmp.h"
592 /**********************************************************************/
593 /* Render pipeline stage */
594 /**********************************************************************/
597 static GLboolean
radeon_run_render( GLcontext
*ctx
,
598 struct tnl_pipeline_stage
*stage
)
600 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
601 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
602 struct vertex_buffer
*VB
= &tnl
->vb
;
603 tnl_render_func
*tab
= TAG(render_tab_verts
);
606 if (rmesa
->swtcl
.indexed_verts
.buf
&& (!VB
->Elts
|| stage
->changed_inputs
))
609 if (rmesa
->swtcl
.RenderIndex
!= 0 ||
610 !radeon_dma_validate_render( ctx
, VB
))
613 tnl
->Driver
.Render
.Start( ctx
);
616 tab
= TAG(render_tab_elts
);
617 if (!rmesa
->swtcl
.indexed_verts
.buf
) {
618 if (VB
->Count
> GET_SUBSEQUENT_VB_MAX_VERTS())
620 EMIT_INDEXED_VERTS(ctx
, 0, VB
->Count
);
624 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
626 GLuint prim
= VB
->Primitive
[i
].mode
;
627 GLuint start
= VB
->Primitive
[i
].start
;
628 GLuint length
= VB
->Primitive
[i
].count
;
633 if (RADEON_DEBUG
& DEBUG_PRIMS
)
634 fprintf(stderr
, "radeon_render.c: prim %s %d..%d\n",
635 _mesa_lookup_enum_by_nr(prim
& PRIM_MODE_MASK
),
636 start
, start
+length
);
639 tab
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
, prim
);
642 tnl
->Driver
.Render
.Finish( ctx
);
644 return GL_FALSE
; /* finished the pipe */
649 static void radeon_check_render( GLcontext
*ctx
,
650 struct tnl_pipeline_stage
*stage
)
652 stage
->inputs
= TNL_CONTEXT(ctx
)->render_inputs
;
656 static void dtr( struct tnl_pipeline_stage
*stage
)
662 const struct tnl_pipeline_stage _radeon_render_stage
=
665 (_DD_NEW_SEPARATE_SPECULAR
|
668 _NEW_RENDERMODE
), /* re-check (new inputs) */
669 0, /* re-run (always runs) */
670 GL_TRUE
, /* active */
671 0, 0, /* inputs (set in check_render), outputs */
672 0, 0, /* changed_inputs, private */
673 dtr
, /* destructor */
674 radeon_check_render
, /* check - initially set to alloc data */
675 radeon_run_render
/* run */
679 /**************************************************************************/
681 /* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension
682 * as in the extension spec. Need to translate here.
684 * Note that swrast expects 0..dimension, so if a fallback is active,
685 * don't do anything. (Maybe need to configure swrast to match hw)
687 struct texrect_stage_data
{
688 GLvector4f texcoord
[MAX_TEXTURE_UNITS
];
691 #define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
694 static GLboolean
run_texrect_stage( GLcontext
*ctx
,
695 struct tnl_pipeline_stage
*stage
)
697 struct texrect_stage_data
*store
= TEXRECT_STAGE_DATA(stage
);
698 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
699 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
700 struct vertex_buffer
*VB
= &tnl
->vb
;
706 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
707 if (!(ctx
->Texture
.Unit
[i
]._ReallyEnabled
& TEXTURE_RECT_BIT
))
710 if (stage
->changed_inputs
& VERT_BIT_TEX(i
)) {
711 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
].CurrentRect
;
712 struct gl_texture_image
*texImage
= texObj
->Image
[0][texObj
->BaseLevel
];
713 const GLfloat iw
= 1.0/texImage
->Width
;
714 const GLfloat ih
= 1.0/texImage
->Height
;
715 GLfloat
*in
= (GLfloat
*)VB
->TexCoordPtr
[i
]->data
;
716 GLint instride
= VB
->TexCoordPtr
[i
]->stride
;
717 GLfloat (*out
)[4] = store
->texcoord
[i
].data
;
720 for (j
= 0 ; j
< VB
->Count
; j
++) {
721 out
[j
][0] = in
[0] * iw
;
722 out
[j
][1] = in
[1] * ih
;
723 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
727 VB
->TexCoordPtr
[i
] = &store
->texcoord
[i
];
734 /* Called the first time stage->run() is invoked.
736 static GLboolean
alloc_texrect_data( GLcontext
*ctx
,
737 struct tnl_pipeline_stage
*stage
)
739 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
740 struct texrect_stage_data
*store
;
743 stage
->privatePtr
= CALLOC(sizeof(*store
));
744 store
= TEXRECT_STAGE_DATA(stage
);
748 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
749 _mesa_vector4f_alloc( &store
->texcoord
[i
], 0, VB
->Size
, 32 );
751 /* Now run the stage.
753 stage
->run
= run_texrect_stage
;
754 return stage
->run( ctx
, stage
);
758 static void check_texrect( GLcontext
*ctx
,
759 struct tnl_pipeline_stage
*stage
)
763 if (ctx
->Texture
.Unit
[0]._ReallyEnabled
& TEXTURE_RECT_BIT
)
764 flags
|= VERT_BIT_TEX0
;
766 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
& TEXTURE_RECT_BIT
)
767 flags
|= VERT_BIT_TEX1
;
769 stage
->inputs
= flags
;
770 stage
->outputs
= flags
;
771 stage
->active
= (flags
!= 0);
775 static void free_texrect_data( struct tnl_pipeline_stage
*stage
)
777 struct texrect_stage_data
*store
= TEXRECT_STAGE_DATA(stage
);
781 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
782 if (store
->texcoord
[i
].data
)
783 _mesa_vector4f_free( &store
->texcoord
[i
] );
785 stage
->privatePtr
= 0;
790 const struct tnl_pipeline_stage _radeon_texrect_stage
=
792 "radeon texrect stage", /* name */
793 _NEW_TEXTURE
, /* check_state */
794 _NEW_TEXTURE
, /* run_state */
795 GL_TRUE
, /* active? */
798 0, /* changed_inputs */
799 NULL
, /* private data */
800 free_texrect_data
, /* destructor */
801 check_texrect
, /* check */
802 alloc_texrect_data
, /* run -- initially set to init */
806 /**************************************************************************/
809 static const GLuint reduced_hw_prim
[GL_POLYGON
+1] = {
810 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
,
811 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
812 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
813 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
814 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
815 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
816 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
817 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
818 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
819 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
822 static void radeonRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
823 static void radeonRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
824 static void radeonResetLineStipple( GLcontext
*ctx
);
827 /***********************************************************************
828 * Emit primitives as inline vertices *
829 ***********************************************************************/
833 #define CTX_ARG radeonContextPtr rmesa
834 #define CTX_ARG2 rmesa
835 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
836 #define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, size * 4 )
839 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
840 const char *radeonverts = (char *)rmesa->swtcl.verts;
841 #define VERT(x) (radeonVertex *)(radeonverts + (x * vertsize * sizeof(int)))
842 #define VERTEX radeonVertex
844 #define TAG(x) radeon_##x
845 #include "tnl_dd/t_dd_triemit.h"
848 /***********************************************************************
849 * Macros for t_dd_tritmp.h to draw basic primitives *
850 ***********************************************************************/
852 #define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d )
853 #define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c )
854 #define LINE( a, b ) radeon_line( rmesa, a, b )
855 #define POINT( a ) radeon_point( rmesa, a )
857 /***********************************************************************
858 * Build render functions from dd templates *
859 ***********************************************************************/
861 #define RADEON_TWOSIDE_BIT 0x01
862 #define RADEON_UNFILLED_BIT 0x02
863 #define RADEON_MAX_TRIFUNC 0x08
867 tnl_points_func points
;
869 tnl_triangle_func triangle
;
871 } rast_tab
[RADEON_MAX_TRIFUNC
];
874 #define DO_FALLBACK 0
876 #define DO_UNFILLED (IND & RADEON_UNFILLED_BIT)
877 #define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT)
883 #define DO_FULL_QUAD 1
887 #define HAVE_BACK_COLORS 0
888 #define HAVE_HW_FLATSHADE 1
891 #define DEPTH_SCALE 1.0
892 #define UNFILLED_TRI unfilled_tri
893 #define UNFILLED_QUAD unfilled_quad
894 #define VERT_X(_v) _v->v.x
895 #define VERT_Y(_v) _v->v.y
896 #define VERT_Z(_v) _v->v.z
897 #define AREA_IS_CCW( a ) (a < 0)
898 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e * rmesa->swtcl.vertex_size * sizeof(int)))
900 #define VERT_SET_RGBA( v, c ) \
902 radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \
903 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
904 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
905 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
906 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
909 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
911 #define VERT_SET_SPEC( v0, c ) \
914 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
915 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
916 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
919 #define VERT_COPY_SPEC( v0, v1 ) \
922 v0->v.specular.red = v1->v.specular.red; \
923 v0->v.specular.green = v1->v.specular.green; \
924 v0->v.specular.blue = v1->v.specular.blue; \
928 /* These don't need LE32_TO_CPU() as they used to save and restore
929 * colors which are already in the correct format.
931 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
932 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
933 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
934 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
940 #define LOCAL_VARS(n) \
941 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
942 GLuint color[n], spec[n]; \
943 GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4); \
944 GLboolean havespec = (rmesa->swtcl.vertex_size > 4); \
945 (void) color; (void) spec; (void) coloroffset; (void) havespec;
947 /***********************************************************************
948 * Helpers for rendering unfilled primitives *
949 ***********************************************************************/
951 #define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] )
952 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
955 #include "tnl_dd/t_dd_unfilled.h"
959 /***********************************************************************
960 * Generate GL render functions *
961 ***********************************************************************/
966 #include "tnl_dd/t_dd_tritmp.h"
968 #define IND (RADEON_TWOSIDE_BIT)
969 #define TAG(x) x##_twoside
970 #include "tnl_dd/t_dd_tritmp.h"
972 #define IND (RADEON_UNFILLED_BIT)
973 #define TAG(x) x##_unfilled
974 #include "tnl_dd/t_dd_tritmp.h"
976 #define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT)
977 #define TAG(x) x##_twoside_unfilled
978 #include "tnl_dd/t_dd_tritmp.h"
981 static void init_rast_tab( void )
986 init_twoside_unfilled();
989 /**********************************************************************/
990 /* Render unclipped begin/end objects */
991 /**********************************************************************/
993 #define VERT(x) (radeonVertex *)(radeonverts + (x * vertsize * sizeof(int)))
994 #define RENDER_POINTS( start, count ) \
995 for ( ; start < count ; start++) \
996 radeon_point( rmesa, VERT(start) )
997 #define RENDER_LINE( v0, v1 ) \
998 radeon_line( rmesa, VERT(v0), VERT(v1) )
999 #define RENDER_TRI( v0, v1, v2 ) \
1000 radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
1001 #define RENDER_QUAD( v0, v1, v2, v3 ) \
1002 radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
1004 #define INIT(x) do { \
1005 radeonRenderPrimitive( ctx, x ); \
1008 #define LOCAL_VARS \
1009 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
1010 const GLuint vertsize = rmesa->swtcl.vertex_size; \
1011 const char *radeonverts = (char *)rmesa->swtcl.verts; \
1012 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1013 const GLboolean stipple = ctx->Line.StippleFlag; \
1014 (void) elt; (void) stipple;
1015 #define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx );
1016 #define RESET_OCCLUSION
1017 #define PRESERVE_VB_DEFS
1019 #define TAG(x) radeon_##x##_verts
1020 #include "tnl/t_vb_rendertmp.h"
1023 #define TAG(x) radeon_##x##_elts
1024 #define ELT(x) elt[x]
1025 #include "tnl/t_vb_rendertmp.h"
1029 /**********************************************************************/
1030 /* Choose render functions */
1031 /**********************************************************************/
1033 void radeonChooseRenderState( GLcontext
*ctx
)
1035 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1036 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1038 GLuint flags
= ctx
->_TriangleCaps
;
1040 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
1043 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= RADEON_TWOSIDE_BIT
;
1044 if (flags
& DD_TRI_UNFILLED
) index
|= RADEON_UNFILLED_BIT
;
1046 if (index
!= rmesa
->swtcl
.RenderIndex
) {
1047 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
1048 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
1049 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
1050 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
1051 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
1054 tnl
->Driver
.Render
.PrimTabVerts
= radeon_render_tab_verts
;
1055 tnl
->Driver
.Render
.PrimTabElts
= radeon_render_tab_elts
;
1056 tnl
->Driver
.Render
.ClippedPolygon
= radeon_fast_clipped_poly
;
1058 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
1059 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
1060 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
1063 rmesa
->swtcl
.RenderIndex
= index
;
1068 /**********************************************************************/
1069 /* High level hooks for t_vb_render.c */
1070 /**********************************************************************/
1073 static void radeonRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
1075 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1077 if (rmesa
->swtcl
.hw_primitive
!= hwprim
) {
1078 RADEON_NEWPRIM( rmesa
);
1079 rmesa
->swtcl
.hw_primitive
= hwprim
;
1083 static void radeonRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
1085 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1086 rmesa
->swtcl
.render_primitive
= prim
;
1087 if (prim
< GL_TRIANGLES
|| !(ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
1088 radeonRasterPrimitive( ctx
, reduced_hw_prim
[prim
] );
1091 static void radeonRenderFinish( GLcontext
*ctx
)
1095 static void radeonResetLineStipple( GLcontext
*ctx
)
1097 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1098 RADEON_STATECHANGE( rmesa
, lin
);
1102 /**********************************************************************/
1103 /* Transition to/from hardware rasterization. */
1104 /**********************************************************************/
1106 static const char * const fallbackStrings
[] = {
1108 "glDrawBuffer(GL_FRONT_AND_BACK)",
1109 "glEnable(GL_STENCIL) without hw stencil buffer",
1110 "glRenderMode(selection or feedback)",
1114 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
1118 static const char *getFallbackString(GLuint bit
)
1125 return fallbackStrings
[i
];
1129 void radeonFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
1131 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1132 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1133 GLuint oldfallback
= rmesa
->Fallback
;
1136 rmesa
->Fallback
|= bit
;
1137 if (oldfallback
== 0) {
1138 RADEON_FIREVERTICES( rmesa
);
1139 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_RASTER
, GL_TRUE
);
1140 _swsetup_Wakeup( ctx
);
1141 _tnl_need_projected_coords( ctx
, GL_TRUE
);
1142 rmesa
->swtcl
.RenderIndex
= ~0;
1143 if (RADEON_DEBUG
& DEBUG_FALLBACKS
) {
1144 fprintf(stderr
, "Radeon begin rasterization fallback: 0x%x %s\n",
1145 bit
, getFallbackString(bit
));
1150 rmesa
->Fallback
&= ~bit
;
1151 if (oldfallback
== bit
) {
1152 _swrast_flush( ctx
);
1153 tnl
->Driver
.Render
.Start
= radeonRenderStart
;
1154 tnl
->Driver
.Render
.PrimitiveNotify
= radeonRenderPrimitive
;
1155 tnl
->Driver
.Render
.Finish
= radeonRenderFinish
;
1156 tnl
->Driver
.Render
.BuildVertices
= radeonBuildVertices
;
1157 tnl
->Driver
.Render
.ResetLineStipple
= radeonResetLineStipple
;
1158 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_RASTER
, GL_FALSE
);
1159 if (rmesa
->TclFallback
) {
1160 /* These are already done if rmesa->TclFallback goes to
1161 * zero above. But not if it doesn't (RADEON_NO_TCL for
1164 radeonChooseVertexState( ctx
);
1165 radeonChooseRenderState( ctx
);
1167 if (RADEON_DEBUG
& DEBUG_FALLBACKS
) {
1168 fprintf(stderr
, "Radeon end rasterization fallback: 0x%x %s\n",
1169 bit
, getFallbackString(bit
));
1176 void radeonFlushVertices( GLcontext
*ctx
, GLuint flags
)
1178 _tnl_FlushVertices( ctx
, flags
);
1180 if (flags
& FLUSH_STORED_VERTICES
)
1181 RADEON_NEWPRIM( RADEON_CONTEXT( ctx
) );
1184 /**********************************************************************/
1185 /* Initialization. */
1186 /**********************************************************************/
1188 void radeonInitSwtcl( GLcontext
*ctx
)
1190 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1191 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1192 GLuint size
= TNL_CONTEXT(ctx
)->vb
.Size
;
1193 static int firsttime
= 1;
1201 tnl
->Driver
.Render
.Start
= radeonRenderStart
;
1202 tnl
->Driver
.Render
.Finish
= radeonRenderFinish
;
1203 tnl
->Driver
.Render
.PrimitiveNotify
= radeonRenderPrimitive
;
1204 tnl
->Driver
.Render
.ResetLineStipple
= radeonResetLineStipple
;
1205 tnl
->Driver
.Render
.BuildVertices
= radeonBuildVertices
;
1207 rmesa
->swtcl
.verts
= (GLubyte
*)ALIGN_MALLOC( size
* 16 * 4, 32 );
1208 rmesa
->swtcl
.RenderIndex
= ~0;
1209 rmesa
->swtcl
.render_primitive
= GL_TRIANGLES
;
1210 rmesa
->swtcl
.hw_primitive
= 0;
1214 void radeonDestroySwtcl( GLcontext
*ctx
)
1216 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1218 if (rmesa
->swtcl
.indexed_verts
.buf
)
1219 radeonReleaseDmaRegion( rmesa
, &rmesa
->swtcl
.indexed_verts
,
1222 if (rmesa
->swtcl
.verts
) {
1223 ALIGN_FREE(rmesa
->swtcl
.verts
);
1224 rmesa
->swtcl
.verts
= 0;