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 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.atf
);
92 for (i
= 0; i
< mtu
; ++i
)
93 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.tex
[i
] );
94 for (i
= 0; i
< mtu
; ++i
)
95 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.cube
[i
] );
96 for (i
= 0; i
< 6; ++i
)
97 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.pix
[i
] );
98 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.afs
[0] );
99 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.afs
[1] );
100 for (i
= 0; i
< 8; ++i
)
101 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
] );
102 for (i
= 0; i
< 3 + mtu
; ++i
)
103 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
] );
104 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
105 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
106 for (i
= 0; i
< 2; ++i
)
107 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
[i
] );
108 for (i
= 0; i
< 6; ++i
)
109 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
] );
110 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.spr
);
111 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.ptp
);
112 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.prf
);
113 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.pvs
);
114 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vpp
[0] );
115 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vpp
[1] );
116 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vpi
[0] );
117 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.vpi
[1] );
120 static void r200SaveHwState( r200ContextPtr rmesa
)
122 struct r200_state_atom
*atom
;
123 char * dest
= rmesa
->backup_store
.cmd_buf
;
125 if (R200_DEBUG
& DEBUG_STATE
)
126 fprintf(stderr
, "%s\n", __FUNCTION__
);
128 rmesa
->backup_store
.cmd_used
= 0;
130 foreach( atom
, &rmesa
->hw
.atomlist
) {
131 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
132 int size
= atom
->cmd_size
* 4;
133 memcpy( dest
, atom
->cmd
, size
);
135 rmesa
->backup_store
.cmd_used
+= size
;
136 if (R200_DEBUG
& DEBUG_STATE
)
137 print_state_atom( atom
);
141 assert( rmesa
->backup_store
.cmd_used
<= R200_CMD_BUF_SZ
);
142 if (R200_DEBUG
& DEBUG_STATE
)
143 fprintf(stderr
, "Returning to r200EmitState\n");
146 void r200EmitState( r200ContextPtr rmesa
)
150 struct r200_state_atom
*atom
;
152 if (R200_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
153 fprintf(stderr
, "%s\n", __FUNCTION__
);
155 if (rmesa
->save_on_next_emit
) {
156 r200SaveHwState(rmesa
);
157 rmesa
->save_on_next_emit
= GL_FALSE
;
160 if (!rmesa
->hw
.is_dirty
&& !rmesa
->hw
.all_dirty
)
163 mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
165 /* To avoid going across the entire set of states multiple times, just check
166 * for enough space for the case of emitting all state, and inline the
167 * r200AllocCmdBuf code here without all the checks.
169 r200EnsureCmdBufSpace( rmesa
, rmesa
->hw
.max_state_size
);
171 /* we need to calculate dest after EnsureCmdBufSpace
172 as we may flush the buffer - airlied */
173 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
174 if (R200_DEBUG
& DEBUG_STATE
) {
175 foreach( atom
, &rmesa
->hw
.atomlist
) {
176 if ( atom
->dirty
|| rmesa
->hw
.all_dirty
) {
177 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) )
178 print_state_atom( atom
);
180 fprintf(stderr
, "skip state %s\n", atom
->name
);
185 foreach( atom
, &rmesa
->hw
.atomlist
) {
186 if ( rmesa
->hw
.all_dirty
)
187 atom
->dirty
= GL_TRUE
;
189 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
190 int size
= atom
->cmd_size
* 4;
191 memcpy( dest
, atom
->cmd
, size
);
193 rmesa
->store
.cmd_used
+= size
;
194 atom
->dirty
= GL_FALSE
;
199 assert( rmesa
->store
.cmd_used
<= R200_CMD_BUF_SZ
);
201 rmesa
->hw
.is_dirty
= GL_FALSE
;
202 rmesa
->hw
.all_dirty
= GL_FALSE
;
205 /* Fire a section of the retained (indexed_verts) buffer as a regular
208 void r200EmitVbufPrim( r200ContextPtr rmesa
,
212 drm_radeon_cmd_header_t
*cmd
;
214 assert(!(primitive
& R200_VF_PRIM_WALK_IND
));
216 r200EmitState( rmesa
);
218 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
219 fprintf(stderr
, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__
,
220 rmesa
->store
.cmd_used
/4, primitive
, vertex_nr
);
222 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VBUF_BUFSZ
,
225 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
226 cmd
[1].i
= R200_CP_CMD_3D_DRAW_VBUF_2
;
227 cmd
[2].i
= (primitive
|
228 R200_VF_PRIM_WALK_LIST
|
229 R200_VF_COLOR_ORDER_RGBA
|
230 (vertex_nr
<< R200_VF_VERTEX_NUMBER_SHIFT
));
234 void r200FlushElts( r200ContextPtr rmesa
)
236 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
238 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 12)) / 2;
240 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
241 fprintf(stderr
, "%s\n", __FUNCTION__
);
243 assert( rmesa
->dma
.flush
== r200FlushElts
);
244 rmesa
->dma
.flush
= NULL
;
246 /* Cope with odd number of elts:
248 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
249 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
251 cmd
[1] |= (dwords
- 3) << 16;
252 cmd
[2] |= nr
<< R200_VF_VERTEX_NUMBER_SHIFT
;
254 if (R200_DEBUG
& DEBUG_SYNC
) {
255 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
256 r200Finish( rmesa
->glCtx
);
261 GLushort
*r200AllocEltsOpenEnded( r200ContextPtr rmesa
,
265 drm_radeon_cmd_header_t
*cmd
;
268 if (R200_DEBUG
& DEBUG_IOCTL
)
269 fprintf(stderr
, "%s %d prim %x\n", __FUNCTION__
, min_nr
, primitive
);
271 assert((primitive
& R200_VF_PRIM_WALK_IND
));
273 r200EmitState( rmesa
);
275 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, ELTS_BUFSZ(min_nr
),
278 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
279 cmd
[1].i
= R200_CP_CMD_3D_DRAW_INDX_2
;
280 cmd
[2].i
= (primitive
|
281 R200_VF_PRIM_WALK_IND
|
282 R200_VF_COLOR_ORDER_RGBA
);
285 retval
= (GLushort
*)(cmd
+3);
287 if (R200_DEBUG
& DEBUG_PRIMS
)
288 fprintf(stderr
, "%s: header 0x%x prim %x \n",
290 cmd
[1].i
, primitive
);
292 assert(!rmesa
->dma
.flush
);
293 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
294 rmesa
->dma
.flush
= r200FlushElts
;
296 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
303 void r200EmitVertexAOS( r200ContextPtr rmesa
,
307 drm_radeon_cmd_header_t
*cmd
;
309 if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
310 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
311 __FUNCTION__
, vertex_size
, offset
);
313 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
316 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
317 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (2 << 16);
319 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
324 void r200EmitAOS( r200ContextPtr rmesa
,
325 struct r200_dma_region
**component
,
329 drm_radeon_cmd_header_t
*cmd
;
330 int sz
= AOS_BUFSZ(nr
);
334 if (R200_DEBUG
& DEBUG_IOCTL
)
335 fprintf(stderr
, "%s nr arrays: %d\n", __FUNCTION__
, nr
);
337 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sz
, __FUNCTION__
);
339 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
340 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int)) - 3) << 16);
345 for (i
= 0 ; i
< nr
; i
++) {
347 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
348 (component
[i
]->aos_size
<< 16));
349 cmd
[2].i
= (component
[i
]->aos_start
+
350 offset
* component
[i
]->aos_stride
* 4);
354 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
355 (component
[i
]->aos_size
<< 0));
356 cmd
[1].i
= (component
[i
]->aos_start
+
357 offset
* component
[i
]->aos_stride
* 4);
361 if (R200_DEBUG
& DEBUG_VERTS
) {
362 fprintf(stderr
, "%s:\n", __FUNCTION__
);
363 for (i
= 0 ; i
< sz
; i
++)
364 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
368 void r200EmitBlit( r200ContextPtr rmesa
,
374 GLint srcx
, GLint srcy
,
375 GLint dstx
, GLint dsty
,
378 drm_radeon_cmd_header_t
*cmd
;
380 if (R200_DEBUG
& DEBUG_IOCTL
)
381 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
383 src_pitch
, src_offset
, srcx
, srcy
,
384 dst_pitch
, dst_offset
, dstx
, dsty
,
387 assert( (src_pitch
& 63) == 0 );
388 assert( (dst_pitch
& 63) == 0 );
389 assert( (src_offset
& 1023) == 0 );
390 assert( (dst_offset
& 1023) == 0 );
391 assert( w
< (1<<16) );
392 assert( h
< (1<<16) );
394 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 8 * sizeof(int),
398 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
399 cmd
[1].i
= R200_CP_CMD_BITBLT_MULTI
| (5 << 16);
400 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
401 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
402 RADEON_GMC_BRUSH_NONE
|
404 RADEON_GMC_SRC_DATATYPE_COLOR
|
406 RADEON_DP_SRC_SOURCE_MEMORY
|
407 RADEON_GMC_CLR_CMP_CNTL_DIS
|
408 RADEON_GMC_WR_MSK_DIS
);
410 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
411 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
412 cmd
[5].i
= (srcx
<< 16) | srcy
;
413 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
414 cmd
[7].i
= (w
<< 16) | h
;
418 void r200EmitWait( r200ContextPtr rmesa
, GLuint flags
)
420 drm_radeon_cmd_header_t
*cmd
;
422 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
424 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 1 * sizeof(int),
427 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
428 cmd
[0].wait
.flags
= flags
;