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
]);
156 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.zbs
);
157 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
);
158 for (i
= 0; i
< 3 + mtu
; ++i
)
159 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
]);
160 for (i
= 0; i
< 8; ++i
)
161 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
]);
162 for (i
= 0; i
< 6; ++i
)
163 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
]);
164 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
165 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.grd
);
166 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.fog
);
167 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
170 void radeonEmitState( radeonContextPtr rmesa
)
172 struct radeon_state_atom
*atom
;
175 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
176 fprintf(stderr
, "%s\n", __FUNCTION__
);
178 if (rmesa
->save_on_next_emit
) {
179 radeonSaveHwState(rmesa
);
180 rmesa
->save_on_next_emit
= GL_FALSE
;
183 /* this code used to return here but now it emits zbs */
185 /* To avoid going across the entire set of states multiple times, just check
186 * for enough space for the case of emitting all state, and inline the
187 * radeonAllocCmdBuf code here without all the checks.
189 radeonEnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
);
190 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
192 /* We always always emit zbs, this is due to a bug found by keithw in
193 the hardware and rediscovered after Erics changes by me.
194 if you ever touch this code make sure you emit zbs otherwise
195 you get tcl lockups on at least M7/7500 class of chips - airlied */
196 rmesa
->hw
.zbs
.dirty
=1;
198 if (RADEON_DEBUG
& DEBUG_STATE
) {
199 foreach(atom
, &rmesa
->hw
.atomlist
) {
200 if (atom
->dirty
|| rmesa
->hw
.all_dirty
) {
201 if (atom
->check(rmesa
->glCtx
))
202 print_state_atom(atom
);
204 fprintf(stderr
, "skip state %s\n", atom
->name
);
209 foreach(atom
, &rmesa
->hw
.atomlist
) {
210 if (rmesa
->hw
.all_dirty
)
211 atom
->dirty
= GL_TRUE
;
212 if (!(rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
) &&
214 atom
->dirty
= GL_FALSE
;
216 if (atom
->check(rmesa
->glCtx
)) {
217 int size
= atom
->cmd_size
* 4;
218 memcpy(dest
, atom
->cmd
, size
);
220 rmesa
->store
.cmd_used
+= size
;
221 atom
->dirty
= GL_FALSE
;
226 assert(rmesa
->store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
228 rmesa
->hw
.is_dirty
= GL_FALSE
;
229 rmesa
->hw
.all_dirty
= GL_FALSE
;
232 /* Fire a section of the retained (indexed_verts) buffer as a regular
235 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
236 GLuint vertex_format
,
240 drm_radeon_cmd_header_t
*cmd
;
243 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
245 radeonEmitState( rmesa
);
247 if (RADEON_DEBUG
& DEBUG_IOCTL
)
248 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
249 rmesa
->store
.cmd_used
/4);
251 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VBUF_BUFSZ
,
253 #if RADEON_OLD_PACKETS
255 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
256 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
| (3 << 16);
257 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
258 cmd
[3].i
= vertex_nr
;
259 cmd
[4].i
= vertex_format
;
260 cmd
[5].i
= (primitive
|
261 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
262 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
263 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
264 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
266 if (RADEON_DEBUG
& DEBUG_PRIMS
)
267 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
269 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
272 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
273 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_VBUF
| (1 << 16);
274 cmd
[2].i
= vertex_format
;
275 cmd
[3].i
= (primitive
|
276 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
277 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
278 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
279 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
280 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
283 if (RADEON_DEBUG
& DEBUG_PRIMS
)
284 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
286 cmd
[1].i
, cmd
[2].i
, cmd
[3].i
);
291 void radeonFlushElts( radeonContextPtr rmesa
)
293 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
295 #if RADEON_OLD_PACKETS
296 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 24)) / 2;
298 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 16)) / 2;
301 if (RADEON_DEBUG
& DEBUG_IOCTL
)
302 fprintf(stderr
, "%s\n", __FUNCTION__
);
304 assert( rmesa
->dma
.flush
== radeonFlushElts
);
305 rmesa
->dma
.flush
= NULL
;
307 /* Cope with odd number of elts:
309 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
310 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
312 #if RADEON_OLD_PACKETS
313 cmd
[1] |= (dwords
- 3) << 16;
314 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
316 cmd
[1] |= (dwords
- 3) << 16;
317 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
320 if (RADEON_DEBUG
& DEBUG_SYNC
) {
321 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
322 radeonFinish( rmesa
->glCtx
);
327 GLushort
*radeonAllocEltsOpenEnded( radeonContextPtr rmesa
,
328 GLuint vertex_format
,
332 drm_radeon_cmd_header_t
*cmd
;
335 if (RADEON_DEBUG
& DEBUG_IOCTL
)
336 fprintf(stderr
, "%s %d\n", __FUNCTION__
, min_nr
);
338 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
340 radeonEmitState( rmesa
);
342 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
345 #if RADEON_OLD_PACKETS
347 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
348 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
;
349 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
351 cmd
[4].i
= vertex_format
;
352 cmd
[5].i
= (primitive
|
353 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
354 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
355 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
357 retval
= (GLushort
*)(cmd
+6);
360 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
361 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_INDX
;
362 cmd
[2].i
= vertex_format
;
363 cmd
[3].i
= (primitive
|
364 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
365 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
366 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
367 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
369 retval
= (GLushort
*)(cmd
+4);
372 if (RADEON_DEBUG
& DEBUG_PRIMS
)
373 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
375 cmd
[1].i
, vertex_format
, primitive
);
377 assert(!rmesa
->dma
.flush
);
378 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
379 rmesa
->dma
.flush
= radeonFlushElts
;
381 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
388 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
392 #if RADEON_OLD_PACKETS
393 rmesa
->ioctl
.vertex_size
= vertex_size
;
394 rmesa
->ioctl
.vertex_offset
= offset
;
396 drm_radeon_cmd_header_t
*cmd
;
398 if (RADEON_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
399 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
400 __FUNCTION__
, vertex_size
, offset
);
402 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
406 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
407 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
409 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
415 void radeonEmitAOS( radeonContextPtr rmesa
,
416 struct radeon_dma_region
**component
,
420 #if RADEON_OLD_PACKETS
422 assert( component
[0]->aos_size
== component
[0]->aos_stride
);
423 rmesa
->ioctl
.vertex_size
= component
[0]->aos_size
;
424 rmesa
->ioctl
.vertex_offset
=
425 (component
[0]->aos_start
+ offset
* component
[0]->aos_stride
* 4);
427 drm_radeon_cmd_header_t
*cmd
;
428 int sz
= AOS_BUFSZ(nr
);
432 if (RADEON_DEBUG
& DEBUG_IOCTL
)
433 fprintf(stderr
, "%s\n", __FUNCTION__
);
436 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
,
439 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
440 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int))-3) << 16);
445 for (i
= 0 ; i
< nr
; i
++) {
447 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
448 (component
[i
]->aos_size
<< 16));
449 cmd
[2].i
= (component
[i
]->aos_start
+
450 offset
* component
[i
]->aos_stride
* 4);
454 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
455 (component
[i
]->aos_size
<< 0));
456 cmd
[1].i
= (component
[i
]->aos_start
+
457 offset
* component
[i
]->aos_stride
* 4);
461 if (RADEON_DEBUG
& DEBUG_VERTS
) {
462 fprintf(stderr
, "%s:\n", __FUNCTION__
);
463 for (i
= 0 ; i
< sz
; i
++)
464 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
469 /* using already shifted color_fmt! */
470 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
476 GLint srcx
, GLint srcy
,
477 GLint dstx
, GLint dsty
,
480 drm_radeon_cmd_header_t
*cmd
;
482 if (RADEON_DEBUG
& DEBUG_IOCTL
)
483 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
485 src_pitch
, src_offset
, srcx
, srcy
,
486 dst_pitch
, dst_offset
, dstx
, dsty
,
489 assert( (src_pitch
& 63) == 0 );
490 assert( (dst_pitch
& 63) == 0 );
491 assert( (src_offset
& 1023) == 0 );
492 assert( (dst_offset
& 1023) == 0 );
493 assert( w
< (1<<16) );
494 assert( h
< (1<<16) );
496 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
501 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
502 cmd
[1].i
= RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
| (5 << 16);
503 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
504 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
505 RADEON_GMC_BRUSH_NONE
|
507 RADEON_GMC_SRC_DATATYPE_COLOR
|
509 RADEON_DP_SRC_SOURCE_MEMORY
|
510 RADEON_GMC_CLR_CMP_CNTL_DIS
|
511 RADEON_GMC_WR_MSK_DIS
);
513 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
514 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
515 cmd
[5].i
= (srcx
<< 16) | srcy
;
516 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
517 cmd
[7].i
= (w
<< 16) | h
;
521 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
523 if (rmesa
->dri
.drmMinor
>= 6) {
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
;
537 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
538 const char * caller
)
541 drm_radeon_cmd_buffer_t cmd
;
543 if (rmesa
->lost_context
)
544 radeonBackUpAndEmitLostStateLocked(rmesa
);
546 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
547 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
549 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
550 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
551 fprintf(stderr
, "%d: %x\n", i
/4,
552 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
555 if (RADEON_DEBUG
& DEBUG_DMA
)
556 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
557 rmesa
->dma
.nr_released_bufs
);
560 if (RADEON_DEBUG
& DEBUG_SANITY
) {
561 if (rmesa
->state
.scissor
.enabled
)
562 ret
= radeonSanityCmdBuffer( rmesa
,
563 rmesa
->state
.scissor
.numClipRects
,
564 rmesa
->state
.scissor
.pClipRects
);
566 ret
= radeonSanityCmdBuffer( rmesa
,
570 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
576 cmd
.bufsz
= rmesa
->store
.cmd_used
;
577 cmd
.buf
= rmesa
->store
.cmd_buf
;
579 if (rmesa
->state
.scissor
.enabled
) {
580 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
581 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
583 cmd
.nbox
= rmesa
->numClipRects
;
584 cmd
.boxes
= rmesa
->pClipRects
;
587 ret
= drmCommandWrite( rmesa
->dri
.fd
,
592 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
594 if (RADEON_DEBUG
& DEBUG_SYNC
) {
595 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
596 radeonWaitForIdleLocked( rmesa
);
600 rmesa
->store
.primnr
= 0;
601 rmesa
->store
.statenr
= 0;
602 rmesa
->store
.cmd_used
= 0;
603 rmesa
->dma
.nr_released_bufs
= 0;
604 rmesa
->save_on_next_emit
= 1;
610 /* Note: does not emit any commands to avoid recursion on
613 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
618 LOCK_HARDWARE( rmesa
);
620 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
622 UNLOCK_HARDWARE( rmesa
);
625 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
630 /* =============================================================
631 * Hardware vertex buffer handling
635 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
637 struct radeon_dma_buffer
*dmabuf
;
638 int fd
= rmesa
->dri
.fd
;
644 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
645 fprintf(stderr
, "%s\n", __FUNCTION__
);
647 if (rmesa
->dma
.flush
) {
648 rmesa
->dma
.flush( rmesa
);
651 if (rmesa
->dma
.current
.buf
)
652 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
654 if (rmesa
->dma
.nr_released_bufs
> 4)
655 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
657 dma
.context
= rmesa
->dri
.hwContext
;
659 dma
.send_list
= NULL
;
660 dma
.send_sizes
= NULL
;
662 dma
.request_count
= 1;
663 dma
.request_size
= RADEON_BUFFER_SIZE
;
664 dma
.request_list
= &index
;
665 dma
.request_sizes
= &size
;
666 dma
.granted_count
= 0;
668 LOCK_HARDWARE(rmesa
); /* no need to validate */
670 ret
= drmDMA( fd
, &dma
);
673 /* Free some up this way?
675 if (rmesa
->dma
.nr_released_bufs
) {
676 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
679 if (RADEON_DEBUG
& DEBUG_DMA
)
680 fprintf(stderr
, "Waiting for buffers\n");
682 radeonWaitForIdleLocked( rmesa
);
683 ret
= drmDMA( fd
, &dma
);
686 UNLOCK_HARDWARE( rmesa
);
687 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
692 UNLOCK_HARDWARE(rmesa
);
694 if (RADEON_DEBUG
& DEBUG_DMA
)
695 fprintf(stderr
, "Allocated buffer %d\n", index
);
697 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
698 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
699 dmabuf
->refcount
= 1;
701 rmesa
->dma
.current
.buf
= dmabuf
;
702 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
703 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
704 rmesa
->dma
.current
.start
= 0;
705 rmesa
->dma
.current
.ptr
= 0;
707 rmesa
->c_vertexBuffers
++;
710 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
711 struct radeon_dma_region
*region
,
714 if (RADEON_DEBUG
& DEBUG_IOCTL
)
715 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
720 if (rmesa
->dma
.flush
)
721 rmesa
->dma
.flush( rmesa
);
723 if (--region
->buf
->refcount
== 0) {
724 drm_radeon_cmd_header_t
*cmd
;
726 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
727 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
728 region
->buf
->buf
->idx
);
730 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
732 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
733 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
735 rmesa
->dma
.nr_released_bufs
++;
742 /* Allocates a region from rmesa->dma.current. If there isn't enough
743 * space in current, grab a new buffer (and discard what was left of current)
745 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
746 struct radeon_dma_region
*region
,
750 if (RADEON_DEBUG
& DEBUG_IOCTL
)
751 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
753 if (rmesa
->dma
.flush
)
754 rmesa
->dma
.flush( rmesa
);
757 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
760 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
761 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
763 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
764 radeonRefillCurrentDmaRegion( rmesa
);
766 region
->start
= rmesa
->dma
.current
.start
;
767 region
->ptr
= rmesa
->dma
.current
.start
;
768 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
769 region
->address
= rmesa
->dma
.current
.address
;
770 region
->buf
= rmesa
->dma
.current
.buf
;
771 region
->buf
->refcount
++;
773 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
774 rmesa
->dma
.current
.start
=
775 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
778 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa
,
779 struct radeon_dma_region
*region
,
784 radeonAllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
787 /* ================================================================
788 * SwapBuffers with client-side throttling
791 static u_int32_t
radeonGetLastFrame (radeonContextPtr rmesa
)
793 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
797 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
798 drm_radeon_getparam_t gp
;
800 gp
.param
= RADEON_PARAM_LAST_FRAME
;
801 gp
.value
= (int *)&frame
;
802 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
808 if ( ret
== -EINVAL
) {
809 frame
= INREG( RADEON_LAST_FRAME_REG
);
813 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
820 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
822 drm_radeon_irq_emit_t ie
;
825 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
826 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
829 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
835 static void radeonWaitIrq( radeonContextPtr rmesa
)
840 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
841 &rmesa
->iw
, sizeof(rmesa
->iw
) );
842 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
845 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
851 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
853 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
855 if (rmesa
->do_irqs
) {
856 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
857 if (!rmesa
->irqsEmitted
) {
858 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
862 UNLOCK_HARDWARE( rmesa
);
863 radeonWaitIrq( rmesa
);
864 LOCK_HARDWARE( rmesa
);
866 rmesa
->irqsEmitted
= 10;
869 if (rmesa
->irqsEmitted
) {
870 radeonEmitIrqLocked( rmesa
);
871 rmesa
->irqsEmitted
--;
875 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
876 UNLOCK_HARDWARE( rmesa
);
877 if (rmesa
->do_usleeps
)
879 LOCK_HARDWARE( rmesa
);
884 /* Copy the back color buffer to the front color buffer.
886 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
888 radeonContextPtr rmesa
;
890 GLboolean missed_target
;
894 assert(dPriv
->driContextPriv
);
895 assert(dPriv
->driContextPriv
->driverPrivate
);
897 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
899 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
900 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
903 RADEON_FIREVERTICES( rmesa
);
904 LOCK_HARDWARE( rmesa
);
906 /* Throttle the frame rate -- only allow one pending swap buffers
909 radeonWaitForFrameCompletion( rmesa
);
910 UNLOCK_HARDWARE( rmesa
);
911 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
912 LOCK_HARDWARE( rmesa
);
914 nbox
= dPriv
->numClipRects
; /* must be in locked region */
916 for ( i
= 0 ; i
< nbox
; ) {
917 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
918 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
919 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
922 for ( ; i
< nr
; i
++ ) {
926 rmesa
->sarea
->nbox
= n
;
928 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
931 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
932 UNLOCK_HARDWARE( rmesa
);
937 UNLOCK_HARDWARE( rmesa
);
939 (*dri_interface
->getUST
)( & ust
);
940 if ( missed_target
) {
941 rmesa
->swap_missed_count
++;
942 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
945 rmesa
->swap_ust
= ust
;
946 rmesa
->hw
.all_dirty
= GL_TRUE
;
949 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
951 radeonContextPtr rmesa
;
953 GLboolean missed_target
;
956 assert(dPriv
->driContextPriv
);
957 assert(dPriv
->driContextPriv
->driverPrivate
);
959 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
961 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
962 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
963 rmesa
->sarea
->pfCurrentPage
);
966 RADEON_FIREVERTICES( rmesa
);
967 LOCK_HARDWARE( rmesa
);
969 /* Need to do this for the perf box placement:
971 if (dPriv
->numClipRects
)
973 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
974 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
976 rmesa
->sarea
->nbox
= 1;
979 /* Throttle the frame rate -- only allow a few pending swap buffers
982 radeonWaitForFrameCompletion( rmesa
);
983 UNLOCK_HARDWARE( rmesa
);
984 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
985 if ( missed_target
) {
986 rmesa
->swap_missed_count
++;
987 (void) (*dri_interface
->getUST
)( & rmesa
->swap_missed_ust
);
989 LOCK_HARDWARE( rmesa
);
991 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
993 UNLOCK_HARDWARE( rmesa
);
996 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
1000 rmesa
->swap_count
++;
1001 (void) (*dri_interface
->getUST
)( & rmesa
->swap_ust
);
1003 /* Get ready for drawing next frame. Update the renderbuffers'
1004 * flippedOffset/Pitch fields so we draw into the right place.
1006 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
1007 rmesa
->sarea
->pfCurrentPage
);
1009 radeonUpdateDrawBuffer(rmesa
->glCtx
);
1013 /* ================================================================
1016 #define RADEON_MAX_CLEARS 256
1018 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
1019 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
1021 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1022 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1023 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
1024 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
1027 GLuint color_mask
= 0;
1030 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1031 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
1032 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
1036 LOCK_HARDWARE( rmesa
);
1037 UNLOCK_HARDWARE( rmesa
);
1038 if ( dPriv
->numClipRects
== 0 )
1044 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
1045 flags
|= RADEON_FRONT
;
1046 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1047 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
1050 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
1051 flags
|= RADEON_BACK
;
1052 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1053 mask
&= ~BUFFER_BIT_BACK_LEFT
;
1056 if ( mask
& BUFFER_BIT_DEPTH
) {
1057 flags
|= RADEON_DEPTH
;
1058 mask
&= ~BUFFER_BIT_DEPTH
;
1061 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
1062 flags
|= RADEON_STENCIL
;
1063 mask
&= ~BUFFER_BIT_STENCIL
;
1067 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1068 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1069 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1075 if (rmesa
->using_hyperz
) {
1076 flags
|= RADEON_USE_COMP_ZBUF
;
1077 /* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
1078 flags |= RADEON_USE_HIERZ; */
1079 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
1080 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
1081 ((rmesa
->state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
1082 flags
|= RADEON_CLEAR_FASTZ
;
1086 /* Flip top to bottom */
1088 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1090 LOCK_HARDWARE( rmesa
);
1092 /* Throttle the number of clear ioctls we do.
1097 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1098 drm_radeon_getparam_t gp
;
1100 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1101 gp
.value
= (int *)&clear
;
1102 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1103 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1107 if ( ret
== -EINVAL
) {
1108 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1112 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1115 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1116 fprintf( stderr
, "%s( %d )\n", __FUNCTION__
, (int)clear
);
1117 if ( ret
) fprintf( stderr
, " ( RADEON_LAST_CLEAR register read directly )\n" );
1120 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1124 if ( rmesa
->do_usleeps
) {
1125 UNLOCK_HARDWARE( rmesa
);
1127 LOCK_HARDWARE( rmesa
);
1131 /* Send current state to the hardware */
1132 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1134 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1135 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1136 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1137 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1138 drm_radeon_clear_t clear
;
1139 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1143 for ( ; i
< nr
; i
++ ) {
1144 GLint x
= box
[i
].x1
;
1145 GLint y
= box
[i
].y1
;
1146 GLint w
= box
[i
].x2
- x
;
1147 GLint h
= box
[i
].y2
- y
;
1149 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1150 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1151 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1152 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1153 if ( w
<= 0 ) continue;
1154 if ( h
<= 0 ) continue;
1164 for ( ; i
< nr
; i
++ ) {
1170 rmesa
->sarea
->nbox
= n
;
1172 clear
.flags
= flags
;
1173 clear
.clear_color
= rmesa
->state
.color
.clear
;
1174 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1175 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1176 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1177 clear
.depth_boxes
= depth_boxes
;
1180 b
= rmesa
->sarea
->boxes
;
1181 for ( ; n
>= 0 ; n
-- ) {
1182 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1183 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1184 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1185 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1186 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1187 (float)rmesa
->state
.depth
.clear
;
1190 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1191 &clear
, sizeof(drm_radeon_clear_t
));
1194 UNLOCK_HARDWARE( rmesa
);
1195 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1200 UNLOCK_HARDWARE( rmesa
);
1201 rmesa
->hw
.all_dirty
= GL_TRUE
;
1205 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1207 int fd
= rmesa
->dri
.fd
;
1211 rmesa
->c_drawWaits
++;
1215 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1216 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1217 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1220 UNLOCK_HARDWARE( rmesa
);
1221 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1227 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1229 LOCK_HARDWARE(rmesa
);
1230 radeonWaitForIdleLocked( rmesa
);
1231 UNLOCK_HARDWARE(rmesa
);
1235 void radeonFlush( GLcontext
*ctx
)
1237 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1239 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1240 fprintf(stderr
, "%s\n", __FUNCTION__
);
1242 if (rmesa
->dma
.flush
)
1243 rmesa
->dma
.flush( rmesa
);
1245 radeonEmitState( rmesa
);
1247 if (rmesa
->store
.cmd_used
)
1248 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1251 /* Make sure all commands have been sent to the hardware and have
1252 * completed processing.
1254 void radeonFinish( GLcontext
*ctx
)
1256 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1259 if (rmesa
->do_irqs
) {
1260 LOCK_HARDWARE( rmesa
);
1261 radeonEmitIrqLocked( rmesa
);
1262 UNLOCK_HARDWARE( rmesa
);
1263 radeonWaitIrq( rmesa
);
1266 radeonWaitForIdle( rmesa
);
1270 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1272 ctx
->Driver
.Clear
= radeonClear
;
1273 ctx
->Driver
.Finish
= radeonFinish
;
1274 ctx
->Driver
.Flush
= radeonFlush
;