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 #include "radeon_macros.h" /* for INREG() */
56 #define RADEON_TIMEOUT 512
57 #define RADEON_IDLE_RETRY 16
60 static void radeonWaitForIdle( radeonContextPtr rmesa
);
62 /* =============================================================
63 * Kernel command buffer handling
66 static void print_state_atom( struct radeon_state_atom
*state
)
70 fprintf(stderr
, "emit %s/%d\n", state
->name
, state
->cmd_size
);
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
]);
78 static void radeon_emit_state_list( radeonContextPtr rmesa
,
79 struct radeon_state_atom
*list
)
81 struct radeon_state_atom
*state
, *tmp
;
83 int i
, size
, texunits
;
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
90 * FIXME: This requires knowledge of which state atoms exist.
91 * FIXME: Is the zbs hack below still needed?
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
);
102 else if (RADEON_DEBUG
& DEBUG_STATE
)
103 fprintf(stderr
, "skip state %s\n", state
->name
);
109 dest
= radeonAllocCmdBuf( rmesa
, size
* 4, __FUNCTION__
);
110 texunits
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
112 #define EMIT_ATOM(ATOM) \
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; \
128 for (i
= 0; i
< texunits
; ++i
) {
134 for (i
= 0; i
< 3 + texunits
; ++i
)
136 for (i
= 0; i
< 8; ++i
)
138 for (i
= 0; i
< 6; ++i
)
149 void radeonEmitState( radeonContextPtr rmesa
)
151 struct radeon_state_atom
*state
, *tmp
;
153 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
154 fprintf(stderr
, "%s\n", __FUNCTION__
);
156 /* Somewhat overkill:
158 if (rmesa
->lost_context
) {
159 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
|DEBUG_IOCTL
))
160 fprintf(stderr
, "%s - lost context\n", __FUNCTION__
);
162 foreach_s( state
, tmp
, &(rmesa
->hw
.clean
) )
163 move_to_tail(&(rmesa
->hw
.dirty
), state
);
165 rmesa
->lost_context
= 0;
168 /* This is a darstardly kludge to work around a lockup that I
169 * haven't otherwise figured out.
171 move_to_tail(&(rmesa
->hw
.dirty
), &(rmesa
->hw
.zbs
) );
174 if (!(rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
)) {
175 foreach_s( state
, tmp
, &(rmesa
->hw
.dirty
) ) {
177 move_to_head( &(rmesa
->hw
.clean
), state
);
182 radeon_emit_state_list( rmesa
, &rmesa
->hw
.dirty
);
187 /* Fire a section of the retained (indexed_verts) buffer as a regular
190 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
191 GLuint vertex_format
,
195 drm_radeon_cmd_header_t
*cmd
;
198 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
200 radeonEmitState( rmesa
);
202 if (RADEON_DEBUG
& DEBUG_IOCTL
)
203 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
204 rmesa
->store
.cmd_used
/4);
206 #if RADEON_OLD_PACKETS
207 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 6 * sizeof(*cmd
),
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
));
220 if (RADEON_DEBUG
& DEBUG_PRIMS
)
221 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
223 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
225 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 4 * sizeof(*cmd
),
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 #if RADEON_OLD_PACKETS
294 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
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);
310 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
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
);
323 retval
= (GLushort
*)(cmd
+4);
326 if (RADEON_DEBUG
& DEBUG_PRIMS
)
327 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
329 cmd
[1].i
, vertex_format
, primitive
);
331 assert(!rmesa
->dma
.flush
);
332 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
333 rmesa
->dma
.flush
= radeonFlushElts
;
335 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
342 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
346 #if RADEON_OLD_PACKETS
347 rmesa
->ioctl
.vertex_size
= vertex_size
;
348 rmesa
->ioctl
.vertex_offset
= offset
;
350 drm_radeon_cmd_header_t
*cmd
;
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
);
356 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 5 * sizeof(int),
360 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
361 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
363 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
369 void radeonEmitAOS( radeonContextPtr rmesa
,
370 struct radeon_dma_region
**component
,
374 #if RADEON_OLD_PACKETS
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);
381 drm_radeon_cmd_header_t
*cmd
;
382 int sz
= 3 + (nr
/2 * 3) + (nr
& 1) * 2;
386 if (RADEON_DEBUG
& DEBUG_IOCTL
)
387 fprintf(stderr
, "%s\n", __FUNCTION__
);
390 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
* sizeof(int),
393 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
394 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| ((sz
-3) << 16);
399 for (i
= 0 ; i
< nr
; i
++) {
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);
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);
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
]);
423 /* using already shifted color_fmt! */
424 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
430 GLint srcx
, GLint srcy
,
431 GLint dstx
, GLint dsty
,
434 drm_radeon_cmd_header_t
*cmd
;
436 if (RADEON_DEBUG
& DEBUG_IOCTL
)
437 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
439 src_pitch
, src_offset
, srcx
, srcy
,
440 dst_pitch
, dst_offset
, dstx
, dsty
,
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) );
450 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
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
|
461 RADEON_GMC_SRC_DATATYPE_COLOR
|
463 RADEON_DP_SRC_SOURCE_MEMORY
|
464 RADEON_GMC_CLR_CMP_CNTL_DIS
|
465 RADEON_GMC_WR_MSK_DIS
);
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
;
475 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
477 if (rmesa
->dri
.drmMinor
>= 6) {
478 drm_radeon_cmd_header_t
*cmd
;
480 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
482 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 1 * sizeof(int),
485 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
486 cmd
[0].wait
.flags
= flags
;
491 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
492 const char * caller
)
495 drm_radeon_cmd_buffer_t cmd
;
497 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
498 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
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
]));
506 if (RADEON_DEBUG
& DEBUG_DMA
)
507 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
508 rmesa
->dma
.nr_released_bufs
);
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
);
517 ret
= radeonSanityCmdBuffer( rmesa
,
521 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
527 cmd
.bufsz
= rmesa
->store
.cmd_used
;
528 cmd
.buf
= rmesa
->store
.cmd_buf
;
530 if (rmesa
->state
.scissor
.enabled
) {
531 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
532 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
534 cmd
.nbox
= rmesa
->numClipRects
;
535 cmd
.boxes
= rmesa
->pClipRects
;
538 ret
= drmCommandWrite( rmesa
->dri
.fd
,
543 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
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;
555 /* Note: does not emit any commands to avoid recursion on
558 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
563 LOCK_HARDWARE( rmesa
);
565 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
567 UNLOCK_HARDWARE( rmesa
);
570 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
575 /* =============================================================
576 * Hardware vertex buffer handling
580 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
582 struct radeon_dma_buffer
*dmabuf
;
583 int fd
= rmesa
->dri
.fd
;
589 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
590 fprintf(stderr
, "%s\n", __FUNCTION__
);
592 if (rmesa
->dma
.flush
) {
593 rmesa
->dma
.flush( rmesa
);
596 if (rmesa
->dma
.current
.buf
)
597 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
599 if (rmesa
->dma
.nr_released_bufs
> 4)
600 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
602 dma
.context
= rmesa
->dri
.hwContext
;
604 dma
.send_list
= NULL
;
605 dma
.send_sizes
= NULL
;
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;
613 LOCK_HARDWARE(rmesa
); /* no need to validate */
615 ret
= drmDMA( fd
, &dma
);
618 /* Free some up this way?
620 if (rmesa
->dma
.nr_released_bufs
) {
621 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
624 if (RADEON_DEBUG
& DEBUG_DMA
)
625 fprintf(stderr
, "Waiting for buffers\n");
627 radeonWaitForIdleLocked( rmesa
);
628 ret
= drmDMA( fd
, &dma
);
631 UNLOCK_HARDWARE( rmesa
);
632 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
637 UNLOCK_HARDWARE(rmesa
);
639 if (RADEON_DEBUG
& DEBUG_DMA
)
640 fprintf(stderr
, "Allocated buffer %d\n", index
);
642 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
643 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
644 dmabuf
->refcount
= 1;
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;
652 rmesa
->c_vertexBuffers
++;
655 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
656 struct radeon_dma_region
*region
,
659 if (RADEON_DEBUG
& DEBUG_IOCTL
)
660 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
665 if (rmesa
->dma
.flush
)
666 rmesa
->dma
.flush( rmesa
);
668 if (--region
->buf
->refcount
== 0) {
669 drm_radeon_cmd_header_t
*cmd
;
671 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
672 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
673 region
->buf
->buf
->idx
);
675 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
677 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
678 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
680 rmesa
->dma
.nr_released_bufs
++;
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)
690 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
691 struct radeon_dma_region
*region
,
695 if (RADEON_DEBUG
& DEBUG_IOCTL
)
696 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
698 if (rmesa
->dma
.flush
)
699 rmesa
->dma
.flush( rmesa
);
702 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
705 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
706 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
708 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
709 radeonRefillCurrentDmaRegion( rmesa
);
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
++;
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;
723 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa
,
724 struct radeon_dma_region
*region
,
729 radeonAllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
732 /* ================================================================
733 * SwapBuffers with client-side throttling
736 static int32_t radeonGetLastFrame (radeonContextPtr rmesa
)
738 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
742 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
743 drm_radeon_getparam_t gp
;
745 gp
.param
= RADEON_PARAM_LAST_FRAME
;
746 gp
.value
= (int *)&frame
;
747 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
754 if ( ret
== -EINVAL
) {
755 frame
= INREG( RADEON_LAST_FRAME_REG
);
760 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
767 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
769 drm_radeon_irq_emit_t ie
;
772 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
773 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
776 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
782 static void radeonWaitIrq( radeonContextPtr rmesa
)
787 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
788 &rmesa
->iw
, sizeof(rmesa
->iw
) );
789 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
792 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
798 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
800 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
802 if (rmesa
->do_irqs
) {
803 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
804 if (!rmesa
->irqsEmitted
) {
805 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
809 UNLOCK_HARDWARE( rmesa
);
810 radeonWaitIrq( rmesa
);
811 LOCK_HARDWARE( rmesa
);
813 rmesa
->irqsEmitted
= 10;
816 if (rmesa
->irqsEmitted
) {
817 radeonEmitIrqLocked( rmesa
);
818 rmesa
->irqsEmitted
--;
822 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
823 UNLOCK_HARDWARE( rmesa
);
824 if (rmesa
->do_usleeps
)
826 LOCK_HARDWARE( rmesa
);
831 /* Copy the back color buffer to the front color buffer.
833 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
835 radeonContextPtr rmesa
;
837 GLboolean missed_target
;
841 assert(dPriv
->driContextPriv
);
842 assert(dPriv
->driContextPriv
->driverPrivate
);
844 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
846 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
847 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, rmesa
->glCtx
);
850 RADEON_FIREVERTICES( rmesa
);
851 LOCK_HARDWARE( rmesa
);
853 /* Throttle the frame rate -- only allow one pending swap buffers
856 radeonWaitForFrameCompletion( rmesa
);
857 UNLOCK_HARDWARE( rmesa
);
858 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
859 LOCK_HARDWARE( rmesa
);
861 nbox
= dPriv
->numClipRects
; /* must be in locked region */
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
;
869 for ( ; i
< nr
; i
++ ) {
873 rmesa
->sarea
->nbox
= n
;
875 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
878 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
879 UNLOCK_HARDWARE( rmesa
);
884 UNLOCK_HARDWARE( rmesa
);
886 (*rmesa
->get_ust
)( & ust
);
887 if ( missed_target
) {
888 rmesa
->swap_missed_count
++;
889 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
892 rmesa
->swap_ust
= ust
;
895 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
897 radeonContextPtr rmesa
;
899 GLboolean missed_target
;
902 assert(dPriv
->driContextPriv
);
903 assert(dPriv
->driContextPriv
->driverPrivate
);
905 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
907 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
908 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
909 rmesa
->sarea
->pfCurrentPage
);
912 RADEON_FIREVERTICES( rmesa
);
913 LOCK_HARDWARE( rmesa
);
915 /* Need to do this for the perf box placement:
917 if (dPriv
->numClipRects
)
919 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
920 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
922 rmesa
->sarea
->nbox
= 1;
925 /* Throttle the frame rate -- only allow a few pending swap buffers
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
);
935 LOCK_HARDWARE( rmesa
);
937 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
939 UNLOCK_HARDWARE( rmesa
);
942 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
947 (void) (*rmesa
->get_ust
)( & rmesa
->swap_ust
);
949 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
950 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->frontOffset
;
951 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->frontPitch
;
953 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->backOffset
;
954 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->backPitch
;
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
;
964 /* ================================================================
967 #define RADEON_MAX_CLEARS 256
969 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
970 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
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
;
978 GLuint color_mask
= 0;
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
);
986 radeonEmitState( rmesa
);
988 /* Need to cope with lostcontext here as kernel relies on
989 * some residual state:
991 RADEON_FIREVERTICES( rmesa
);
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
;
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
;
1005 if ( mask
& DD_DEPTH_BIT
) {
1006 if ( ctx
->Depth
.Mask
) flags
|= RADEON_DEPTH
; /* FIXME: ??? */
1007 mask
&= ~DD_DEPTH_BIT
;
1010 if ( (mask
& DD_STENCIL_BIT
) && rmesa
->state
.stencil
.hwBuffer
) {
1011 flags
|= RADEON_STENCIL
;
1012 mask
&= ~DD_STENCIL_BIT
;
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
);
1025 /* Flip top to bottom */
1027 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1029 LOCK_HARDWARE( rmesa
);
1031 /* Throttle the number of clear ioctls we do.
1036 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1037 drm_radeon_getparam_t gp
;
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
) );
1047 if ( ret
== -EINVAL
) {
1048 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1053 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
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" );
1061 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1065 if ( rmesa
->do_usleeps
) {
1066 UNLOCK_HARDWARE( rmesa
);
1068 LOCK_HARDWARE( rmesa
);
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
];
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
;
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;
1102 for ( ; i
< nr
; i
++ ) {
1108 rmesa
->sarea
->nbox
= n
;
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
;
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
;
1128 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1129 &clear
, sizeof(drm_radeon_clear_t
));
1132 UNLOCK_HARDWARE( rmesa
);
1133 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1138 UNLOCK_HARDWARE( rmesa
);
1142 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1144 int fd
= rmesa
->dri
.fd
;
1148 rmesa
->c_drawWaits
++;
1152 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1153 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1154 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1157 UNLOCK_HARDWARE( rmesa
);
1158 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1164 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1166 LOCK_HARDWARE(rmesa
);
1167 radeonWaitForIdleLocked( rmesa
);
1168 UNLOCK_HARDWARE(rmesa
);
1172 void radeonFlush( GLcontext
*ctx
)
1174 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1176 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1177 fprintf(stderr
, "%s\n", __FUNCTION__
);
1179 if (rmesa
->dma
.flush
)
1180 rmesa
->dma
.flush( rmesa
);
1182 if (!is_empty_list(&rmesa
->hw
.dirty
))
1183 radeonEmitState( rmesa
);
1185 if (rmesa
->store
.cmd_used
)
1186 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1189 /* Make sure all commands have been sent to the hardware and have
1190 * completed processing.
1192 void radeonFinish( GLcontext
*ctx
)
1194 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1197 if (rmesa
->do_irqs
) {
1198 LOCK_HARDWARE( rmesa
);
1199 radeonEmitIrqLocked( rmesa
);
1200 UNLOCK_HARDWARE( rmesa
);
1201 radeonWaitIrq( rmesa
);
1204 radeonWaitForIdle( rmesa
);
1208 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1210 ctx
->Driver
.Clear
= radeonClear
;
1211 ctx
->Driver
.Finish
= radeonFinish
;
1212 ctx
->Driver
.Flush
= radeonFlush
;