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 if (rmesa
->dri
.drmMinor
>= 6) {
525 drm_radeon_cmd_header_t
*cmd
;
527 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
529 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 1 * sizeof(int),
532 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
533 cmd
[0].wait
.flags
= flags
;
538 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
539 const char * caller
)
542 drm_radeon_cmd_buffer_t cmd
;
544 if (rmesa
->lost_context
)
545 radeonBackUpAndEmitLostStateLocked(rmesa
);
547 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
548 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
550 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
551 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
552 fprintf(stderr
, "%d: %x\n", i
/4,
553 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
556 if (RADEON_DEBUG
& DEBUG_DMA
)
557 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
558 rmesa
->dma
.nr_released_bufs
);
561 if (RADEON_DEBUG
& DEBUG_SANITY
) {
562 if (rmesa
->state
.scissor
.enabled
)
563 ret
= radeonSanityCmdBuffer( rmesa
,
564 rmesa
->state
.scissor
.numClipRects
,
565 rmesa
->state
.scissor
.pClipRects
);
567 ret
= radeonSanityCmdBuffer( rmesa
,
571 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
577 cmd
.bufsz
= rmesa
->store
.cmd_used
;
578 cmd
.buf
= rmesa
->store
.cmd_buf
;
580 if (rmesa
->state
.scissor
.enabled
) {
581 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
582 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
584 cmd
.nbox
= rmesa
->numClipRects
;
585 cmd
.boxes
= rmesa
->pClipRects
;
588 ret
= drmCommandWrite( rmesa
->dri
.fd
,
593 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
595 if (RADEON_DEBUG
& DEBUG_SYNC
) {
596 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
597 radeonWaitForIdleLocked( rmesa
);
601 rmesa
->store
.primnr
= 0;
602 rmesa
->store
.statenr
= 0;
603 rmesa
->store
.cmd_used
= 0;
604 rmesa
->dma
.nr_released_bufs
= 0;
605 rmesa
->save_on_next_emit
= 1;
611 /* Note: does not emit any commands to avoid recursion on
614 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
619 LOCK_HARDWARE( rmesa
);
621 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
623 UNLOCK_HARDWARE( rmesa
);
626 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
631 /* =============================================================
632 * Hardware vertex buffer handling
636 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
638 struct radeon_dma_buffer
*dmabuf
;
639 int fd
= rmesa
->dri
.fd
;
645 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
646 fprintf(stderr
, "%s\n", __FUNCTION__
);
648 if (rmesa
->dma
.flush
) {
649 rmesa
->dma
.flush( rmesa
);
652 if (rmesa
->dma
.current
.buf
)
653 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
655 if (rmesa
->dma
.nr_released_bufs
> 4)
656 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
658 dma
.context
= rmesa
->dri
.hwContext
;
660 dma
.send_list
= NULL
;
661 dma
.send_sizes
= NULL
;
663 dma
.request_count
= 1;
664 dma
.request_size
= RADEON_BUFFER_SIZE
;
665 dma
.request_list
= &index
;
666 dma
.request_sizes
= &size
;
667 dma
.granted_count
= 0;
669 LOCK_HARDWARE(rmesa
); /* no need to validate */
671 ret
= drmDMA( fd
, &dma
);
674 /* Free some up this way?
676 if (rmesa
->dma
.nr_released_bufs
) {
677 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
680 if (RADEON_DEBUG
& DEBUG_DMA
)
681 fprintf(stderr
, "Waiting for buffers\n");
683 radeonWaitForIdleLocked( rmesa
);
684 ret
= drmDMA( fd
, &dma
);
687 UNLOCK_HARDWARE( rmesa
);
688 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
693 UNLOCK_HARDWARE(rmesa
);
695 if (RADEON_DEBUG
& DEBUG_DMA
)
696 fprintf(stderr
, "Allocated buffer %d\n", index
);
698 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
699 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
700 dmabuf
->refcount
= 1;
702 rmesa
->dma
.current
.buf
= dmabuf
;
703 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
704 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
705 rmesa
->dma
.current
.start
= 0;
706 rmesa
->dma
.current
.ptr
= 0;
708 rmesa
->c_vertexBuffers
++;
711 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
712 struct radeon_dma_region
*region
,
715 if (RADEON_DEBUG
& DEBUG_IOCTL
)
716 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
721 if (rmesa
->dma
.flush
)
722 rmesa
->dma
.flush( rmesa
);
724 if (--region
->buf
->refcount
== 0) {
725 drm_radeon_cmd_header_t
*cmd
;
727 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
728 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
729 region
->buf
->buf
->idx
);
731 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
733 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
734 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
736 rmesa
->dma
.nr_released_bufs
++;
743 /* Allocates a region from rmesa->dma.current. If there isn't enough
744 * space in current, grab a new buffer (and discard what was left of current)
746 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
747 struct radeon_dma_region
*region
,
751 if (RADEON_DEBUG
& DEBUG_IOCTL
)
752 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
754 if (rmesa
->dma
.flush
)
755 rmesa
->dma
.flush( rmesa
);
758 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
761 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
762 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
764 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
765 radeonRefillCurrentDmaRegion( rmesa
);
767 region
->start
= rmesa
->dma
.current
.start
;
768 region
->ptr
= rmesa
->dma
.current
.start
;
769 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
770 region
->address
= rmesa
->dma
.current
.address
;
771 region
->buf
= rmesa
->dma
.current
.buf
;
772 region
->buf
->refcount
++;
774 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
775 rmesa
->dma
.current
.start
=
776 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
779 /* ================================================================
780 * SwapBuffers with client-side throttling
783 static u_int32_t
radeonGetLastFrame (radeonContextPtr rmesa
)
785 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
789 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
790 drm_radeon_getparam_t gp
;
792 gp
.param
= RADEON_PARAM_LAST_FRAME
;
793 gp
.value
= (int *)&frame
;
794 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
800 if ( ret
== -EINVAL
) {
801 frame
= INREG( RADEON_LAST_FRAME_REG
);
805 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
812 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
814 drm_radeon_irq_emit_t ie
;
817 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
818 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
821 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
827 static void radeonWaitIrq( radeonContextPtr rmesa
)
832 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
833 &rmesa
->iw
, sizeof(rmesa
->iw
) );
834 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
837 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
843 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
845 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
847 if (rmesa
->do_irqs
) {
848 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
849 if (!rmesa
->irqsEmitted
) {
850 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
854 UNLOCK_HARDWARE( rmesa
);
855 radeonWaitIrq( rmesa
);
856 LOCK_HARDWARE( rmesa
);
858 rmesa
->irqsEmitted
= 10;
861 if (rmesa
->irqsEmitted
) {
862 radeonEmitIrqLocked( rmesa
);
863 rmesa
->irqsEmitted
--;
867 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
868 UNLOCK_HARDWARE( rmesa
);
869 if (rmesa
->do_usleeps
)
871 LOCK_HARDWARE( rmesa
);
876 /* Copy the back color buffer to the front color buffer.
878 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
,
879 const drm_clip_rect_t
*rect
)
881 radeonContextPtr rmesa
;
883 GLboolean missed_target
;
887 assert(dPriv
->driContextPriv
);
888 assert(dPriv
->driContextPriv
->driverPrivate
);
890 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
892 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
893 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
896 RADEON_FIREVERTICES( rmesa
);
897 LOCK_HARDWARE( rmesa
);
899 /* Throttle the frame rate -- only allow one pending swap buffers
902 radeonWaitForFrameCompletion( rmesa
);
905 UNLOCK_HARDWARE( rmesa
);
906 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
907 LOCK_HARDWARE( rmesa
);
910 nbox
= dPriv
->numClipRects
; /* must be in locked region */
912 for ( i
= 0 ; i
< nbox
; ) {
913 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
914 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
915 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
918 for ( ; i
< nr
; i
++ ) {
924 if (rect
->x1
> b
->x1
)
926 if (rect
->y1
> b
->y1
)
928 if (rect
->x2
< b
->x2
)
930 if (rect
->y2
< b
->y2
)
933 if (b
->x1
< b
->x2
&& b
->y1
< b
->y2
)
941 rmesa
->sarea
->nbox
= n
;
943 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
946 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
947 UNLOCK_HARDWARE( rmesa
);
952 UNLOCK_HARDWARE( rmesa
);
956 (*dri_interface
->getUST
)( & ust
);
957 if ( missed_target
) {
958 rmesa
->swap_missed_count
++;
959 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
962 rmesa
->swap_ust
= ust
;
963 rmesa
->hw
.all_dirty
= GL_TRUE
;
967 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
969 radeonContextPtr rmesa
;
971 GLboolean missed_target
;
974 assert(dPriv
->driContextPriv
);
975 assert(dPriv
->driContextPriv
->driverPrivate
);
977 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
979 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
980 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
981 rmesa
->sarea
->pfCurrentPage
);
984 RADEON_FIREVERTICES( rmesa
);
985 LOCK_HARDWARE( rmesa
);
987 /* Need to do this for the perf box placement:
989 if (dPriv
->numClipRects
)
991 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
992 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
994 rmesa
->sarea
->nbox
= 1;
997 /* Throttle the frame rate -- only allow a few pending swap buffers
1000 radeonWaitForFrameCompletion( rmesa
);
1001 UNLOCK_HARDWARE( rmesa
);
1002 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
1003 if ( missed_target
) {
1004 rmesa
->swap_missed_count
++;
1005 (void) (*dri_interface
->getUST
)( & rmesa
->swap_missed_ust
);
1007 LOCK_HARDWARE( rmesa
);
1009 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
1011 UNLOCK_HARDWARE( rmesa
);
1014 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
1018 rmesa
->swap_count
++;
1019 (void) (*dri_interface
->getUST
)( & rmesa
->swap_ust
);
1021 /* Get ready for drawing next frame. Update the renderbuffers'
1022 * flippedOffset/Pitch fields so we draw into the right place.
1024 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
1025 rmesa
->sarea
->pfCurrentPage
);
1027 radeonUpdateDrawBuffer(rmesa
->glCtx
);
1031 /* ================================================================
1034 #define RADEON_MAX_CLEARS 256
1036 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
1037 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
1039 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1040 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1041 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
1042 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
1045 GLuint color_mask
= 0;
1048 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1049 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
1050 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
1054 LOCK_HARDWARE( rmesa
);
1055 UNLOCK_HARDWARE( rmesa
);
1056 if ( dPriv
->numClipRects
== 0 )
1062 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
1063 flags
|= RADEON_FRONT
;
1064 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1065 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
1068 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
1069 flags
|= RADEON_BACK
;
1070 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1071 mask
&= ~BUFFER_BIT_BACK_LEFT
;
1074 if ( mask
& BUFFER_BIT_DEPTH
) {
1075 flags
|= RADEON_DEPTH
;
1076 mask
&= ~BUFFER_BIT_DEPTH
;
1079 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
1080 flags
|= RADEON_STENCIL
;
1081 mask
&= ~BUFFER_BIT_STENCIL
;
1085 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1086 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1087 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1093 if (rmesa
->using_hyperz
) {
1094 flags
|= RADEON_USE_COMP_ZBUF
;
1095 /* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
1096 flags |= RADEON_USE_HIERZ; */
1097 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
1098 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
1099 ((rmesa
->state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
1100 flags
|= RADEON_CLEAR_FASTZ
;
1104 /* Flip top to bottom */
1106 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1108 LOCK_HARDWARE( rmesa
);
1110 /* Throttle the number of clear ioctls we do.
1115 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1116 drm_radeon_getparam_t gp
;
1118 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1119 gp
.value
= (int *)&clear
;
1120 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1121 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1125 if ( ret
== -EINVAL
) {
1126 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1130 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1133 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1134 fprintf( stderr
, "%s( %d )\n", __FUNCTION__
, (int)clear
);
1135 if ( ret
) fprintf( stderr
, " ( RADEON_LAST_CLEAR register read directly )\n" );
1138 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1142 if ( rmesa
->do_usleeps
) {
1143 UNLOCK_HARDWARE( rmesa
);
1145 LOCK_HARDWARE( rmesa
);
1149 /* Send current state to the hardware */
1150 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1152 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1153 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1154 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1155 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1156 drm_radeon_clear_t clear
;
1157 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1161 for ( ; i
< nr
; i
++ ) {
1162 GLint x
= box
[i
].x1
;
1163 GLint y
= box
[i
].y1
;
1164 GLint w
= box
[i
].x2
- x
;
1165 GLint h
= box
[i
].y2
- y
;
1167 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1168 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1169 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1170 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1171 if ( w
<= 0 ) continue;
1172 if ( h
<= 0 ) continue;
1182 for ( ; i
< nr
; i
++ ) {
1188 rmesa
->sarea
->nbox
= n
;
1190 clear
.flags
= flags
;
1191 clear
.clear_color
= rmesa
->state
.color
.clear
;
1192 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1193 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1194 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1195 clear
.depth_boxes
= depth_boxes
;
1198 b
= rmesa
->sarea
->boxes
;
1199 for ( ; n
>= 0 ; n
-- ) {
1200 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1201 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1202 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1203 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1204 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1205 (float)rmesa
->state
.depth
.clear
;
1208 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1209 &clear
, sizeof(drm_radeon_clear_t
));
1212 UNLOCK_HARDWARE( rmesa
);
1213 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1218 UNLOCK_HARDWARE( rmesa
);
1219 rmesa
->hw
.all_dirty
= GL_TRUE
;
1223 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1225 int fd
= rmesa
->dri
.fd
;
1229 rmesa
->c_drawWaits
++;
1233 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1234 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1235 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1238 UNLOCK_HARDWARE( rmesa
);
1239 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1245 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1247 LOCK_HARDWARE(rmesa
);
1248 radeonWaitForIdleLocked( rmesa
);
1249 UNLOCK_HARDWARE(rmesa
);
1253 void radeonFlush( GLcontext
*ctx
)
1255 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1257 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1258 fprintf(stderr
, "%s\n", __FUNCTION__
);
1260 if (rmesa
->dma
.flush
)
1261 rmesa
->dma
.flush( rmesa
);
1263 radeonEmitState( rmesa
);
1265 if (rmesa
->store
.cmd_used
)
1266 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1269 /* Make sure all commands have been sent to the hardware and have
1270 * completed processing.
1272 void radeonFinish( GLcontext
*ctx
)
1274 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1277 if (rmesa
->do_irqs
) {
1278 LOCK_HARDWARE( rmesa
);
1279 radeonEmitIrqLocked( rmesa
);
1280 UNLOCK_HARDWARE( rmesa
);
1281 radeonWaitIrq( rmesa
);
1284 radeonWaitForIdle( rmesa
);
1288 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1290 ctx
->Driver
.Clear
= radeonClear
;
1291 ctx
->Driver
.Finish
= radeonFinish
;
1292 ctx
->Driver
.Flush
= radeonFlush
;