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() */
55 #include "drirenderbuffer.h"
58 #define RADEON_TIMEOUT 512
59 #define RADEON_IDLE_RETRY 16
62 static void radeonWaitForIdle( radeonContextPtr rmesa
);
63 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
64 const char * caller
);
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 radeonSaveHwState( radeonContextPtr rmesa
)
80 struct radeon_state_atom
*atom
;
81 char * dest
= rmesa
->backup_store
.cmd_buf
;
83 if (RADEON_DEBUG
& DEBUG_STATE
)
84 fprintf(stderr
, "%s\n", __FUNCTION__
);
86 rmesa
->backup_store
.cmd_used
= 0;
88 foreach( atom
, &rmesa
->hw
.atomlist
) {
89 if ( atom
->check( rmesa
->glCtx
) ) {
90 int size
= atom
->cmd_size
* 4;
91 memcpy( dest
, atom
->cmd
, size
);
93 rmesa
->backup_store
.cmd_used
+= size
;
94 if (RADEON_DEBUG
& DEBUG_STATE
)
95 print_state_atom( atom
);
99 assert( rmesa
->backup_store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
100 if (RADEON_DEBUG
& DEBUG_STATE
)
101 fprintf(stderr
, "Returning to radeonEmitState\n");
104 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
105 * we need to unwire our current cmdbuf, hook the one with the saved state in
106 * it, flush it, and then put the current one back. This is so commands at the
107 * start of a cmdbuf can rely on the state being kept from the previous one.
109 static void radeonBackUpAndEmitLostStateLocked( radeonContextPtr rmesa
)
111 GLuint nr_released_bufs
;
112 struct radeon_store saved_store
;
114 if (rmesa
->backup_store
.cmd_used
== 0)
117 if (RADEON_DEBUG
& DEBUG_STATE
)
118 fprintf(stderr
, "Emitting backup state on lost context\n");
120 rmesa
->lost_context
= GL_FALSE
;
122 nr_released_bufs
= rmesa
->dma
.nr_released_bufs
;
123 saved_store
= rmesa
->store
;
124 rmesa
->dma
.nr_released_bufs
= 0;
125 rmesa
->store
= rmesa
->backup_store
;
126 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
127 rmesa
->dma
.nr_released_bufs
= nr_released_bufs
;
128 rmesa
->store
= saved_store
;
131 /* =============================================================
132 * Kernel command buffer handling
135 /* The state atoms will be emitted in the order they appear in the atom list,
136 * so this step is important.
138 void radeonSetUpAtomList( radeonContextPtr rmesa
)
140 int i
, mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
142 make_empty_list(&rmesa
->hw
.atomlist
);
143 rmesa
->hw
.atomlist
.name
= "atom-list";
145 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.ctx
);
146 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.set
);
147 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.lin
);
148 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.msk
);
149 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.vpt
);
150 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.tcl
);
151 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.msc
);
152 for (i
= 0; i
< mtu
; ++i
) {
153 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.tex
[i
]);
154 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.txr
[i
]);
155 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.cube
[i
]);
157 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.zbs
);
158 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
);
159 for (i
= 0; i
< 3 + mtu
; ++i
)
160 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
]);
161 for (i
= 0; i
< 8; ++i
)
162 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
]);
163 for (i
= 0; i
< 6; ++i
)
164 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
]);
165 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
166 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.grd
);
167 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.fog
);
168 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
171 void radeonEmitState( radeonContextPtr rmesa
)
173 struct radeon_state_atom
*atom
;
176 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
177 fprintf(stderr
, "%s\n", __FUNCTION__
);
179 if (rmesa
->save_on_next_emit
) {
180 radeonSaveHwState(rmesa
);
181 rmesa
->save_on_next_emit
= GL_FALSE
;
184 /* this code used to return here but now it emits zbs */
186 /* To avoid going across the entire set of states multiple times, just check
187 * for enough space for the case of emitting all state, and inline the
188 * radeonAllocCmdBuf code here without all the checks.
190 radeonEnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
);
191 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
193 /* We always always emit zbs, this is due to a bug found by keithw in
194 the hardware and rediscovered after Erics changes by me.
195 if you ever touch this code make sure you emit zbs otherwise
196 you get tcl lockups on at least M7/7500 class of chips - airlied */
197 rmesa
->hw
.zbs
.dirty
=1;
199 if (RADEON_DEBUG
& DEBUG_STATE
) {
200 foreach(atom
, &rmesa
->hw
.atomlist
) {
201 if (atom
->dirty
|| rmesa
->hw
.all_dirty
) {
202 if (atom
->check(rmesa
->glCtx
))
203 print_state_atom(atom
);
205 fprintf(stderr
, "skip state %s\n", atom
->name
);
210 foreach(atom
, &rmesa
->hw
.atomlist
) {
211 if (rmesa
->hw
.all_dirty
)
212 atom
->dirty
= GL_TRUE
;
213 if (!(rmesa
->radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
) &&
215 atom
->dirty
= GL_FALSE
;
217 if (atom
->check(rmesa
->glCtx
)) {
218 int size
= atom
->cmd_size
* 4;
219 memcpy(dest
, atom
->cmd
, size
);
221 rmesa
->store
.cmd_used
+= size
;
222 atom
->dirty
= GL_FALSE
;
227 assert(rmesa
->store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
229 rmesa
->hw
.is_dirty
= GL_FALSE
;
230 rmesa
->hw
.all_dirty
= GL_FALSE
;
233 /* Fire a section of the retained (indexed_verts) buffer as a regular
236 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
237 GLuint vertex_format
,
241 drm_radeon_cmd_header_t
*cmd
;
244 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
246 radeonEmitState( rmesa
);
248 if (RADEON_DEBUG
& DEBUG_IOCTL
)
249 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
250 rmesa
->store
.cmd_used
/4);
252 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VBUF_BUFSZ
,
254 #if RADEON_OLD_PACKETS
256 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
257 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
| (3 << 16);
258 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
259 cmd
[3].i
= vertex_nr
;
260 cmd
[4].i
= vertex_format
;
261 cmd
[5].i
= (primitive
|
262 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
263 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
264 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
265 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
267 if (RADEON_DEBUG
& DEBUG_PRIMS
)
268 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
270 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
273 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
274 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_VBUF
| (1 << 16);
275 cmd
[2].i
= vertex_format
;
276 cmd
[3].i
= (primitive
|
277 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
278 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
279 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
280 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
281 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
284 if (RADEON_DEBUG
& DEBUG_PRIMS
)
285 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
287 cmd
[1].i
, cmd
[2].i
, cmd
[3].i
);
292 void radeonFlushElts( radeonContextPtr rmesa
)
294 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
296 #if RADEON_OLD_PACKETS
297 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 24)) / 2;
299 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 16)) / 2;
302 if (RADEON_DEBUG
& DEBUG_IOCTL
)
303 fprintf(stderr
, "%s\n", __FUNCTION__
);
305 assert( rmesa
->dma
.flush
== radeonFlushElts
);
306 rmesa
->dma
.flush
= NULL
;
308 /* Cope with odd number of elts:
310 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
311 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
313 #if RADEON_OLD_PACKETS
314 cmd
[1] |= (dwords
- 3) << 16;
315 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
317 cmd
[1] |= (dwords
- 3) << 16;
318 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
321 if (RADEON_DEBUG
& DEBUG_SYNC
) {
322 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
323 radeonFinish( rmesa
->glCtx
);
328 GLushort
*radeonAllocEltsOpenEnded( radeonContextPtr rmesa
,
329 GLuint vertex_format
,
333 drm_radeon_cmd_header_t
*cmd
;
336 if (RADEON_DEBUG
& DEBUG_IOCTL
)
337 fprintf(stderr
, "%s %d\n", __FUNCTION__
, min_nr
);
339 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
341 radeonEmitState( rmesa
);
343 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
346 #if RADEON_OLD_PACKETS
348 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
349 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
;
350 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
352 cmd
[4].i
= vertex_format
;
353 cmd
[5].i
= (primitive
|
354 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
355 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
356 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
358 retval
= (GLushort
*)(cmd
+6);
361 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
362 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_INDX
;
363 cmd
[2].i
= vertex_format
;
364 cmd
[3].i
= (primitive
|
365 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
366 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
367 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
368 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
370 retval
= (GLushort
*)(cmd
+4);
373 if (RADEON_DEBUG
& DEBUG_PRIMS
)
374 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
376 cmd
[1].i
, vertex_format
, primitive
);
378 assert(!rmesa
->dma
.flush
);
379 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
380 rmesa
->dma
.flush
= radeonFlushElts
;
382 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
389 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
393 #if RADEON_OLD_PACKETS
394 rmesa
->ioctl
.vertex_size
= vertex_size
;
395 rmesa
->ioctl
.vertex_offset
= offset
;
397 drm_radeon_cmd_header_t
*cmd
;
399 if (RADEON_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
400 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
401 __FUNCTION__
, vertex_size
, offset
);
403 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
407 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
408 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
410 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
416 void radeonEmitAOS( radeonContextPtr rmesa
,
417 struct radeon_dma_region
**component
,
421 #if RADEON_OLD_PACKETS
423 assert( component
[0]->aos_size
== component
[0]->aos_stride
);
424 rmesa
->ioctl
.vertex_size
= component
[0]->aos_size
;
425 rmesa
->ioctl
.vertex_offset
=
426 (component
[0]->aos_start
+ offset
* component
[0]->aos_stride
* 4);
428 drm_radeon_cmd_header_t
*cmd
;
429 int sz
= AOS_BUFSZ(nr
);
433 if (RADEON_DEBUG
& DEBUG_IOCTL
)
434 fprintf(stderr
, "%s\n", __FUNCTION__
);
437 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
,
440 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
441 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int))-3) << 16);
446 for (i
= 0 ; i
< nr
; i
++) {
448 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
449 (component
[i
]->aos_size
<< 16));
450 cmd
[2].i
= (component
[i
]->aos_start
+
451 offset
* component
[i
]->aos_stride
* 4);
455 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
456 (component
[i
]->aos_size
<< 0));
457 cmd
[1].i
= (component
[i
]->aos_start
+
458 offset
* component
[i
]->aos_stride
* 4);
462 if (RADEON_DEBUG
& DEBUG_VERTS
) {
463 fprintf(stderr
, "%s:\n", __FUNCTION__
);
464 for (i
= 0 ; i
< sz
; i
++)
465 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
470 /* using already shifted color_fmt! */
471 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
477 GLint srcx
, GLint srcy
,
478 GLint dstx
, GLint dsty
,
481 drm_radeon_cmd_header_t
*cmd
;
483 if (RADEON_DEBUG
& DEBUG_IOCTL
)
484 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
486 src_pitch
, src_offset
, srcx
, srcy
,
487 dst_pitch
, dst_offset
, dstx
, dsty
,
490 assert( (src_pitch
& 63) == 0 );
491 assert( (dst_pitch
& 63) == 0 );
492 assert( (src_offset
& 1023) == 0 );
493 assert( (dst_offset
& 1023) == 0 );
494 assert( w
< (1<<16) );
495 assert( h
< (1<<16) );
497 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
502 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
503 cmd
[1].i
= RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
| (5 << 16);
504 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
505 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
506 RADEON_GMC_BRUSH_NONE
|
508 RADEON_GMC_SRC_DATATYPE_COLOR
|
510 RADEON_DP_SRC_SOURCE_MEMORY
|
511 RADEON_GMC_CLR_CMP_CNTL_DIS
|
512 RADEON_GMC_WR_MSK_DIS
);
514 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
515 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
516 cmd
[5].i
= (srcx
<< 16) | srcy
;
517 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
518 cmd
[7].i
= (w
<< 16) | h
;
522 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
524 drm_radeon_cmd_header_t
*cmd
;
526 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
528 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 1 * sizeof(int),
531 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
532 cmd
[0].wait
.flags
= flags
;
536 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
537 const char * caller
)
540 drm_radeon_cmd_buffer_t cmd
;
542 if (rmesa
->lost_context
)
543 radeonBackUpAndEmitLostStateLocked(rmesa
);
545 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
546 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
548 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
549 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
550 fprintf(stderr
, "%d: %x\n", i
/4,
551 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
554 if (RADEON_DEBUG
& DEBUG_DMA
)
555 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
556 rmesa
->dma
.nr_released_bufs
);
559 if (RADEON_DEBUG
& DEBUG_SANITY
) {
560 if (rmesa
->state
.scissor
.enabled
)
561 ret
= radeonSanityCmdBuffer( rmesa
,
562 rmesa
->state
.scissor
.numClipRects
,
563 rmesa
->state
.scissor
.pClipRects
);
565 ret
= radeonSanityCmdBuffer( rmesa
,
569 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
575 cmd
.bufsz
= rmesa
->store
.cmd_used
;
576 cmd
.buf
= rmesa
->store
.cmd_buf
;
578 if (rmesa
->state
.scissor
.enabled
) {
579 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
580 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
582 cmd
.nbox
= rmesa
->numClipRects
;
583 cmd
.boxes
= rmesa
->pClipRects
;
586 ret
= drmCommandWrite( rmesa
->dri
.fd
,
591 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
593 if (RADEON_DEBUG
& DEBUG_SYNC
) {
594 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
595 radeonWaitForIdleLocked( rmesa
);
599 rmesa
->store
.primnr
= 0;
600 rmesa
->store
.statenr
= 0;
601 rmesa
->store
.cmd_used
= 0;
602 rmesa
->dma
.nr_released_bufs
= 0;
603 rmesa
->save_on_next_emit
= 1;
609 /* Note: does not emit any commands to avoid recursion on
612 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
617 LOCK_HARDWARE( rmesa
);
619 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
621 UNLOCK_HARDWARE( rmesa
);
624 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
629 /* =============================================================
630 * Hardware vertex buffer handling
634 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
636 struct radeon_dma_buffer
*dmabuf
;
637 int fd
= rmesa
->dri
.fd
;
643 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
644 fprintf(stderr
, "%s\n", __FUNCTION__
);
646 if (rmesa
->dma
.flush
) {
647 rmesa
->dma
.flush( rmesa
);
650 if (rmesa
->dma
.current
.buf
)
651 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
653 if (rmesa
->dma
.nr_released_bufs
> 4)
654 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
656 dma
.context
= rmesa
->dri
.hwContext
;
658 dma
.send_list
= NULL
;
659 dma
.send_sizes
= NULL
;
661 dma
.request_count
= 1;
662 dma
.request_size
= RADEON_BUFFER_SIZE
;
663 dma
.request_list
= &index
;
664 dma
.request_sizes
= &size
;
665 dma
.granted_count
= 0;
667 LOCK_HARDWARE(rmesa
); /* no need to validate */
669 ret
= drmDMA( fd
, &dma
);
672 /* Free some up this way?
674 if (rmesa
->dma
.nr_released_bufs
) {
675 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
678 if (RADEON_DEBUG
& DEBUG_DMA
)
679 fprintf(stderr
, "Waiting for buffers\n");
681 radeonWaitForIdleLocked( rmesa
);
682 ret
= drmDMA( fd
, &dma
);
685 UNLOCK_HARDWARE( rmesa
);
686 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
691 UNLOCK_HARDWARE(rmesa
);
693 if (RADEON_DEBUG
& DEBUG_DMA
)
694 fprintf(stderr
, "Allocated buffer %d\n", index
);
696 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
697 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
698 dmabuf
->refcount
= 1;
700 rmesa
->dma
.current
.buf
= dmabuf
;
701 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
702 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
703 rmesa
->dma
.current
.start
= 0;
704 rmesa
->dma
.current
.ptr
= 0;
706 rmesa
->c_vertexBuffers
++;
709 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
710 struct radeon_dma_region
*region
,
713 if (RADEON_DEBUG
& DEBUG_IOCTL
)
714 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
719 if (rmesa
->dma
.flush
)
720 rmesa
->dma
.flush( rmesa
);
722 if (--region
->buf
->refcount
== 0) {
723 drm_radeon_cmd_header_t
*cmd
;
725 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
726 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
727 region
->buf
->buf
->idx
);
729 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
731 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
732 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
734 rmesa
->dma
.nr_released_bufs
++;
741 /* Allocates a region from rmesa->dma.current. If there isn't enough
742 * space in current, grab a new buffer (and discard what was left of current)
744 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
745 struct radeon_dma_region
*region
,
749 if (RADEON_DEBUG
& DEBUG_IOCTL
)
750 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
752 if (rmesa
->dma
.flush
)
753 rmesa
->dma
.flush( rmesa
);
756 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
759 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
760 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
762 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
763 radeonRefillCurrentDmaRegion( rmesa
);
765 region
->start
= rmesa
->dma
.current
.start
;
766 region
->ptr
= rmesa
->dma
.current
.start
;
767 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
768 region
->address
= rmesa
->dma
.current
.address
;
769 region
->buf
= rmesa
->dma
.current
.buf
;
770 region
->buf
->refcount
++;
772 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
773 rmesa
->dma
.current
.start
=
774 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
777 /* ================================================================
778 * SwapBuffers with client-side throttling
781 static u_int32_t
radeonGetLastFrame (radeonContextPtr rmesa
)
783 drm_radeon_getparam_t gp
;
787 gp
.param
= RADEON_PARAM_LAST_FRAME
;
788 gp
.value
= (int *)&frame
;
789 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
793 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
800 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
802 drm_radeon_irq_emit_t ie
;
805 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
806 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
809 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
815 static void radeonWaitIrq( radeonContextPtr rmesa
)
820 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
821 &rmesa
->iw
, sizeof(rmesa
->iw
) );
822 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
825 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
831 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
833 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
835 if (rmesa
->do_irqs
) {
836 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
837 if (!rmesa
->irqsEmitted
) {
838 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
842 UNLOCK_HARDWARE( rmesa
);
843 radeonWaitIrq( rmesa
);
844 LOCK_HARDWARE( rmesa
);
846 rmesa
->irqsEmitted
= 10;
849 if (rmesa
->irqsEmitted
) {
850 radeonEmitIrqLocked( rmesa
);
851 rmesa
->irqsEmitted
--;
855 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
856 UNLOCK_HARDWARE( rmesa
);
857 if (rmesa
->do_usleeps
)
859 LOCK_HARDWARE( rmesa
);
864 /* Copy the back color buffer to the front color buffer.
866 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
,
867 const drm_clip_rect_t
*rect
)
869 radeonContextPtr rmesa
;
871 GLboolean missed_target
;
875 assert(dPriv
->driContextPriv
);
876 assert(dPriv
->driContextPriv
->driverPrivate
);
878 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
880 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
881 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
884 RADEON_FIREVERTICES( rmesa
);
885 LOCK_HARDWARE( rmesa
);
887 /* Throttle the frame rate -- only allow one pending swap buffers
890 radeonWaitForFrameCompletion( rmesa
);
893 UNLOCK_HARDWARE( rmesa
);
894 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
895 LOCK_HARDWARE( rmesa
);
898 nbox
= dPriv
->numClipRects
; /* must be in locked region */
900 for ( i
= 0 ; i
< nbox
; ) {
901 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
902 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
903 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
906 for ( ; i
< nr
; i
++ ) {
912 if (rect
->x1
> b
->x1
)
914 if (rect
->y1
> b
->y1
)
916 if (rect
->x2
< b
->x2
)
918 if (rect
->y2
< b
->y2
)
921 if (b
->x1
< b
->x2
&& b
->y1
< b
->y2
)
929 rmesa
->sarea
->nbox
= n
;
931 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
934 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
935 UNLOCK_HARDWARE( rmesa
);
940 UNLOCK_HARDWARE( rmesa
);
944 (*dri_interface
->getUST
)( & ust
);
945 if ( missed_target
) {
946 rmesa
->swap_missed_count
++;
947 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
950 rmesa
->swap_ust
= ust
;
951 rmesa
->hw
.all_dirty
= GL_TRUE
;
955 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
957 radeonContextPtr rmesa
;
959 GLboolean missed_target
;
962 assert(dPriv
->driContextPriv
);
963 assert(dPriv
->driContextPriv
->driverPrivate
);
965 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
967 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
968 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
969 rmesa
->sarea
->pfCurrentPage
);
972 RADEON_FIREVERTICES( rmesa
);
973 LOCK_HARDWARE( rmesa
);
975 /* Need to do this for the perf box placement:
977 if (dPriv
->numClipRects
)
979 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
980 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
982 rmesa
->sarea
->nbox
= 1;
985 /* Throttle the frame rate -- only allow a few pending swap buffers
988 radeonWaitForFrameCompletion( rmesa
);
989 UNLOCK_HARDWARE( rmesa
);
990 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
991 if ( missed_target
) {
992 rmesa
->swap_missed_count
++;
993 (void) (*dri_interface
->getUST
)( & rmesa
->swap_missed_ust
);
995 LOCK_HARDWARE( rmesa
);
997 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
999 UNLOCK_HARDWARE( rmesa
);
1002 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
1006 rmesa
->swap_count
++;
1007 (void) (*dri_interface
->getUST
)( & rmesa
->swap_ust
);
1009 /* Get ready for drawing next frame. Update the renderbuffers'
1010 * flippedOffset/Pitch fields so we draw into the right place.
1012 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
1013 rmesa
->sarea
->pfCurrentPage
);
1015 radeonUpdateDrawBuffer(rmesa
->glCtx
);
1019 /* ================================================================
1022 #define RADEON_MAX_CLEARS 256
1024 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
1025 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
1027 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1028 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1029 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
1032 GLuint color_mask
= 0;
1035 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1036 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
1037 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
1041 LOCK_HARDWARE( rmesa
);
1042 UNLOCK_HARDWARE( rmesa
);
1043 if ( dPriv
->numClipRects
== 0 )
1049 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
1050 flags
|= RADEON_FRONT
;
1051 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1052 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
1055 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
1056 flags
|= RADEON_BACK
;
1057 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1058 mask
&= ~BUFFER_BIT_BACK_LEFT
;
1061 if ( mask
& BUFFER_BIT_DEPTH
) {
1062 flags
|= RADEON_DEPTH
;
1063 mask
&= ~BUFFER_BIT_DEPTH
;
1066 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
1067 flags
|= RADEON_STENCIL
;
1068 mask
&= ~BUFFER_BIT_STENCIL
;
1072 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1073 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1074 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1080 if (rmesa
->using_hyperz
) {
1081 flags
|= RADEON_USE_COMP_ZBUF
;
1082 /* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
1083 flags |= RADEON_USE_HIERZ; */
1084 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
1085 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
1086 ((rmesa
->state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
1087 flags
|= RADEON_CLEAR_FASTZ
;
1091 /* Flip top to bottom */
1093 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1095 LOCK_HARDWARE( rmesa
);
1097 /* Throttle the number of clear ioctls we do.
1101 drm_radeon_getparam_t gp
;
1103 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1104 gp
.value
= (int *)&clear
;
1105 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1106 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1109 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1113 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1117 if ( rmesa
->do_usleeps
) {
1118 UNLOCK_HARDWARE( rmesa
);
1120 LOCK_HARDWARE( rmesa
);
1124 /* Send current state to the hardware */
1125 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1127 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1128 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1129 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1130 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1131 drm_radeon_clear_t clear
;
1132 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1136 for ( ; i
< nr
; i
++ ) {
1137 GLint x
= box
[i
].x1
;
1138 GLint y
= box
[i
].y1
;
1139 GLint w
= box
[i
].x2
- x
;
1140 GLint h
= box
[i
].y2
- y
;
1142 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1143 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1144 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1145 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1146 if ( w
<= 0 ) continue;
1147 if ( h
<= 0 ) continue;
1157 for ( ; i
< nr
; i
++ ) {
1163 rmesa
->sarea
->nbox
= n
;
1165 clear
.flags
= flags
;
1166 clear
.clear_color
= rmesa
->state
.color
.clear
;
1167 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1168 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1169 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1170 clear
.depth_boxes
= depth_boxes
;
1173 b
= rmesa
->sarea
->boxes
;
1174 for ( ; n
>= 0 ; n
-- ) {
1175 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1176 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1177 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1178 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1179 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1180 (float)rmesa
->state
.depth
.clear
;
1183 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1184 &clear
, sizeof(drm_radeon_clear_t
));
1187 UNLOCK_HARDWARE( rmesa
);
1188 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1193 UNLOCK_HARDWARE( rmesa
);
1194 rmesa
->hw
.all_dirty
= GL_TRUE
;
1198 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1200 int fd
= rmesa
->dri
.fd
;
1204 rmesa
->c_drawWaits
++;
1208 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1209 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1210 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1213 UNLOCK_HARDWARE( rmesa
);
1214 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1220 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1222 LOCK_HARDWARE(rmesa
);
1223 radeonWaitForIdleLocked( rmesa
);
1224 UNLOCK_HARDWARE(rmesa
);
1228 void radeonFlush( GLcontext
*ctx
)
1230 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1232 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1233 fprintf(stderr
, "%s\n", __FUNCTION__
);
1235 if (rmesa
->dma
.flush
)
1236 rmesa
->dma
.flush( rmesa
);
1238 radeonEmitState( rmesa
);
1240 if (rmesa
->store
.cmd_used
)
1241 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1244 /* Make sure all commands have been sent to the hardware and have
1245 * completed processing.
1247 void radeonFinish( GLcontext
*ctx
)
1249 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1252 if (rmesa
->do_irqs
) {
1253 LOCK_HARDWARE( rmesa
);
1254 radeonEmitIrqLocked( rmesa
);
1255 UNLOCK_HARDWARE( rmesa
);
1256 radeonWaitIrq( rmesa
);
1259 radeonWaitForIdle( rmesa
);
1263 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1265 ctx
->Driver
.Clear
= radeonClear
;
1266 ctx
->Driver
.Finish
= radeonFinish
;
1267 ctx
->Driver
.Flush
= radeonFlush
;