1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes 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 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com>
43 #include "simple_list.h"
44 #include "swrast/swrast.h"
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"
52 #define STANDALONE_MMIO
53 #include "radeon_macros.h" /* for INREG() */
57 #define RADEON_TIMEOUT 512
58 #define RADEON_IDLE_RETRY 16
61 static void radeonWaitForIdle( radeonContextPtr rmesa
);
63 /* =============================================================
64 * Kernel command buffer handling
67 static void print_state_atom( struct radeon_state_atom
*state
)
71 fprintf(stderr
, "emit %s/%d\n", state
->name
, state
->cmd_size
);
73 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
74 for (i
= 0 ; i
< state
->cmd_size
; i
++)
75 fprintf(stderr
, "\t%s[%d]: %x\n", state
->name
, i
, state
->cmd
[i
]);
79 static void radeon_emit_state_list( radeonContextPtr rmesa
,
80 struct radeon_state_atom
*list
)
82 struct radeon_state_atom
*state
, *tmp
;
84 int i
, size
, texunits
;
86 /* It appears that some permutations of state atoms lock up the
87 * chip. Therefore we make sure that state atoms are emitted in a
88 * fixed order. First mark all dirty state atoms and then go
89 * through all state atoms in a well defined order and emit only
91 * FIXME: This requires knowledge of which state atoms exist.
92 * FIXME: Is the zbs hack below still needed?
95 foreach_s( state
, tmp
, list
) {
96 if (state
->check( rmesa
->glCtx
)) {
97 size
+= state
->cmd_size
;
98 state
->dirty
= GL_TRUE
;
99 move_to_head( &(rmesa
->hw
.clean
), state
);
100 if (RADEON_DEBUG
& DEBUG_STATE
)
101 print_state_atom( state
);
103 else if (RADEON_DEBUG
& DEBUG_STATE
)
104 fprintf(stderr
, "skip state %s\n", state
->name
);
110 dest
= radeonAllocCmdBuf( rmesa
, size
* 4, __FUNCTION__
);
111 texunits
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
113 #define EMIT_ATOM(ATOM) \
115 if (rmesa->hw.ATOM.dirty) { \
116 rmesa->hw.ATOM.dirty = GL_FALSE; \
117 memcpy( dest, rmesa->hw.ATOM.cmd, rmesa->hw.ATOM.cmd_size * 4); \
118 dest += rmesa->hw.ATOM.cmd_size * 4; \
129 for (i
= 0; i
< texunits
; ++i
) {
135 for (i
= 0; i
< 3 + texunits
; ++i
)
137 for (i
= 0; i
< 8; ++i
)
139 for (i
= 0; i
< 6; ++i
)
150 void radeonEmitState( radeonContextPtr rmesa
)
152 struct radeon_state_atom
*state
, *tmp
;
154 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
155 fprintf(stderr
, "%s\n", __FUNCTION__
);
157 /* Somewhat overkill:
159 if (rmesa
->lost_context
) {
160 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
|DEBUG_IOCTL
))
161 fprintf(stderr
, "%s - lost context\n", __FUNCTION__
);
163 foreach_s( state
, tmp
, &(rmesa
->hw
.clean
) )
164 move_to_tail(&(rmesa
->hw
.dirty
), state
);
166 rmesa
->lost_context
= 0;
169 /* This is a darstardly kludge to work around a lockup that I
170 * haven't otherwise figured out.
172 move_to_tail(&(rmesa
->hw
.dirty
), &(rmesa
->hw
.zbs
) );
175 if (!(rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
)) {
176 foreach_s( state
, tmp
, &(rmesa
->hw
.dirty
) ) {
178 move_to_head( &(rmesa
->hw
.clean
), state
);
183 radeon_emit_state_list( rmesa
, &rmesa
->hw
.dirty
);
188 /* Fire a section of the retained (indexed_verts) buffer as a regular
191 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
192 GLuint vertex_format
,
196 drm_radeon_cmd_header_t
*cmd
;
199 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
201 radeonEmitState( rmesa
);
203 if (RADEON_DEBUG
& DEBUG_IOCTL
)
204 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
205 rmesa
->store
.cmd_used
/4);
207 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VBUF_BUFSZ
,
209 #if RADEON_OLD_PACKETS
211 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
212 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
| (3 << 16);
213 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
214 cmd
[3].i
= vertex_nr
;
215 cmd
[4].i
= vertex_format
;
216 cmd
[5].i
= (primitive
|
217 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
218 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
219 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
220 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
222 if (RADEON_DEBUG
& DEBUG_PRIMS
)
223 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
225 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
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
));
239 if (RADEON_DEBUG
& DEBUG_PRIMS
)
240 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
242 cmd
[1].i
, cmd
[2].i
, cmd
[3].i
);
247 void radeonFlushElts( radeonContextPtr rmesa
)
249 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
251 #if RADEON_OLD_PACKETS
252 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 24)) / 2;
254 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 16)) / 2;
257 if (RADEON_DEBUG
& DEBUG_IOCTL
)
258 fprintf(stderr
, "%s\n", __FUNCTION__
);
260 assert( rmesa
->dma
.flush
== radeonFlushElts
);
261 rmesa
->dma
.flush
= 0;
263 /* Cope with odd number of elts:
265 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
266 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
268 #if RADEON_OLD_PACKETS
269 cmd
[1] |= (dwords
- 3) << 16;
270 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
272 cmd
[1] |= (dwords
- 3) << 16;
273 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
278 GLushort
*radeonAllocEltsOpenEnded( radeonContextPtr rmesa
,
279 GLuint vertex_format
,
283 drm_radeon_cmd_header_t
*cmd
;
286 if (RADEON_DEBUG
& DEBUG_IOCTL
)
287 fprintf(stderr
, "%s %d\n", __FUNCTION__
, min_nr
);
289 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
291 radeonEmitState( rmesa
);
293 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
296 #if RADEON_OLD_PACKETS
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
;
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
);
308 retval
= (GLushort
*)(cmd
+6);
311 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
312 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_INDX
;
313 cmd
[2].i
= vertex_format
;
314 cmd
[3].i
= (primitive
|
315 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
316 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
317 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
318 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
320 retval
= (GLushort
*)(cmd
+4);
323 if (RADEON_DEBUG
& DEBUG_PRIMS
)
324 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
326 cmd
[1].i
, vertex_format
, primitive
);
328 assert(!rmesa
->dma
.flush
);
329 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
330 rmesa
->dma
.flush
= radeonFlushElts
;
332 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
339 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
343 #if RADEON_OLD_PACKETS
344 rmesa
->ioctl
.vertex_size
= vertex_size
;
345 rmesa
->ioctl
.vertex_offset
= offset
;
347 drm_radeon_cmd_header_t
*cmd
;
349 if (RADEON_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
350 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
351 __FUNCTION__
, vertex_size
, offset
);
353 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
357 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
358 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
360 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
366 void radeonEmitAOS( radeonContextPtr rmesa
,
367 struct radeon_dma_region
**component
,
371 #if RADEON_OLD_PACKETS
373 assert( component
[0]->aos_size
== component
[0]->aos_stride
);
374 rmesa
->ioctl
.vertex_size
= component
[0]->aos_size
;
375 rmesa
->ioctl
.vertex_offset
=
376 (component
[0]->aos_start
+ offset
* component
[0]->aos_stride
* 4);
378 drm_radeon_cmd_header_t
*cmd
;
383 if (RADEON_DEBUG
& DEBUG_IOCTL
)
384 fprintf(stderr
, "%s\n", __FUNCTION__
);
387 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
,
390 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
391 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int))-3) << 16);
396 for (i
= 0 ; i
< nr
; i
++) {
398 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
399 (component
[i
]->aos_size
<< 16));
400 cmd
[2].i
= (component
[i
]->aos_start
+
401 offset
* component
[i
]->aos_stride
* 4);
405 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
406 (component
[i
]->aos_size
<< 0));
407 cmd
[1].i
= (component
[i
]->aos_start
+
408 offset
* component
[i
]->aos_stride
* 4);
412 if (RADEON_DEBUG
& DEBUG_VERTS
) {
413 fprintf(stderr
, "%s:\n", __FUNCTION__
);
414 for (i
= 0 ; i
< sz
; i
++)
415 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
420 /* using already shifted color_fmt! */
421 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
427 GLint srcx
, GLint srcy
,
428 GLint dstx
, GLint dsty
,
431 drm_radeon_cmd_header_t
*cmd
;
433 if (RADEON_DEBUG
& DEBUG_IOCTL
)
434 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
436 src_pitch
, src_offset
, srcx
, srcy
,
437 dst_pitch
, dst_offset
, dstx
, dsty
,
440 assert( (src_pitch
& 63) == 0 );
441 assert( (dst_pitch
& 63) == 0 );
442 assert( (src_offset
& 1023) == 0 );
443 assert( (dst_offset
& 1023) == 0 );
444 assert( w
< (1<<16) );
445 assert( h
< (1<<16) );
447 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
452 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
453 cmd
[1].i
= RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
| (5 << 16);
454 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
455 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
456 RADEON_GMC_BRUSH_NONE
|
458 RADEON_GMC_SRC_DATATYPE_COLOR
|
460 RADEON_DP_SRC_SOURCE_MEMORY
|
461 RADEON_GMC_CLR_CMP_CNTL_DIS
|
462 RADEON_GMC_WR_MSK_DIS
);
464 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
465 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
466 cmd
[5].i
= (srcx
<< 16) | srcy
;
467 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
468 cmd
[7].i
= (w
<< 16) | h
;
472 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
474 if (rmesa
->dri
.drmMinor
>= 6) {
475 drm_radeon_cmd_header_t
*cmd
;
477 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
479 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 1 * sizeof(int),
482 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
483 cmd
[0].wait
.flags
= flags
;
488 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
489 const char * caller
)
492 drm_radeon_cmd_buffer_t cmd
;
494 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
495 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
497 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
498 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
499 fprintf(stderr
, "%d: %x\n", i
/4,
500 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
503 if (RADEON_DEBUG
& DEBUG_DMA
)
504 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
505 rmesa
->dma
.nr_released_bufs
);
508 if (RADEON_DEBUG
& DEBUG_SANITY
) {
509 if (rmesa
->state
.scissor
.enabled
)
510 ret
= radeonSanityCmdBuffer( rmesa
,
511 rmesa
->state
.scissor
.numClipRects
,
512 rmesa
->state
.scissor
.pClipRects
);
514 ret
= radeonSanityCmdBuffer( rmesa
,
518 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
524 cmd
.bufsz
= rmesa
->store
.cmd_used
;
525 cmd
.buf
= rmesa
->store
.cmd_buf
;
527 if (rmesa
->state
.scissor
.enabled
) {
528 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
529 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
531 cmd
.nbox
= rmesa
->numClipRects
;
532 cmd
.boxes
= rmesa
->pClipRects
;
535 ret
= drmCommandWrite( rmesa
->dri
.fd
,
540 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
543 rmesa
->store
.primnr
= 0;
544 rmesa
->store
.statenr
= 0;
545 rmesa
->store
.cmd_used
= 0;
546 rmesa
->dma
.nr_released_bufs
= 0;
547 /* Set lost_context so that the first state emit on the new buffer is a full
548 * one. This is because the context might get lost while preparing the next
549 * buffer, and when we lock and find out, we don't have the information to
550 * recreate the state. This function should always be called before the new
551 * buffer is begun, so it's sufficient to just set lost_context here.
553 * The alternative to this would be to copy out the state on unlock
554 * (approximately) and if we did lose the context, dispatch a cmdbuf to reset
555 * the state to that old copy before continuing with the accumulated command
558 rmesa
->lost_context
= 1;
564 /* Note: does not emit any commands to avoid recursion on
567 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
572 LOCK_HARDWARE( rmesa
);
574 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
576 UNLOCK_HARDWARE( rmesa
);
579 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
584 /* =============================================================
585 * Hardware vertex buffer handling
589 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
591 struct radeon_dma_buffer
*dmabuf
;
592 int fd
= rmesa
->dri
.fd
;
598 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
599 fprintf(stderr
, "%s\n", __FUNCTION__
);
601 if (rmesa
->dma
.flush
) {
602 rmesa
->dma
.flush( rmesa
);
605 if (rmesa
->dma
.current
.buf
)
606 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
608 if (rmesa
->dma
.nr_released_bufs
> 4)
609 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
611 dma
.context
= rmesa
->dri
.hwContext
;
613 dma
.send_list
= NULL
;
614 dma
.send_sizes
= NULL
;
616 dma
.request_count
= 1;
617 dma
.request_size
= RADEON_BUFFER_SIZE
;
618 dma
.request_list
= &index
;
619 dma
.request_sizes
= &size
;
620 dma
.granted_count
= 0;
622 LOCK_HARDWARE(rmesa
); /* no need to validate */
624 ret
= drmDMA( fd
, &dma
);
627 /* Free some up this way?
629 if (rmesa
->dma
.nr_released_bufs
) {
630 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
633 if (RADEON_DEBUG
& DEBUG_DMA
)
634 fprintf(stderr
, "Waiting for buffers\n");
636 radeonWaitForIdleLocked( rmesa
);
637 ret
= drmDMA( fd
, &dma
);
640 UNLOCK_HARDWARE( rmesa
);
641 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
646 UNLOCK_HARDWARE(rmesa
);
648 if (RADEON_DEBUG
& DEBUG_DMA
)
649 fprintf(stderr
, "Allocated buffer %d\n", index
);
651 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
652 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
653 dmabuf
->refcount
= 1;
655 rmesa
->dma
.current
.buf
= dmabuf
;
656 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
657 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
658 rmesa
->dma
.current
.start
= 0;
659 rmesa
->dma
.current
.ptr
= 0;
661 rmesa
->c_vertexBuffers
++;
664 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
665 struct radeon_dma_region
*region
,
668 if (RADEON_DEBUG
& DEBUG_IOCTL
)
669 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
674 if (rmesa
->dma
.flush
)
675 rmesa
->dma
.flush( rmesa
);
677 if (--region
->buf
->refcount
== 0) {
678 drm_radeon_cmd_header_t
*cmd
;
680 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
681 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
682 region
->buf
->buf
->idx
);
684 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
686 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
687 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
689 rmesa
->dma
.nr_released_bufs
++;
696 /* Allocates a region from rmesa->dma.current. If there isn't enough
697 * space in current, grab a new buffer (and discard what was left of current)
699 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
700 struct radeon_dma_region
*region
,
704 if (RADEON_DEBUG
& DEBUG_IOCTL
)
705 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
707 if (rmesa
->dma
.flush
)
708 rmesa
->dma
.flush( rmesa
);
711 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
714 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
715 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
717 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
718 radeonRefillCurrentDmaRegion( rmesa
);
720 region
->start
= rmesa
->dma
.current
.start
;
721 region
->ptr
= rmesa
->dma
.current
.start
;
722 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
723 region
->address
= rmesa
->dma
.current
.address
;
724 region
->buf
= rmesa
->dma
.current
.buf
;
725 region
->buf
->refcount
++;
727 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
728 rmesa
->dma
.current
.start
=
729 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
732 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa
,
733 struct radeon_dma_region
*region
,
738 radeonAllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
741 /* ================================================================
742 * SwapBuffers with client-side throttling
745 static uint32_t radeonGetLastFrame (radeonContextPtr rmesa
)
747 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
751 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
752 drm_radeon_getparam_t gp
;
754 gp
.param
= RADEON_PARAM_LAST_FRAME
;
755 gp
.value
= (int *)&frame
;
756 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
762 if ( ret
== -EINVAL
) {
763 frame
= INREG( RADEON_LAST_FRAME_REG
);
767 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
774 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
776 drm_radeon_irq_emit_t ie
;
779 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
780 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
783 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
789 static void radeonWaitIrq( radeonContextPtr rmesa
)
794 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
795 &rmesa
->iw
, sizeof(rmesa
->iw
) );
796 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
799 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
805 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
807 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
809 if (rmesa
->do_irqs
) {
810 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
811 if (!rmesa
->irqsEmitted
) {
812 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
816 UNLOCK_HARDWARE( rmesa
);
817 radeonWaitIrq( rmesa
);
818 LOCK_HARDWARE( rmesa
);
820 rmesa
->irqsEmitted
= 10;
823 if (rmesa
->irqsEmitted
) {
824 radeonEmitIrqLocked( rmesa
);
825 rmesa
->irqsEmitted
--;
829 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
830 UNLOCK_HARDWARE( rmesa
);
831 if (rmesa
->do_usleeps
)
833 LOCK_HARDWARE( rmesa
);
838 /* Copy the back color buffer to the front color buffer.
840 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
842 radeonContextPtr rmesa
;
844 GLboolean missed_target
;
848 assert(dPriv
->driContextPriv
);
849 assert(dPriv
->driContextPriv
->driverPrivate
);
851 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
853 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
854 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
857 RADEON_FIREVERTICES( rmesa
);
858 LOCK_HARDWARE( rmesa
);
860 /* Throttle the frame rate -- only allow one pending swap buffers
863 radeonWaitForFrameCompletion( rmesa
);
864 UNLOCK_HARDWARE( rmesa
);
865 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
866 LOCK_HARDWARE( rmesa
);
868 nbox
= dPriv
->numClipRects
; /* must be in locked region */
870 for ( i
= 0 ; i
< nbox
; ) {
871 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
872 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
873 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
876 for ( ; i
< nr
; i
++ ) {
880 rmesa
->sarea
->nbox
= n
;
882 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
885 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
886 UNLOCK_HARDWARE( rmesa
);
891 UNLOCK_HARDWARE( rmesa
);
893 (*rmesa
->get_ust
)( & ust
);
894 if ( missed_target
) {
895 rmesa
->swap_missed_count
++;
896 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
899 rmesa
->swap_ust
= ust
;
902 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
904 radeonContextPtr rmesa
;
906 GLboolean missed_target
;
909 assert(dPriv
->driContextPriv
);
910 assert(dPriv
->driContextPriv
->driverPrivate
);
912 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
914 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
915 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
916 rmesa
->sarea
->pfCurrentPage
);
919 RADEON_FIREVERTICES( rmesa
);
920 LOCK_HARDWARE( rmesa
);
922 /* Need to do this for the perf box placement:
924 if (dPriv
->numClipRects
)
926 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
927 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
929 rmesa
->sarea
->nbox
= 1;
932 /* Throttle the frame rate -- only allow a few pending swap buffers
935 radeonWaitForFrameCompletion( rmesa
);
936 UNLOCK_HARDWARE( rmesa
);
937 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
938 if ( missed_target
) {
939 rmesa
->swap_missed_count
++;
940 (void) (*rmesa
->get_ust
)( & rmesa
->swap_missed_ust
);
942 LOCK_HARDWARE( rmesa
);
944 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
946 UNLOCK_HARDWARE( rmesa
);
949 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
954 (void) (*rmesa
->get_ust
)( & rmesa
->swap_ust
);
956 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
957 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->frontOffset
;
958 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->frontPitch
;
960 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->backOffset
;
961 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->backPitch
;
964 RADEON_STATECHANGE( rmesa
, ctx
);
965 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
966 + rmesa
->radeonScreen
->fbLocation
;
967 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
971 /* ================================================================
974 #define RADEON_MAX_CLEARS 256
976 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
977 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
979 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
980 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
981 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
982 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
985 GLuint color_mask
= 0;
988 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
989 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
990 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
993 RADEON_FIREVERTICES( rmesa
);
995 if ( mask
& DD_FRONT_LEFT_BIT
) {
996 flags
|= RADEON_FRONT
;
997 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
998 mask
&= ~DD_FRONT_LEFT_BIT
;
1001 if ( mask
& DD_BACK_LEFT_BIT
) {
1002 flags
|= RADEON_BACK
;
1003 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1004 mask
&= ~DD_BACK_LEFT_BIT
;
1007 if ( mask
& DD_DEPTH_BIT
) {
1008 if ( ctx
->Depth
.Mask
) flags
|= RADEON_DEPTH
; /* FIXME: ??? */
1009 mask
&= ~DD_DEPTH_BIT
;
1012 if ( (mask
& DD_STENCIL_BIT
) && rmesa
->state
.stencil
.hwBuffer
) {
1013 flags
|= RADEON_STENCIL
;
1014 mask
&= ~DD_STENCIL_BIT
;
1018 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1019 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1020 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1027 /* Flip top to bottom */
1029 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1031 /* We have to emit state along with the clear, since the kernel relies on
1032 * some of it. The EmitState that was above RADEON_FIREVERTICES was an
1033 * attempt to do that, except that another context may come in and cause us
1034 * to lose our context while we're unlocked.
1036 radeonEmitState( rmesa
);
1038 LOCK_HARDWARE( rmesa
);
1040 /* Throttle the number of clear ioctls we do.
1045 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1046 drm_radeon_getparam_t gp
;
1048 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1049 gp
.value
= (int *)&clear
;
1050 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1051 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1055 if ( ret
== -EINVAL
) {
1056 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1060 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1063 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1064 fprintf( stderr
, "%s( %d )\n", __FUNCTION__
, (int)clear
);
1065 if ( ret
) fprintf( stderr
, " ( RADEON_LAST_CLEAR register read directly )\n" );
1068 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1072 if ( rmesa
->do_usleeps
) {
1073 UNLOCK_HARDWARE( rmesa
);
1075 LOCK_HARDWARE( rmesa
);
1079 /* Send current state to the hardware */
1080 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1082 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1083 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1084 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1085 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1086 drm_radeon_clear_t clear
;
1087 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1091 for ( ; i
< nr
; i
++ ) {
1092 GLint x
= box
[i
].x1
;
1093 GLint y
= box
[i
].y1
;
1094 GLint w
= box
[i
].x2
- x
;
1095 GLint h
= box
[i
].y2
- y
;
1097 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1098 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1099 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1100 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1101 if ( w
<= 0 ) continue;
1102 if ( h
<= 0 ) continue;
1112 for ( ; i
< nr
; i
++ ) {
1118 rmesa
->sarea
->nbox
= n
;
1120 clear
.flags
= flags
;
1121 clear
.clear_color
= rmesa
->state
.color
.clear
;
1122 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1123 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1124 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1125 clear
.depth_boxes
= depth_boxes
;
1128 b
= rmesa
->sarea
->boxes
;
1129 for ( ; n
>= 0 ; n
-- ) {
1130 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1131 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1132 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1133 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1134 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1135 (float)rmesa
->state
.depth
.clear
;
1138 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1139 &clear
, sizeof(drm_radeon_clear_t
));
1142 UNLOCK_HARDWARE( rmesa
);
1143 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1148 UNLOCK_HARDWARE( rmesa
);
1152 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1154 int fd
= rmesa
->dri
.fd
;
1158 rmesa
->c_drawWaits
++;
1162 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1163 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1164 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1167 UNLOCK_HARDWARE( rmesa
);
1168 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1174 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1176 LOCK_HARDWARE(rmesa
);
1177 radeonWaitForIdleLocked( rmesa
);
1178 UNLOCK_HARDWARE(rmesa
);
1182 void radeonFlush( GLcontext
*ctx
)
1184 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1186 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1187 fprintf(stderr
, "%s\n", __FUNCTION__
);
1189 if (rmesa
->dma
.flush
)
1190 rmesa
->dma
.flush( rmesa
);
1192 if (!is_empty_list(&rmesa
->hw
.dirty
))
1193 radeonEmitState( rmesa
);
1195 if (rmesa
->store
.cmd_used
)
1196 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1199 /* Make sure all commands have been sent to the hardware and have
1200 * completed processing.
1202 void radeonFinish( GLcontext
*ctx
)
1204 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1207 if (rmesa
->do_irqs
) {
1208 LOCK_HARDWARE( rmesa
);
1209 radeonEmitIrqLocked( rmesa
);
1210 UNLOCK_HARDWARE( rmesa
);
1211 radeonWaitIrq( rmesa
);
1214 radeonWaitForIdle( rmesa
);
1218 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1220 ctx
->Driver
.Clear
= radeonClear
;
1221 ctx
->Driver
.Finish
= radeonFinish
;
1222 ctx
->Driver
.Flush
= radeonFlush
;