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 if (R200_DEBUG
& DEBUG_STATE
)
116 fprintf(stderr
, "%s\n", __FUNCTION__
);
118 rmesa
->backup_store
.cmd_used
= 0;
120 foreach( atom
, &rmesa
->hw
.atomlist
) {
121 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
122 int size
= atom
->cmd_size
* 4;
123 memcpy( dest
, atom
->cmd
, size
);
125 rmesa
->backup_store
.cmd_used
+= size
;
126 if (R200_DEBUG
& DEBUG_STATE
)
127 print_state_atom( atom
);
131 assert( rmesa
->backup_store
.cmd_used
<= R200_CMD_BUF_SZ
);
132 if (R200_DEBUG
& DEBUG_STATE
)
133 fprintf(stderr
, "Returning to r200EmitState\n");
136 void r200EmitState( r200ContextPtr rmesa
)
140 struct r200_state_atom
*atom
;
142 if (R200_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
143 fprintf(stderr
, "%s\n", __FUNCTION__
);
145 if (rmesa
->save_on_next_emit
) {
146 r200SaveHwState(rmesa
);
147 rmesa
->save_on_next_emit
= GL_FALSE
;
150 if (!rmesa
->hw
.is_dirty
&& !rmesa
->hw
.all_dirty
)
153 mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
155 /* To avoid going across the entire set of states multiple times, just check
156 * for enough space for the case of emitting all state, and inline the
157 * r200AllocCmdBuf code here without all the checks.
159 r200EnsureCmdBufSpace( rmesa
, rmesa
->hw
.max_state_size
);
161 /* we need to calculate dest after EnsureCmdBufSpace
162 as we may flush the buffer - airlied */
163 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
164 if (R200_DEBUG
& DEBUG_STATE
) {
165 foreach( atom
, &rmesa
->hw
.atomlist
) {
166 if ( atom
->dirty
|| rmesa
->hw
.all_dirty
) {
167 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) )
168 print_state_atom( atom
);
170 fprintf(stderr
, "skip state %s\n", atom
->name
);
175 foreach( atom
, &rmesa
->hw
.atomlist
) {
176 if ( rmesa
->hw
.all_dirty
)
177 atom
->dirty
= GL_TRUE
;
179 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
180 int size
= atom
->cmd_size
* 4;
181 memcpy( dest
, atom
->cmd
, size
);
183 rmesa
->store
.cmd_used
+= size
;
184 atom
->dirty
= GL_FALSE
;
189 assert( rmesa
->store
.cmd_used
<= R200_CMD_BUF_SZ
);
191 rmesa
->hw
.is_dirty
= GL_FALSE
;
192 rmesa
->hw
.all_dirty
= GL_FALSE
;
195 /* Fire a section of the retained (indexed_verts) buffer as a regular
198 void r200EmitVbufPrim( r200ContextPtr rmesa
,
202 drm_radeon_cmd_header_t
*cmd
;
204 assert(!(primitive
& R200_VF_PRIM_WALK_IND
));
206 r200EmitState( rmesa
);
208 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
209 fprintf(stderr
, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__
,
210 rmesa
->store
.cmd_used
/4, primitive
, vertex_nr
);
212 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VBUF_BUFSZ
,
215 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
216 cmd
[1].i
= R200_CP_CMD_3D_DRAW_VBUF_2
;
217 cmd
[2].i
= (primitive
|
218 R200_VF_PRIM_WALK_LIST
|
219 R200_VF_COLOR_ORDER_RGBA
|
220 (vertex_nr
<< R200_VF_VERTEX_NUMBER_SHIFT
));
224 void r200FlushElts( r200ContextPtr rmesa
)
226 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
228 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 12)) / 2;
230 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
231 fprintf(stderr
, "%s\n", __FUNCTION__
);
233 assert( rmesa
->dma
.flush
== r200FlushElts
);
234 rmesa
->dma
.flush
= NULL
;
236 /* Cope with odd number of elts:
238 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
239 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
241 cmd
[1] |= (dwords
- 3) << 16;
242 cmd
[2] |= nr
<< R200_VF_VERTEX_NUMBER_SHIFT
;
244 if (R200_DEBUG
& DEBUG_SYNC
) {
245 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
246 r200Finish( rmesa
->glCtx
);
251 GLushort
*r200AllocEltsOpenEnded( r200ContextPtr rmesa
,
255 drm_radeon_cmd_header_t
*cmd
;
258 if (R200_DEBUG
& DEBUG_IOCTL
)
259 fprintf(stderr
, "%s %d prim %x\n", __FUNCTION__
, min_nr
, primitive
);
261 assert((primitive
& R200_VF_PRIM_WALK_IND
));
263 r200EmitState( rmesa
);
265 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, ELTS_BUFSZ(min_nr
),
268 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
269 cmd
[1].i
= R200_CP_CMD_3D_DRAW_INDX_2
;
270 cmd
[2].i
= (primitive
|
271 R200_VF_PRIM_WALK_IND
|
272 R200_VF_COLOR_ORDER_RGBA
);
275 retval
= (GLushort
*)(cmd
+3);
277 if (R200_DEBUG
& DEBUG_PRIMS
)
278 fprintf(stderr
, "%s: header 0x%x prim %x \n",
280 cmd
[1].i
, primitive
);
282 assert(!rmesa
->dma
.flush
);
283 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
284 rmesa
->dma
.flush
= r200FlushElts
;
286 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
293 void r200EmitVertexAOS( r200ContextPtr rmesa
,
297 drm_radeon_cmd_header_t
*cmd
;
299 if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
300 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
301 __FUNCTION__
, vertex_size
, offset
);
303 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
306 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
307 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (2 << 16);
309 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
314 void r200EmitAOS( r200ContextPtr rmesa
,
315 struct r200_dma_region
**component
,
319 drm_radeon_cmd_header_t
*cmd
;
320 int sz
= AOS_BUFSZ(nr
);
324 if (R200_DEBUG
& DEBUG_IOCTL
)
325 fprintf(stderr
, "%s nr arrays: %d\n", __FUNCTION__
, nr
);
327 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sz
, __FUNCTION__
);
329 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
330 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int)) - 3) << 16);
335 for (i
= 0 ; i
< nr
; i
++) {
337 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
338 (component
[i
]->aos_size
<< 16));
339 cmd
[2].i
= (component
[i
]->aos_start
+
340 offset
* component
[i
]->aos_stride
* 4);
344 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
345 (component
[i
]->aos_size
<< 0));
346 cmd
[1].i
= (component
[i
]->aos_start
+
347 offset
* component
[i
]->aos_stride
* 4);
351 if (R200_DEBUG
& DEBUG_VERTS
) {
352 fprintf(stderr
, "%s:\n", __FUNCTION__
);
353 for (i
= 0 ; i
< sz
; i
++)
354 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
358 void r200EmitBlit( r200ContextPtr rmesa
,
364 GLint srcx
, GLint srcy
,
365 GLint dstx
, GLint dsty
,
368 drm_radeon_cmd_header_t
*cmd
;
370 if (R200_DEBUG
& DEBUG_IOCTL
)
371 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
373 src_pitch
, src_offset
, srcx
, srcy
,
374 dst_pitch
, dst_offset
, dstx
, dsty
,
377 assert( (src_pitch
& 63) == 0 );
378 assert( (dst_pitch
& 63) == 0 );
379 assert( (src_offset
& 1023) == 0 );
380 assert( (dst_offset
& 1023) == 0 );
381 assert( w
< (1<<16) );
382 assert( h
< (1<<16) );
384 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 8 * sizeof(int),
388 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
389 cmd
[1].i
= R200_CP_CMD_BITBLT_MULTI
| (5 << 16);
390 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
391 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
392 RADEON_GMC_BRUSH_NONE
|
394 RADEON_GMC_SRC_DATATYPE_COLOR
|
396 RADEON_DP_SRC_SOURCE_MEMORY
|
397 RADEON_GMC_CLR_CMP_CNTL_DIS
|
398 RADEON_GMC_WR_MSK_DIS
);
400 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
401 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
402 cmd
[5].i
= (srcx
<< 16) | srcy
;
403 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
404 cmd
[7].i
= (w
<< 16) | h
;
408 void r200EmitWait( r200ContextPtr rmesa
, GLuint flags
)
410 if (rmesa
->dri
.drmMinor
>= 6) {
411 drm_radeon_cmd_header_t
*cmd
;
413 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
415 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 1 * sizeof(int),
418 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
419 cmd
[0].wait
.flags
= flags
;