r200_cmdbuf.c revision 44dace86eaf9eded8e6465adfadf6345658686dd
1/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_cmdbuf.c,v 1.1 2002/10/30 12:51:51 alanh Exp $ */ 2/* 3Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 4 5The Weather Channel (TM) funded Tungsten Graphics to develop the 6initial release of the Radeon 8500 driver under the XFree86 license. 7This notice must be preserved. 8 9Permission is hereby granted, free of charge, to any person obtaining 10a copy of this software and associated documentation files (the 11"Software"), to deal in the Software without restriction, including 12without limitation the rights to use, copy, modify, merge, publish, 13distribute, sublicense, and/or sell copies of the Software, and to 14permit persons to whom the Software is furnished to do so, subject to 15the following conditions: 16 17The above copyright notice and this permission notice (including the 18next paragraph) shall be included in all copies or substantial 19portions of the Software. 20 21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28*/ 29 30/* 31 * Authors: 32 * Keith Whitwell <keith@tungstengraphics.com> 33 */ 34 35#include "glheader.h" 36#include "imports.h" 37#include "macros.h" 38#include "context.h" 39#include "swrast/swrast.h" 40#include "simple_list.h" 41 42#include "r200_context.h" 43#include "r200_state.h" 44#include "r200_ioctl.h" 45#include "r200_tcl.h" 46#include "r200_sanity.h" 47#include "radeon_reg.h" 48 49static void print_state_atom( struct r200_state_atom *state ) 50{ 51 int i; 52 53 fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size); 54 55 if (0 & R200_DEBUG & DEBUG_VERBOSE) 56 for (i = 0 ; i < state->cmd_size ; i++) 57 fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]); 58 59} 60 61/* The state atoms will be emitted in the order they appear in the atom list, 62 * so this step is important. 63 */ 64void r200SetUpAtomList( r200ContextPtr rmesa ) 65{ 66 int i, mtu; 67 68 mtu = rmesa->glCtx->Const.MaxTextureUnits; 69 70 make_empty_list(&rmesa->hw.atomlist); 71 rmesa->hw.atomlist.name = "atom-list"; 72 73 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ctx ); 74 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.set ); 75 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lin ); 76 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msk ); 77 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vpt ); 78 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vtx ); 79 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vap ); 80 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.vte ); 81 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msc ); 82 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cst ); 83 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.zbs ); 84 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcl ); 85 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.msl ); 86 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tcg ); 87 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.grd ); 88 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.fog ); 89 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tam ); 90 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tf ); 91 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.atf ); 92 for (i = 0; i < mtu; ++i) 93 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.tex[i] ); 94 for (i = 0; i < mtu; ++i) 95 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.cube[i] ); 96 for (i = 0; i < 6; ++i) 97 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] ); 98 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.afs[0] ); 99 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.afs[1] ); 100 for (i = 0; i < 8; ++i) 101 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.lit[i] ); 102 for (i = 0; i < 3 + mtu; ++i) 103 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mat[i] ); 104 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.eye ); 105 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.glt ); 106 for (i = 0; i < 2; ++i) 107 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.mtl[i] ); 108 for (i = 0; i < 6; ++i) 109 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.ucp[i] ); 110 /* FIXME: is this a good place to insert that atom ? */ 111 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.spr ); 112 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.prf ); 113} 114 115static void r200SaveHwState( r200ContextPtr rmesa ) 116{ 117 struct r200_state_atom *atom; 118 char * dest = rmesa->backup_store.cmd_buf; 119 120 if (R200_DEBUG & DEBUG_STATE) 121 fprintf(stderr, "%s\n", __FUNCTION__); 122 123 rmesa->backup_store.cmd_used = 0; 124 125 foreach( atom, &rmesa->hw.atomlist ) { 126 if ( atom->check( rmesa->glCtx, atom->idx ) ) { 127 int size = atom->cmd_size * 4; 128 memcpy( dest, atom->cmd, size); 129 dest += size; 130 rmesa->backup_store.cmd_used += size; 131 if (R200_DEBUG & DEBUG_STATE) 132 print_state_atom( atom ); 133 } 134 } 135 136 assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ ); 137 if (R200_DEBUG & DEBUG_STATE) 138 fprintf(stderr, "Returning to r200EmitState\n"); 139} 140 141void r200EmitState( r200ContextPtr rmesa ) 142{ 143 char *dest; 144 int mtu; 145 struct r200_state_atom *atom; 146 147 if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS)) 148 fprintf(stderr, "%s\n", __FUNCTION__); 149 150 if (rmesa->save_on_next_emit) { 151 r200SaveHwState(rmesa); 152 rmesa->save_on_next_emit = GL_FALSE; 153 } 154 155 if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty) 156 return; 157 158 mtu = rmesa->glCtx->Const.MaxTextureUnits; 159 160 /* To avoid going across the entire set of states multiple times, just check 161 * for enough space for the case of emitting all state, and inline the 162 * r200AllocCmdBuf code here without all the checks. 163 */ 164 r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size ); 165 166 /* we need to calculate dest after EnsureCmdBufSpace 167 as we may flush the buffer - airlied */ 168 dest = rmesa->store.cmd_buf + rmesa->store.cmd_used; 169 if (R200_DEBUG & DEBUG_STATE) { 170 foreach( atom, &rmesa->hw.atomlist ) { 171 if ( atom->dirty || rmesa->hw.all_dirty ) { 172 if ( atom->check( rmesa->glCtx, atom->idx ) ) 173 print_state_atom( atom ); 174 else 175 fprintf(stderr, "skip state %s\n", atom->name); 176 } 177 } 178 } 179 180 foreach( atom, &rmesa->hw.atomlist ) { 181 if ( rmesa->hw.all_dirty ) 182 atom->dirty = GL_TRUE; 183 if ( atom->dirty ) { 184 if ( atom->check( rmesa->glCtx, atom->idx ) ) { 185 int size = atom->cmd_size * 4; 186 memcpy( dest, atom->cmd, size); 187 dest += size; 188 rmesa->store.cmd_used += size; 189 atom->dirty = GL_FALSE; 190 } 191 } 192 } 193 194 assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ ); 195 196 rmesa->hw.is_dirty = GL_FALSE; 197 rmesa->hw.all_dirty = GL_FALSE; 198} 199 200/* Fire a section of the retained (indexed_verts) buffer as a regular 201 * primtive. 202 */ 203void r200EmitVbufPrim( r200ContextPtr rmesa, 204 GLuint primitive, 205 GLuint vertex_nr ) 206{ 207 drm_radeon_cmd_header_t *cmd; 208 209 assert(!(primitive & R200_VF_PRIM_WALK_IND)); 210 211 r200EmitState( rmesa ); 212 213 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS)) 214 fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__, 215 rmesa->store.cmd_used/4, primitive, vertex_nr); 216 217 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ, 218 __FUNCTION__ ); 219 cmd[0].i = 0; 220 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; 221 cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2; 222 cmd[2].i = (primitive | 223 R200_VF_PRIM_WALK_LIST | 224 R200_VF_COLOR_ORDER_RGBA | 225 (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT)); 226} 227 228 229void r200FlushElts( r200ContextPtr rmesa ) 230{ 231 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start); 232 int dwords; 233 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2; 234 235 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS)) 236 fprintf(stderr, "%s\n", __FUNCTION__); 237 238 assert( rmesa->dma.flush == r200FlushElts ); 239 rmesa->dma.flush = NULL; 240 241 /* Cope with odd number of elts: 242 */ 243 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2; 244 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4; 245 246 cmd[1] |= (dwords - 3) << 16; 247 cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT; 248 249 if (R200_DEBUG & DEBUG_SYNC) { 250 fprintf(stderr, "%s: Syncing\n", __FUNCTION__); 251 r200Finish( rmesa->glCtx ); 252 } 253} 254 255 256GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa, 257 GLuint primitive, 258 GLuint min_nr ) 259{ 260 drm_radeon_cmd_header_t *cmd; 261 GLushort *retval; 262 263 if (R200_DEBUG & DEBUG_IOCTL) 264 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive); 265 266 assert((primitive & R200_VF_PRIM_WALK_IND)); 267 268 r200EmitState( rmesa ); 269 270 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr), 271 __FUNCTION__ ); 272 cmd[0].i = 0; 273 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; 274 cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2; 275 cmd[2].i = (primitive | 276 R200_VF_PRIM_WALK_IND | 277 R200_VF_COLOR_ORDER_RGBA); 278 279 280 retval = (GLushort *)(cmd+3); 281 282 if (R200_DEBUG & DEBUG_PRIMS) 283 fprintf(stderr, "%s: header 0x%x prim %x \n", 284 __FUNCTION__, 285 cmd[1].i, primitive); 286 287 assert(!rmesa->dma.flush); 288 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; 289 rmesa->dma.flush = r200FlushElts; 290 291 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf; 292 293 return retval; 294} 295 296 297 298void r200EmitVertexAOS( r200ContextPtr rmesa, 299 GLuint vertex_size, 300 GLuint offset ) 301{ 302 drm_radeon_cmd_header_t *cmd; 303 304 if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL)) 305 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", 306 __FUNCTION__, vertex_size, offset); 307 308 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ, 309 __FUNCTION__ ); 310 311 cmd[0].header.cmd_type = RADEON_CMD_PACKET3; 312 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16); 313 cmd[2].i = 1; 314 cmd[3].i = vertex_size | (vertex_size << 8); 315 cmd[4].i = offset; 316} 317 318 319void r200EmitAOS( r200ContextPtr rmesa, 320 struct r200_dma_region **component, 321 GLuint nr, 322 GLuint offset ) 323{ 324 drm_radeon_cmd_header_t *cmd; 325 int sz = AOS_BUFSZ(nr); 326 int i; 327 int *tmp; 328 329 if (R200_DEBUG & DEBUG_IOCTL) 330 fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr); 331 332 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ ); 333 cmd[0].i = 0; 334 cmd[0].header.cmd_type = RADEON_CMD_PACKET3; 335 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16); 336 cmd[2].i = nr; 337 tmp = &cmd[0].i; 338 cmd += 3; 339 340 for (i = 0 ; i < nr ; i++) { 341 if (i & 1) { 342 cmd[0].i |= ((component[i]->aos_stride << 24) | 343 (component[i]->aos_size << 16)); 344 cmd[2].i = (component[i]->aos_start + 345 offset * component[i]->aos_stride * 4); 346 cmd += 3; 347 } 348 else { 349 cmd[0].i = ((component[i]->aos_stride << 8) | 350 (component[i]->aos_size << 0)); 351 cmd[1].i = (component[i]->aos_start + 352 offset * component[i]->aos_stride * 4); 353 } 354 } 355 356 if (R200_DEBUG & DEBUG_VERTS) { 357 fprintf(stderr, "%s:\n", __FUNCTION__); 358 for (i = 0 ; i < sz ; i++) 359 fprintf(stderr, " %d: %x\n", i, tmp[i]); 360 } 361} 362 363void r200EmitBlit( r200ContextPtr rmesa, 364 GLuint color_fmt, 365 GLuint src_pitch, 366 GLuint src_offset, 367 GLuint dst_pitch, 368 GLuint dst_offset, 369 GLint srcx, GLint srcy, 370 GLint dstx, GLint dsty, 371 GLuint w, GLuint h ) 372{ 373 drm_radeon_cmd_header_t *cmd; 374 375 if (R200_DEBUG & DEBUG_IOCTL) 376 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n", 377 __FUNCTION__, 378 src_pitch, src_offset, srcx, srcy, 379 dst_pitch, dst_offset, dstx, dsty, 380 w, h); 381 382 assert( (src_pitch & 63) == 0 ); 383 assert( (dst_pitch & 63) == 0 ); 384 assert( (src_offset & 1023) == 0 ); 385 assert( (dst_offset & 1023) == 0 ); 386 assert( w < (1<<16) ); 387 assert( h < (1<<16) ); 388 389 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int), 390 __FUNCTION__ ); 391 392 393 cmd[0].header.cmd_type = RADEON_CMD_PACKET3; 394 cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16); 395 cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 396 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 397 RADEON_GMC_BRUSH_NONE | 398 (color_fmt << 8) | 399 RADEON_GMC_SRC_DATATYPE_COLOR | 400 RADEON_ROP3_S | 401 RADEON_DP_SRC_SOURCE_MEMORY | 402 RADEON_GMC_CLR_CMP_CNTL_DIS | 403 RADEON_GMC_WR_MSK_DIS ); 404 405 cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10); 406 cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10); 407 cmd[5].i = (srcx << 16) | srcy; 408 cmd[6].i = (dstx << 16) | dsty; /* dst */ 409 cmd[7].i = (w << 16) | h; 410} 411 412 413void r200EmitWait( r200ContextPtr rmesa, GLuint flags ) 414{ 415 if (rmesa->dri.drmMinor >= 6) { 416 drm_radeon_cmd_header_t *cmd; 417 418 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) ); 419 420 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int), 421 __FUNCTION__ ); 422 cmd[0].i = 0; 423 cmd[0].wait.cmd_type = RADEON_CMD_WAIT; 424 cmd[0].wait.flags = flags; 425 } 426} 427