radeon_swtcl.c revision c4f7de5d785266237fd46ee420d4715771f67dfb
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c,v 1.6 2003/05/06 23:52:08 daenzer Exp $ */ 25267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)/************************************************************************** 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) VA Linux Systems Inc., Fremont, California. 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)All Rights Reserved. 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Permission is hereby granted, free of charge, to any person obtaining 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)a copy of this software and associated documentation files (the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)"Software"), to deal in the Software without restriction, including 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)without limitation the rights to use, copy, modify, merge, publish, 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)distribute, sublicense, and/or sell copies of the Software, and to 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)permit persons to whom the Software is furnished to do so, subject to 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)the following conditions: 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)The above copyright notice and this permission notice (including the 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)next paragraph) shall be included in all copies or substantial 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)portions of the Software. 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)**************************************************************************/ 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * Authors: 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Keith Whitwell <keith@tungstengraphics.com> 3406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) */ 355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "glheader.h" 375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "mtypes.h" 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "colormac.h" 39926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#include "enums.h" 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "imports.h" 415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "macros.h" 425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "swrast_setup/swrast_setup.h" 445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "math/m_translate.h" 455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "tnl/tnl.h" 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tnl/t_context.h" 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "tnl/t_pipeline.h" 485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#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 * Build render functions from dd templates * 58 ***********************************************************************/ 59 60 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 68 69static void flush_last_swtcl_prim( radeonContextPtr rmesa ); 70 71static struct { 72 void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint ); 73 interp_func interp; 74 copy_pv_func copy_pv; 75 GLboolean (*check_tex_sizes)( GLcontext *ctx ); 76 GLuint vertex_size; 77 GLuint vertex_stride_shift; 78 GLuint vertex_format; 79} setup_tab[RADEON_MAX_SETUP]; 80 81 82#define TINY_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ 83 RADEON_CP_VC_FRMT_Z | \ 84 RADEON_CP_VC_FRMT_PKCOLOR) 85 86#define NOTEX_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ 87 RADEON_CP_VC_FRMT_Z | \ 88 RADEON_CP_VC_FRMT_W0 | \ 89 RADEON_CP_VC_FRMT_PKCOLOR | \ 90 RADEON_CP_VC_FRMT_PKSPEC) 91 92#define TEX0_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ 93 RADEON_CP_VC_FRMT_Z | \ 94 RADEON_CP_VC_FRMT_W0 | \ 95 RADEON_CP_VC_FRMT_PKCOLOR | \ 96 RADEON_CP_VC_FRMT_PKSPEC | \ 97 RADEON_CP_VC_FRMT_ST0) 98 99#define TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ 100 RADEON_CP_VC_FRMT_Z | \ 101 RADEON_CP_VC_FRMT_W0 | \ 102 RADEON_CP_VC_FRMT_PKCOLOR | \ 103 RADEON_CP_VC_FRMT_PKSPEC | \ 104 RADEON_CP_VC_FRMT_ST0 | \ 105 RADEON_CP_VC_FRMT_ST1) 106 107#define PROJ_TEX1_VERTEX_FORMAT (RADEON_CP_VC_FRMT_XY | \ 108 RADEON_CP_VC_FRMT_Z | \ 109 RADEON_CP_VC_FRMT_W0 | \ 110 RADEON_CP_VC_FRMT_PKCOLOR | \ 111 RADEON_CP_VC_FRMT_PKSPEC | \ 112 RADEON_CP_VC_FRMT_ST0 | \ 113 RADEON_CP_VC_FRMT_Q0 | \ 114 RADEON_CP_VC_FRMT_ST1 | \ 115 RADEON_CP_VC_FRMT_Q1) 116 117#define TEX2_VERTEX_FORMAT 0 118#define TEX3_VERTEX_FORMAT 0 119#define PROJ_TEX3_VERTEX_FORMAT 0 120 121#define DO_XYZW (IND & RADEON_XYZW_BIT) 122#define DO_RGBA (IND & RADEON_RGBA_BIT) 123#define DO_SPEC (IND & RADEON_SPEC_BIT) 124#define DO_FOG (IND & RADEON_SPEC_BIT) 125#define DO_TEX0 (IND & RADEON_TEX0_BIT) 126#define DO_TEX1 (IND & RADEON_TEX1_BIT) 127#define DO_TEX2 0 128#define DO_TEX3 0 129#define DO_PTEX (IND & RADEON_PTEX_BIT) 130 131#define VERTEX radeonVertex 132#define VERTEX_COLOR radeon_color_t 133#define GET_VIEWPORT_MAT() 0 134#define GET_TEXSOURCE(n) n 135#define GET_VERTEX_FORMAT() RADEON_CONTEXT(ctx)->swtcl.vertex_format 136#define GET_VERTEX_STORE() RADEON_CONTEXT(ctx)->swtcl.verts 137#define GET_VERTEX_STRIDE_SHIFT() RADEON_CONTEXT(ctx)->swtcl.vertex_stride_shift 138#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor 139#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor 140 141#define HAVE_HW_VIEWPORT 1 142/* Tiny vertices don't seem to work atm - haven't looked into why. 143 */ 144#define HAVE_HW_DIVIDE (IND & ~(RADEON_XYZW_BIT|RADEON_RGBA_BIT)) 145#define HAVE_TINY_VERTICES 1 146#define HAVE_RGBA_COLOR 1 147#define HAVE_NOTEX_VERTICES 1 148#define HAVE_TEX0_VERTICES 1 149#define HAVE_TEX1_VERTICES 1 150#define HAVE_TEX2_VERTICES 0 151#define HAVE_TEX3_VERTICES 0 152#define HAVE_PTEX_VERTICES 1 153 154#define CHECK_HW_DIVIDE (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \ 155 DD_TRI_UNFILLED))) 156 157#define IMPORT_QUALIFIER 158#define IMPORT_FLOAT_COLORS radeon_import_float_colors 159#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors 160 161#define INTERP_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].interp 162#define COPY_PV_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv 163 164 165/*********************************************************************** 166 * Generate pv-copying and translation functions * 167 ***********************************************************************/ 168 169#define TAG(x) radeon_##x 170#define IND ~0 171#include "tnl_dd/t_dd_vb.c" 172#undef IND 173 174 175/*********************************************************************** 176 * Generate vertex emit and interp functions * 177 ***********************************************************************/ 178 179#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT) 180#define TAG(x) x##_wg 181#include "tnl_dd/t_dd_vbtmp.h" 182 183#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT) 184#define TAG(x) x##_wgt0 185#include "tnl_dd/t_dd_vbtmp.h" 186 187#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_PTEX_BIT) 188#define TAG(x) x##_wgpt0 189#include "tnl_dd/t_dd_vbtmp.h" 190 191#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT) 192#define TAG(x) x##_wgt0t1 193#include "tnl_dd/t_dd_vbtmp.h" 194 195#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\ 196 RADEON_PTEX_BIT) 197#define TAG(x) x##_wgpt0t1 198#include "tnl_dd/t_dd_vbtmp.h" 199 200#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT) 201#define TAG(x) x##_wgfs 202#include "tnl_dd/t_dd_vbtmp.h" 203 204#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ 205 RADEON_TEX0_BIT) 206#define TAG(x) x##_wgfst0 207#include "tnl_dd/t_dd_vbtmp.h" 208 209#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ 210 RADEON_TEX0_BIT|RADEON_PTEX_BIT) 211#define TAG(x) x##_wgfspt0 212#include "tnl_dd/t_dd_vbtmp.h" 213 214#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ 215 RADEON_TEX0_BIT|RADEON_TEX1_BIT) 216#define TAG(x) x##_wgfst0t1 217#include "tnl_dd/t_dd_vbtmp.h" 218 219#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\ 220 RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_PTEX_BIT) 221#define TAG(x) x##_wgfspt0t1 222#include "tnl_dd/t_dd_vbtmp.h" 223 224 225/*********************************************************************** 226 * Initialization 227 ***********************************************************************/ 228 229static void init_setup_tab( void ) 230{ 231 init_wg(); 232 init_wgt0(); 233 init_wgpt0(); 234 init_wgt0t1(); 235 init_wgpt0t1(); 236 init_wgfs(); 237 init_wgfst0(); 238 init_wgfspt0(); 239 init_wgfst0t1(); 240 init_wgfspt0t1(); 241} 242 243 244 245void radeonPrintSetupFlags(char *msg, GLuint flags ) 246{ 247 fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n", 248 msg, 249 (int)flags, 250 (flags & RADEON_XYZW_BIT) ? " xyzw," : "", 251 (flags & RADEON_RGBA_BIT) ? " rgba," : "", 252 (flags & RADEON_SPEC_BIT) ? " spec/fog," : "", 253 (flags & RADEON_TEX0_BIT) ? " tex-0," : "", 254 (flags & RADEON_TEX1_BIT) ? " tex-1," : "", 255 (flags & RADEON_PTEX_BIT) ? " proj-tex," : ""); 256} 257 258 259static void radeonRenderStart( GLcontext *ctx ) 260{ 261 TNLcontext *tnl = TNL_CONTEXT(ctx); 262 radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); 263 264 if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) { 265 GLuint ind = rmesa->swtcl.SetupIndex |= (RADEON_PTEX_BIT|RADEON_RGBA_BIT); 266 267 /* Projective textures are handled nicely; just have to change 268 * up to the new vertex format. 269 */ 270 if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) { 271 RADEON_NEWPRIM(rmesa); 272 rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format; 273 rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size; 274 rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift; 275 } 276 277 if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { 278 tnl->Driver.Render.Interp = setup_tab[rmesa->swtcl.SetupIndex].interp; 279 tnl->Driver.Render.CopyPV = setup_tab[rmesa->swtcl.SetupIndex].copy_pv; 280 } 281 } 282 283 if (rmesa->dma.flush != 0 && 284 rmesa->dma.flush != flush_last_swtcl_prim) 285 rmesa->dma.flush( rmesa ); 286} 287 288 289void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count, 290 GLuint newinputs ) 291{ 292 radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); 293 GLubyte *v = ((GLubyte *)rmesa->swtcl.verts + 294 (start << rmesa->swtcl.vertex_stride_shift)); 295 GLuint stride = 1 << rmesa->swtcl.vertex_stride_shift; 296 297 newinputs |= rmesa->swtcl.SetupNewInputs; 298 rmesa->swtcl.SetupNewInputs = 0; 299 300 if (!newinputs) 301 return; 302 303 setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride ); 304} 305 306void radeonChooseVertexState( GLcontext *ctx ) 307{ 308 radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); 309 TNLcontext *tnl = TNL_CONTEXT(ctx); 310 GLuint ind = (RADEON_XYZW_BIT | RADEON_RGBA_BIT); 311 312 if (!rmesa->TclFallback || rmesa->Fallback) 313 return; 314 315 if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)) 316 ind |= RADEON_SPEC_BIT; 317 318 if (ctx->Texture._EnabledUnits & 0x2) 319 /* unit 1 enabled */ 320 ind |= RADEON_TEX0_BIT|RADEON_TEX1_BIT; 321 else if (ctx->Texture._EnabledUnits & 0x1) 322 /* unit 0 enabled */ 323 ind |= RADEON_TEX0_BIT; 324 325 rmesa->swtcl.SetupIndex = ind; 326 327 if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { 328 tnl->Driver.Render.Interp = radeon_interp_extras; 329 tnl->Driver.Render.CopyPV = radeon_copy_pv_extras; 330 } 331 else { 332 tnl->Driver.Render.Interp = setup_tab[ind].interp; 333 tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; 334 } 335 336 if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) { 337 RADEON_NEWPRIM(rmesa); 338 rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format; 339 rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size; 340 rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift; 341 } 342 343 { 344 GLuint se_coord_fmt, needproj; 345 346 /* HW perspective divide is a win, but tiny vertex formats are a 347 * bigger one. 348 */ 349 if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT || 350 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { 351 needproj = GL_TRUE; 352 se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 | 353 RADEON_VTX_Z_PRE_MULT_1_OVER_W0 | 354 RADEON_TEX1_W_ROUTING_USE_Q1); 355 } 356 else { 357 needproj = GL_FALSE; 358 se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 | 359 RADEON_TEX1_W_ROUTING_USE_Q1); 360 } 361 362 if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) { 363 RADEON_STATECHANGE( rmesa, set ); 364 rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt; 365 } 366 _tnl_need_projected_coords( ctx, needproj ); 367 } 368} 369 370 371/* Flush vertices in the current dma region. 372 */ 373static void flush_last_swtcl_prim( radeonContextPtr rmesa ) 374{ 375 if (RADEON_DEBUG & DEBUG_IOCTL) 376 fprintf(stderr, "%s\n", __FUNCTION__); 377 378 rmesa->dma.flush = 0; 379 380 if (rmesa->dma.current.buf) { 381 struct radeon_dma_region *current = &rmesa->dma.current; 382 GLuint current_offset = (rmesa->radeonScreen->gart_buffer_offset + 383 current->buf->buf->idx * RADEON_BUFFER_SIZE + 384 current->start); 385 386 assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); 387 388 assert (current->start + 389 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == 390 current->ptr); 391 392 if (rmesa->dma.current.start != rmesa->dma.current.ptr) { 393 radeonEmitVertexAOS( rmesa, 394 rmesa->swtcl.vertex_size, 395 current_offset); 396 397 radeonEmitVbufPrim( rmesa, 398 rmesa->swtcl.vertex_format, 399 rmesa->swtcl.hw_primitive, 400 rmesa->swtcl.numverts); 401 } 402 403 rmesa->swtcl.numverts = 0; 404 current->start = current->ptr; 405 } 406} 407 408 409/* Alloc space in the current dma region. 410 */ 411static __inline void *radeonAllocDmaLowVerts( radeonContextPtr rmesa, 412 int nverts, int vsize ) 413{ 414 GLuint bytes = vsize * nverts; 415 416 if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) 417 radeonRefillCurrentDmaRegion( rmesa ); 418 419 if (!rmesa->dma.flush) { 420 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; 421 rmesa->dma.flush = flush_last_swtcl_prim; 422 } 423 424 assert( vsize == rmesa->swtcl.vertex_size * 4 ); 425 assert( rmesa->dma.flush == flush_last_swtcl_prim ); 426 assert (rmesa->dma.current.start + 427 rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 == 428 rmesa->dma.current.ptr); 429 430 431 { 432 GLubyte *head = (GLubyte *)(rmesa->dma.current.address + rmesa->dma.current.ptr); 433 rmesa->dma.current.ptr += bytes; 434 rmesa->swtcl.numverts += nverts; 435 return head; 436 } 437 438} 439 440 441 442 443void radeon_emit_contiguous_verts( GLcontext *ctx, GLuint start, GLuint count ) 444{ 445 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 446 GLuint vertex_size = rmesa->swtcl.vertex_size * 4; 447 CARD32 *dest = radeonAllocDmaLowVerts( rmesa, count-start, vertex_size ); 448 setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest, 449 vertex_size ); 450} 451 452 453 454void radeon_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count ) 455{ 456 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 457 458 radeonAllocDmaRegionVerts( rmesa, 459 &rmesa->swtcl.indexed_verts, 460 count - start, 461 rmesa->swtcl.vertex_size * 4, 462 64); 463 464 setup_tab[rmesa->swtcl.SetupIndex].emit( 465 ctx, start, count, 466 rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start, 467 rmesa->swtcl.vertex_size * 4 ); 468} 469 470 471/* 472 * Render unclipped vertex buffers by emitting vertices directly to 473 * dma buffers. Use strip/fan hardware primitives where possible. 474 * Try to simulate missing primitives with indexed vertices. 475 */ 476#define HAVE_POINTS 1 477#define HAVE_LINES 1 478#define HAVE_LINE_STRIPS 1 479#define HAVE_TRIANGLES 1 480#define HAVE_TRI_STRIPS 1 481#define HAVE_TRI_STRIP_1 0 482#define HAVE_TRI_FANS 1 483#define HAVE_QUADS 0 484#define HAVE_QUAD_STRIPS 0 485#define HAVE_POLYGONS 0 486#define HAVE_ELTS 1 487 488static const GLuint hw_prim[GL_POLYGON+1] = { 489 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT, 490 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, 491 0, 492 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP, 493 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, 494 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP, 495 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN, 496 0, 497 0, 498 0 499}; 500 501static __inline void radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim ) 502{ 503 RADEON_NEWPRIM( rmesa ); 504 rmesa->swtcl.hw_primitive = hw_prim[prim]; 505 assert(rmesa->dma.current.ptr == rmesa->dma.current.start); 506} 507 508static __inline void radeonEltPrimitive( radeonContextPtr rmesa, GLenum prim ) 509{ 510 RADEON_NEWPRIM( rmesa ); 511 rmesa->swtcl.hw_primitive = hw_prim[prim] | RADEON_CP_VC_CNTL_PRIM_WALK_IND; 512} 513 514 515static void VERT_FALLBACK( GLcontext *ctx, 516 GLuint start, 517 GLuint count, 518 GLuint flags ) 519{ 520 TNLcontext *tnl = TNL_CONTEXT(ctx); 521 tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK ); 522 tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 ); 523 tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags ); 524 RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_BIT_POS; 525} 526 527static void ELT_FALLBACK( GLcontext *ctx, 528 GLuint start, 529 GLuint count, 530 GLuint flags ) 531{ 532 TNLcontext *tnl = TNL_CONTEXT(ctx); 533 tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK ); 534 tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 ); 535 tnl->Driver.Render.PrimTabElts[flags&PRIM_MODE_MASK]( ctx, start, count, flags ); 536 RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_BIT_POS; 537} 538 539 540#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx) 541#define ELTS_VARS GLushort *dest 542#define INIT( prim ) radeonDmaPrimitive( rmesa, prim ) 543#define ELT_INIT(prim) radeonEltPrimitive( rmesa, prim ) 544#define NEW_PRIMITIVE() RADEON_NEWPRIM( rmesa ) 545#define NEW_BUFFER() radeonRefillCurrentDmaRegion( rmesa ) 546#define GET_CURRENT_VB_MAX_VERTS() \ 547 (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4)) 548#define GET_SUBSEQUENT_VB_MAX_VERTS() \ 549 ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4)) 550 551#if RADEON_OLD_PACKETS 552# define GET_CURRENT_VB_MAX_ELTS() \ 553 ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 24)) / 2) 554#else 555# define GET_CURRENT_VB_MAX_ELTS() \ 556 ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2) 557#endif 558#define GET_SUBSEQUENT_VB_MAX_ELTS() \ 559 ((RADEON_CMD_BUF_SZ - 1024) / 2) 560 561 562 563/* How do you extend an existing primitive? 564 */ 565#define ALLOC_ELTS(nr) \ 566do { \ 567 if (rmesa->dma.flush == radeonFlushElts && \ 568 rmesa->store.cmd_used + nr*2 < RADEON_CMD_BUF_SZ) { \ 569 \ 570 dest = (GLushort *)(rmesa->store.cmd_buf + \ 571 rmesa->store.cmd_used); \ 572 rmesa->store.cmd_used += nr*2; \ 573 } \ 574 else { \ 575 if (rmesa->dma.flush) { \ 576 rmesa->dma.flush( rmesa ); \ 577 } \ 578 \ 579 radeonEmitVertexAOS( rmesa, \ 580 rmesa->swtcl.vertex_size, \ 581 (rmesa->radeonScreen->gart_buffer_offset + \ 582 rmesa->swtcl.indexed_verts.buf->buf->idx * \ 583 RADEON_BUFFER_SIZE + \ 584 rmesa->swtcl.indexed_verts.start)); \ 585 \ 586 dest = radeonAllocEltsOpenEnded( rmesa, \ 587 rmesa->swtcl.vertex_format, \ 588 rmesa->swtcl.hw_primitive, \ 589 nr ); \ 590 } \ 591} while (0) 592 593#define ALLOC_ELTS_NEW_PRIMITIVE(nr) ALLOC_ELTS( nr ) 594 595#ifdef MESA_BIG_ENDIAN 596/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ 597#define EMIT_ELT(offset, x) do { \ 598 int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 ); \ 599 GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 ); \ 600 (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0) 601#else 602#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x) 603#endif 604#define EMIT_TWO_ELTS(offset, x, y) *(GLuint *)(dest+offset) = ((y)<<16)|(x); 605#define INCR_ELTS( nr ) dest += nr 606#define RELEASE_ELT_VERTS() \ 607 radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ ) 608#define EMIT_VERTS( ctx, j, nr ) \ 609 radeon_emit_contiguous_verts(ctx, j, (j)+(nr)) 610#define EMIT_INDEXED_VERTS( ctx, start, count ) \ 611 radeon_emit_indexed_verts( ctx, start, count ) 612 613 614#define TAG(x) radeon_dma_##x 615#include "tnl_dd/t_dd_dmatmp.h" 616 617 618/**********************************************************************/ 619/* Render pipeline stage */ 620/**********************************************************************/ 621 622 623static GLboolean radeon_run_render( GLcontext *ctx, 624 struct tnl_pipeline_stage *stage ) 625{ 626 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 627 TNLcontext *tnl = TNL_CONTEXT(ctx); 628 struct vertex_buffer *VB = &tnl->vb; 629 GLuint i, length, flags = 0; 630 render_func *tab = TAG(render_tab_verts); 631 632 if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs)) 633 RELEASE_ELT_VERTS(); 634 635 if (VB->ClipOrMask || /* No clipping */ 636 rmesa->swtcl.RenderIndex != 0 || /* No per-vertex manipulations */ 637 ctx->Line.StippleFlag) /* GH: THIS IS A HACK!!! */ 638 return GL_TRUE; 639 640 tnl->Driver.Render.Start( ctx ); 641 642 if (VB->Elts) { 643 tab = TAG(render_tab_elts); 644 if (!rmesa->swtcl.indexed_verts.buf) 645 if (!TAG(emit_elt_verts)(ctx, 0, VB->Count)) 646 return GL_TRUE; /* too many vertices */ 647 } 648 649 for (i = 0 ; i < VB->PrimitiveCount ; i++) 650 { 651 GLuint prim = VB->Primitive[i].mode; 652 GLuint start = VB->Primitive[i].start; 653 GLuint length = VB->Primitive[i].count; 654 655 if (!length) 656 continue; 657 658 if (RADEON_DEBUG & DEBUG_PRIMS) 659 fprintf(stderr, "r200_render.c: prim %s %d..%d\n", 660 _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), 661 start, start+length); 662 663 if (length) 664 tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, flags ); 665 } 666 667 tnl->Driver.Render.Finish( ctx ); 668 669 return GL_FALSE; /* finished the pipe */ 670} 671 672 673 674static void radeon_check_render( GLcontext *ctx, 675 struct tnl_pipeline_stage *stage ) 676{ 677 GLuint inputs = VERT_BIT_POS | VERT_BIT_COLOR0; 678 679 if (ctx->RenderMode == GL_RENDER) { 680 if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) 681 inputs |= VERT_BIT_COLOR1; 682 683 if (ctx->Texture.Unit[0]._ReallyEnabled) 684 inputs |= VERT_BIT_TEX0; 685 686 if (ctx->Texture.Unit[1]._ReallyEnabled) 687 inputs |= VERT_BIT_TEX1; 688 689 if (ctx->Fog.Enabled) 690 inputs |= VERT_BIT_FOG; 691 } 692 693 stage->inputs = inputs; 694} 695 696 697static void dtr( struct tnl_pipeline_stage *stage ) 698{ 699 (void)stage; 700} 701 702 703const struct tnl_pipeline_stage _radeon_render_stage = 704{ 705 "radeon render", 706 (_DD_NEW_SEPARATE_SPECULAR | 707 _NEW_TEXTURE| 708 _NEW_FOG| 709 _NEW_RENDERMODE), /* re-check (new inputs) */ 710 0, /* re-run (always runs) */ 711 GL_TRUE, /* active */ 712 0, 0, /* inputs (set in check_render), outputs */ 713 0, 0, /* changed_inputs, private */ 714 dtr, /* destructor */ 715 radeon_check_render, /* check - initially set to alloc data */ 716 radeon_run_render /* run */ 717}; 718 719 720/**************************************************************************/ 721 722/* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension 723 * as in the extension spec. Need to translate here. 724 * 725 * Note that swrast expects 0..dimension, so if a fallback is active, 726 * don't do anything. (Maybe need to configure swrast to match hw) 727 */ 728struct texrect_stage_data { 729 GLvector4f texcoord[MAX_TEXTURE_UNITS]; 730}; 731 732#define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr) 733 734 735static GLboolean run_texrect_stage( GLcontext *ctx, 736 struct tnl_pipeline_stage *stage ) 737{ 738 struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage); 739 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 740 TNLcontext *tnl = TNL_CONTEXT(ctx); 741 struct vertex_buffer *VB = &tnl->vb; 742 GLuint i; 743 744 if (rmesa->Fallback) 745 return GL_TRUE; 746 747 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { 748 if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT)) 749 continue; 750 751 if (stage->changed_inputs & VERT_BIT_TEX(i)) { 752 struct gl_texture_object *texObj = ctx->Texture.Unit[i].CurrentRect; 753 struct gl_texture_image *texImage = texObj->Image[texObj->BaseLevel]; 754 const GLfloat iw = 1.0/texImage->Width; 755 const GLfloat ih = 1.0/texImage->Height; 756 GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data; 757 GLint instride = VB->TexCoordPtr[i]->stride; 758 GLfloat (*out)[4] = store->texcoord[i].data; 759 GLint j; 760 761 for (j = 0 ; j < VB->Count ; j++) { 762 out[j][0] = in[0] * iw; 763 out[j][1] = in[1] * ih; 764 in = (GLfloat *)((GLubyte *)in + instride); 765 } 766 } 767 768 VB->TexCoordPtr[i] = &store->texcoord[i]; 769 } 770 771 return GL_TRUE; 772} 773 774 775/* Called the first time stage->run() is invoked. 776 */ 777static GLboolean alloc_texrect_data( GLcontext *ctx, 778 struct tnl_pipeline_stage *stage ) 779{ 780 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 781 struct texrect_stage_data *store; 782 GLuint i; 783 784 stage->privatePtr = CALLOC(sizeof(*store)); 785 store = TEXRECT_STAGE_DATA(stage); 786 if (!store) 787 return GL_FALSE; 788 789 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) 790 _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); 791 792 /* Now run the stage. 793 */ 794 stage->run = run_texrect_stage; 795 return stage->run( ctx, stage ); 796} 797 798 799static void check_texrect( GLcontext *ctx, 800 struct tnl_pipeline_stage *stage ) 801{ 802 GLuint flags = 0; 803 804 if (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT) 805 flags |= VERT_BIT_TEX0; 806 807 if (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT) 808 flags |= VERT_BIT_TEX1; 809 810 stage->inputs = flags; 811 stage->outputs = flags; 812 stage->active = (flags != 0); 813} 814 815 816static void free_texrect_data( struct tnl_pipeline_stage *stage ) 817{ 818 struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage); 819 GLuint i; 820 821 if (store) { 822 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) 823 if (store->texcoord[i].data) 824 _mesa_vector4f_free( &store->texcoord[i] ); 825 FREE( store ); 826 stage->privatePtr = 0; 827 } 828} 829 830 831const struct tnl_pipeline_stage _radeon_texrect_stage = 832{ 833 "radeon texrect stage", /* name */ 834 _NEW_TEXTURE, /* check_state */ 835 _NEW_TEXTURE, /* run_state */ 836 GL_TRUE, /* active? */ 837 0, /* inputs */ 838 0, /* outputs */ 839 0, /* changed_inputs */ 840 NULL, /* private data */ 841 free_texrect_data, /* destructor */ 842 check_texrect, /* check */ 843 alloc_texrect_data, /* run -- initially set to init */ 844}; 845 846 847/**************************************************************************/ 848 849 850static const GLuint reduced_hw_prim[GL_POLYGON+1] = { 851 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT, 852 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, 853 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, 854 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE, 855 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, 856 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, 857 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, 858 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, 859 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST, 860 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 861}; 862 863static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim ); 864static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim ); 865static void radeonResetLineStipple( GLcontext *ctx ); 866 867 868/*********************************************************************** 869 * Emit primitives as inline vertices * 870 ***********************************************************************/ 871 872#undef LOCAL_VARS 873#define CTX_ARG radeonContextPtr rmesa 874#define CTX_ARG2 rmesa 875#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size 876#define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, size * 4 ) 877#undef LOCAL_VARS 878#define LOCAL_VARS \ 879 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ 880 const GLuint shift = rmesa->swtcl.vertex_stride_shift; \ 881 const char *radeonverts = (char *)rmesa->swtcl.verts; 882#define VERT(x) (radeonVertex *)(radeonverts + (x << shift)) 883#define VERTEX radeonVertex 884#undef TAG 885#define TAG(x) radeon_##x 886#include "tnl_dd/t_dd_triemit.h" 887 888 889/*********************************************************************** 890 * Macros for t_dd_tritmp.h to draw basic primitives * 891 ***********************************************************************/ 892 893#define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d ) 894#define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c ) 895#define LINE( a, b ) radeon_line( rmesa, a, b ) 896#define POINT( a ) radeon_point( rmesa, a ) 897 898/*********************************************************************** 899 * Build render functions from dd templates * 900 ***********************************************************************/ 901 902#define RADEON_TWOSIDE_BIT 0x01 903#define RADEON_UNFILLED_BIT 0x02 904#define RADEON_MAX_TRIFUNC 0x08 905 906 907static struct { 908 points_func points; 909 line_func line; 910 triangle_func triangle; 911 quad_func quad; 912} rast_tab[RADEON_MAX_TRIFUNC]; 913 914 915#define DO_FALLBACK 0 916#define DO_OFFSET 0 917#define DO_UNFILLED (IND & RADEON_UNFILLED_BIT) 918#define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT) 919#define DO_FLAT 0 920#define DO_TRI 1 921#define DO_QUAD 1 922#define DO_LINE 1 923#define DO_POINTS 1 924#define DO_FULL_QUAD 1 925 926#define HAVE_RGBA 1 927#define HAVE_SPEC 1 928#define HAVE_INDEX 0 929#define HAVE_BACK_COLORS 0 930#define HAVE_HW_FLATSHADE 1 931#define TAB rast_tab 932 933#define DEPTH_SCALE 1.0 934#define UNFILLED_TRI unfilled_tri 935#define UNFILLED_QUAD unfilled_quad 936#define VERT_X(_v) _v->v.x 937#define VERT_Y(_v) _v->v.y 938#define VERT_Z(_v) _v->v.z 939#define AREA_IS_CCW( a ) (a < 0) 940#define GET_VERTEX(e) (rmesa->swtcl.verts + (e<<rmesa->swtcl.vertex_stride_shift)) 941 942#define VERT_SET_RGBA( v, c ) \ 943do { \ 944 radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \ 945 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ 946 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ 947 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ 948 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \ 949} while (0) 950 951#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] 952 953#define VERT_SET_SPEC( v0, c ) \ 954do { \ 955 if (havespec) { \ 956 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \ 957 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \ 958 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \ 959 } \ 960} while (0) 961#define VERT_COPY_SPEC( v0, v1 ) \ 962do { \ 963 if (havespec) { \ 964 v0->v.specular.red = v1->v.specular.red; \ 965 v0->v.specular.green = v1->v.specular.green; \ 966 v0->v.specular.blue = v1->v.specular.blue; \ 967 } \ 968} while (0) 969 970/* These don't need LE32_TO_CPU() as they used to save and restore 971 * colors which are already in the correct format. 972 */ 973#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] 974#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] 975#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5] 976#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx] 977 978#undef LOCAL_VARS 979#undef TAG 980#undef INIT 981 982#define LOCAL_VARS(n) \ 983 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ 984 GLuint color[n], spec[n]; \ 985 GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4); \ 986 GLboolean havespec = (rmesa->swtcl.vertex_size > 4); \ 987 (void) color; (void) spec; (void) coloroffset; (void) havespec; 988 989/*********************************************************************** 990 * Helpers for rendering unfilled primitives * 991 ***********************************************************************/ 992 993#define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] ) 994#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive 995#undef TAG 996#define TAG(x) x 997#include "tnl_dd/t_dd_unfilled.h" 998#undef IND 999 1000 1001/*********************************************************************** 1002 * Generate GL render functions * 1003 ***********************************************************************/ 1004 1005 1006#define IND (0) 1007#define TAG(x) x 1008#include "tnl_dd/t_dd_tritmp.h" 1009 1010#define IND (RADEON_TWOSIDE_BIT) 1011#define TAG(x) x##_twoside 1012#include "tnl_dd/t_dd_tritmp.h" 1013 1014#define IND (RADEON_UNFILLED_BIT) 1015#define TAG(x) x##_unfilled 1016#include "tnl_dd/t_dd_tritmp.h" 1017 1018#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT) 1019#define TAG(x) x##_twoside_unfilled 1020#include "tnl_dd/t_dd_tritmp.h" 1021 1022 1023static void init_rast_tab( void ) 1024{ 1025 init(); 1026 init_twoside(); 1027 init_unfilled(); 1028 init_twoside_unfilled(); 1029} 1030 1031/**********************************************************************/ 1032/* Render unclipped begin/end objects */ 1033/**********************************************************************/ 1034 1035#define VERT(x) (radeonVertex *)(radeonverts + (x << shift)) 1036#define RENDER_POINTS( start, count ) \ 1037 for ( ; start < count ; start++) \ 1038 radeon_point( rmesa, VERT(start) ) 1039#define RENDER_LINE( v0, v1 ) \ 1040 radeon_line( rmesa, VERT(v0), VERT(v1) ) 1041#define RENDER_TRI( v0, v1, v2 ) \ 1042 radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) 1043#define RENDER_QUAD( v0, v1, v2, v3 ) \ 1044 radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) 1045#undef INIT 1046#define INIT(x) do { \ 1047 radeonRenderPrimitive( ctx, x ); \ 1048} while (0) 1049#undef LOCAL_VARS 1050#define LOCAL_VARS \ 1051 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ 1052 const GLuint shift = rmesa->swtcl.vertex_stride_shift; \ 1053 const char *radeonverts = (char *)rmesa->swtcl.verts; \ 1054 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ 1055 const GLboolean stipple = ctx->Line.StippleFlag; \ 1056 (void) elt; (void) stipple; 1057#define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx ); 1058#define RESET_OCCLUSION 1059#define PRESERVE_VB_DEFS 1060#define ELT(x) (x) 1061#define TAG(x) radeon_##x##_verts 1062#include "tnl/t_vb_rendertmp.h" 1063#undef ELT 1064#undef TAG 1065#define TAG(x) radeon_##x##_elts 1066#define ELT(x) elt[x] 1067#include "tnl/t_vb_rendertmp.h" 1068 1069 1070 1071/**********************************************************************/ 1072/* Choose render functions */ 1073/**********************************************************************/ 1074 1075void radeonChooseRenderState( GLcontext *ctx ) 1076{ 1077 TNLcontext *tnl = TNL_CONTEXT(ctx); 1078 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1079 GLuint index = 0; 1080 GLuint flags = ctx->_TriangleCaps; 1081 1082 if (!rmesa->TclFallback || rmesa->Fallback) 1083 return; 1084 1085 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= RADEON_TWOSIDE_BIT; 1086 if (flags & DD_TRI_UNFILLED) index |= RADEON_UNFILLED_BIT; 1087 1088 if (index != rmesa->swtcl.RenderIndex) { 1089 tnl->Driver.Render.Points = rast_tab[index].points; 1090 tnl->Driver.Render.Line = rast_tab[index].line; 1091 tnl->Driver.Render.ClippedLine = rast_tab[index].line; 1092 tnl->Driver.Render.Triangle = rast_tab[index].triangle; 1093 tnl->Driver.Render.Quad = rast_tab[index].quad; 1094 1095 if (index == 0) { 1096 tnl->Driver.Render.PrimTabVerts = radeon_render_tab_verts; 1097 tnl->Driver.Render.PrimTabElts = radeon_render_tab_elts; 1098 tnl->Driver.Render.ClippedPolygon = radeon_fast_clipped_poly; 1099 } else { 1100 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; 1101 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; 1102 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; 1103 } 1104 1105 rmesa->swtcl.RenderIndex = index; 1106 } 1107} 1108 1109 1110/**********************************************************************/ 1111/* High level hooks for t_vb_render.c */ 1112/**********************************************************************/ 1113 1114 1115static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim ) 1116{ 1117 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1118 1119 if (rmesa->swtcl.hw_primitive != hwprim) { 1120 RADEON_NEWPRIM( rmesa ); 1121 rmesa->swtcl.hw_primitive = hwprim; 1122 } 1123} 1124 1125static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim ) 1126{ 1127 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1128 rmesa->swtcl.render_primitive = prim; 1129 if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED)) 1130 radeonRasterPrimitive( ctx, reduced_hw_prim[prim] ); 1131} 1132 1133static void radeonRenderFinish( GLcontext *ctx ) 1134{ 1135} 1136 1137static void radeonResetLineStipple( GLcontext *ctx ) 1138{ 1139 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1140 RADEON_STATECHANGE( rmesa, lin ); 1141} 1142 1143 1144/**********************************************************************/ 1145/* Transition to/from hardware rasterization. */ 1146/**********************************************************************/ 1147 1148static const char * const fallbackStrings[] = { 1149 "Texture mode", 1150 "glDrawBuffer(GL_FRONT_AND_BACK)", 1151 "glEnable(GL_STENCIL) without hw stencil buffer", 1152 "glRenderMode(selection or feedback)", 1153 "glBlendEquation", 1154 "glBlendFunc", 1155 "RADEON_NO_RAST", 1156 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)" 1157}; 1158 1159 1160static const char *getFallbackString(GLuint bit) 1161{ 1162 int i = 0; 1163 while (bit > 1) { 1164 i++; 1165 bit >>= 1; 1166 } 1167 return fallbackStrings[i]; 1168} 1169 1170 1171void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode ) 1172{ 1173 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1174 TNLcontext *tnl = TNL_CONTEXT(ctx); 1175 GLuint oldfallback = rmesa->Fallback; 1176 1177 if (mode) { 1178 rmesa->Fallback |= bit; 1179 if (oldfallback == 0) { 1180 RADEON_FIREVERTICES( rmesa ); 1181 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE ); 1182 _swsetup_Wakeup( ctx ); 1183 _tnl_need_projected_coords( ctx, GL_TRUE ); 1184 rmesa->swtcl.RenderIndex = ~0; 1185 if (RADEON_DEBUG & DEBUG_FALLBACKS) { 1186 fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n", 1187 bit, getFallbackString(bit)); 1188 } 1189 } 1190 } 1191 else { 1192 rmesa->Fallback &= ~bit; 1193 if (oldfallback == bit) { 1194 _swrast_flush( ctx ); 1195 tnl->Driver.Render.Start = radeonRenderStart; 1196 tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive; 1197 tnl->Driver.Render.Finish = radeonRenderFinish; 1198 tnl->Driver.Render.BuildVertices = radeonBuildVertices; 1199 tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple; 1200 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE ); 1201 if (rmesa->TclFallback) { 1202 /* These are already done if rmesa->TclFallback goes to 1203 * zero above. But not if it doesn't (RADEON_NO_TCL for 1204 * example?) 1205 */ 1206 radeonChooseVertexState( ctx ); 1207 radeonChooseRenderState( ctx ); 1208 } 1209 if (RADEON_DEBUG & DEBUG_FALLBACKS) { 1210 fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n", 1211 bit, getFallbackString(bit)); 1212 } 1213 } 1214 } 1215} 1216 1217 1218void radeonFlushVertices( GLcontext *ctx, GLuint flags ) 1219{ 1220 _tnl_FlushVertices( ctx, flags ); 1221 1222 if (flags & FLUSH_STORED_VERTICES) 1223 RADEON_NEWPRIM( RADEON_CONTEXT( ctx ) ); 1224} 1225 1226/**********************************************************************/ 1227/* Initialization. */ 1228/**********************************************************************/ 1229 1230void radeonInitSwtcl( GLcontext *ctx ) 1231{ 1232 TNLcontext *tnl = TNL_CONTEXT(ctx); 1233 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1234 GLuint size = TNL_CONTEXT(ctx)->vb.Size; 1235 static int firsttime = 1; 1236 1237 if (firsttime) { 1238 init_rast_tab(); 1239 init_setup_tab(); 1240 firsttime = 0; 1241 } 1242 1243 tnl->Driver.Render.Start = radeonRenderStart; 1244 tnl->Driver.Render.Finish = radeonRenderFinish; 1245 tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive; 1246 tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple; 1247 tnl->Driver.Render.BuildVertices = radeonBuildVertices; 1248 1249 rmesa->swtcl.verts = (GLubyte *)ALIGN_MALLOC( size * 16 * 4, 32 ); 1250 rmesa->swtcl.RenderIndex = ~0; 1251 rmesa->swtcl.render_primitive = GL_TRIANGLES; 1252 rmesa->swtcl.hw_primitive = 0; 1253} 1254 1255 1256void radeonDestroySwtcl( GLcontext *ctx ) 1257{ 1258 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1259 1260 if (rmesa->swtcl.indexed_verts.buf) 1261 radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, 1262 __FUNCTION__ ); 1263 1264 if (rmesa->swtcl.verts) { 1265 ALIGN_FREE(rmesa->swtcl.verts); 1266 rmesa->swtcl.verts = 0; 1267 } 1268 1269} 1270