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
] );
108 /* FIXME: is this a good place to insert that atom ? */
109 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.prf
);
112 static void r200SaveHwState( r200ContextPtr rmesa
)
114 struct r200_state_atom
*atom
;
115 char * dest
= rmesa
->backup_store
.cmd_buf
;
117 if (R200_DEBUG
& DEBUG_STATE
)
118 fprintf(stderr
, "%s\n", __FUNCTION__
);
120 rmesa
->backup_store
.cmd_used
= 0;
122 foreach( atom
, &rmesa
->hw
.atomlist
) {
123 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
124 int size
= atom
->cmd_size
* 4;
125 memcpy( dest
, atom
->cmd
, size
);
127 rmesa
->backup_store
.cmd_used
+= size
;
128 if (R200_DEBUG
& DEBUG_STATE
)
129 print_state_atom( atom
);
133 assert( rmesa
->backup_store
.cmd_used
<= R200_CMD_BUF_SZ
);
134 if (R200_DEBUG
& DEBUG_STATE
)
135 fprintf(stderr
, "Returning to r200EmitState\n");
138 void r200EmitState( r200ContextPtr rmesa
)
142 struct r200_state_atom
*atom
;
144 if (R200_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
145 fprintf(stderr
, "%s\n", __FUNCTION__
);
147 if (rmesa
->save_on_next_emit
) {
148 r200SaveHwState(rmesa
);
149 rmesa
->save_on_next_emit
= GL_FALSE
;
152 if (!rmesa
->hw
.is_dirty
&& !rmesa
->hw
.all_dirty
)
155 mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
157 /* To avoid going across the entire set of states multiple times, just check
158 * for enough space for the case of emitting all state, and inline the
159 * r200AllocCmdBuf code here without all the checks.
161 r200EnsureCmdBufSpace( rmesa
, rmesa
->hw
.max_state_size
);
163 /* we need to calculate dest after EnsureCmdBufSpace
164 as we may flush the buffer - airlied */
165 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
166 if (R200_DEBUG
& DEBUG_STATE
) {
167 foreach( atom
, &rmesa
->hw
.atomlist
) {
168 if ( atom
->dirty
|| rmesa
->hw
.all_dirty
) {
169 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) )
170 print_state_atom( atom
);
172 fprintf(stderr
, "skip state %s\n", atom
->name
);
177 foreach( atom
, &rmesa
->hw
.atomlist
) {
178 if ( rmesa
->hw
.all_dirty
)
179 atom
->dirty
= GL_TRUE
;
181 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
182 int size
= atom
->cmd_size
* 4;
183 memcpy( dest
, atom
->cmd
, size
);
185 rmesa
->store
.cmd_used
+= size
;
186 atom
->dirty
= GL_FALSE
;
191 assert( rmesa
->store
.cmd_used
<= R200_CMD_BUF_SZ
);
193 rmesa
->hw
.is_dirty
= GL_FALSE
;
194 rmesa
->hw
.all_dirty
= GL_FALSE
;
197 /* Fire a section of the retained (indexed_verts) buffer as a regular
200 void r200EmitVbufPrim( r200ContextPtr rmesa
,
204 drm_radeon_cmd_header_t
*cmd
;
206 assert(!(primitive
& R200_VF_PRIM_WALK_IND
));
208 r200EmitState( rmesa
);
210 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
211 fprintf(stderr
, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__
,
212 rmesa
->store
.cmd_used
/4, primitive
, vertex_nr
);
214 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VBUF_BUFSZ
,
217 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
218 cmd
[1].i
= R200_CP_CMD_3D_DRAW_VBUF_2
;
219 cmd
[2].i
= (primitive
|
220 R200_VF_PRIM_WALK_LIST
|
221 R200_VF_COLOR_ORDER_RGBA
|
222 (vertex_nr
<< R200_VF_VERTEX_NUMBER_SHIFT
));
226 void r200FlushElts( r200ContextPtr rmesa
)
228 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
230 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 12)) / 2;
232 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
233 fprintf(stderr
, "%s\n", __FUNCTION__
);
235 assert( rmesa
->dma
.flush
== r200FlushElts
);
236 rmesa
->dma
.flush
= NULL
;
238 /* Cope with odd number of elts:
240 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
241 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
243 cmd
[1] |= (dwords
- 3) << 16;
244 cmd
[2] |= nr
<< R200_VF_VERTEX_NUMBER_SHIFT
;
246 if (R200_DEBUG
& DEBUG_SYNC
) {
247 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
248 r200Finish( rmesa
->glCtx
);
253 GLushort
*r200AllocEltsOpenEnded( r200ContextPtr rmesa
,
257 drm_radeon_cmd_header_t
*cmd
;
260 if (R200_DEBUG
& DEBUG_IOCTL
)
261 fprintf(stderr
, "%s %d prim %x\n", __FUNCTION__
, min_nr
, primitive
);
263 assert((primitive
& R200_VF_PRIM_WALK_IND
));
265 r200EmitState( rmesa
);
267 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, ELTS_BUFSZ(min_nr
),
270 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
271 cmd
[1].i
= R200_CP_CMD_3D_DRAW_INDX_2
;
272 cmd
[2].i
= (primitive
|
273 R200_VF_PRIM_WALK_IND
|
274 R200_VF_COLOR_ORDER_RGBA
);
277 retval
= (GLushort
*)(cmd
+3);
279 if (R200_DEBUG
& DEBUG_PRIMS
)
280 fprintf(stderr
, "%s: header 0x%x prim %x \n",
282 cmd
[1].i
, primitive
);
284 assert(!rmesa
->dma
.flush
);
285 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
286 rmesa
->dma
.flush
= r200FlushElts
;
288 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
295 void r200EmitVertexAOS( r200ContextPtr rmesa
,
299 drm_radeon_cmd_header_t
*cmd
;
301 if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
302 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
303 __FUNCTION__
, vertex_size
, offset
);
305 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
308 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
309 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (2 << 16);
311 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
316 void r200EmitAOS( r200ContextPtr rmesa
,
317 struct r200_dma_region
**component
,
321 drm_radeon_cmd_header_t
*cmd
;
322 int sz
= AOS_BUFSZ(nr
);
326 if (R200_DEBUG
& DEBUG_IOCTL
)
327 fprintf(stderr
, "%s nr arrays: %d\n", __FUNCTION__
, nr
);
329 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sz
, __FUNCTION__
);
331 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
332 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int)) - 3) << 16);
337 for (i
= 0 ; i
< nr
; i
++) {
339 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
340 (component
[i
]->aos_size
<< 16));
341 cmd
[2].i
= (component
[i
]->aos_start
+
342 offset
* component
[i
]->aos_stride
* 4);
346 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
347 (component
[i
]->aos_size
<< 0));
348 cmd
[1].i
= (component
[i
]->aos_start
+
349 offset
* component
[i
]->aos_stride
* 4);
353 if (R200_DEBUG
& DEBUG_VERTS
) {
354 fprintf(stderr
, "%s:\n", __FUNCTION__
);
355 for (i
= 0 ; i
< sz
; i
++)
356 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
360 void r200EmitBlit( r200ContextPtr rmesa
,
366 GLint srcx
, GLint srcy
,
367 GLint dstx
, GLint dsty
,
370 drm_radeon_cmd_header_t
*cmd
;
372 if (R200_DEBUG
& DEBUG_IOCTL
)
373 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
375 src_pitch
, src_offset
, srcx
, srcy
,
376 dst_pitch
, dst_offset
, dstx
, dsty
,
379 assert( (src_pitch
& 63) == 0 );
380 assert( (dst_pitch
& 63) == 0 );
381 assert( (src_offset
& 1023) == 0 );
382 assert( (dst_offset
& 1023) == 0 );
383 assert( w
< (1<<16) );
384 assert( h
< (1<<16) );
386 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 8 * sizeof(int),
390 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
391 cmd
[1].i
= R200_CP_CMD_BITBLT_MULTI
| (5 << 16);
392 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
393 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
394 RADEON_GMC_BRUSH_NONE
|
396 RADEON_GMC_SRC_DATATYPE_COLOR
|
398 RADEON_DP_SRC_SOURCE_MEMORY
|
399 RADEON_GMC_CLR_CMP_CNTL_DIS
|
400 RADEON_GMC_WR_MSK_DIS
);
402 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
403 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
404 cmd
[5].i
= (srcx
<< 16) | srcy
;
405 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
406 cmd
[7].i
= (w
<< 16) | h
;
410 void r200EmitWait( r200ContextPtr rmesa
, GLuint flags
)
412 if (rmesa
->dri
.drmMinor
>= 6) {
413 drm_radeon_cmd_header_t
*cmd
;
415 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
417 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 1 * sizeof(int),
420 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
421 cmd
[0].wait
.flags
= flags
;