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
< 3 + mtu
; ++i
)
96 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.mat
[i
] );
97 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.eye
);
98 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.glt
);
99 for (i
= 0; i
< 2; ++i
)
100 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.mtl
[i
] );
101 for (i
= 0; i
< 8; ++i
)
102 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.lit
[i
] );
103 for (i
= 0; i
< 6; ++i
)
104 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.ucp
[i
] );
105 for (i
= 0; i
< 6; ++i
)
106 insert_at_tail( &rmesa
->hw
.atomlist
, &rmesa
->hw
.pix
[i
] );
109 void r200EmitState( r200ContextPtr rmesa
)
113 struct r200_state_atom
*atom
;
115 if (R200_DEBUG
& (DEBUG_STATE
|DEBUG_PRIMS
))
116 fprintf(stderr
, "%s\n", __FUNCTION__
);
118 if (!rmesa
->hw
.is_dirty
&& !rmesa
->hw
.all_dirty
)
121 mtu
= rmesa
->glCtx
->Const
.MaxTextureUnits
;
123 /* To avoid going across the entire set of states multiple times, just check
124 * for enough space for the case of emitting all state, and inline the
125 * r200AllocCmdBuf code here without all the checks.
127 r200EnsureCmdBufSpace( rmesa
, rmesa
->hw
.max_state_size
);
129 /* we need to calculate dest after EnsureCmdBufSpace
130 as we may flush the buffer - airlied */
131 dest
= rmesa
->store
.cmd_buf
+ rmesa
->store
.cmd_used
;
132 if (R200_DEBUG
& DEBUG_STATE
) {
133 foreach( atom
, &rmesa
->hw
.atomlist
) {
134 if ( atom
->dirty
|| rmesa
->hw
.all_dirty
) {
135 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) )
136 print_state_atom( atom
);
138 fprintf(stderr
, "skip state %s\n", atom
->name
);
143 foreach( atom
, &rmesa
->hw
.atomlist
) {
144 if ( rmesa
->hw
.all_dirty
)
145 atom
->dirty
= GL_TRUE
;
147 if ( atom
->check( rmesa
->glCtx
, atom
->idx
) ) {
148 int size
= atom
->cmd_size
* 4;
149 memcpy( dest
, atom
->cmd
, size
);
151 rmesa
->store
.cmd_used
+= size
;
152 atom
->dirty
= GL_FALSE
;
157 assert( rmesa
->store
.cmd_used
<= R200_CMD_BUF_SZ
);
159 rmesa
->hw
.is_dirty
= GL_FALSE
;
160 rmesa
->hw
.all_dirty
= GL_FALSE
;
163 /* Fire a section of the retained (indexed_verts) buffer as a regular
166 extern void r200EmitVbufPrim( r200ContextPtr rmesa
,
170 drm_radeon_cmd_header_t
*cmd
;
172 assert(!(primitive
& R200_VF_PRIM_WALK_IND
));
174 r200EmitState( rmesa
);
176 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
177 fprintf(stderr
, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__
,
178 rmesa
->store
.cmd_used
/4, primitive
, vertex_nr
);
180 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VBUF_BUFSZ
,
183 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
184 cmd
[1].i
= R200_CP_CMD_3D_DRAW_VBUF_2
;
185 cmd
[2].i
= (primitive
|
186 R200_VF_PRIM_WALK_LIST
|
187 R200_VF_COLOR_ORDER_RGBA
|
188 (vertex_nr
<< R200_VF_VERTEX_NUMBER_SHIFT
));
192 void r200FlushElts( r200ContextPtr rmesa
)
194 int *cmd
= (int *)(rmesa
->store
.cmd_buf
+ rmesa
->store
.elts_start
);
196 int nr
= (rmesa
->store
.cmd_used
- (rmesa
->store
.elts_start
+ 12)) / 2;
198 if (R200_DEBUG
& (DEBUG_IOCTL
|DEBUG_PRIMS
))
199 fprintf(stderr
, "%s\n", __FUNCTION__
);
201 assert( rmesa
->dma
.flush
== r200FlushElts
);
202 rmesa
->dma
.flush
= 0;
204 /* Cope with odd number of elts:
206 rmesa
->store
.cmd_used
= (rmesa
->store
.cmd_used
+ 2) & ~2;
207 dwords
= (rmesa
->store
.cmd_used
- rmesa
->store
.elts_start
) / 4;
209 cmd
[1] |= (dwords
- 3) << 16;
210 cmd
[2] |= nr
<< R200_VF_VERTEX_NUMBER_SHIFT
;
212 if (R200_DEBUG
& DEBUG_SYNC
) {
213 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
214 r200Finish( rmesa
->glCtx
);
219 GLushort
*r200AllocEltsOpenEnded( r200ContextPtr rmesa
,
223 drm_radeon_cmd_header_t
*cmd
;
226 if (R200_DEBUG
& DEBUG_IOCTL
)
227 fprintf(stderr
, "%s %d prim %x\n", __FUNCTION__
, min_nr
, primitive
);
229 assert((primitive
& R200_VF_PRIM_WALK_IND
));
231 r200EmitState( rmesa
);
233 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, ELTS_BUFSZ(min_nr
),
236 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3_CLIP
;
237 cmd
[1].i
= R200_CP_CMD_3D_DRAW_INDX_2
;
238 cmd
[2].i
= (primitive
|
239 R200_VF_PRIM_WALK_IND
|
240 R200_VF_COLOR_ORDER_RGBA
);
243 retval
= (GLushort
*)(cmd
+3);
245 if (R200_DEBUG
& DEBUG_PRIMS
)
246 fprintf(stderr
, "%s: header 0x%x prim %x \n",
248 cmd
[1].i
, primitive
);
250 assert(!rmesa
->dma
.flush
);
251 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
252 rmesa
->dma
.flush
= r200FlushElts
;
254 rmesa
->store
.elts_start
= ((char *)cmd
) - rmesa
->store
.cmd_buf
;
261 void r200EmitVertexAOS( r200ContextPtr rmesa
,
265 drm_radeon_cmd_header_t
*cmd
;
267 if (R200_DEBUG
& (DEBUG_PRIMS
|DEBUG_IOCTL
))
268 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
269 __FUNCTION__
, vertex_size
, offset
);
271 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, VERT_AOS_BUFSZ
,
274 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
275 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (2 << 16);
277 cmd
[3].i
= vertex_size
| (vertex_size
<< 8);
282 void r200EmitAOS( r200ContextPtr rmesa
,
283 struct r200_dma_region
**component
,
287 drm_radeon_cmd_header_t
*cmd
;
288 int sz
= AOS_BUFSZ(nr
);
292 if (R200_DEBUG
& DEBUG_IOCTL
)
293 fprintf(stderr
, "%s nr arrays: %d\n", __FUNCTION__
, nr
);
295 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, sz
, __FUNCTION__
);
297 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
298 cmd
[1].i
= R200_CP_CMD_3D_LOAD_VBPNTR
| (((sz
/ sizeof(int)) - 3) << 16);
303 for (i
= 0 ; i
< nr
; i
++) {
305 cmd
[0].i
|= ((component
[i
]->aos_stride
<< 24) |
306 (component
[i
]->aos_size
<< 16));
307 cmd
[2].i
= (component
[i
]->aos_start
+
308 offset
* component
[i
]->aos_stride
* 4);
312 cmd
[0].i
= ((component
[i
]->aos_stride
<< 8) |
313 (component
[i
]->aos_size
<< 0));
314 cmd
[1].i
= (component
[i
]->aos_start
+
315 offset
* component
[i
]->aos_stride
* 4);
319 if (R200_DEBUG
& DEBUG_VERTS
) {
320 fprintf(stderr
, "%s:\n", __FUNCTION__
);
321 for (i
= 0 ; i
< sz
; i
++)
322 fprintf(stderr
, " %d: %x\n", i
, tmp
[i
]);
326 void r200EmitBlit( r200ContextPtr rmesa
,
332 GLint srcx
, GLint srcy
,
333 GLint dstx
, GLint dsty
,
336 drm_radeon_cmd_header_t
*cmd
;
338 if (R200_DEBUG
& DEBUG_IOCTL
)
339 fprintf(stderr
, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
341 src_pitch
, src_offset
, srcx
, srcy
,
342 dst_pitch
, dst_offset
, dstx
, dsty
,
345 assert( (src_pitch
& 63) == 0 );
346 assert( (dst_pitch
& 63) == 0 );
347 assert( (src_offset
& 1023) == 0 );
348 assert( (dst_offset
& 1023) == 0 );
349 assert( w
< (1<<16) );
350 assert( h
< (1<<16) );
352 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 8 * sizeof(int),
356 cmd
[0].header
.cmd_type
= RADEON_CMD_PACKET3
;
357 cmd
[1].i
= R200_CP_CMD_BITBLT_MULTI
| (5 << 16);
358 cmd
[2].i
= (RADEON_GMC_SRC_PITCH_OFFSET_CNTL
|
359 RADEON_GMC_DST_PITCH_OFFSET_CNTL
|
360 RADEON_GMC_BRUSH_NONE
|
362 RADEON_GMC_SRC_DATATYPE_COLOR
|
364 RADEON_DP_SRC_SOURCE_MEMORY
|
365 RADEON_GMC_CLR_CMP_CNTL_DIS
|
366 RADEON_GMC_WR_MSK_DIS
);
368 cmd
[3].i
= ((src_pitch
/64)<<22) | (src_offset
>> 10);
369 cmd
[4].i
= ((dst_pitch
/64)<<22) | (dst_offset
>> 10);
370 cmd
[5].i
= (srcx
<< 16) | srcy
;
371 cmd
[6].i
= (dstx
<< 16) | dsty
; /* dst */
372 cmd
[7].i
= (w
<< 16) | h
;
376 void r200EmitWait( r200ContextPtr rmesa
, GLuint flags
)
378 if (rmesa
->dri
.drmMinor
>= 6) {
379 drm_radeon_cmd_header_t
*cmd
;
381 assert( !(flags
& ~(RADEON_WAIT_2D
|RADEON_WAIT_3D
)) );
383 cmd
= (drm_radeon_cmd_header_t
*)r200AllocCmdBuf( rmesa
, 1 * sizeof(int),
386 cmd
[0].wait
.cmd_type
= RADEON_CMD_WAIT
;
387 cmd
[0].wait
.flags
= flags
;