1 /**************************************************************************
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Kevin E. Martin <martin@valinux.com>
33 * Gareth Hughes <gareth@valinux.com>
34 * Keith Whitwell <keith@tungstengraphics.com>
40 #include "main/glheader.h"
41 #include "main/imports.h"
42 #include "main/simple_list.h"
43 #include "swrast/swrast.h"
45 #include "radeon_context.h"
46 #include "radeon_state.h"
47 #include "radeon_ioctl.h"
48 #include "radeon_tcl.h"
49 #include "radeon_sanity.h"
51 #define STANDALONE_MMIO
52 #include "radeon_macros.h" /* for INREG() */
54 #include "drirenderbuffer.h"
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
]);
154 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.cube
[i
]);
156 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.zbs
);
157 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
);
158 for (i
= 0; i
< 3 + mtu
; ++i
)
159 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
]);
160 for (i
= 0; i
< 8; ++i
)
161 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
]);
162 for (i
= 0; i
< 6; ++i
)
163 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
]);
164 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
165 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.grd
);
166 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.fog
);
167 insert_at_tail(&rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
170 void radeonEmitState( radeonContextPtr rmesa
)
172 struct radeon_state_atom
*atom
;
175 if (RADEON_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
176 fprintf(stderr
, "%s\n", __FUNCTION__
);
178 if (rmesa
->save_on_next_emit
) {
179 radeonSaveHwState(rmesa
);
180 rmesa
->save_on_next_emit
= GL_FALSE
;
183 /* this code used to return here but now it emits zbs */
185 /* To avoid going across the entire set of states multiple times, just check
186 * for enough space for the case of emitting all state, and inline the
187 * radeonAllocCmdBuf code here without all the checks.
189 radeonEnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
);
190 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
192 /* We always always emit zbs, this is due to a bug found by keithw in
193 the hardware and rediscovered after Erics changes by me.
194 if you ever touch this code make sure you emit zbs otherwise
195 you get tcl lockups on at least M7/7500 class of chips - airlied */
196 rmesa
->hw
.zbs
.dirty
=1;
198 if (RADEON_DEBUG
& DEBUG_STATE
) {
199 foreach(atom
, &rmesa
->hw
.atomlist
) {
200 if (atom
->dirty
|| rmesa
->hw
.all_dirty
) {
201 if (atom
->check(rmesa
->glCtx
))
202 print_state_atom(atom
);
204 fprintf(stderr
, "skip state %s\n", atom
->name
);
209 foreach(atom
, &rmesa
->hw
.atomlist
) {
210 if (rmesa
->hw
.all_dirty
)
211 atom
->dirty
= GL_TRUE
;
212 if (!(rmesa
->radeonScreen
->chip_flags
& RADEON_CHIPSET_TCL
) &&
214 atom
->dirty
= GL_FALSE
;
216 if (atom
->check(rmesa
->glCtx
)) {
217 int size
= atom
->cmd_size
* 4;
218 memcpy(dest
, atom
->cmd
, size
);
220 rmesa
->store
.cmd_used
+= size
;
221 atom
->dirty
= GL_FALSE
;
226 assert(rmesa
->store
.cmd_used
<= RADEON_CMD_BUF_SZ
);
228 rmesa
->hw
.is_dirty
= GL_FALSE
;
229 rmesa
->hw
.all_dirty
= GL_FALSE
;
232 /* Fire a section of the retained (indexed_verts) buffer as a regular
235 extern void radeonEmitVbufPrim( radeonContextPtr rmesa
,
236 GLuint vertex_format
,
240 drm_radeon_cmd_header_t
*cmd
;
243 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
245 radeonEmitState( rmesa
);
247 if (RADEON_DEBUG
& DEBUG_IOCTL
)
248 fprintf(stderr
, "%s cmd_used/4: %d\n", __FUNCTION__
,
249 rmesa
->store
.cmd_used
/4);
251 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VBUF_BUFSZ
,
253 #if RADEON_OLD_PACKETS
255 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
256 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
| (3 << 16);
257 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
258 cmd
[3].i
= vertex_nr
;
259 cmd
[4].i
= vertex_format
;
260 cmd
[5].i
= (primitive
|
261 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
262 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
263 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
264 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
266 if (RADEON_DEBUG
& DEBUG_PRIMS
)
267 fprintf(stderr
, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
269 cmd
[1].i
, cmd
[2].i
, cmd
[4].i
, cmd
[5].i
);
272 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
273 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_VBUF
| (1 << 16);
274 cmd
[2].i
= vertex_format
;
275 cmd
[3].i
= (primitive
|
276 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
277 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
278 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
279 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
280 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
283 if (RADEON_DEBUG
& DEBUG_PRIMS
)
284 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
286 cmd
[1].i
, cmd
[2].i
, cmd
[3].i
);
291 void radeonFlushElts( radeonContextPtr rmesa
)
293 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
295 #if RADEON_OLD_PACKETS
296 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 24)) / 2;
298 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 16)) / 2;
301 if (RADEON_DEBUG
& DEBUG_IOCTL
)
302 fprintf(stderr
, "%s\n", __FUNCTION__
);
304 assert( rmesa
->dma
.flush
== radeonFlushElts
);
305 rmesa
->dma
.flush
= NULL
;
307 /* Cope with odd number of elts:
309 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
310 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
312 #if RADEON_OLD_PACKETS
313 cmd
[1] |= (dwords
- 3) << 16;
314 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
316 cmd
[1] |= (dwords
- 3) << 16;
317 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
320 if (RADEON_DEBUG
& DEBUG_SYNC
) {
321 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
322 radeonFinish( rmesa
->glCtx
);
327 GLushort
*radeonAllocEltsOpenEnded( radeonContextPtr rmesa
,
328 GLuint vertex_format
,
332 drm_radeon_cmd_header_t
*cmd
;
335 if (RADEON_DEBUG
& DEBUG_IOCTL
)
336 fprintf(stderr
, "%s %d\n", __FUNCTION__
, min_nr
);
338 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
340 radeonEmitState( rmesa
);
342 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
,
345 #if RADEON_OLD_PACKETS
347 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
348 cmd
[1].i
= RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
;
349 cmd
[2].i
= rmesa
->ioctl
.vertex_offset
;
351 cmd
[4].i
= vertex_format
;
352 cmd
[5].i
= (primitive
|
353 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
354 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
355 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
357 retval
= (GLushort
*)(cmd
+6);
360 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
361 cmd
[1].i
= RADEON_CP_PACKET3_3D_DRAW_INDX
;
362 cmd
[2].i
= vertex_format
;
363 cmd
[3].i
= (primitive
|
364 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
365 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
366 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
367 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
369 retval
= (GLushort
*)(cmd
+4);
372 if (RADEON_DEBUG
& DEBUG_PRIMS
)
373 fprintf(stderr
, "%s: header 0x%x vfmt 0x%x prim %x \n",
375 cmd
[1].i
, vertex_format
, primitive
);
377 assert(!rmesa
->dma
.flush
);
378 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
379 rmesa
->dma
.flush
= radeonFlushElts
;
381 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
388 void radeonEmitVertexAOS( radeonContextPtr rmesa
,
392 #if RADEON_OLD_PACKETS
393 rmesa
->ioctl
.vertex_size
= vertex_size
;
394 rmesa
->ioctl
.vertex_offset
= offset
;
396 drm_radeon_cmd_header_t
*cmd
;
398 if (RADEON_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
399 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
400 __FUNCTION__
, vertex_size
, offset
);
402 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
406 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
407 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (2 << 16);
409 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
415 void radeonEmitAOS( radeonContextPtr rmesa
,
416 struct radeon_dma_region
**component
,
420 #if RADEON_OLD_PACKETS
422 assert( component
[0]->aos_size
== component
[0]->aos_stride
);
423 rmesa
->ioctl
.vertex_size
= component
[0]->aos_size
;
424 rmesa
->ioctl
.vertex_offset
=
425 (component
[0]->aos_start
+ offset
* component
[0]->aos_stride
* 4);
427 drm_radeon_cmd_header_t
*cmd
;
428 int sz
= AOS_BUFSZ(nr
);
432 if (RADEON_DEBUG
& DEBUG_IOCTL
)
433 fprintf(stderr
, "%s\n", __FUNCTION__
);
436 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sz
,
439 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
440 cmd
[1].i
= RADEON_CP_PACKET3_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int))-3) << 16);
445 for (i
= 0 ; i
< nr
; i
++) {
447 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
448 (component
[i
]->aos_size
<< 16));
449 cmd
[2].i
= (component
[i
]->aos_start
+
450 offset
* component
[i
]->aos_stride
* 4);
454 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
455 (component
[i
]->aos_size
<< 0));
456 cmd
[1].i
= (component
[i
]->aos_start
+
457 offset
* component
[i
]->aos_stride
* 4);
461 if (RADEON_DEBUG
& DEBUG_VERTS
) {
462 fprintf(stderr
, "%s:\n", __FUNCTION__
);
463 for (i
= 0 ; i
< sz
; i
++)
464 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
469 /* using already shifted color_fmt! */
470 void radeonEmitBlit( radeonContextPtr rmesa
, /* FIXME: which drmMinor is required? */
476 GLint srcx
, GLint srcy
,
477 GLint dstx
, GLint dsty
,
480 drm_radeon_cmd_header_t
*cmd
;
482 if (RADEON_DEBUG
& DEBUG_IOCTL
)
483 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
485 src_pitch
, src_offset
, srcx
, srcy
,
486 dst_pitch
, dst_offset
, dstx
, dsty
,
489 assert( (src_pitch
& 63) == 0 );
490 assert( (dst_pitch
& 63) == 0 );
491 assert( (src_offset
& 1023) == 0 );
492 assert( (dst_offset
& 1023) == 0 );
493 assert( w
< (1<<16) );
494 assert( h
< (1<<16) );
496 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, 8 * sizeof(int),
501 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
502 cmd
[1].i
= RADEON_CP_PACKET3_CNTL_BITBLT_MULTI
| (5 << 16);
503 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
504 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
505 RADEON_GMC_BRUSH_NONE
|
507 RADEON_GMC_SRC_DATATYPE_COLOR
|
509 RADEON_DP_SRC_SOURCE_MEMORY
|
510 RADEON_GMC_CLR_CMP_CNTL_DIS
|
511 RADEON_GMC_WR_MSK_DIS
);
513 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
514 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
515 cmd
[5].i
= (srcx
<< 16) | srcy
;
516 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
517 cmd
[7].i
= (w
<< 16) | h
;
521 void radeonEmitWait( radeonContextPtr rmesa
, GLuint flags
)
523 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
;
535 static int radeonFlushCmdBufLocked( radeonContextPtr rmesa
,
536 const char * caller
)
539 drm_radeon_cmd_buffer_t cmd
;
541 if (rmesa
->lost_context
)
542 radeonBackUpAndEmitLostStateLocked(rmesa
);
544 if (RADEON_DEBUG
& DEBUG_IOCTL
) {
545 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
547 if (RADEON_DEBUG
& DEBUG_VERBOSE
)
548 for (i
= 0 ; i
< rmesa
->store
.cmd_used
; i
+= 4 )
549 fprintf(stderr
, "%d: %x\n", i
/4,
550 *(int *)(&rmesa
->store
.cmd_buf
[i
]));
553 if (RADEON_DEBUG
& DEBUG_DMA
)
554 fprintf(stderr
, "%s: Releasing %d buffers\n", __FUNCTION__
,
555 rmesa
->dma
.nr_released_bufs
);
558 if (RADEON_DEBUG
& DEBUG_SANITY
) {
559 if (rmesa
->state
.scissor
.enabled
)
560 ret
= radeonSanityCmdBuffer( rmesa
,
561 rmesa
->state
.scissor
.numClipRects
,
562 rmesa
->state
.scissor
.pClipRects
);
564 ret
= radeonSanityCmdBuffer( rmesa
,
568 fprintf(stderr
, "drmSanityCommandWrite: %d\n", ret
);
574 cmd
.bufsz
= rmesa
->store
.cmd_used
;
575 cmd
.buf
= rmesa
->store
.cmd_buf
;
577 if (rmesa
->state
.scissor
.enabled
) {
578 cmd
.nbox
= rmesa
->state
.scissor
.numClipRects
;
579 cmd
.boxes
= rmesa
->state
.scissor
.pClipRects
;
581 cmd
.nbox
= rmesa
->numClipRects
;
582 cmd
.boxes
= rmesa
->pClipRects
;
585 ret
= drmCommandWrite( rmesa
->dri
.fd
,
590 fprintf(stderr
, "drmCommandWrite: %d\n", ret
);
592 if (RADEON_DEBUG
& DEBUG_SYNC
) {
593 fprintf(stderr
, "\nSyncing in %s\n\n", __FUNCTION__
);
594 radeonWaitForIdleLocked( rmesa
);
598 rmesa
->store
.primnr
= 0;
599 rmesa
->store
.statenr
= 0;
600 rmesa
->store
.cmd_used
= 0;
601 rmesa
->dma
.nr_released_bufs
= 0;
602 rmesa
->save_on_next_emit
= 1;
608 /* Note: does not emit any commands to avoid recursion on
611 void radeonFlushCmdBuf( radeonContextPtr rmesa
, const char *caller
)
616 LOCK_HARDWARE( rmesa
);
618 ret
= radeonFlushCmdBufLocked( rmesa
, caller
);
620 UNLOCK_HARDWARE( rmesa
);
623 fprintf(stderr
, "drm_radeon_cmd_buffer_t: %d (exiting)\n", ret
);
628 /* =============================================================
629 * Hardware vertex buffer handling
633 void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa
)
635 struct radeon_dma_buffer
*dmabuf
;
636 int fd
= rmesa
->dri
.fd
;
642 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
643 fprintf(stderr
, "%s\n", __FUNCTION__
);
645 if (rmesa
->dma
.flush
) {
646 rmesa
->dma
.flush( rmesa
);
649 if (rmesa
->dma
.current
.buf
)
650 radeonReleaseDmaRegion( rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
652 if (rmesa
->dma
.nr_released_bufs
> 4)
653 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
655 dma
.context
= rmesa
->dri
.hwContext
;
657 dma
.send_list
= NULL
;
658 dma
.send_sizes
= NULL
;
660 dma
.request_count
= 1;
661 dma
.request_size
= RADEON_BUFFER_SIZE
;
662 dma
.request_list
= &index
;
663 dma
.request_sizes
= &size
;
664 dma
.granted_count
= 0;
666 LOCK_HARDWARE(rmesa
); /* no need to validate */
668 ret
= drmDMA( fd
, &dma
);
671 /* Free some up this way?
673 if (rmesa
->dma
.nr_released_bufs
) {
674 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
677 if (RADEON_DEBUG
& DEBUG_DMA
)
678 fprintf(stderr
, "Waiting for buffers\n");
680 radeonWaitForIdleLocked( rmesa
);
681 ret
= drmDMA( fd
, &dma
);
684 UNLOCK_HARDWARE( rmesa
);
685 fprintf( stderr
, "Error: Could not get dma buffer... exiting\n" );
690 UNLOCK_HARDWARE(rmesa
);
692 if (RADEON_DEBUG
& DEBUG_DMA
)
693 fprintf(stderr
, "Allocated buffer %d\n", index
);
695 dmabuf
= CALLOC_STRUCT( radeon_dma_buffer
);
696 dmabuf
->buf
= &rmesa
->radeonScreen
->buffers
->list
[index
];
697 dmabuf
->refcount
= 1;
699 rmesa
->dma
.current
.buf
= dmabuf
;
700 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
701 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
702 rmesa
->dma
.current
.start
= 0;
703 rmesa
->dma
.current
.ptr
= 0;
705 rmesa
->c_vertexBuffers
++;
708 void radeonReleaseDmaRegion( radeonContextPtr rmesa
,
709 struct radeon_dma_region
*region
,
712 if (RADEON_DEBUG
& DEBUG_IOCTL
)
713 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
718 if (rmesa
->dma
.flush
)
719 rmesa
->dma
.flush( rmesa
);
721 if (--region
->buf
->refcount
== 0) {
722 drm_radeon_cmd_header_t
*cmd
;
724 if (RADEON_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
725 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
726 region
->buf
->buf
->idx
);
728 cmd
= (drm_radeon_cmd_header_t
*)radeonAllocCmdBuf( rmesa
, sizeof(*cmd
),
730 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
731 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
733 rmesa
->dma
.nr_released_bufs
++;
740 /* Allocates a region from rmesa->dma.current. If there isn't enough
741 * space in current, grab a new buffer (and discard what was left of current)
743 void radeonAllocDmaRegion( radeonContextPtr rmesa
,
744 struct radeon_dma_region
*region
,
748 if (RADEON_DEBUG
& DEBUG_IOCTL
)
749 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
751 if (rmesa
->dma
.flush
)
752 rmesa
->dma
.flush( rmesa
);
755 radeonReleaseDmaRegion( rmesa
, region
, __FUNCTION__
);
758 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
759 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
761 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
762 radeonRefillCurrentDmaRegion( rmesa
);
764 region
->start
= rmesa
->dma
.current
.start
;
765 region
->ptr
= rmesa
->dma
.current
.start
;
766 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
767 region
->address
= rmesa
->dma
.current
.address
;
768 region
->buf
= rmesa
->dma
.current
.buf
;
769 region
->buf
->refcount
++;
771 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
772 rmesa
->dma
.current
.start
=
773 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
776 /* ================================================================
777 * SwapBuffers with client-side throttling
780 static uint32_t radeonGetLastFrame (radeonContextPtr rmesa
)
782 drm_radeon_getparam_t gp
;
786 gp
.param
= RADEON_PARAM_LAST_FRAME
;
787 gp
.value
= (int *)&frame
;
788 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_GETPARAM
,
792 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
799 static void radeonEmitIrqLocked( radeonContextPtr rmesa
)
801 drm_radeon_irq_emit_t ie
;
804 ie
.irq_seq
= &rmesa
->iw
.irq_seq
;
805 ret
= drmCommandWriteRead( rmesa
->dri
.fd
, DRM_RADEON_IRQ_EMIT
,
808 fprintf( stderr
, "%s: drm_radeon_irq_emit_t: %d\n", __FUNCTION__
, ret
);
814 static void radeonWaitIrq( radeonContextPtr rmesa
)
819 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_IRQ_WAIT
,
820 &rmesa
->iw
, sizeof(rmesa
->iw
) );
821 } while (ret
&& (errno
== EINTR
|| errno
== EBUSY
));
824 fprintf( stderr
, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__
, ret
);
830 static void radeonWaitForFrameCompletion( radeonContextPtr rmesa
)
832 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
834 if (rmesa
->do_irqs
) {
835 if (radeonGetLastFrame(rmesa
) < sarea
->last_frame
) {
836 if (!rmesa
->irqsEmitted
) {
837 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
)
841 UNLOCK_HARDWARE( rmesa
);
842 radeonWaitIrq( rmesa
);
843 LOCK_HARDWARE( rmesa
);
845 rmesa
->irqsEmitted
= 10;
848 if (rmesa
->irqsEmitted
) {
849 radeonEmitIrqLocked( rmesa
);
850 rmesa
->irqsEmitted
--;
854 while (radeonGetLastFrame (rmesa
) < sarea
->last_frame
) {
855 UNLOCK_HARDWARE( rmesa
);
856 if (rmesa
->do_usleeps
)
858 LOCK_HARDWARE( rmesa
);
863 /* Copy the back color buffer to the front color buffer.
865 void radeonCopyBuffer( __DRIdrawablePrivate
*dPriv
,
866 const drm_clip_rect_t
*rect
)
868 radeonContextPtr rmesa
;
870 GLboolean missed_target
;
872 __DRIscreenPrivate
*psp
;
875 assert(dPriv
->driContextPriv
);
876 assert(dPriv
->driContextPriv
->driverPrivate
);
878 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
880 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
881 fprintf( stderr
, "\n%s( %p )\n\n", __FUNCTION__
, (void *) rmesa
->glCtx
);
884 RADEON_FIREVERTICES( rmesa
);
885 LOCK_HARDWARE( rmesa
);
887 /* Throttle the frame rate -- only allow one pending swap buffers
890 radeonWaitForFrameCompletion( rmesa
);
893 UNLOCK_HARDWARE( rmesa
);
894 driWaitForVBlank( dPriv
, & missed_target
);
895 LOCK_HARDWARE( rmesa
);
898 nbox
= dPriv
->numClipRects
; /* must be in locked region */
900 for ( i
= 0 ; i
< nbox
; ) {
901 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, nbox
);
902 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
903 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
906 for ( ; i
< nr
; i
++ ) {
912 if (rect
->x1
> b
->x1
)
914 if (rect
->y1
> b
->y1
)
916 if (rect
->x2
< b
->x2
)
918 if (rect
->y2
< b
->y2
)
921 if (b
->x1
>= b
->x2
|| b
->y1
>= b
->y2
)
928 rmesa
->sarea
->nbox
= n
;
933 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_SWAP
);
936 fprintf( stderr
, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret
);
937 UNLOCK_HARDWARE( rmesa
);
942 UNLOCK_HARDWARE( rmesa
);
945 psp
= dPriv
->driScreenPriv
;
947 (*psp
->systemTime
->getUST
)( & ust
);
948 if ( missed_target
) {
949 rmesa
->swap_missed_count
++;
950 rmesa
->swap_missed_ust
= ust
- rmesa
->swap_ust
;
953 rmesa
->swap_ust
= ust
;
954 rmesa
->hw
.all_dirty
= GL_TRUE
;
958 void radeonPageFlip( __DRIdrawablePrivate
*dPriv
)
960 radeonContextPtr rmesa
;
962 GLboolean missed_target
;
963 __DRIscreenPrivate
*psp
;
966 assert(dPriv
->driContextPriv
);
967 assert(dPriv
->driContextPriv
->driverPrivate
);
969 rmesa
= (radeonContextPtr
) dPriv
->driContextPriv
->driverPrivate
;
970 psp
= dPriv
->driScreenPriv
;
972 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
973 fprintf(stderr
, "%s: pfCurrentPage: %d\n", __FUNCTION__
,
974 rmesa
->sarea
->pfCurrentPage
);
977 RADEON_FIREVERTICES( rmesa
);
978 LOCK_HARDWARE( rmesa
);
980 /* Need to do this for the perf box placement:
982 if (dPriv
->numClipRects
)
984 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
985 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
987 rmesa
->sarea
->nbox
= 1;
990 /* Throttle the frame rate -- only allow a few pending swap buffers
993 radeonWaitForFrameCompletion( rmesa
);
994 UNLOCK_HARDWARE( rmesa
);
995 driWaitForVBlank( dPriv
, & missed_target
);
996 if ( missed_target
) {
997 rmesa
->swap_missed_count
++;
998 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_missed_ust
);
1000 LOCK_HARDWARE( rmesa
);
1002 ret
= drmCommandNone( rmesa
->dri
.fd
, DRM_RADEON_FLIP
);
1004 UNLOCK_HARDWARE( rmesa
);
1007 fprintf( stderr
, "DRM_RADEON_FLIP: return = %d\n", ret
);
1011 rmesa
->swap_count
++;
1012 (void) (*psp
->systemTime
->getUST
)( & rmesa
->swap_ust
);
1014 /* Get ready for drawing next frame. Update the renderbuffers'
1015 * flippedOffset/Pitch fields so we draw into the right place.
1017 driFlipRenderbuffers(rmesa
->glCtx
->WinSysDrawBuffer
,
1018 rmesa
->sarea
->pfCurrentPage
);
1020 radeonUpdateDrawBuffer(rmesa
->glCtx
);
1024 /* ================================================================
1027 #define RADEON_MAX_CLEARS 256
1029 static void radeonClear( GLcontext
*ctx
, GLbitfield mask
)
1031 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1032 __DRIdrawablePrivate
*dPriv
= rmesa
->dri
.drawable
;
1033 drm_radeon_sarea_t
*sarea
= rmesa
->sarea
;
1036 GLuint color_mask
= 0;
1038 GLint cx
, cy
, cw
, ch
;
1040 if ( RADEON_DEBUG
& DEBUG_IOCTL
) {
1041 fprintf( stderr
, "radeonClear\n");
1045 LOCK_HARDWARE( rmesa
);
1046 UNLOCK_HARDWARE( rmesa
);
1047 if ( dPriv
->numClipRects
== 0 )
1053 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
1054 flags
|= RADEON_FRONT
;
1055 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1056 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
1059 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
1060 flags
|= RADEON_BACK
;
1061 color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1062 mask
&= ~BUFFER_BIT_BACK_LEFT
;
1065 if ( mask
& BUFFER_BIT_DEPTH
) {
1066 flags
|= RADEON_DEPTH
;
1067 mask
&= ~BUFFER_BIT_DEPTH
;
1070 if ( (mask
& BUFFER_BIT_STENCIL
) && rmesa
->state
.stencil
.hwBuffer
) {
1071 flags
|= RADEON_STENCIL
;
1072 mask
&= ~BUFFER_BIT_STENCIL
;
1076 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
1077 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
1078 _swrast_Clear( ctx
, mask
);
1084 if (rmesa
->using_hyperz
) {
1085 flags
|= RADEON_USE_COMP_ZBUF
;
1086 /* if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)
1087 flags |= RADEON_USE_HIERZ; */
1088 if (!(rmesa
->state
.stencil
.hwBuffer
) ||
1089 ((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
1090 ((rmesa
->state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
1091 flags
|= RADEON_CLEAR_FASTZ
;
1095 LOCK_HARDWARE( rmesa
);
1097 /* compute region after locking: */
1098 cx
= ctx
->DrawBuffer
->_Xmin
;
1099 cy
= ctx
->DrawBuffer
->_Ymin
;
1100 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
1101 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
1103 /* Flip top to bottom */
1105 cy
= dPriv
->y
+ dPriv
->h
- cy
- ch
;
1107 /* Throttle the number of clear ioctls we do.
1111 drm_radeon_getparam_t gp
;
1113 gp
.param
= RADEON_PARAM_LAST_CLEAR
;
1114 gp
.value
= (int *)&clear
;
1115 ret
= drmCommandWriteRead( rmesa
->dri
.fd
,
1116 DRM_RADEON_GETPARAM
, &gp
, sizeof(gp
) );
1119 fprintf( stderr
, "%s: drm_radeon_getparam_t: %d\n", __FUNCTION__
, ret
);
1123 if ( sarea
->last_clear
- clear
<= RADEON_MAX_CLEARS
) {
1127 if ( rmesa
->do_usleeps
) {
1128 UNLOCK_HARDWARE( rmesa
);
1130 LOCK_HARDWARE( rmesa
);
1134 /* Send current state to the hardware */
1135 radeonFlushCmdBufLocked( rmesa
, __FUNCTION__
);
1137 for ( i
= 0 ; i
< dPriv
->numClipRects
; ) {
1138 GLint nr
= MIN2( i
+ RADEON_NR_SAREA_CLIPRECTS
, dPriv
->numClipRects
);
1139 drm_clip_rect_t
*box
= dPriv
->pClipRects
;
1140 drm_clip_rect_t
*b
= rmesa
->sarea
->boxes
;
1141 drm_radeon_clear_t clear
;
1142 drm_radeon_clear_rect_t depth_boxes
[RADEON_NR_SAREA_CLIPRECTS
];
1145 if (cw
!= dPriv
->w
|| ch
!= dPriv
->h
) {
1146 /* clear subregion */
1147 for ( ; i
< nr
; i
++ ) {
1148 GLint x
= box
[i
].x1
;
1149 GLint y
= box
[i
].y1
;
1150 GLint w
= box
[i
].x2
- x
;
1151 GLint h
= box
[i
].y2
- y
;
1153 if ( x
< cx
) w
-= cx
- x
, x
= cx
;
1154 if ( y
< cy
) h
-= cy
- y
, y
= cy
;
1155 if ( x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
1156 if ( y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
1157 if ( w
<= 0 ) continue;
1158 if ( h
<= 0 ) continue;
1168 /* clear whole buffer */
1169 for ( ; i
< nr
; i
++ ) {
1175 rmesa
->sarea
->nbox
= n
;
1177 clear
.flags
= flags
;
1178 clear
.clear_color
= rmesa
->state
.color
.clear
;
1179 clear
.clear_depth
= rmesa
->state
.depth
.clear
;
1180 clear
.color_mask
= rmesa
->hw
.msk
.cmd
[MSK_RB3D_PLANEMASK
];
1181 clear
.depth_mask
= rmesa
->state
.stencil
.clear
;
1182 clear
.depth_boxes
= depth_boxes
;
1185 b
= rmesa
->sarea
->boxes
;
1186 for ( ; n
>= 0 ; n
-- ) {
1187 depth_boxes
[n
].f
[CLEAR_X1
] = (float)b
[n
].x1
;
1188 depth_boxes
[n
].f
[CLEAR_Y1
] = (float)b
[n
].y1
;
1189 depth_boxes
[n
].f
[CLEAR_X2
] = (float)b
[n
].x2
;
1190 depth_boxes
[n
].f
[CLEAR_Y2
] = (float)b
[n
].y2
;
1191 depth_boxes
[n
].f
[CLEAR_DEPTH
] =
1192 (float)rmesa
->state
.depth
.clear
;
1195 ret
= drmCommandWrite( rmesa
->dri
.fd
, DRM_RADEON_CLEAR
,
1196 &clear
, sizeof(drm_radeon_clear_t
));
1199 UNLOCK_HARDWARE( rmesa
);
1200 fprintf( stderr
, "DRM_RADEON_CLEAR: return = %d\n", ret
);
1205 UNLOCK_HARDWARE( rmesa
);
1206 rmesa
->hw
.all_dirty
= GL_TRUE
;
1210 void radeonWaitForIdleLocked( radeonContextPtr rmesa
)
1212 int fd
= rmesa
->dri
.fd
;
1216 rmesa
->c_drawWaits
++;
1220 ret
= drmCommandNone( fd
, DRM_RADEON_CP_IDLE
);
1221 } while ( ret
&& errno
== EBUSY
&& i
++ < RADEON_IDLE_RETRY
);
1222 } while ( ( ret
== -EBUSY
) && ( to
++ < RADEON_TIMEOUT
) );
1225 UNLOCK_HARDWARE( rmesa
);
1226 fprintf( stderr
, "Error: Radeon timed out... exiting\n" );
1232 static void radeonWaitForIdle( radeonContextPtr rmesa
)
1234 LOCK_HARDWARE(rmesa
);
1235 radeonWaitForIdleLocked( rmesa
);
1236 UNLOCK_HARDWARE(rmesa
);
1240 void radeonFlush( GLcontext
*ctx
)
1242 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
1244 if (RADEON_DEBUG
& DEBUG_IOCTL
)
1245 fprintf(stderr
, "%s\n", __FUNCTION__
);
1247 if (rmesa
->dma
.flush
)
1248 rmesa
->dma
.flush( rmesa
);
1250 radeonEmitState( rmesa
);
1252 if (rmesa
->store
.cmd_used
)
1253 radeonFlushCmdBuf( rmesa
, __FUNCTION__
);
1256 /* Make sure all commands have been sent to the hardware and have
1257 * completed processing.
1259 void radeonFinish( GLcontext
*ctx
)
1261 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1264 if (rmesa
->do_irqs
) {
1265 LOCK_HARDWARE( rmesa
);
1266 radeonEmitIrqLocked( rmesa
);
1267 UNLOCK_HARDWARE( rmesa
);
1268 radeonWaitIrq( rmesa
);
1271 radeonWaitForIdle( rmesa
);
1275 void radeonInitIoctlFuncs( GLcontext
*ctx
)
1277 ctx
->Driver
.Clear
= radeonClear
;
1278 ctx
->Driver
.Finish
= radeonFinish
;
1279 ctx
->Driver
.Flush
= radeonFlush
;