384c1634ea0fd7834d2242fb9fba7d70df7a4a3b
[mesa.git] / src / mesa / drivers / dri / r200 / r200_cmdbuf.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_cmdbuf.c,v 1.1 2002/10/30 12:51:51 alanh Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
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.
8
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:
16
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.
20
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.
28 */
29
30 /*
31 * Authors:
32 * Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35 #include "glheader.h"
36 #include "imports.h"
37 #include "macros.h"
38 #include "context.h"
39 #include "swrast/swrast.h"
40 #include "simple_list.h"
41
42 #include "r200_context.h"
43 #include "r200_state.h"
44 #include "r200_ioctl.h"
45 #include "r200_tcl.h"
46 #include "r200_sanity.h"
47 #include "radeon_reg.h"
48
49 static void print_state_atom( struct r200_state_atom *state )
50 {
51 int i;
52
53 fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
54
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]);
58
59 }
60
61 /* The state atoms will be emitted in the order they appear in the atom list,
62 * so this step is important.
63 */
64 void r200SetUpAtomList( r200ContextPtr rmesa )
65 {
66 int i, mtu;
67
68 mtu = rmesa->glCtx->Const.MaxTextureUnits;
69
70 make_empty_list(&rmesa->hw.atomlist);
71 rmesa->hw.atomlist.name = "atom-list";
72
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] );
107 }
108
109 void r200EmitState( r200ContextPtr rmesa )
110 {
111 char *dest;
112 int mtu;
113 struct r200_state_atom *atom;
114
115 if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
116 fprintf(stderr, "%s\n", __FUNCTION__);
117
118 if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
119 return;
120
121 mtu = rmesa->glCtx->Const.MaxTextureUnits;
122
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.
126 */
127 r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
128
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 );
137 else
138 fprintf(stderr, "skip state %s\n", atom->name);
139 }
140 }
141 }
142
143 foreach( atom, &rmesa->hw.atomlist ) {
144 if ( rmesa->hw.all_dirty )
145 atom->dirty = GL_TRUE;
146 if ( atom->dirty ) {
147 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
148 int size = atom->cmd_size * 4;
149 memcpy( dest, atom->cmd, size);
150 dest += size;
151 rmesa->store.cmd_used += size;
152 atom->dirty = GL_FALSE;
153 }
154 }
155 }
156
157 assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
158
159 rmesa->hw.is_dirty = GL_FALSE;
160 rmesa->hw.all_dirty = GL_FALSE;
161 }
162
163 /* Fire a section of the retained (indexed_verts) buffer as a regular
164 * primtive.
165 */
166 extern void r200EmitVbufPrim( r200ContextPtr rmesa,
167 GLuint primitive,
168 GLuint vertex_nr )
169 {
170 drm_radeon_cmd_header_t *cmd;
171
172 assert(!(primitive & R200_VF_PRIM_WALK_IND));
173
174 r200EmitState( rmesa );
175
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);
179
180 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
181 __FUNCTION__ );
182 cmd[0].i = 0;
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));
189 }
190
191
192 void r200FlushElts( r200ContextPtr rmesa )
193 {
194 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
195 int dwords;
196 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
197
198 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
199 fprintf(stderr, "%s\n", __FUNCTION__);
200
201 assert( rmesa->dma.flush == r200FlushElts );
202 rmesa->dma.flush = 0;
203
204 /* Cope with odd number of elts:
205 */
206 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
207 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
208
209 cmd[1] |= (dwords - 3) << 16;
210 cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
211
212 if (R200_DEBUG & DEBUG_SYNC) {
213 fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
214 r200Finish( rmesa->glCtx );
215 }
216 }
217
218
219 GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
220 GLuint primitive,
221 GLuint min_nr )
222 {
223 drm_radeon_cmd_header_t *cmd;
224 GLushort *retval;
225
226 if (R200_DEBUG & DEBUG_IOCTL)
227 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
228
229 assert((primitive & R200_VF_PRIM_WALK_IND));
230
231 r200EmitState( rmesa );
232
233 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
234 __FUNCTION__ );
235 cmd[0].i = 0;
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);
241
242
243 retval = (GLushort *)(cmd+3);
244
245 if (R200_DEBUG & DEBUG_PRIMS)
246 fprintf(stderr, "%s: header 0x%x prim %x \n",
247 __FUNCTION__,
248 cmd[1].i, primitive);
249
250 assert(!rmesa->dma.flush);
251 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
252 rmesa->dma.flush = r200FlushElts;
253
254 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
255
256 return retval;
257 }
258
259
260
261 void r200EmitVertexAOS( r200ContextPtr rmesa,
262 GLuint vertex_size,
263 GLuint offset )
264 {
265 drm_radeon_cmd_header_t *cmd;
266
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);
270
271 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
272 __FUNCTION__ );
273
274 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
275 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
276 cmd[2].i = 1;
277 cmd[3].i = vertex_size | (vertex_size << 8);
278 cmd[4].i = offset;
279 }
280
281
282 void r200EmitAOS( r200ContextPtr rmesa,
283 struct r200_dma_region **component,
284 GLuint nr,
285 GLuint offset )
286 {
287 drm_radeon_cmd_header_t *cmd;
288 int sz = AOS_BUFSZ(nr);
289 int i;
290 int *tmp;
291
292 if (R200_DEBUG & DEBUG_IOCTL)
293 fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
294
295 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
296 cmd[0].i = 0;
297 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
298 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
299 cmd[2].i = nr;
300 tmp = &cmd[0].i;
301 cmd += 3;
302
303 for (i = 0 ; i < nr ; i++) {
304 if (i & 1) {
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);
309 cmd += 3;
310 }
311 else {
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);
316 }
317 }
318
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]);
323 }
324 }
325
326 void r200EmitBlit( r200ContextPtr rmesa,
327 GLuint color_fmt,
328 GLuint src_pitch,
329 GLuint src_offset,
330 GLuint dst_pitch,
331 GLuint dst_offset,
332 GLint srcx, GLint srcy,
333 GLint dstx, GLint dsty,
334 GLuint w, GLuint h )
335 {
336 drm_radeon_cmd_header_t *cmd;
337
338 if (R200_DEBUG & DEBUG_IOCTL)
339 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
340 __FUNCTION__,
341 src_pitch, src_offset, srcx, srcy,
342 dst_pitch, dst_offset, dstx, dsty,
343 w, h);
344
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) );
351
352 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
353 __FUNCTION__ );
354
355
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 |
361 (color_fmt << 8) |
362 RADEON_GMC_SRC_DATATYPE_COLOR |
363 RADEON_ROP3_S |
364 RADEON_DP_SRC_SOURCE_MEMORY |
365 RADEON_GMC_CLR_CMP_CNTL_DIS |
366 RADEON_GMC_WR_MSK_DIS );
367
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;
373 }
374
375
376 void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
377 {
378 if (rmesa->dri.drmMinor >= 6) {
379 drm_radeon_cmd_header_t *cmd;
380
381 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
382
383 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
384 __FUNCTION__ );
385 cmd[0].i = 0;
386 cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
387 cmd[0].wait.flags = flags;
388 }
389 }