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;
551 /* Note: does not emit any commands to avoid recursion on
554 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
559 LOCK_HARDWARE( rmesa
);
561 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
563 UNLOCK_HARDWARE( rmesa
);
566 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
571 /* =============================================================
572 * Hardware vertex buffer handling
576 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
578 struct radeon_dma_buffer
*dmabuf
;
579 int fd
= rmesa
->dri
.fd
;
585 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
586 fprintf(stderr
, "%s\n", __FUNCTION__
);
588 if (rmesa
->dma
.flush
) {
589 rmesa
->dma
.flush( rmesa
);
592 if (rmesa
->dma
.current
.buf
)
593 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
595 if (rmesa
->dma
.nr_released_bufs
> 4)
596 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
598 dma
.context
= rmesa
->dri
.hwContext
;
600 dma
.send_list
= NULL
;
601 dma
.send_sizes
= NULL
;
603 dma
.request_count
= 1;
604 dma
.request_size
= RADEON_BUFFER_SIZE
;
605 dma
.request_list
= &index
;
606 dma
.request_sizes
= &size
;
607 dma
.granted_count
= 0;
609 LOCK_HARDWARE(rmesa
); /* no need to validate */
611 ret
= drmDMA( fd
, &dma
);
614 /* Free some up this way?
616 if (rmesa
->dma
.nr_released_bufs
) {
617 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
620 if (RADEON_DEBUG
& DEBUG_DMA
)
621 fprintf(stderr
, "Waiting for buffers\n");
623 radeonWaitForIdleLocked( rmesa
);
624 ret
= drmDMA( fd
, &dma
);
627 UNLOCK_HARDWARE( rmesa
);
628 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
633 UNLOCK_HARDWARE(rmesa
);
635 if (RADEON_DEBUG
& DEBUG_DMA
)
636 fprintf(stderr
, "Allocated buffer %d\n", index
);
638 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
639 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
640 dmabuf
->refcount
= 1;
642 rmesa
->dma
.current
.buf
= dmabuf
;
643 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
644 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
645 rmesa
->dma
.current
.start
= 0;
646 rmesa
->dma
.current
.ptr
= 0;
648 rmesa
->c_vertexBuffers
++;
651 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
652 struct radeon_dma_region
*region
,
655 if (RADEON_DEBUG
& DEBUG_IOCTL
)
656 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
661 if (rmesa
->dma
.flush
)
662 rmesa
->dma
.flush( rmesa
);
664 if (--region
->buf
->refcount
== 0) {
665 drm_radeon_cmd_header_t
*cmd
;
667 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
668 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
669 region
->buf
->buf
->idx
);
671 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
673 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
674 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
676 rmesa
->dma
.nr_released_bufs
++;
683 /* Allocates a region from rmesa->dma.current. If there isn't enough
684 * space in current, grab a new buffer (and discard what was left of current)
686 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
687 struct radeon_dma_region
*region
,
691 if (RADEON_DEBUG
& DEBUG_IOCTL
)
692 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
694 if (rmesa
->dma
.flush
)
695 rmesa
->dma
.flush( rmesa
);
698 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
701 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
702 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
704 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
705 radeonRefillCurrentDmaRegion( rmesa
);
707 region
->start
= rmesa
->dma
.current
.start
;
708 region
->ptr
= rmesa
->dma
.current
.start
;
709 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
710 region
->address
= rmesa
->dma
.current
.address
;
711 region
->buf
= rmesa
->dma
.current
.buf
;
712 region
->buf
->refcount
++;
714 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
715 rmesa
->dma
.current
.start
=
716 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
719 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa
,
720 struct radeon_dma_region
*region
,
725 radeonAllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
728 /* ================================================================
729 * SwapBuffers with client-side throttling
732 static uint32_t radeonGetLastFrame (radeonContextPtr rmesa
)
734 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
738 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
739 drm_radeon_getparam_t gp
;
741 gp
.param
= RADEON_PARAM_LAST_FRAME
;
742 gp
.value
= (int *)&frame
;
743 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
749 if ( ret
== -EINVAL
) {
750 frame
= INREG( RADEON_LAST_FRAME_REG
);
754 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
761 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
763 drm_radeon_irq_emit_t ie
;
766 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
767 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
770 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
776 static void radeonWaitIrq( radeonContextPtr rmesa
)
781 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
782 &rmesa
->iw
, sizeof(rmesa
->iw
) );
783 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
786 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
792 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
794 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
796 if (rmesa
->do_irqs
) {
797 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
798 if (!rmesa
->irqsEmitted
) {
799 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
803 UNLOCK_HARDWARE( rmesa
);
804 radeonWaitIrq( rmesa
);
805 LOCK_HARDWARE( rmesa
);
807 rmesa
->irqsEmitted
= 10;
810 if (rmesa
->irqsEmitted
) {
811 radeonEmitIrqLocked( rmesa
);
812 rmesa
->irqsEmitted
--;
816 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
817 UNLOCK_HARDWARE( rmesa
);
818 if (rmesa
->do_usleeps
)
820 LOCK_HARDWARE( rmesa
);
825 /* Copy the back color buffer to the front color buffer.
827 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
829 radeonContextPtr rmesa
;
831 GLboolean missed_target
;
835 assert(dPriv
->driContextPriv
);
836 assert(dPriv
->driContextPriv
->driverPrivate
);
838 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
840 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
841 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
844 RADEON_FIREVERTICES( rmesa
);
845 LOCK_HARDWARE( rmesa
);
847 /* Throttle the frame rate -- only allow one pending swap buffers
850 radeonWaitForFrameCompletion( rmesa
);
851 UNLOCK_HARDWARE( rmesa
);
852 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
853 LOCK_HARDWARE( rmesa
);
855 nbox
= dPriv
->numClipRects
; /* must be in locked region */
857 for ( i
= 0 ; i
< nbox
; ) {
858 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
859 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
860 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
863 for ( ; i
< nr
; i
++ ) {
867 rmesa
->sarea
->nbox
= n
;
869 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
872 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
873 UNLOCK_HARDWARE( rmesa
);
878 UNLOCK_HARDWARE( rmesa
);
880 (*rmesa
->get_ust
)( & ust
);
881 if ( missed_target
) {
882 rmesa
->swap_missed_count
++;
883 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
886 rmesa
->swap_ust
= ust
;
889 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
891 radeonContextPtr rmesa
;
893 GLboolean missed_target
;
896 assert(dPriv
->driContextPriv
);
897 assert(dPriv
->driContextPriv
->driverPrivate
);
899 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
901 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
902 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
903 rmesa
->sarea
->pfCurrentPage
);
906 RADEON_FIREVERTICES( rmesa
);
907 LOCK_HARDWARE( rmesa
);
909 /* Need to do this for the perf box placement:
911 if (dPriv
->numClipRects
)
913 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
914 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
916 rmesa
->sarea
->nbox
= 1;
919 /* Throttle the frame rate -- only allow a few pending swap buffers
922 radeonWaitForFrameCompletion( rmesa
);
923 UNLOCK_HARDWARE( rmesa
);
924 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
925 if ( missed_target
) {
926 rmesa
->swap_missed_count
++;
927 (void) (*rmesa
->get_ust
)( & rmesa
->swap_missed_ust
);
929 LOCK_HARDWARE( rmesa
);
931 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
933 UNLOCK_HARDWARE( rmesa
);
936 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
941 (void) (*rmesa
->get_ust
)( & rmesa
->swap_ust
);
943 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
944 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->frontOffset
;
945 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->frontPitch
;
947 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->backOffset
;
948 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->backPitch
;
951 RADEON_STATECHANGE( rmesa
, ctx
);
952 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
953 + rmesa
->radeonScreen
->fbLocation
;
954 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
958 /* ================================================================
961 #define RADEON_MAX_CLEARS 256
963 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
964 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
966 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
967 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
968 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
969 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
972 GLuint color_mask
= 0;
975 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
976 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
977 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
980 /* Need to cope with lostcontext here as kernel relies on
981 * some residual state:
983 RADEON_FIREVERTICES( rmesa
);
985 if ( mask
& DD_FRONT_LEFT_BIT
) {
986 flags
|= RADEON_FRONT
;
987 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
988 mask
&= ~DD_FRONT_LEFT_BIT
;
991 if ( mask
& DD_BACK_LEFT_BIT
) {
992 flags
|= RADEON_BACK
;
993 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
994 mask
&= ~DD_BACK_LEFT_BIT
;
997 if ( mask
& DD_DEPTH_BIT
) {
998 if ( ctx
->Depth
.Mask
) flags
|= RADEON_DEPTH
; /* FIXME: ??? */
999 mask
&= ~DD_DEPTH_BIT
;
1002 if ( (mask
& DD_STENCIL_BIT
) && rmesa
->state
.stencil
.hwBuffer
) {
1003 flags
|= RADEON_STENCIL
;
1004 mask
&= ~DD_STENCIL_BIT
;
1008 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1009 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1010 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1017 /* Flip top to bottom */
1019 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1021 LOCK_HARDWARE( rmesa
);
1023 /* Throttle the number of clear ioctls we do.
1028 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1029 drm_radeon_getparam_t gp
;
1031 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1032 gp
.value
= (int *)&clear
;
1033 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1034 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1038 if ( ret
== -EINVAL
) {
1039 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1043 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1046 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1047 fprintf( stderr
, "%s( %d )\n", __FUNCTION__
, (int)clear
);
1048 if ( ret
) fprintf( stderr
, " ( RADEON_LAST_CLEAR register read directly )\n" );
1051 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1055 if ( rmesa
->do_usleeps
) {
1056 UNLOCK_HARDWARE( rmesa
);
1058 LOCK_HARDWARE( rmesa
);
1062 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1063 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1064 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1065 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1066 drm_radeon_clear_t clear
;
1067 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1071 for ( ; i
< nr
; i
++ ) {
1072 GLint x
= box
[i
].x1
;
1073 GLint y
= box
[i
].y1
;
1074 GLint w
= box
[i
].x2
- x
;
1075 GLint h
= box
[i
].y2
- y
;
1077 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1078 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1079 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1080 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1081 if ( w
<= 0 ) continue;
1082 if ( h
<= 0 ) continue;
1092 for ( ; i
< nr
; i
++ ) {
1098 rmesa
->sarea
->nbox
= n
;
1100 clear
.flags
= flags
;
1101 clear
.clear_color
= rmesa
->state
.color
.clear
;
1102 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1103 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1104 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1105 clear
.depth_boxes
= depth_boxes
;
1108 b
= rmesa
->sarea
->boxes
;
1109 for ( ; n
>= 0 ; n
-- ) {
1110 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1111 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1112 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1113 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1114 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1115 (float)rmesa
->state
.depth
.clear
;
1118 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1119 &clear
, sizeof(drm_radeon_clear_t
));
1122 UNLOCK_HARDWARE( rmesa
);
1123 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1128 UNLOCK_HARDWARE( rmesa
);
1132 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1134 int fd
= rmesa
->dri
.fd
;
1138 rmesa
->c_drawWaits
++;
1142 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1143 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1144 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1147 UNLOCK_HARDWARE( rmesa
);
1148 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1154 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1156 LOCK_HARDWARE(rmesa
);
1157 radeonWaitForIdleLocked( rmesa
);
1158 UNLOCK_HARDWARE(rmesa
);
1162 void radeonFlush( GLcontext
*ctx
)
1164 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1166 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1167 fprintf(stderr
, "%s\n", __FUNCTION__
);
1169 if (rmesa
->dma
.flush
)
1170 rmesa
->dma
.flush( rmesa
);
1172 if (!is_empty_list(&rmesa
->hw
.dirty
))
1173 radeonEmitState( rmesa
);
1175 if (rmesa
->store
.cmd_used
)
1176 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1179 /* Make sure all commands have been sent to the hardware and have
1180 * completed processing.
1182 void radeonFinish( GLcontext
*ctx
)
1184 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1187 if (rmesa
->do_irqs
) {
1188 LOCK_HARDWARE( rmesa
);
1189 radeonEmitIrqLocked( rmesa
);
1190 UNLOCK_HARDWARE( rmesa
);
1191 radeonWaitIrq( rmesa
);
1194 radeonWaitForIdle( rmesa
);
1198 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1200 ctx
->Driver
.Clear
= radeonClear
;
1201 ctx
->Driver
.Finish
= radeonFinish
;
1202 ctx
->Driver
.Flush
= radeonFlush
;