radeon_ioctl.c revision 16c704e8f7cd9b7d7c5d6667cb38e016e3b608d1
1/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes Exp $ */ 2/************************************************************************** 3 4Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and 5 VA Linux Systems Inc., Fremont, California. 6 7All Rights Reserved. 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/* 32 * Authors: 33 * Kevin E. Martin <martin@valinux.com> 34 * Gareth Hughes <gareth@valinux.com> 35 * Keith Whitwell <keith@tungstengraphics.com> 36 */ 37 38#include <sched.h> 39#include <errno.h> 40 41#include "glheader.h" 42#include "imports.h" 43#include "simple_list.h" 44#include "swrast/swrast.h" 45 46#include "radeon_context.h" 47#include "radeon_state.h" 48#include "radeon_ioctl.h" 49#include "radeon_tcl.h" 50#include "radeon_sanity.h" 51 52#include "radeon_macros.h" /* for INREG() */ 53 54#include "vblank.h" 55 56#define RADEON_TIMEOUT 512 57#define RADEON_IDLE_RETRY 16 58 59 60static void radeonWaitForIdle( radeonContextPtr rmesa ); 61 62/* ============================================================= 63 * Kernel command buffer handling 64 */ 65 66static void print_state_atom( struct radeon_state_atom *state ) 67{ 68 int i; 69 70 fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size); 71 72 if (RADEON_DEBUG & DEBUG_VERBOSE) 73 for (i = 0 ; i < state->cmd_size ; i++) 74 fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]); 75 76} 77 78static void radeon_emit_state_list( radeonContextPtr rmesa, 79 struct radeon_state_atom *list ) 80{ 81 struct radeon_state_atom *state, *tmp; 82 char *dest; 83 int i, size, texunits; 84 85 /* It appears that some permutations of state atoms lock up the 86 * chip. Therefore we make sure that state atoms are emitted in a 87 * fixed order. First mark all dirty state atoms and then go 88 * through all state atoms in a well defined order and emit only 89 * the marked ones. 90 * FIXME: This requires knowledge of which state atoms exist. 91 * FIXME: Is the zbs hack below still needed? 92 */ 93 size = 0; 94 foreach_s( state, tmp, list ) { 95 if (state->check( rmesa->glCtx )) { 96 size += state->cmd_size; 97 state->dirty = GL_TRUE; 98 move_to_head( &(rmesa->hw.clean), state ); 99 if (RADEON_DEBUG & DEBUG_STATE) 100 print_state_atom( state ); 101 } 102 else if (RADEON_DEBUG & DEBUG_STATE) 103 fprintf(stderr, "skip state %s\n", state->name); 104 } 105 /* short cut */ 106 if (!size) 107 return; 108 109 dest = radeonAllocCmdBuf( rmesa, size * 4, __FUNCTION__); 110 texunits = rmesa->glCtx->Const.MaxTextureUnits; 111 112#define EMIT_ATOM(ATOM) \ 113do { \ 114 if (rmesa->hw.ATOM.dirty) { \ 115 rmesa->hw.ATOM.dirty = GL_FALSE; \ 116 memcpy( dest, rmesa->hw.ATOM.cmd, rmesa->hw.ATOM.cmd_size * 4); \ 117 dest += rmesa->hw.ATOM.cmd_size * 4; \ 118 } \ 119} while (0) 120 121 EMIT_ATOM (ctx); 122 EMIT_ATOM (set); 123 EMIT_ATOM (lin); 124 EMIT_ATOM (msk); 125 EMIT_ATOM (vpt); 126 EMIT_ATOM (tcl); 127 EMIT_ATOM (msc); 128 for (i = 0; i < texunits; ++i) { 129 EMIT_ATOM (tex[i]); 130 EMIT_ATOM (txr[i]); 131 } 132 EMIT_ATOM (zbs); 133 EMIT_ATOM (mtl); 134 for (i = 0; i < 3 + texunits; ++i) 135 EMIT_ATOM (mat[i]); 136 for (i = 0; i < 8; ++i) 137 EMIT_ATOM (lit[i]); 138 for (i = 0; i < 6; ++i) 139 EMIT_ATOM (ucp[i]); 140 EMIT_ATOM (eye); 141 EMIT_ATOM (grd); 142 EMIT_ATOM (fog); 143 EMIT_ATOM (glt); 144 145#undef EMIT_ATOM 146} 147 148 149void radeonEmitState( radeonContextPtr rmesa ) 150{ 151 struct radeon_state_atom *state, *tmp; 152 153 if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS)) 154 fprintf(stderr, "%s\n", __FUNCTION__); 155 156 /* Somewhat overkill: 157 */ 158 if (rmesa->lost_context) { 159 if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL)) 160 fprintf(stderr, "%s - lost context\n", __FUNCTION__); 161 162 foreach_s( state, tmp, &(rmesa->hw.clean) ) 163 move_to_tail(&(rmesa->hw.dirty), state ); 164 165 rmesa->lost_context = 0; 166 } 167 else if (1) { 168 /* This is a darstardly kludge to work around a lockup that I 169 * haven't otherwise figured out. 170 */ 171 move_to_tail(&(rmesa->hw.dirty), &(rmesa->hw.zbs) ); 172 } 173 174 if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) { 175 foreach_s( state, tmp, &(rmesa->hw.dirty) ) { 176 if (state->is_tcl) { 177 move_to_head( &(rmesa->hw.clean), state ); 178 } 179 } 180 } 181 182 radeon_emit_state_list( rmesa, &rmesa->hw.dirty ); 183} 184 185 186 187/* Fire a section of the retained (indexed_verts) buffer as a regular 188 * primtive. 189 */ 190extern void radeonEmitVbufPrim( radeonContextPtr rmesa, 191 GLuint vertex_format, 192 GLuint primitive, 193 GLuint vertex_nr ) 194{ 195 drm_radeon_cmd_header_t *cmd; 196 197 198 assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); 199 200 radeonEmitState( rmesa ); 201 202 if (RADEON_DEBUG & DEBUG_IOCTL) 203 fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__, 204 rmesa->store.cmd_used/4); 205 206#if RADEON_OLD_PACKETS 207 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 6 * sizeof(*cmd), 208 __FUNCTION__ ); 209 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; 210 cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16); 211 cmd[2].i = rmesa->ioctl.vertex_offset; 212 cmd[3].i = vertex_nr; 213 cmd[4].i = vertex_format; 214 cmd[5].i = (primitive | 215 RADEON_CP_VC_CNTL_PRIM_WALK_LIST | 216 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | 217 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | 218 (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT)); 219 220 if (RADEON_DEBUG & DEBUG_PRIMS) 221 fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n", 222 __FUNCTION__, 223 cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i); 224#else 225 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 4 * sizeof(*cmd), 226 __FUNCTION__ ); 227 cmd[0].i = 0; 228 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; 229 cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16); 230 cmd[2].i = vertex_format; 231 cmd[3].i = (primitive | 232 RADEON_CP_VC_CNTL_PRIM_WALK_LIST | 233 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | 234 RADEON_CP_VC_CNTL_MAOS_ENABLE | 235 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE | 236 (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT)); 237 238 239 if (RADEON_DEBUG & DEBUG_PRIMS) 240 fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n", 241 __FUNCTION__, 242 cmd[1].i, cmd[2].i, cmd[3].i); 243#endif 244} 245 246 247void radeonFlushElts( radeonContextPtr rmesa ) 248{ 249 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start); 250 int dwords; 251#if RADEON_OLD_PACKETS 252 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2; 253#else 254 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2; 255#endif 256 257 if (RADEON_DEBUG & DEBUG_IOCTL) 258 fprintf(stderr, "%s\n", __FUNCTION__); 259 260 assert( rmesa->dma.flush == radeonFlushElts ); 261 rmesa->dma.flush = 0; 262 263 /* Cope with odd number of elts: 264 */ 265 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2; 266 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4; 267 268#if RADEON_OLD_PACKETS 269 cmd[1] |= (dwords - 3) << 16; 270 cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT; 271#else 272 cmd[1] |= (dwords - 3) << 16; 273 cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT; 274#endif 275} 276 277 278GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa, 279 GLuint vertex_format, 280 GLuint primitive, 281 GLuint min_nr ) 282{ 283 drm_radeon_cmd_header_t *cmd; 284 GLushort *retval; 285 286 if (RADEON_DEBUG & DEBUG_IOCTL) 287 fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr); 288 289 assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND)); 290 291 radeonEmitState( rmesa ); 292 293#if RADEON_OLD_PACKETS 294 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 295 24 + min_nr*2, 296 __FUNCTION__ ); 297 cmd[0].i = 0; 298 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; 299 cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM; 300 cmd[2].i = rmesa->ioctl.vertex_offset; 301 cmd[3].i = 0xffff; 302 cmd[4].i = vertex_format; 303 cmd[5].i = (primitive | 304 RADEON_CP_VC_CNTL_PRIM_WALK_IND | 305 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | 306 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE); 307 308 retval = (GLushort *)(cmd+6); 309#else 310 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 311 16 + min_nr*2, 312 __FUNCTION__ ); 313 cmd[0].i = 0; 314 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP; 315 cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX; 316 cmd[2].i = vertex_format; 317 cmd[3].i = (primitive | 318 RADEON_CP_VC_CNTL_PRIM_WALK_IND | 319 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA | 320 RADEON_CP_VC_CNTL_MAOS_ENABLE | 321 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE); 322 323 retval = (GLushort *)(cmd+4); 324#endif 325 326 if (RADEON_DEBUG & DEBUG_PRIMS) 327 fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n", 328 __FUNCTION__, 329 cmd[1].i, vertex_format, primitive); 330 331 assert(!rmesa->dma.flush); 332 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; 333 rmesa->dma.flush = radeonFlushElts; 334 335 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf; 336 337 return retval; 338} 339 340 341 342void radeonEmitVertexAOS( radeonContextPtr rmesa, 343 GLuint vertex_size, 344 GLuint offset ) 345{ 346#if RADEON_OLD_PACKETS 347 rmesa->ioctl.vertex_size = vertex_size; 348 rmesa->ioctl.vertex_offset = offset; 349#else 350 drm_radeon_cmd_header_t *cmd; 351 352 if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL)) 353 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n", 354 __FUNCTION__, vertex_size, offset); 355 356 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 5 * sizeof(int), 357 __FUNCTION__ ); 358 359 cmd[0].i = 0; 360 cmd[0].header.cmd_type = RADEON_CMD_PACKET3; 361 cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16); 362 cmd[2].i = 1; 363 cmd[3].i = vertex_size | (vertex_size << 8); 364 cmd[4].i = offset; 365#endif 366} 367 368 369void radeonEmitAOS( radeonContextPtr rmesa, 370 struct radeon_dma_region **component, 371 GLuint nr, 372 GLuint offset ) 373{ 374#if RADEON_OLD_PACKETS 375 assert( nr == 1 ); 376 assert( component[0]->aos_size == component[0]->aos_stride ); 377 rmesa->ioctl.vertex_size = component[0]->aos_size; 378 rmesa->ioctl.vertex_offset = 379 (component[0]->aos_start + offset * component[0]->aos_stride * 4); 380#else 381 drm_radeon_cmd_header_t *cmd; 382 int sz = 3 + (nr/2 * 3) + (nr & 1) * 2; 383 int i; 384 int *tmp; 385 386 if (RADEON_DEBUG & DEBUG_IOCTL) 387 fprintf(stderr, "%s\n", __FUNCTION__); 388 389 390 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sz * sizeof(int), 391 __FUNCTION__ ); 392 cmd[0].i = 0; 393 cmd[0].header.cmd_type = RADEON_CMD_PACKET3; 394 cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | ((sz-3) << 16); 395 cmd[2].i = nr; 396 tmp = &cmd[0].i; 397 cmd += 3; 398 399 for (i = 0 ; i < nr ; i++) { 400 if (i & 1) { 401 cmd[0].i |= ((component[i]->aos_stride << 24) | 402 (component[i]->aos_size << 16)); 403 cmd[2].i = (component[i]->aos_start + 404 offset * component[i]->aos_stride * 4); 405 cmd += 3; 406 } 407 else { 408 cmd[0].i = ((component[i]->aos_stride << 8) | 409 (component[i]->aos_size << 0)); 410 cmd[1].i = (component[i]->aos_start + 411 offset * component[i]->aos_stride * 4); 412 } 413 } 414 415 if (RADEON_DEBUG & DEBUG_VERTS) { 416 fprintf(stderr, "%s:\n", __FUNCTION__); 417 for (i = 0 ; i < sz ; i++) 418 fprintf(stderr, " %d: %x\n", i, tmp[i]); 419 } 420#endif 421} 422 423/* using already shifted color_fmt! */ 424void radeonEmitBlit( radeonContextPtr rmesa, /* FIXME: which drmMinor is required? */ 425 GLuint color_fmt, 426 GLuint src_pitch, 427 GLuint src_offset, 428 GLuint dst_pitch, 429 GLuint dst_offset, 430 GLint srcx, GLint srcy, 431 GLint dstx, GLint dsty, 432 GLuint w, GLuint h ) 433{ 434 drm_radeon_cmd_header_t *cmd; 435 436 if (RADEON_DEBUG & DEBUG_IOCTL) 437 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n", 438 __FUNCTION__, 439 src_pitch, src_offset, srcx, srcy, 440 dst_pitch, dst_offset, dstx, dsty, 441 w, h); 442 443 assert( (src_pitch & 63) == 0 ); 444 assert( (dst_pitch & 63) == 0 ); 445 assert( (src_offset & 1023) == 0 ); 446 assert( (dst_offset & 1023) == 0 ); 447 assert( w < (1<<16) ); 448 assert( h < (1<<16) ); 449 450 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int), 451 __FUNCTION__ ); 452 453 454 cmd[0].i = 0; 455 cmd[0].header.cmd_type = RADEON_CMD_PACKET3; 456 cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16); 457 cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 458 RADEON_GMC_DST_PITCH_OFFSET_CNTL | 459 RADEON_GMC_BRUSH_NONE | 460 color_fmt | 461 RADEON_GMC_SRC_DATATYPE_COLOR | 462 RADEON_ROP3_S | 463 RADEON_DP_SRC_SOURCE_MEMORY | 464 RADEON_GMC_CLR_CMP_CNTL_DIS | 465 RADEON_GMC_WR_MSK_DIS ); 466 467 cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10); 468 cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10); 469 cmd[5].i = (srcx << 16) | srcy; 470 cmd[6].i = (dstx << 16) | dsty; /* dst */ 471 cmd[7].i = (w << 16) | h; 472} 473 474 475void radeonEmitWait( radeonContextPtr rmesa, GLuint flags ) 476{ 477 if (rmesa->dri.drmMinor >= 6) { 478 drm_radeon_cmd_header_t *cmd; 479 480 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) ); 481 482 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int), 483 __FUNCTION__ ); 484 cmd[0].i = 0; 485 cmd[0].wait.cmd_type = RADEON_CMD_WAIT; 486 cmd[0].wait.flags = flags; 487 } 488} 489 490 491static int radeonFlushCmdBufLocked( radeonContextPtr rmesa, 492 const char * caller ) 493{ 494 int ret, i; 495 drm_radeon_cmd_buffer_t cmd; 496 497 if (RADEON_DEBUG & DEBUG_IOCTL) { 498 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); 499 500 if (RADEON_DEBUG & DEBUG_VERBOSE) 501 for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 ) 502 fprintf(stderr, "%d: %x\n", i/4, 503 *(int *)(&rmesa->store.cmd_buf[i])); 504 } 505 506 if (RADEON_DEBUG & DEBUG_DMA) 507 fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__, 508 rmesa->dma.nr_released_bufs); 509 510 511 if (RADEON_DEBUG & DEBUG_SANITY) { 512 if (rmesa->state.scissor.enabled) 513 ret = radeonSanityCmdBuffer( rmesa, 514 rmesa->state.scissor.numClipRects, 515 rmesa->state.scissor.pClipRects); 516 else 517 ret = radeonSanityCmdBuffer( rmesa, 518 rmesa->numClipRects, 519 rmesa->pClipRects); 520 if (ret) { 521 fprintf(stderr, "drmSanityCommandWrite: %d\n", ret); 522 goto out; 523 } 524 } 525 526 527 cmd.bufsz = rmesa->store.cmd_used; 528 cmd.buf = rmesa->store.cmd_buf; 529 530 if (rmesa->state.scissor.enabled) { 531 cmd.nbox = rmesa->state.scissor.numClipRects; 532 cmd.boxes = rmesa->state.scissor.pClipRects; 533 } else { 534 cmd.nbox = rmesa->numClipRects; 535 cmd.boxes = rmesa->pClipRects; 536 } 537 538 ret = drmCommandWrite( rmesa->dri.fd, 539 DRM_RADEON_CMDBUF, 540 &cmd, sizeof(cmd) ); 541 542 if (ret) 543 fprintf(stderr, "drmCommandWrite: %d\n", ret); 544 545 out: 546 rmesa->store.primnr = 0; 547 rmesa->store.statenr = 0; 548 rmesa->store.cmd_used = 0; 549 rmesa->dma.nr_released_bufs = 0; 550 rmesa->lost_context = 1; 551 return ret; 552} 553 554 555/* Note: does not emit any commands to avoid recursion on 556 * radeonAllocCmdBuf. 557 */ 558void radeonFlushCmdBuf( radeonContextPtr rmesa, const char *caller ) 559{ 560 int ret; 561 562 563 LOCK_HARDWARE( rmesa ); 564 565 ret = radeonFlushCmdBufLocked( rmesa, caller ); 566 567 UNLOCK_HARDWARE( rmesa ); 568 569 if (ret) { 570 fprintf(stderr, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret); 571 exit(ret); 572 } 573} 574 575/* ============================================================= 576 * Hardware vertex buffer handling 577 */ 578 579 580void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa ) 581{ 582 struct radeon_dma_buffer *dmabuf; 583 int fd = rmesa->dri.fd; 584 int index = 0; 585 int size = 0; 586 drmDMAReq dma; 587 int ret; 588 589 if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) 590 fprintf(stderr, "%s\n", __FUNCTION__); 591 592 if (rmesa->dma.flush) { 593 rmesa->dma.flush( rmesa ); 594 } 595 596 if (rmesa->dma.current.buf) 597 radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ ); 598 599 if (rmesa->dma.nr_released_bufs > 4) 600 radeonFlushCmdBuf( rmesa, __FUNCTION__ ); 601 602 dma.context = rmesa->dri.hwContext; 603 dma.send_count = 0; 604 dma.send_list = NULL; 605 dma.send_sizes = NULL; 606 dma.flags = 0; 607 dma.request_count = 1; 608 dma.request_size = RADEON_BUFFER_SIZE; 609 dma.request_list = &index; 610 dma.request_sizes = &size; 611 dma.granted_count = 0; 612 613 LOCK_HARDWARE(rmesa); /* no need to validate */ 614 615 ret = drmDMA( fd, &dma ); 616 617 if (ret != 0) { 618 /* Free some up this way? 619 */ 620 if (rmesa->dma.nr_released_bufs) { 621 radeonFlushCmdBufLocked( rmesa, __FUNCTION__ ); 622 } 623 624 if (RADEON_DEBUG & DEBUG_DMA) 625 fprintf(stderr, "Waiting for buffers\n"); 626 627 radeonWaitForIdleLocked( rmesa ); 628 ret = drmDMA( fd, &dma ); 629 630 if ( ret != 0 ) { 631 UNLOCK_HARDWARE( rmesa ); 632 fprintf( stderr, "Error: Could not get dma buffer... exiting\n" ); 633 exit( -1 ); 634 } 635 } 636 637 UNLOCK_HARDWARE(rmesa); 638 639 if (RADEON_DEBUG & DEBUG_DMA) 640 fprintf(stderr, "Allocated buffer %d\n", index); 641 642 dmabuf = CALLOC_STRUCT( radeon_dma_buffer ); 643 dmabuf->buf = &rmesa->radeonScreen->buffers->list[index]; 644 dmabuf->refcount = 1; 645 646 rmesa->dma.current.buf = dmabuf; 647 rmesa->dma.current.address = dmabuf->buf->address; 648 rmesa->dma.current.end = dmabuf->buf->total; 649 rmesa->dma.current.start = 0; 650 rmesa->dma.current.ptr = 0; 651 652 rmesa->c_vertexBuffers++; 653} 654 655void radeonReleaseDmaRegion( radeonContextPtr rmesa, 656 struct radeon_dma_region *region, 657 const char *caller ) 658{ 659 if (RADEON_DEBUG & DEBUG_IOCTL) 660 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); 661 662 if (!region->buf) 663 return; 664 665 if (rmesa->dma.flush) 666 rmesa->dma.flush( rmesa ); 667 668 if (--region->buf->refcount == 0) { 669 drm_radeon_cmd_header_t *cmd; 670 671 if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA)) 672 fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__, 673 region->buf->buf->idx); 674 675 cmd = (drm_radeon_cmd_header_t *)radeonAllocCmdBuf( rmesa, sizeof(*cmd), 676 __FUNCTION__ ); 677 cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD; 678 cmd->dma.buf_idx = region->buf->buf->idx; 679 FREE(region->buf); 680 rmesa->dma.nr_released_bufs++; 681 } 682 683 region->buf = 0; 684 region->start = 0; 685} 686 687/* Allocates a region from rmesa->dma.current. If there isn't enough 688 * space in current, grab a new buffer (and discard what was left of current) 689 */ 690void radeonAllocDmaRegion( radeonContextPtr rmesa, 691 struct radeon_dma_region *region, 692 int bytes, 693 int alignment ) 694{ 695 if (RADEON_DEBUG & DEBUG_IOCTL) 696 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes); 697 698 if (rmesa->dma.flush) 699 rmesa->dma.flush( rmesa ); 700 701 if (region->buf) 702 radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ ); 703 704 alignment--; 705 rmesa->dma.current.start = rmesa->dma.current.ptr = 706 (rmesa->dma.current.ptr + alignment) & ~alignment; 707 708 if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) 709 radeonRefillCurrentDmaRegion( rmesa ); 710 711 region->start = rmesa->dma.current.start; 712 region->ptr = rmesa->dma.current.start; 713 region->end = rmesa->dma.current.start + bytes; 714 region->address = rmesa->dma.current.address; 715 region->buf = rmesa->dma.current.buf; 716 region->buf->refcount++; 717 718 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */ 719 rmesa->dma.current.start = 720 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7; 721} 722 723void radeonAllocDmaRegionVerts( radeonContextPtr rmesa, 724 struct radeon_dma_region *region, 725 int numverts, 726 int vertsize, 727 int alignment ) 728{ 729 radeonAllocDmaRegion( rmesa, region, vertsize * numverts, alignment ); 730} 731 732/* ================================================================ 733 * SwapBuffers with client-side throttling 734 */ 735 736static int32_t radeonGetLastFrame (radeonContextPtr rmesa) 737{ 738 unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map; 739 int ret; 740 int32_t frame; 741 742 if (rmesa->dri.screen->drmMinor >= 4) { 743 drm_radeon_getparam_t gp; 744 745 gp.param = RADEON_PARAM_LAST_FRAME; 746 gp.value = (int *)&frame; 747 ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM, 748 &gp, sizeof(gp) ); 749 } 750 else 751 ret = -EINVAL; 752 753#ifndef __alpha__ 754 if ( ret == -EINVAL ) { 755 frame = INREG( RADEON_LAST_FRAME_REG ); 756 ret = 0; 757 } 758#endif 759 if ( ret ) { 760 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret ); 761 exit(1); 762 } 763 764 return frame; 765} 766 767static void radeonEmitIrqLocked( radeonContextPtr rmesa ) 768{ 769 drm_radeon_irq_emit_t ie; 770 int ret; 771 772 ie.irq_seq = &rmesa->iw.irq_seq; 773 ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT, 774 &ie, sizeof(ie) ); 775 if ( ret ) { 776 fprintf( stderr, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__, ret ); 777 exit(1); 778 } 779} 780 781 782static void radeonWaitIrq( radeonContextPtr rmesa ) 783{ 784 int ret; 785 786 do { 787 ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT, 788 &rmesa->iw, sizeof(rmesa->iw) ); 789 } while (ret && (errno == EINTR || errno == EAGAIN)); 790 791 if ( ret ) { 792 fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret ); 793 exit(1); 794 } 795} 796 797 798static void radeonWaitForFrameCompletion( radeonContextPtr rmesa ) 799{ 800 drm_radeon_sarea_t *sarea = rmesa->sarea; 801 802 if (rmesa->do_irqs) { 803 if (radeonGetLastFrame(rmesa) < sarea->last_frame) { 804 if (!rmesa->irqsEmitted) { 805 while (radeonGetLastFrame (rmesa) < sarea->last_frame) 806 ; 807 } 808 else { 809 UNLOCK_HARDWARE( rmesa ); 810 radeonWaitIrq( rmesa ); 811 LOCK_HARDWARE( rmesa ); 812 } 813 rmesa->irqsEmitted = 10; 814 } 815 816 if (rmesa->irqsEmitted) { 817 radeonEmitIrqLocked( rmesa ); 818 rmesa->irqsEmitted--; 819 } 820 } 821 else { 822 while (radeonGetLastFrame (rmesa) < sarea->last_frame) { 823 UNLOCK_HARDWARE( rmesa ); 824 if (rmesa->do_usleeps) 825 DO_USLEEP( 1 ); 826 LOCK_HARDWARE( rmesa ); 827 } 828 } 829} 830 831/* Copy the back color buffer to the front color buffer. 832 */ 833void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv ) 834{ 835 radeonContextPtr rmesa; 836 GLint nbox, i, ret; 837 GLboolean missed_target; 838 int64_t ust; 839 840 assert(dPriv); 841 assert(dPriv->driContextPriv); 842 assert(dPriv->driContextPriv->driverPrivate); 843 844 rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; 845 846 if ( RADEON_DEBUG & DEBUG_IOCTL ) { 847 fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx ); 848 } 849 850 RADEON_FIREVERTICES( rmesa ); 851 LOCK_HARDWARE( rmesa ); 852 853 /* Throttle the frame rate -- only allow one pending swap buffers 854 * request at a time. 855 */ 856 radeonWaitForFrameCompletion( rmesa ); 857 UNLOCK_HARDWARE( rmesa ); 858 driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target ); 859 LOCK_HARDWARE( rmesa ); 860 861 nbox = dPriv->numClipRects; /* must be in locked region */ 862 863 for ( i = 0 ; i < nbox ; ) { 864 GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox ); 865 drm_clip_rect_t *box = dPriv->pClipRects; 866 drm_clip_rect_t *b = rmesa->sarea->boxes; 867 GLint n = 0; 868 869 for ( ; i < nr ; i++ ) { 870 *b++ = box[i]; 871 n++; 872 } 873 rmesa->sarea->nbox = n; 874 875 ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP ); 876 877 if ( ret ) { 878 fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret ); 879 UNLOCK_HARDWARE( rmesa ); 880 exit( 1 ); 881 } 882 } 883 884 UNLOCK_HARDWARE( rmesa ); 885 rmesa->swap_count++; 886 (*rmesa->get_ust)( & ust ); 887 if ( missed_target ) { 888 rmesa->swap_missed_count++; 889 rmesa->swap_missed_ust = ust - rmesa->swap_ust; 890 } 891 892 rmesa->swap_ust = ust; 893} 894 895void radeonPageFlip( const __DRIdrawablePrivate *dPriv ) 896{ 897 radeonContextPtr rmesa; 898 GLint ret; 899 GLboolean missed_target; 900 901 assert(dPriv); 902 assert(dPriv->driContextPriv); 903 assert(dPriv->driContextPriv->driverPrivate); 904 905 rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate; 906 907 if ( RADEON_DEBUG & DEBUG_IOCTL ) { 908 fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__, 909 rmesa->sarea->pfCurrentPage); 910 } 911 912 RADEON_FIREVERTICES( rmesa ); 913 LOCK_HARDWARE( rmesa ); 914 915 /* Need to do this for the perf box placement: 916 */ 917 if (dPriv->numClipRects) 918 { 919 drm_clip_rect_t *box = dPriv->pClipRects; 920 drm_clip_rect_t *b = rmesa->sarea->boxes; 921 b[0] = box[0]; 922 rmesa->sarea->nbox = 1; 923 } 924 925 /* Throttle the frame rate -- only allow a few pending swap buffers 926 * request at a time. 927 */ 928 radeonWaitForFrameCompletion( rmesa ); 929 UNLOCK_HARDWARE( rmesa ); 930 driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target ); 931 if ( missed_target ) { 932 rmesa->swap_missed_count++; 933 (void) (*rmesa->get_ust)( & rmesa->swap_missed_ust ); 934 } 935 LOCK_HARDWARE( rmesa ); 936 937 ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP ); 938 939 UNLOCK_HARDWARE( rmesa ); 940 941 if ( ret ) { 942 fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret ); 943 exit( 1 ); 944 } 945 946 rmesa->swap_count++; 947 (void) (*rmesa->get_ust)( & rmesa->swap_ust ); 948 949 if ( rmesa->sarea->pfCurrentPage == 1 ) { 950 rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset; 951 rmesa->state.color.drawPitch = rmesa->radeonScreen->frontPitch; 952 } else { 953 rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset; 954 rmesa->state.color.drawPitch = rmesa->radeonScreen->backPitch; 955 } 956 957 RADEON_STATECHANGE( rmesa, ctx ); 958 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset 959 + rmesa->radeonScreen->fbLocation; 960 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch; 961} 962 963 964/* ================================================================ 965 * Buffer clear 966 */ 967#define RADEON_MAX_CLEARS 256 968 969static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all, 970 GLint cx, GLint cy, GLint cw, GLint ch ) 971{ 972 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 973 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 974 drm_radeon_sarea_t *sarea = rmesa->sarea; 975 unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map; 976 int32_t clear; 977 GLuint flags = 0; 978 GLuint color_mask = 0; 979 GLint ret, i; 980 981 if ( RADEON_DEBUG & DEBUG_IOCTL ) { 982 fprintf( stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n", 983 __FUNCTION__, all, cx, cy, cw, ch ); 984 } 985 986 radeonEmitState( rmesa ); 987 988 /* Need to cope with lostcontext here as kernel relies on 989 * some residual state: 990 */ 991 RADEON_FIREVERTICES( rmesa ); 992 993 if ( mask & DD_FRONT_LEFT_BIT ) { 994 flags |= RADEON_FRONT; 995 color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; 996 mask &= ~DD_FRONT_LEFT_BIT; 997 } 998 999 if ( mask & DD_BACK_LEFT_BIT ) { 1000 flags |= RADEON_BACK; 1001 color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; 1002 mask &= ~DD_BACK_LEFT_BIT; 1003 } 1004 1005 if ( mask & DD_DEPTH_BIT ) { 1006 if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */ 1007 mask &= ~DD_DEPTH_BIT; 1008 } 1009 1010 if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) { 1011 flags |= RADEON_STENCIL; 1012 mask &= ~DD_STENCIL_BIT; 1013 } 1014 1015 if ( mask ) { 1016 if (RADEON_DEBUG & DEBUG_FALLBACKS) 1017 fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask); 1018 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); 1019 } 1020 1021 if ( !flags ) 1022 return; 1023 1024 1025 /* Flip top to bottom */ 1026 cx += dPriv->x; 1027 cy = dPriv->y + dPriv->h - cy - ch; 1028 1029 LOCK_HARDWARE( rmesa ); 1030 1031 /* Throttle the number of clear ioctls we do. 1032 */ 1033 while ( 1 ) { 1034 int ret; 1035 1036 if (rmesa->dri.screen->drmMinor >= 4) { 1037 drm_radeon_getparam_t gp; 1038 1039 gp.param = RADEON_PARAM_LAST_CLEAR; 1040 gp.value = (int *)&clear; 1041 ret = drmCommandWriteRead( rmesa->dri.fd, 1042 DRM_RADEON_GETPARAM, &gp, sizeof(gp) ); 1043 } else 1044 ret = -EINVAL; 1045 1046#ifndef __alpha__ 1047 if ( ret == -EINVAL ) { 1048 clear = INREG( RADEON_LAST_CLEAR_REG ); 1049 ret = 0; 1050 } 1051#endif 1052 if ( ret ) { 1053 fprintf( stderr, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__, ret ); 1054 exit(1); 1055 } 1056 if ( RADEON_DEBUG & DEBUG_IOCTL ) { 1057 fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)clear ); 1058 if ( ret ) fprintf( stderr, " ( RADEON_LAST_CLEAR register read directly )\n" ); 1059 } 1060 1061 if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) { 1062 break; 1063 } 1064 1065 if ( rmesa->do_usleeps ) { 1066 UNLOCK_HARDWARE( rmesa ); 1067 DO_USLEEP( 1 ); 1068 LOCK_HARDWARE( rmesa ); 1069 } 1070 } 1071 1072 for ( i = 0 ; i < dPriv->numClipRects ; ) { 1073 GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects ); 1074 drm_clip_rect_t *box = dPriv->pClipRects; 1075 drm_clip_rect_t *b = rmesa->sarea->boxes; 1076 drm_radeon_clear_t clear; 1077 drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; 1078 GLint n = 0; 1079 1080 if ( !all ) { 1081 for ( ; i < nr ; i++ ) { 1082 GLint x = box[i].x1; 1083 GLint y = box[i].y1; 1084 GLint w = box[i].x2 - x; 1085 GLint h = box[i].y2 - y; 1086 1087 if ( x < cx ) w -= cx - x, x = cx; 1088 if ( y < cy ) h -= cy - y, y = cy; 1089 if ( x + w > cx + cw ) w = cx + cw - x; 1090 if ( y + h > cy + ch ) h = cy + ch - y; 1091 if ( w <= 0 ) continue; 1092 if ( h <= 0 ) continue; 1093 1094 b->x1 = x; 1095 b->y1 = y; 1096 b->x2 = x + w; 1097 b->y2 = y + h; 1098 b++; 1099 n++; 1100 } 1101 } else { 1102 for ( ; i < nr ; i++ ) { 1103 *b++ = box[i]; 1104 n++; 1105 } 1106 } 1107 1108 rmesa->sarea->nbox = n; 1109 1110 clear.flags = flags; 1111 clear.clear_color = rmesa->state.color.clear; 1112 clear.clear_depth = rmesa->state.depth.clear; 1113 clear.color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK]; 1114 clear.depth_mask = rmesa->state.stencil.clear; 1115 clear.depth_boxes = depth_boxes; 1116 1117 n--; 1118 b = rmesa->sarea->boxes; 1119 for ( ; n >= 0 ; n-- ) { 1120 depth_boxes[n].f[CLEAR_X1] = (float)b[n].x1; 1121 depth_boxes[n].f[CLEAR_Y1] = (float)b[n].y1; 1122 depth_boxes[n].f[CLEAR_X2] = (float)b[n].x2; 1123 depth_boxes[n].f[CLEAR_Y2] = (float)b[n].y2; 1124 depth_boxes[n].f[CLEAR_DEPTH] = 1125 (float)rmesa->state.depth.clear; 1126 } 1127 1128 ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR, 1129 &clear, sizeof(drm_radeon_clear_t)); 1130 1131 if ( ret ) { 1132 UNLOCK_HARDWARE( rmesa ); 1133 fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret ); 1134 exit( 1 ); 1135 } 1136 } 1137 1138 UNLOCK_HARDWARE( rmesa ); 1139} 1140 1141 1142void radeonWaitForIdleLocked( radeonContextPtr rmesa ) 1143{ 1144 int fd = rmesa->dri.fd; 1145 int to = 0; 1146 int ret, i = 0; 1147 1148 rmesa->c_drawWaits++; 1149 1150 do { 1151 do { 1152 ret = drmCommandNone( fd, DRM_RADEON_CP_IDLE); 1153 } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY ); 1154 } while ( ( ret == -EBUSY ) && ( to++ < RADEON_TIMEOUT ) ); 1155 1156 if ( ret < 0 ) { 1157 UNLOCK_HARDWARE( rmesa ); 1158 fprintf( stderr, "Error: Radeon timed out... exiting\n" ); 1159 exit( -1 ); 1160 } 1161} 1162 1163 1164static void radeonWaitForIdle( radeonContextPtr rmesa ) 1165{ 1166 LOCK_HARDWARE(rmesa); 1167 radeonWaitForIdleLocked( rmesa ); 1168 UNLOCK_HARDWARE(rmesa); 1169} 1170 1171 1172void radeonFlush( GLcontext *ctx ) 1173{ 1174 radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); 1175 1176 if (RADEON_DEBUG & DEBUG_IOCTL) 1177 fprintf(stderr, "%s\n", __FUNCTION__); 1178 1179 if (rmesa->dma.flush) 1180 rmesa->dma.flush( rmesa ); 1181 1182 if (!is_empty_list(&rmesa->hw.dirty)) 1183 radeonEmitState( rmesa ); 1184 1185 if (rmesa->store.cmd_used) 1186 radeonFlushCmdBuf( rmesa, __FUNCTION__ ); 1187} 1188 1189/* Make sure all commands have been sent to the hardware and have 1190 * completed processing. 1191 */ 1192void radeonFinish( GLcontext *ctx ) 1193{ 1194 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1195 radeonFlush( ctx ); 1196 1197 if (rmesa->do_irqs) { 1198 LOCK_HARDWARE( rmesa ); 1199 radeonEmitIrqLocked( rmesa ); 1200 UNLOCK_HARDWARE( rmesa ); 1201 radeonWaitIrq( rmesa ); 1202 } 1203 else 1204 radeonWaitForIdle( rmesa ); 1205} 1206 1207 1208void radeonInitIoctlFuncs( GLcontext *ctx ) 1209{ 1210 ctx->Driver.Clear = radeonClear; 1211 ctx->Driver.Finish = radeonFinish; 1212 ctx->Driver.Flush = radeonFlush; 1213} 1214 1215