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 /* this code used to return here but now it emits zbs */
184 /* To avoid going across the entire set of states multiple times, just check
185 * for enough space for the case of emitting all state, and inline the
186 * radeonAllocCmdBuf code here without all the checks.
188 radeonEnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
);
189 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
191 /* We always always emit zbs, this is due to a bug found by keithw in
192 the hardware and rediscovered after Erics changes by me.
193 if you ever touch this code make sure you emit zbs otherwise
194 you get tcl lockups on at least M7/7500 class of chips - airlied */
195 rmesa
->hw
.zbs
.dirty
=1;
197 if (RADEON_DEBUG
& DEBUG_STATE
) {
198 foreach(atom
, &rmesa
->hw
.atomlist
) {
199 if (atom
->dirty
|| rmesa
->hw
.all_dirty
) {
200 if (atom
->check(rmesa
->glCtx
))
201 print_state_atom(atom
);
203 fprintf(stderr
, "skip state %s\n", atom
->name
);
208 foreach(atom
, &rmesa
->hw
.atomlist
) {
209 if (rmesa
->hw
.all_dirty
)
210 atom
->dirty
= GL_TRUE
;
211 if (!(rmesa
->radeonScreen
->chipset
& RADEON_CHIPSET_TCL
) &&
213 atom
->dirty
= GL_FALSE
;
215 if (atom
->check(rmesa
->glCtx
)) {
216 int size
= atom
->cmd_size
* 4;
217 memcpy(dest
, atom
->cmd
, size
);
219 rmesa
->store
.cmd_used
+= size
;
220 atom
->dirty
= GL_FALSE
;
225 assert(rmesa
->store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
227 rmesa
->hw
.is_dirty
= GL_FALSE
;
228 rmesa
->hw
.all_dirty
= GL_FALSE
;
231 /* Fire a section of the retained (indexed_verts) buffer as a regular
234 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
235 GLuint vertex_format
,
239 drm_radeon_cmd_header_t
*cmd
;
242 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
244 radeonEmitState( rmesa
);
246 if (RADEON_DEBUG
& DEBUG_IOCTL
)
247 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
248 rmesa
->store
.cmd_used
/4);
250 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VBUF_BUFSZ
,
252 #if RADEON_OLD_PACKETS
254 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
255 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
| (3 << 16);
256 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
257 cmd
[3].i
= vertex_nr
;
258 cmd
[4].i
= vertex_format
;
259 cmd
[5].i
= (primitive
|
260 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
261 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
262 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
263 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
265 if (RADEON_DEBUG
& DEBUG_PRIMS
)
266 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
268 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
271 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
272 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_VBUF
| (1 << 16);
273 cmd
[2].i
= vertex_format
;
274 cmd
[3].i
= (primitive
|
275 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
276 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
277 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
278 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
279 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
282 if (RADEON_DEBUG
& DEBUG_PRIMS
)
283 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
285 cmd
[1].i
, cmd
[2].i
, cmd
[3].i
);
290 void radeonFlushElts( radeonContextPtr rmesa
)
292 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
294 #if RADEON_OLD_PACKETS
295 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 24)) / 2;
297 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 16)) / 2;
300 if (RADEON_DEBUG
& DEBUG_IOCTL
)
301 fprintf(stderr
, "%s\n", __FUNCTION__
);
303 assert( rmesa
->dma
.flush
== radeonFlushElts
);
304 rmesa
->dma
.flush
= NULL
;
306 /* Cope with odd number of elts:
308 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
309 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
311 #if RADEON_OLD_PACKETS
312 cmd
[1] |= (dwords
- 3) << 16;
313 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
315 cmd
[1] |= (dwords
- 3) << 16;
316 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
319 if (RADEON_DEBUG
& DEBUG_SYNC
) {
320 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
321 radeonFinish( rmesa
->glCtx
);
326 GLushort
*radeonAllocEltsOpenEnded( radeonContextPtr rmesa
,
327 GLuint vertex_format
,
331 drm_radeon_cmd_header_t
*cmd
;
334 if (RADEON_DEBUG
& DEBUG_IOCTL
)
335 fprintf(stderr
, "%s %d\n", __FUNCTION__
, min_nr
);
337 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
339 radeonEmitState( rmesa
);
341 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
344 #if RADEON_OLD_PACKETS
346 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
347 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
;
348 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
350 cmd
[4].i
= vertex_format
;
351 cmd
[5].i
= (primitive
|
352 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
353 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
354 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
356 retval
= (GLushort
*)(cmd
+6);
359 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
360 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_INDX
;
361 cmd
[2].i
= vertex_format
;
362 cmd
[3].i
= (primitive
|
363 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
364 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
365 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
366 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
368 retval
= (GLushort
*)(cmd
+4);
371 if (RADEON_DEBUG
& DEBUG_PRIMS
)
372 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
374 cmd
[1].i
, vertex_format
, primitive
);
376 assert(!rmesa
->dma
.flush
);
377 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
378 rmesa
->dma
.flush
= radeonFlushElts
;
380 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
387 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
391 #if RADEON_OLD_PACKETS
392 rmesa
->ioctl
.vertex_size
= vertex_size
;
393 rmesa
->ioctl
.vertex_offset
= offset
;
395 drm_radeon_cmd_header_t
*cmd
;
397 if (RADEON_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
398 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
399 __FUNCTION__
, vertex_size
, offset
);
401 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
405 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
406 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
408 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
414 void radeonEmitAOS( radeonContextPtr rmesa
,
415 struct radeon_dma_region
**component
,
419 #if RADEON_OLD_PACKETS
421 assert( component
[0]->aos_size
== component
[0]->aos_stride
);
422 rmesa
->ioctl
.vertex_size
= component
[0]->aos_size
;
423 rmesa
->ioctl
.vertex_offset
=
424 (component
[0]->aos_start
+ offset
* component
[0]->aos_stride
* 4);
426 drm_radeon_cmd_header_t
*cmd
;
427 int sz
= AOS_BUFSZ(nr
);
431 if (RADEON_DEBUG
& DEBUG_IOCTL
)
432 fprintf(stderr
, "%s\n", __FUNCTION__
);
435 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
,
438 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
439 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int))-3) << 16);
444 for (i
= 0 ; i
< nr
; i
++) {
446 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
447 (component
[i
]->aos_size
<< 16));
448 cmd
[2].i
= (component
[i
]->aos_start
+
449 offset
* component
[i
]->aos_stride
* 4);
453 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
454 (component
[i
]->aos_size
<< 0));
455 cmd
[1].i
= (component
[i
]->aos_start
+
456 offset
* component
[i
]->aos_stride
* 4);
460 if (RADEON_DEBUG
& DEBUG_VERTS
) {
461 fprintf(stderr
, "%s:\n", __FUNCTION__
);
462 for (i
= 0 ; i
< sz
; i
++)
463 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
468 /* using already shifted color_fmt! */
469 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
475 GLint srcx
, GLint srcy
,
476 GLint dstx
, GLint dsty
,
479 drm_radeon_cmd_header_t
*cmd
;
481 if (RADEON_DEBUG
& DEBUG_IOCTL
)
482 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
484 src_pitch
, src_offset
, srcx
, srcy
,
485 dst_pitch
, dst_offset
, dstx
, dsty
,
488 assert( (src_pitch
& 63) == 0 );
489 assert( (dst_pitch
& 63) == 0 );
490 assert( (src_offset
& 1023) == 0 );
491 assert( (dst_offset
& 1023) == 0 );
492 assert( w
< (1<<16) );
493 assert( h
< (1<<16) );
495 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
500 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
501 cmd
[1].i
= RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
| (5 << 16);
502 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
503 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
504 RADEON_GMC_BRUSH_NONE
|
506 RADEON_GMC_SRC_DATATYPE_COLOR
|
508 RADEON_DP_SRC_SOURCE_MEMORY
|
509 RADEON_GMC_CLR_CMP_CNTL_DIS
|
510 RADEON_GMC_WR_MSK_DIS
);
512 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
513 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
514 cmd
[5].i
= (srcx
<< 16) | srcy
;
515 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
516 cmd
[7].i
= (w
<< 16) | h
;
520 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
522 if (rmesa
->dri
.drmMinor
>= 6) {
523 drm_radeon_cmd_header_t
*cmd
;
525 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
527 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 1 * sizeof(int),
530 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
531 cmd
[0].wait
.flags
= flags
;
536 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
537 const char * caller
)
540 drm_radeon_cmd_buffer_t cmd
;
542 if (rmesa
->lost_context
)
543 radeonBackUpAndEmitLostStateLocked(rmesa
);
545 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
546 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
548 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
549 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
550 fprintf(stderr
, "%d: %x\n", i
/4,
551 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
554 if (RADEON_DEBUG
& DEBUG_DMA
)
555 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
556 rmesa
->dma
.nr_released_bufs
);
559 if (RADEON_DEBUG
& DEBUG_SANITY
) {
560 if (rmesa
->state
.scissor
.enabled
)
561 ret
= radeonSanityCmdBuffer( rmesa
,
562 rmesa
->state
.scissor
.numClipRects
,
563 rmesa
->state
.scissor
.pClipRects
);
565 ret
= radeonSanityCmdBuffer( rmesa
,
569 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
575 cmd
.bufsz
= rmesa
->store
.cmd_used
;
576 cmd
.buf
= rmesa
->store
.cmd_buf
;
578 if (rmesa
->state
.scissor
.enabled
) {
579 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
580 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
582 cmd
.nbox
= rmesa
->numClipRects
;
583 cmd
.boxes
= rmesa
->pClipRects
;
586 ret
= drmCommandWrite( rmesa
->dri
.fd
,
591 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
593 if (RADEON_DEBUG
& DEBUG_SYNC
) {
594 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
595 radeonWaitForIdleLocked( rmesa
);
599 rmesa
->store
.primnr
= 0;
600 rmesa
->store
.statenr
= 0;
601 rmesa
->store
.cmd_used
= 0;
602 rmesa
->dma
.nr_released_bufs
= 0;
603 rmesa
->save_on_next_emit
= 1;
609 /* Note: does not emit any commands to avoid recursion on
612 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
617 LOCK_HARDWARE( rmesa
);
619 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
621 UNLOCK_HARDWARE( rmesa
);
624 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
629 /* =============================================================
630 * Hardware vertex buffer handling
634 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
636 struct radeon_dma_buffer
*dmabuf
;
637 int fd
= rmesa
->dri
.fd
;
643 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
644 fprintf(stderr
, "%s\n", __FUNCTION__
);
646 if (rmesa
->dma
.flush
) {
647 rmesa
->dma
.flush( rmesa
);
650 if (rmesa
->dma
.current
.buf
)
651 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
653 if (rmesa
->dma
.nr_released_bufs
> 4)
654 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
656 dma
.context
= rmesa
->dri
.hwContext
;
658 dma
.send_list
= NULL
;
659 dma
.send_sizes
= NULL
;
661 dma
.request_count
= 1;
662 dma
.request_size
= RADEON_BUFFER_SIZE
;
663 dma
.request_list
= &index
;
664 dma
.request_sizes
= &size
;
665 dma
.granted_count
= 0;
667 LOCK_HARDWARE(rmesa
); /* no need to validate */
669 ret
= drmDMA( fd
, &dma
);
672 /* Free some up this way?
674 if (rmesa
->dma
.nr_released_bufs
) {
675 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
678 if (RADEON_DEBUG
& DEBUG_DMA
)
679 fprintf(stderr
, "Waiting for buffers\n");
681 radeonWaitForIdleLocked( rmesa
);
682 ret
= drmDMA( fd
, &dma
);
685 UNLOCK_HARDWARE( rmesa
);
686 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
691 UNLOCK_HARDWARE(rmesa
);
693 if (RADEON_DEBUG
& DEBUG_DMA
)
694 fprintf(stderr
, "Allocated buffer %d\n", index
);
696 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
697 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
698 dmabuf
->refcount
= 1;
700 rmesa
->dma
.current
.buf
= dmabuf
;
701 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
702 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
703 rmesa
->dma
.current
.start
= 0;
704 rmesa
->dma
.current
.ptr
= 0;
706 rmesa
->c_vertexBuffers
++;
709 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
710 struct radeon_dma_region
*region
,
713 if (RADEON_DEBUG
& DEBUG_IOCTL
)
714 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
719 if (rmesa
->dma
.flush
)
720 rmesa
->dma
.flush( rmesa
);
722 if (--region
->buf
->refcount
== 0) {
723 drm_radeon_cmd_header_t
*cmd
;
725 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
726 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
727 region
->buf
->buf
->idx
);
729 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
731 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
732 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
734 rmesa
->dma
.nr_released_bufs
++;
741 /* Allocates a region from rmesa->dma.current. If there isn't enough
742 * space in current, grab a new buffer (and discard what was left of current)
744 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
745 struct radeon_dma_region
*region
,
749 if (RADEON_DEBUG
& DEBUG_IOCTL
)
750 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
752 if (rmesa
->dma
.flush
)
753 rmesa
->dma
.flush( rmesa
);
756 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
759 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
760 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
762 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
763 radeonRefillCurrentDmaRegion( rmesa
);
765 region
->start
= rmesa
->dma
.current
.start
;
766 region
->ptr
= rmesa
->dma
.current
.start
;
767 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
768 region
->address
= rmesa
->dma
.current
.address
;
769 region
->buf
= rmesa
->dma
.current
.buf
;
770 region
->buf
->refcount
++;
772 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
773 rmesa
->dma
.current
.start
=
774 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
777 void radeonAllocDmaRegionVerts( radeonContextPtr rmesa
,
778 struct radeon_dma_region
*region
,
783 radeonAllocDmaRegion( rmesa
, region
, vertsize
* numverts
, alignment
);
786 /* ================================================================
787 * SwapBuffers with client-side throttling
790 static u_int32_t
radeonGetLastFrame (radeonContextPtr rmesa
)
792 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
796 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
797 drm_radeon_getparam_t gp
;
799 gp
.param
= RADEON_PARAM_LAST_FRAME
;
800 gp
.value
= (int *)&frame
;
801 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
807 if ( ret
== -EINVAL
) {
808 frame
= INREG( RADEON_LAST_FRAME_REG
);
812 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
819 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
821 drm_radeon_irq_emit_t ie
;
824 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
825 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
828 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
834 static void radeonWaitIrq( radeonContextPtr rmesa
)
839 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
840 &rmesa
->iw
, sizeof(rmesa
->iw
) );
841 } while (ret
&& (errno
== EINTR
|| errno
== EAGAIN
));
844 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
850 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
852 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
854 if (rmesa
->do_irqs
) {
855 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
856 if (!rmesa
->irqsEmitted
) {
857 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
861 UNLOCK_HARDWARE( rmesa
);
862 radeonWaitIrq( rmesa
);
863 LOCK_HARDWARE( rmesa
);
865 rmesa
->irqsEmitted
= 10;
868 if (rmesa
->irqsEmitted
) {
869 radeonEmitIrqLocked( rmesa
);
870 rmesa
->irqsEmitted
--;
874 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
875 UNLOCK_HARDWARE( rmesa
);
876 if (rmesa
->do_usleeps
)
878 LOCK_HARDWARE( rmesa
);
883 /* Copy the back color buffer to the front color buffer.
885 void radeonCopyBuffer( const __DRIdrawablePrivate
*dPriv
)
887 radeonContextPtr rmesa
;
889 GLboolean missed_target
;
893 assert(dPriv
->driContextPriv
);
894 assert(dPriv
->driContextPriv
->driverPrivate
);
896 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
898 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
899 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
902 RADEON_FIREVERTICES( rmesa
);
903 LOCK_HARDWARE( rmesa
);
905 /* Throttle the frame rate -- only allow one pending swap buffers
908 radeonWaitForFrameCompletion( rmesa
);
909 UNLOCK_HARDWARE( rmesa
);
910 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
911 LOCK_HARDWARE( rmesa
);
913 nbox
= dPriv
->numClipRects
; /* must be in locked region */
915 for ( i
= 0 ; i
< nbox
; ) {
916 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
917 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
918 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
921 for ( ; i
< nr
; i
++ ) {
925 rmesa
->sarea
->nbox
= n
;
927 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
930 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
931 UNLOCK_HARDWARE( rmesa
);
936 UNLOCK_HARDWARE( rmesa
);
938 (*dri_interface
->getUST
)( & ust
);
939 if ( missed_target
) {
940 rmesa
->swap_missed_count
++;
941 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
944 rmesa
->swap_ust
= ust
;
945 rmesa
->hw
.all_dirty
= GL_TRUE
;
948 void radeonPageFlip( const __DRIdrawablePrivate
*dPriv
)
950 radeonContextPtr rmesa
;
952 GLboolean missed_target
;
955 assert(dPriv
->driContextPriv
);
956 assert(dPriv
->driContextPriv
->driverPrivate
);
958 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
960 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
961 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
962 rmesa
->sarea
->pfCurrentPage
);
965 RADEON_FIREVERTICES( rmesa
);
966 LOCK_HARDWARE( rmesa
);
968 /* Need to do this for the perf box placement:
970 if (dPriv
->numClipRects
)
972 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
973 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
975 rmesa
->sarea
->nbox
= 1;
978 /* Throttle the frame rate -- only allow a few pending swap buffers
981 radeonWaitForFrameCompletion( rmesa
);
982 UNLOCK_HARDWARE( rmesa
);
983 driWaitForVBlank( dPriv
, & rmesa
->vbl_seq
, rmesa
->vblank_flags
, & missed_target
);
984 if ( missed_target
) {
985 rmesa
->swap_missed_count
++;
986 (void) (*dri_interface
->getUST
)( & rmesa
->swap_missed_ust
);
988 LOCK_HARDWARE( rmesa
);
990 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
992 UNLOCK_HARDWARE( rmesa
);
995 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
1000 (void) (*dri_interface
->getUST
)( & rmesa
->swap_ust
);
1002 if ( rmesa
->sarea
->pfCurrentPage
== 1 ) {
1003 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->frontOffset
;
1004 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->frontPitch
;
1006 rmesa
->state
.color
.drawOffset
= rmesa
->radeonScreen
->backOffset
;
1007 rmesa
->state
.color
.drawPitch
= rmesa
->radeonScreen
->backPitch
;
1010 RADEON_STATECHANGE( rmesa
, ctx
);
1011 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLOROFFSET
] = rmesa
->state
.color
.drawOffset
1012 + rmesa
->radeonScreen
->fbLocation
;
1013 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] = rmesa
->state
.color
.drawPitch
;
1014 if (rmesa
->sarea
->tiling_enabled
) {
1015 rmesa
->hw
.ctx
.cmd
[CTX_RB3D_COLORPITCH
] |= RADEON_COLOR_TILE_ENABLE
;
1020 /* ================================================================
1023 #define RADEON_MAX_CLEARS 256
1025 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
1026 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
1028 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1029 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1030 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
1031 unsigned char *RADEONMMIO
= rmesa
->radeonScreen
->mmio
.map
;
1034 GLuint color_mask
= 0;
1037 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1038 fprintf( stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
1039 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
1043 LOCK_HARDWARE( rmesa
);
1044 UNLOCK_HARDWARE( rmesa
);
1045 if ( dPriv
->numClipRects
== 0 )
1051 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
1052 flags
|= RADEON_FRONT
;
1053 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1054 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
1057 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
1058 flags
|= RADEON_BACK
;
1059 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1060 mask
&= ~BUFFER_BIT_BACK_LEFT
;
1063 if ( mask
& BUFFER_BIT_DEPTH
) {
1064 flags
|= RADEON_DEPTH
;
1065 mask
&= ~BUFFER_BIT_DEPTH
;
1068 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
1069 flags
|= RADEON_STENCIL
;
1070 mask
&= ~BUFFER_BIT_STENCIL
;
1074 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1075 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1076 _swrast_Clear( ctx
, mask
, all
, cx
, cy
, cw
, ch
);
1082 if (rmesa
->using_hyperz
) {
1083 flags
|= RADEON_USE_COMP_ZBUF
;
1084 /* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
1085 flags |= RADEON_USE_HIERZ; */
1086 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
1087 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
1088 ((rmesa
->state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
1089 flags
|= RADEON_CLEAR_FASTZ
;
1093 /* Flip top to bottom */
1095 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1097 LOCK_HARDWARE( rmesa
);
1099 /* Throttle the number of clear ioctls we do.
1104 if (rmesa
->dri
.screen
->drmMinor
>= 4) {
1105 drm_radeon_getparam_t gp
;
1107 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1108 gp
.value
= (int *)&clear
;
1109 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1110 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1114 if ( ret
== -EINVAL
) {
1115 clear
= INREG( RADEON_LAST_CLEAR_REG
);
1119 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1122 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1123 fprintf( stderr
, "%s( %d )\n", __FUNCTION__
, (int)clear
);
1124 if ( ret
) fprintf( stderr
, " ( RADEON_LAST_CLEAR register read directly )\n" );
1127 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1131 if ( rmesa
->do_usleeps
) {
1132 UNLOCK_HARDWARE( rmesa
);
1134 LOCK_HARDWARE( rmesa
);
1138 /* Send current state to the hardware */
1139 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1141 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1142 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1143 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1144 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1145 drm_radeon_clear_t clear
;
1146 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1150 for ( ; i
< nr
; i
++ ) {
1151 GLint x
= box
[i
].x1
;
1152 GLint y
= box
[i
].y1
;
1153 GLint w
= box
[i
].x2
- x
;
1154 GLint h
= box
[i
].y2
- y
;
1156 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1157 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1158 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1159 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1160 if ( w
<= 0 ) continue;
1161 if ( h
<= 0 ) continue;
1171 for ( ; i
< nr
; i
++ ) {
1177 rmesa
->sarea
->nbox
= n
;
1179 clear
.flags
= flags
;
1180 clear
.clear_color
= rmesa
->state
.color
.clear
;
1181 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1182 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1183 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1184 clear
.depth_boxes
= depth_boxes
;
1187 b
= rmesa
->sarea
->boxes
;
1188 for ( ; n
>= 0 ; n
-- ) {
1189 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1190 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1191 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1192 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1193 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1194 (float)rmesa
->state
.depth
.clear
;
1197 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1198 &clear
, sizeof(drm_radeon_clear_t
));
1201 UNLOCK_HARDWARE( rmesa
);
1202 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1207 UNLOCK_HARDWARE( rmesa
);
1208 rmesa
->hw
.all_dirty
= GL_TRUE
;
1212 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1214 int fd
= rmesa
->dri
.fd
;
1218 rmesa
->c_drawWaits
++;
1222 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1223 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1224 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1227 UNLOCK_HARDWARE( rmesa
);
1228 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1234 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1236 LOCK_HARDWARE(rmesa
);
1237 radeonWaitForIdleLocked( rmesa
);
1238 UNLOCK_HARDWARE(rmesa
);
1242 void radeonFlush( GLcontext
*ctx
)
1244 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1246 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1247 fprintf(stderr
, "%s\n", __FUNCTION__
);
1249 if (rmesa
->dma
.flush
)
1250 rmesa
->dma
.flush( rmesa
);
1252 radeonEmitState( rmesa
);
1254 if (rmesa
->store
.cmd_used
)
1255 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1258 /* Make sure all commands have been sent to the hardware and have
1259 * completed processing.
1261 void radeonFinish( GLcontext
*ctx
)
1263 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1266 if (rmesa
->do_irqs
) {
1267 LOCK_HARDWARE( rmesa
);
1268 radeonEmitIrqLocked( rmesa
);
1269 UNLOCK_HARDWARE( rmesa
);
1270 radeonWaitIrq( rmesa
);
1273 radeonWaitForIdle( rmesa
);
1277 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1279 ctx
->Driver
.Clear
= radeonClear
;
1280 ctx
->Driver
.Finish
= radeonFinish
;
1281 ctx
->Driver
.Flush
= radeonFlush
;