1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_cmdbuf.c,v 1.1 2002/10/30 12:51:51 alanh Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
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.
32 * Keith Whitwell <keith@tungstengraphics.com>
39 #include "swrast/swrast.h"
40 #include "simple_list.h"
42 #include "r200_context.h"
43 #include "r200_state.h"
44 #include "r200_ioctl.h"
46 #include "r200_sanity.h"
47 #include "radeon_reg.h"
49 static void print_state_atom( struct r200_state_atom
*state
)
53 fprintf(stderr
, "emit %s/%d\n", state
->name
, state
->cmd_size
);
55 if (0 & R200_DEBUG
& DEBUG_VERBOSE
)
56 for (i
= 0 ; i
< state
->cmd_size
; i
++)
57 fprintf(stderr
, "\t%s[%d]: %x\n", state
->name
, i
, state
->cmd
[i
]);
61 /* The state atoms will be emitted in the order they appear in the atom list,
62 * so this step is important.
64 void r200SetUpAtomList( r200ContextPtr rmesa
)
68 mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
70 make_empty_list(&rmesa
->hw
.atomlist
);
71 rmesa
->hw
.atomlist
.name
= "atom-list";
73 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.ctx
);
74 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.set
);
75 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.lin
);
76 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.msk
);
77 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vpt
);
78 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vtx
);
79 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vap
);
80 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vte
);
81 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.msc
);
82 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.cst
);
83 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.zbs
);
84 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.tcl
);
85 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.msl
);
86 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.tcg
);
87 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.grd
);
88 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.fog
);
89 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.tam
);
90 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.tf
);
91 for (i
= 0; i
< mtu
; ++i
)
92 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.tex
[i
] );
93 for (i
= 0; i
< mtu
; ++i
)
94 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.cube
[i
] );
95 for (i
= 0; i
< 6; ++i
)
96 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.pix
[i
] );
98 for (i
= 0; i
< 8; ++i
)
99 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
] );
100 for (i
= 0; i
< 3 + mtu
; ++i
)
101 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
] );
102 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
103 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
104 for (i
= 0; i
< 2; ++i
)
105 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
[i
] );
106 for (i
= 0; i
< 6; ++i
)
107 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
] );
110 static void r200SaveHwState( r200ContextPtr rmesa
)
112 struct r200_state_atom
*atom
;
113 char * dest
= rmesa
->backup_store
.cmd_buf
;
115 rmesa
->backup_store
.cmd_used
= 0;
117 foreach( atom
, &rmesa
->hw
.atomlist
) {
118 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
119 int size
= atom
->cmd_size
* 4;
120 memcpy( dest
, atom
->cmd
, size
);
122 rmesa
->backup_store
.cmd_used
+= size
;
126 assert( rmesa
->backup_store
.cmd_used
<= R200_CMD_BUF_SZ
);
129 void r200EmitState( r200ContextPtr rmesa
)
133 struct r200_state_atom
*atom
;
135 if (R200_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
136 fprintf(stderr
, "%s\n", __FUNCTION__
);
138 if (rmesa
->save_on_next_emit
) {
139 r200SaveHwState(rmesa
);
140 rmesa
->save_on_next_emit
= GL_FALSE
;
143 if (!rmesa
->hw
.is_dirty
&& !rmesa
->hw
.all_dirty
)
146 mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
148 /* To avoid going across the entire set of states multiple times, just check
149 * for enough space for the case of emitting all state, and inline the
150 * r200AllocCmdBuf code here without all the checks.
152 r200EnsureCmdBufSpace( rmesa
, rmesa
->hw
.max_state_size
);
154 /* we need to calculate dest after EnsureCmdBufSpace
155 as we may flush the buffer - airlied */
156 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
157 if (R200_DEBUG
& DEBUG_STATE
) {
158 foreach( atom
, &rmesa
->hw
.atomlist
) {
159 if ( atom
->dirty
|| rmesa
->hw
.all_dirty
) {
160 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) )
161 print_state_atom( atom
);
163 fprintf(stderr
, "skip state %s\n", atom
->name
);
168 foreach( atom
, &rmesa
->hw
.atomlist
) {
169 if ( rmesa
->hw
.all_dirty
)
170 atom
->dirty
= GL_TRUE
;
172 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
173 int size
= atom
->cmd_size
* 4;
174 memcpy( dest
, atom
->cmd
, size
);
176 rmesa
->store
.cmd_used
+= size
;
177 atom
->dirty
= GL_FALSE
;
182 assert( rmesa
->store
.cmd_used
<= R200_CMD_BUF_SZ
);
184 rmesa
->hw
.is_dirty
= GL_FALSE
;
185 rmesa
->hw
.all_dirty
= GL_FALSE
;
188 /* Fire a section of the retained (indexed_verts) buffer as a regular
191 extern void r200EmitVbufPrim( r200ContextPtr rmesa
,
195 drm_radeon_cmd_header_t
*cmd
;
197 assert(!(primitive
& R200_VF_PRIM_WALK_IND
));
199 r200EmitState( rmesa
);
201 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
202 fprintf(stderr
, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__
,
203 rmesa
->store
.cmd_used
/4, primitive
, vertex_nr
);
205 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VBUF_BUFSZ
,
208 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
209 cmd
[1].i
= R200_CP_CMD_3D_DRAW_VBUF_2
;
210 cmd
[2].i
= (primitive
|
211 R200_VF_PRIM_WALK_LIST
|
212 R200_VF_COLOR_ORDER_RGBA
|
213 (vertex_nr
<< R200_VF_VERTEX_NUMBER_SHIFT
));
217 void r200FlushElts( r200ContextPtr rmesa
)
219 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
221 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 12)) / 2;
223 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
224 fprintf(stderr
, "%s\n", __FUNCTION__
);
226 assert( rmesa
->dma
.flush
== r200FlushElts
);
227 rmesa
->dma
.flush
= 0;
229 /* Cope with odd number of elts:
231 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
232 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
234 cmd
[1] |= (dwords
- 3) << 16;
235 cmd
[2] |= nr
<< R200_VF_VERTEX_NUMBER_SHIFT
;
237 if (R200_DEBUG
& DEBUG_SYNC
) {
238 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
239 r200Finish( rmesa
->glCtx
);
244 GLushort
*r200AllocEltsOpenEnded( r200ContextPtr rmesa
,
248 drm_radeon_cmd_header_t
*cmd
;
251 if (R200_DEBUG
& DEBUG_IOCTL
)
252 fprintf(stderr
, "%s %d prim %x\n", __FUNCTION__
, min_nr
, primitive
);
254 assert((primitive
& R200_VF_PRIM_WALK_IND
));
256 r200EmitState( rmesa
);
258 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, ELTS_BUFSZ(min_nr
),
261 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
262 cmd
[1].i
= R200_CP_CMD_3D_DRAW_INDX_2
;
263 cmd
[2].i
= (primitive
|
264 R200_VF_PRIM_WALK_IND
|
265 R200_VF_COLOR_ORDER_RGBA
);
268 retval
= (GLushort
*)(cmd
+3);
270 if (R200_DEBUG
& DEBUG_PRIMS
)
271 fprintf(stderr
, "%s: header 0x%x prim %x \n",
273 cmd
[1].i
, primitive
);
275 assert(!rmesa
->dma
.flush
);
276 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
277 rmesa
->dma
.flush
= r200FlushElts
;
279 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
286 void r200EmitVertexAOS( r200ContextPtr rmesa
,
290 drm_radeon_cmd_header_t
*cmd
;
292 if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
293 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
294 __FUNCTION__
, vertex_size
, offset
);
296 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
299 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
300 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (2 << 16);
302 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
307 void r200EmitAOS( r200ContextPtr rmesa
,
308 struct r200_dma_region
**component
,
312 drm_radeon_cmd_header_t
*cmd
;
313 int sz
= AOS_BUFSZ(nr
);
317 if (R200_DEBUG
& DEBUG_IOCTL
)
318 fprintf(stderr
, "%s nr arrays: %d\n", __FUNCTION__
, nr
);
320 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sz
, __FUNCTION__
);
322 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
323 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int)) - 3) << 16);
328 for (i
= 0 ; i
< nr
; i
++) {
330 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
331 (component
[i
]->aos_size
<< 16));
332 cmd
[2].i
= (component
[i
]->aos_start
+
333 offset
* component
[i
]->aos_stride
* 4);
337 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
338 (component
[i
]->aos_size
<< 0));
339 cmd
[1].i
= (component
[i
]->aos_start
+
340 offset
* component
[i
]->aos_stride
* 4);
344 if (R200_DEBUG
& DEBUG_VERTS
) {
345 fprintf(stderr
, "%s:\n", __FUNCTION__
);
346 for (i
= 0 ; i
< sz
; i
++)
347 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
351 void r200EmitBlit( r200ContextPtr rmesa
,
357 GLint srcx
, GLint srcy
,
358 GLint dstx
, GLint dsty
,
361 drm_radeon_cmd_header_t
*cmd
;
363 if (R200_DEBUG
& DEBUG_IOCTL
)
364 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
366 src_pitch
, src_offset
, srcx
, srcy
,
367 dst_pitch
, dst_offset
, dstx
, dsty
,
370 assert( (src_pitch
& 63) == 0 );
371 assert( (dst_pitch
& 63) == 0 );
372 assert( (src_offset
& 1023) == 0 );
373 assert( (dst_offset
& 1023) == 0 );
374 assert( w
< (1<<16) );
375 assert( h
< (1<<16) );
377 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 8 * sizeof(int),
381 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
382 cmd
[1].i
= R200_CP_CMD_BITBLT_MULTI
| (5 << 16);
383 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
384 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
385 RADEON_GMC_BRUSH_NONE
|
387 RADEON_GMC_SRC_DATATYPE_COLOR
|
389 RADEON_DP_SRC_SOURCE_MEMORY
|
390 RADEON_GMC_CLR_CMP_CNTL_DIS
|
391 RADEON_GMC_WR_MSK_DIS
);
393 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
394 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
395 cmd
[5].i
= (srcx
<< 16) | srcy
;
396 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
397 cmd
[7].i
= (w
<< 16) | h
;
401 void r200EmitWait( r200ContextPtr rmesa
, GLuint flags
)
403 if (rmesa
->dri
.drmMinor
>= 6) {
404 drm_radeon_cmd_header_t
*cmd
;
406 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
408 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 1 * sizeof(int),
411 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
412 cmd
[0].wait
.flags
= flags
;