1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes Exp $ */
2 /**************************************************************************
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Kevin E. Martin <martin@valinux.com>
34 * Gareth Hughes <gareth@valinux.com>
35 * Keith Whitwell <keith@tungstengraphics.com>
43 #include "simple_list.h"
44 #include "swrast/swrast.h"
46 #include "radeon_context.h"
47 #include "radeon_state.h"
48 #include "radeon_ioctl.h"
49 #include "radeon_tcl.h"
50 #include "radeon_sanity.h"
52 #define STANDALONE_MMIO
53 #include "radeon_macros.h" /* for INREG() */
57 #define RADEON_TIMEOUT 512
58 #define RADEON_IDLE_RETRY 16
61 static void radeonWaitForIdle( radeonContextPtr rmesa
);
62 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
63 const char * caller
);
65 static void print_state_atom( struct radeon_state_atom
*state
)
69 fprintf(stderr
, "emit %s/%d\n", state
->name
, state
->cmd_size
);
71 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
72 for (i
= 0 ; i
< state
->cmd_size
; i
++)
73 fprintf(stderr
, "\t%s[%d]: %x\n", state
->name
, i
, state
->cmd
[i
]);
77 static void radeonSaveHwState( radeonContextPtr rmesa
)
79 struct radeon_state_atom
*atom
;
80 char * dest
= rmesa
->backup_store
.cmd_buf
;
82 if (RADEON_DEBUG
& DEBUG_STATE
)
83 fprintf(stderr
, "%s\n", __FUNCTION__
);
85 rmesa
->backup_store
.cmd_used
= 0;
87 foreach( atom
, &rmesa
->hw
.atomlist
) {
88 if ( atom
->check( rmesa
->glCtx
) ) {
89 int size
= atom
->cmd_size
* 4;
90 memcpy( dest
, atom
->cmd
, size
);
92 rmesa
->backup_store
.cmd_used
+= size
;
93 if (RADEON_DEBUG
& DEBUG_STATE
)
94 print_state_atom( atom
);
98 assert( rmesa
->backup_store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
99 if (RADEON_DEBUG
& DEBUG_STATE
)
100 fprintf(stderr
, "Returning to radeonEmitState\n");
103 /* At this point we were in FlushCmdBufLocked but we had lost our context, so
104 * we need to unwire our current cmdbuf, hook the one with the saved state in
105 * it, flush it, and then put the current one back. This is so commands at the
106 * start of a cmdbuf can rely on the state being kept from the previous one.
108 static void radeonBackUpAndEmitLostStateLocked( radeonContextPtr rmesa
)
110 GLuint nr_released_bufs
;
111 struct radeon_store saved_store
;
113 if (rmesa
->backup_store
.cmd_used
== 0)
116 if (RADEON_DEBUG
& DEBUG_STATE
)
117 fprintf(stderr
, "Emitting backup state on lost context\n");
119 rmesa
->lost_context
= GL_FALSE
;
121 nr_released_bufs
= rmesa
->dma
.nr_released_bufs
;
122 saved_store
= rmesa
->store
;
123 rmesa
->dma
.nr_released_bufs
= 0;
124 rmesa
->store
= rmesa
->backup_store
;
125 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
126 rmesa
->dma
.nr_released_bufs
= nr_released_bufs
;
127 rmesa
->store
= saved_store
;
130 /* =============================================================
131 * Kernel command buffer handling
134 /* The state atoms will be emitted in the order they appear in the atom list,
135 * so this step is important.
137 void radeonSetUpAtomList( radeonContextPtr rmesa
)
139 int i
, mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
141 make_empty_list(&rmesa
->hw
.atomlist
);
142 rmesa
->hw
.atomlist
.name
= "atom-list";
144 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.ctx
);
145 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.set
);
146 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.lin
);
147 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.msk
);
148 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.vpt
);
149 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.tcl
);
150 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.msc
);
151 for (i
= 0; i
< mtu
; ++i
) {
152 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.tex
[i
]);
153 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.txr
[i
]);
155 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.zbs
);
156 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
);
157 for (i
= 0; i
< 3 + mtu
; ++i
)
158 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
]);
159 for (i
= 0; i
< 8; ++i
)
160 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
]);
161 for (i
= 0; i
< 6; ++i
)
162 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
]);
163 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
164 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.grd
);
165 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.fog
);
166 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
169 void radeonEmitState( radeonContextPtr rmesa
)
171 struct radeon_state_atom
*atom
;
174 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
175 fprintf(stderr
, "%s\n", __FUNCTION__
);
177 if (rmesa
->save_on_next_emit
) {
178 radeonSaveHwState(rmesa
);
179 rmesa
->save_on_next_emit
= GL_FALSE
;
182 if (!rmesa
->hw
.is_dirty
&& !rmesa
->hw
.all_dirty
)
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 if (RADEON_DEBUG
& DEBUG_STATE
) {
193 foreach(atom
, &rmesa
->hw
.atomlist
) {
194 if (atom
->dirty
|| rmesa
->hw
.all_dirty
) {
195 if (atom
->check(rmesa
->glCtx
))
196 print_state_atom(atom
);
198 fprintf(stderr
, "skip state %s\n", atom
->name
);
203 foreach(atom
, &rmesa
->hw
.atomlist
) {
204 if (rmesa
->hw
.all_dirty
)
205 atom
->dirty
= GL_TRUE
;
206 if (!(rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
) &&
208 atom
->dirty
= GL_FALSE
;
210 if (atom
->check(rmesa
->glCtx
)) {
211 int size
= atom
->cmd_size
* 4;
212 memcpy(dest
, atom
->cmd
, size
);
214 rmesa
->store
.cmd_used
+= size
;
215 atom
->dirty
= GL_FALSE
;
220 assert(rmesa
->store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
222 rmesa
->hw
.is_dirty
= GL_FALSE
;
223 rmesa
->hw
.all_dirty
= GL_FALSE
;
226 /* Fire a section of the retained (indexed_verts) buffer as a regular
229 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
230 GLuint vertex_format
,
234 drm_radeon_cmd_header_t
*cmd
;
237 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
239 radeonEmitState( rmesa
);
241 if (RADEON_DEBUG
& DEBUG_IOCTL
)
242 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
243 rmesa
->store
.cmd_used
/4);
245 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VBUF_BUFSZ
,
247 #if RADEON_OLD_PACKETS
249 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
250 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
| (3 << 16);
251 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
252 cmd
[3].i
= vertex_nr
;
253 cmd
[4].i
= vertex_format
;
254 cmd
[5].i
= (primitive
|
255 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
256 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
257 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
258 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
260 if (RADEON_DEBUG
& DEBUG_PRIMS
)
261 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
263 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
266 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
267 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_VBUF
| (1 << 16);
268 cmd
[2].i
= vertex_format
;
269 cmd
[3].i
= (primitive
|
270 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
271 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
272 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
273 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
274 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
277 if (RADEON_DEBUG
& DEBUG_PRIMS
)
278 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
280 cmd
[1].i
, cmd
[2].i
, cmd
[3].i
);
285 void radeonFlushElts( radeonContextPtr rmesa
)
287 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
289 #if RADEON_OLD_PACKETS
290 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 24)) / 2;
292 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 16)) / 2;
295 if (RADEON_DEBUG
& DEBUG_IOCTL
)
296 fprintf(stderr
, "%s\n", __FUNCTION__
);
298 assert( rmesa
->dma
.flush
== radeonFlushElts
);
299 rmesa
->dma
.flush
= 0;
301 /* Cope with odd number of elts:
303 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
304 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
306 #if RADEON_OLD_PACKETS
307 cmd
[1] |= (dwords
- 3) << 16;
308 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
310 cmd
[1] |= (dwords
- 3) << 16;
311 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
316 GLushort
*radeonAllocEltsOpenEnded( radeonContextPtr rmesa
,
317 GLuint vertex_format
,
321 drm_radeon_cmd_header_t
*cmd
;
324 if (RADEON_DEBUG
& DEBUG_IOCTL
)
325 fprintf(stderr
, "%s %d\n", __FUNCTION__
, min_nr
);
327 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
329 radeonEmitState( rmesa
);
331 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
334 #if RADEON_OLD_PACKETS
336 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
337 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
;
338 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
340 cmd
[4].i
= vertex_format
;
341 cmd
[5].i
= (primitive
|
342 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
343 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
344 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
346 retval
= (GLushort
*)(cmd
+6);
349 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
350 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_INDX
;
351 cmd
[2].i
= vertex_format
;
352 cmd
[3].i
= (primitive
|
353 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
354 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
355 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
356 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
358 retval
= (GLushort
*)(cmd
+4);
361 if (RADEON_DEBUG
& DEBUG_PRIMS
)
362 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
364 cmd
[1].i
, vertex_format
, primitive
);
366 assert(!rmesa
->dma
.flush
);
367 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
368 rmesa
->dma
.flush
= radeonFlushElts
;
370 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
377 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
381 #if RADEON_OLD_PACKETS
382 rmesa
->ioctl
.vertex_size
= vertex_size
;
383 rmesa
->ioctl
.vertex_offset
= offset
;
385 drm_radeon_cmd_header_t
*cmd
;
387 if (RADEON_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
388 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
389 __FUNCTION__
, vertex_size
, offset
);
391 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
395 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
396 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
398 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
404 void radeonEmitAOS( radeonContextPtr rmesa
,
405 struct radeon_dma_region
**component
,
409 #if RADEON_OLD_PACKETS
411 assert( component
[0]->aos_size
== component
[0]->aos_stride
);
412 rmesa
->ioctl
.vertex_size
= component
[0]->aos_size
;
413 rmesa
->ioctl
.vertex_offset
=
414 (component
[0]->aos_start
+ offset
* component
[0]->aos_stride
* 4);
416 drm_radeon_cmd_header_t
*cmd
;
417 int sz
= AOS_BUFSZ(nr
);
421 if (RADEON_DEBUG
& DEBUG_IOCTL
)
422 fprintf(stderr
, "%s\n", __FUNCTION__
);
425 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
,
428 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
429 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int))-3) << 16);
434 for (i
= 0 ; i
< nr
; i
++) {
436 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
437 (component
[i
]->aos_size
<< 16));
438 cmd
[2].i
= (component
[i
]->aos_start
+
439 offset
* component
[i
]->aos_stride
* 4);
443 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
444 (component
[i
]->aos_size
<< 0));
445 cmd
[1].i
= (component
[i
]->aos_start
+
446 offset
* component
[i
]->aos_stride
* 4);
450 if (RADEON_DEBUG
& DEBUG_VERTS
) {
451 fprintf(stderr
, "%s:\n", __FUNCTION__
);
452 for (i
= 0 ; i
< sz
; i
++)
453 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
458 /* using already shifted color_fmt! */
459 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
465 GLint srcx
, GLint srcy
,
466 GLint dstx
, GLint dsty
,
469 drm_radeon_cmd_header_t
*cmd
;
471 if (RADEON_DEBUG
& DEBUG_IOCTL
)
472 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
474 src_pitch
, src_offset
, srcx
, srcy
,
475 dst_pitch
, dst_offset
, dstx
, dsty
,
478 assert( (src_pitch
& 63) == 0 );
479 assert( (dst_pitch
& 63) == 0 );
480 assert( (src_offset
& 1023) == 0 );
481 assert( (dst_offset
& 1023) == 0 );
482 assert( w
< (1<<16) );
483 assert( h
< (1<<16) );
485 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
490 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
491 cmd
[1].i
= RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
| (5 << 16);
492 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
493 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
494 RADEON_GMC_BRUSH_NONE
|
496 RADEON_GMC_SRC_DATATYPE_COLOR
|
498 RADEON_DP_SRC_SOURCE_MEMORY
|
499 RADEON_GMC_CLR_CMP_CNTL_DIS
|
500 RADEON_GMC_WR_MSK_DIS
);
502 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
503 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
504 cmd
[5].i
= (srcx
<< 16) | srcy
;
505 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
506 cmd
[7].i
= (w
<< 16) | h
;
510 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
512 if (rmesa
->dri
.drmMinor
>= 6) {
513 drm_radeon_cmd_header_t
*cmd
;
515 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
517 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 1 * sizeof(int),
520 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
521 cmd
[0].wait
.flags
= flags
;
526 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
527 const char * caller
)
530 drm_radeon_cmd_buffer_t cmd
;
532 if (rmesa
->lost_context
)
533 radeonBackUpAndEmitLostStateLocked(rmesa
);
535 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
536 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
538 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
539 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
540 fprintf(stderr
, "%d: %x\n", i
/4,
541 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
544 if (RADEON_DEBUG
& DEBUG_DMA
)
545 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
546 rmesa
->dma
.nr_released_bufs
);
549 if (RADEON_DEBUG
& DEBUG_SANITY
) {
550 if (rmesa
->state
.scissor
.enabled
)
551 ret
= radeonSanityCmdBuffer( rmesa
,
552 rmesa
->state
.scissor
.numClipRects
,
553 rmesa
->state
.scissor
.pClipRects
);
555 ret
= radeonSanityCmdBuffer( rmesa
,
559 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
565 cmd
.bufsz
= rmesa
->store
.cmd_used
;
566 cmd
.buf
= rmesa
->store
.cmd_buf
;
568 if (rmesa
->state
.scissor
.enabled
) {
569 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
570 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
572 cmd
.nbox
= rmesa
->numClipRects
;
573 cmd
.boxes
= rmesa
->pClipRects
;
576 ret
= drmCommandWrite( rmesa
->dri
.fd
,
581 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
584 rmesa
->store
.primnr
= 0;
585 rmesa
->store
.statenr
= 0;
586 rmesa
->store
.cmd_used
= 0;
587 rmesa
->dma
.nr_released_bufs
= 0;
588 rmesa
->save_on_next_emit
= 1;
594 /* Note: does not emit any commands to avoid recursion on
597 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
602 LOCK_HARDWARE( rmesa
);
604 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
606 UNLOCK_HARDWARE( rmesa
);
609 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
614 /* =============================================================
615 * Hardware vertex buffer handling
619 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
621 struct radeon_dma_buffer
*dmabuf
;
622 int fd
= rmesa
->dri
.fd
;
628 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
629 fprintf(stderr
, "%s\n", __FUNCTION__
);
631 if (rmesa
->dma
.flush
) {
632 rmesa
->dma
.flush( rmesa
);
635 if (rmesa
->dma
.current
.buf
)
636 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
638 if (rmesa
->dma
.nr_released_bufs
> 4)
639 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
641 dma
.context
= rmesa
->dri
.hwContext
;
643 dma
.send_list
= NULL
;
644 dma
.send_sizes
= NULL
;
646 dma
.request_count
= 1;
647 dma
.request_size
= RADEON_BUFFER_SIZE
;
648 dma
.request_list
= &index
;
649 dma
.request_sizes
= &size
;
650 dma
.granted_count
= 0;
652 LOCK_HARDWARE(rmesa
); /* no need to validate */
654 ret
= drmDMA( fd
, &dma
);
657 /* Free some up this way?
659 if (rmesa
->dma
.nr_released_bufs
) {
660 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
663 if (RADEON_DEBUG
& DEBUG_DMA
)
664 fprintf(stderr
, "Waiting for buffers\n");
666 radeonWaitForIdleLocked( rmesa
);
667 ret
= drmDMA( fd
, &dma
);
670 UNLOCK_HARDWARE( rmesa
);
671 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
676 UNLOCK_HARDWARE(rmesa
);
678 if (RADEON_DEBUG
& DEBUG_DMA
)
679 fprintf(stderr
, "Allocated buffer %d\n", index
);
681 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
682 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
683 dmabuf
->refcount
= 1;
685 rmesa
->dma
.current
.buf
= dmabuf
;
686 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
687 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
688 rmesa
->dma
.current
.start
= 0;
689 rmesa
->dma
.current
.ptr
= 0;
691 rmesa
->c_vertexBuffers
++;
694 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
695 struct radeon_dma_region
*region
,
698 if (RADEON_DEBUG
& DEBUG_IOCTL
)
699 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
704 if (rmesa
->dma
.flush
)
705 rmesa
->dma
.flush( rmesa
);
707 if (--region
->buf
->refcount
== 0) {
708 drm_radeon_cmd_header_t
*cmd
;
710 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
711 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
712 region
->buf
->buf
->idx
);
714 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
716 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
717 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
719 rmesa
->dma
.nr_released_bufs
++;
726 /* Allocates a region from rmesa->dma.current. If there isn't enough
727 * space in current, grab a new buffer (and discard what was left of current)
729 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
730 struct radeon_dma_region
*region
,
734 if (RADEON_DEBUG
& DEBUG_IOCTL
)
735 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
737 if (rmesa
->dma
.flush
)
738 rmesa
->dma
.flush( rmesa
);
741 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
744 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
745 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
747 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
748 radeonRefillCurrentDmaRegion( rmesa
);
750 region
->start
= rmesa
->dma
.current
.start
;
751 region
->ptr
= rmesa
->dma
.current
.start
;
752 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
753 region
->address
= rmesa
->dma
.current
.address
;
754 region
->buf
= rmesa
->dma
.current
.buf
;
755 region
->buf
->refcount
++;
757 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
758 rmesa
->dma
.current
.start
=
759 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
762 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa
,
763 struct radeon_dma_region
*region
,
768 radeonAllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
771 /* ================================================================
772 * SwapBuffers with client-side throttling
775 static uint32_t radeonGetLastFrame (radeonContextPtr rmesa
)
777 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
781 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
782 drm_radeon_getparam_t gp
;
784 gp
.param
= RADEON_PARAM_LAST_FRAME
;
785 gp
.value
= (int *)&frame
;
786 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
792 if ( ret
== -EINVAL
) {
793 frame
= INREG( RADEON_LAST_FRAME_REG
);
797 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
804 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
806 drm_radeon_irq_emit_t ie
;
809 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
810 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
813 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
819 static void radeonWaitIrq( radeonContextPtr rmesa
)
824 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
825 &rmesa
->iw
, sizeof(rmesa
->iw
) );
826 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
829 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
835 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
837 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
839 if (rmesa
->do_irqs
) {
840 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
841 if (!rmesa
->irqsEmitted
) {
842 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
846 UNLOCK_HARDWARE( rmesa
);
847 radeonWaitIrq( rmesa
);
848 LOCK_HARDWARE( rmesa
);
850 rmesa
->irqsEmitted
= 10;
853 if (rmesa
->irqsEmitted
) {
854 radeonEmitIrqLocked( rmesa
);
855 rmesa
->irqsEmitted
--;
859 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
860 UNLOCK_HARDWARE( rmesa
);
861 if (rmesa
->do_usleeps
)
863 LOCK_HARDWARE( rmesa
);
868 /* Copy the back color buffer to the front color buffer.
870 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
872 radeonContextPtr rmesa
;
874 GLboolean missed_target
;
878 assert(dPriv
->driContextPriv
);
879 assert(dPriv
->driContextPriv
->driverPrivate
);
881 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
883 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
884 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
887 RADEON_FIREVERTICES( rmesa
);
888 LOCK_HARDWARE( rmesa
);
890 /* Throttle the frame rate -- only allow one pending swap buffers
893 radeonWaitForFrameCompletion( rmesa
);
894 UNLOCK_HARDWARE( rmesa
);
895 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
896 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
++ ) {
910 rmesa
->sarea
->nbox
= n
;
912 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
915 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
916 UNLOCK_HARDWARE( rmesa
);
921 UNLOCK_HARDWARE( rmesa
);
923 (*rmesa
->get_ust
)( & ust
);
924 if ( missed_target
) {
925 rmesa
->swap_missed_count
++;
926 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
929 rmesa
->swap_ust
= ust
;
930 rmesa
->hw
.all_dirty
= GL_TRUE
;
933 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
935 radeonContextPtr rmesa
;
937 GLboolean missed_target
;
940 assert(dPriv
->driContextPriv
);
941 assert(dPriv
->driContextPriv
->driverPrivate
);
943 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
945 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
946 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
947 rmesa
->sarea
->pfCurrentPage
);
950 RADEON_FIREVERTICES( rmesa
);
951 LOCK_HARDWARE( rmesa
);
953 /* Need to do this for the perf box placement:
955 if (dPriv
->numClipRects
)
957 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
958 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
960 rmesa
->sarea
->nbox
= 1;
963 /* Throttle the frame rate -- only allow a few pending swap buffers
966 radeonWaitForFrameCompletion( rmesa
);
967 UNLOCK_HARDWARE( rmesa
);
968 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
969 if ( missed_target
) {
970 rmesa
->swap_missed_count
++;
971 (void) (*rmesa
->get_ust
)( & rmesa
->swap_missed_ust
);
973 LOCK_HARDWARE( rmesa
);
975 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
977 UNLOCK_HARDWARE( rmesa
);
980 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
985 (void) (*rmesa
->get_ust
)( & rmesa
->swap_ust
);
987 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
988 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->frontOffset
;
989 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->frontPitch
;
991 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->backOffset
;
992 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->backPitch
;
995 RADEON_STATECHANGE( rmesa
, ctx
);
996 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
997 + rmesa
->radeonScreen
->fbLocation
;
998 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1002 /* ================================================================
1005 #define RADEON_MAX_CLEARS 256
1007 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
1008 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
1010 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1011 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1012 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
1013 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
1016 GLuint color_mask
= 0;
1019 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1020 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
1021 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
1025 LOCK_HARDWARE( rmesa
);
1026 UNLOCK_HARDWARE( rmesa
);
1027 if ( dPriv
->numClipRects
== 0 )
1033 if ( mask
& DD_FRONT_LEFT_BIT
) {
1034 flags
|= RADEON_FRONT
;
1035 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1036 mask
&= ~DD_FRONT_LEFT_BIT
;
1039 if ( mask
& DD_BACK_LEFT_BIT
) {
1040 flags
|= RADEON_BACK
;
1041 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1042 mask
&= ~DD_BACK_LEFT_BIT
;
1045 if ( mask
& DD_DEPTH_BIT
) {
1046 flags
|= RADEON_DEPTH
;
1047 mask
&= ~DD_DEPTH_BIT
;
1050 if ( (mask
& DD_STENCIL_BIT
) && rmesa
->state
.stencil
.hwBuffer
) {
1051 flags
|= RADEON_STENCIL
;
1052 mask
&= ~DD_STENCIL_BIT
;
1056 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1057 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1058 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1064 if (rmesa
->using_hyperz
) {
1065 flags
|= RADEON_USE_COMP_ZBUF
;
1066 /* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
1067 flags |= RADEON_USE_HIERZ; */
1068 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
1069 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
1070 ((rmesa
->state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
1071 flags
|= RADEON_CLEAR_FASTZ
;
1075 /* Flip top to bottom */
1077 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1079 LOCK_HARDWARE( rmesa
);
1081 /* Throttle the number of clear ioctls we do.
1086 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1087 drm_radeon_getparam_t gp
;
1089 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1090 gp
.value
= (int *)&clear
;
1091 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1092 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1096 if ( ret
== -EINVAL
) {
1097 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1101 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1104 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1105 fprintf( stderr
, "%s( %d )\n", __FUNCTION__
, (int)clear
);
1106 if ( ret
) fprintf( stderr
, " ( RADEON_LAST_CLEAR register read directly )\n" );
1109 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1113 if ( rmesa
->do_usleeps
) {
1114 UNLOCK_HARDWARE( rmesa
);
1116 LOCK_HARDWARE( rmesa
);
1120 /* Send current state to the hardware */
1121 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1123 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1124 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1125 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1126 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1127 drm_radeon_clear_t clear
;
1128 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1132 for ( ; i
< nr
; i
++ ) {
1133 GLint x
= box
[i
].x1
;
1134 GLint y
= box
[i
].y1
;
1135 GLint w
= box
[i
].x2
- x
;
1136 GLint h
= box
[i
].y2
- y
;
1138 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1139 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1140 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1141 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1142 if ( w
<= 0 ) continue;
1143 if ( h
<= 0 ) continue;
1153 for ( ; i
< nr
; i
++ ) {
1159 rmesa
->sarea
->nbox
= n
;
1161 clear
.flags
= flags
;
1162 clear
.clear_color
= rmesa
->state
.color
.clear
;
1163 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1164 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1165 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1166 clear
.depth_boxes
= depth_boxes
;
1169 b
= rmesa
->sarea
->boxes
;
1170 for ( ; n
>= 0 ; n
-- ) {
1171 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1172 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1173 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1174 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1175 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1176 (float)rmesa
->state
.depth
.clear
;
1179 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1180 &clear
, sizeof(drm_radeon_clear_t
));
1183 UNLOCK_HARDWARE( rmesa
);
1184 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1189 UNLOCK_HARDWARE( rmesa
);
1190 rmesa
->hw
.all_dirty
= GL_TRUE
;
1194 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1196 int fd
= rmesa
->dri
.fd
;
1200 rmesa
->c_drawWaits
++;
1204 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1205 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1206 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1209 UNLOCK_HARDWARE( rmesa
);
1210 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1216 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1218 LOCK_HARDWARE(rmesa
);
1219 radeonWaitForIdleLocked( rmesa
);
1220 UNLOCK_HARDWARE(rmesa
);
1224 void radeonFlush( GLcontext
*ctx
)
1226 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1228 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1229 fprintf(stderr
, "%s\n", __FUNCTION__
);
1231 if (rmesa
->dma
.flush
)
1232 rmesa
->dma
.flush( rmesa
);
1234 radeonEmitState( rmesa
);
1236 if (rmesa
->store
.cmd_used
)
1237 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1240 /* Make sure all commands have been sent to the hardware and have
1241 * completed processing.
1243 void radeonFinish( GLcontext
*ctx
)
1245 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1248 if (rmesa
->do_irqs
) {
1249 LOCK_HARDWARE( rmesa
);
1250 radeonEmitIrqLocked( rmesa
);
1251 UNLOCK_HARDWARE( rmesa
);
1252 radeonWaitIrq( rmesa
);
1255 radeonWaitForIdle( rmesa
);
1259 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1261 ctx
->Driver
.Clear
= radeonClear
;
1262 ctx
->Driver
.Finish
= radeonFinish
;
1263 ctx
->Driver
.Flush
= radeonFlush
;