OK, one more time. Simplify the state-backup system by just storing the full
[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 < 6; ++i)
96 insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.pix[i] );
97
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 }
109
110 static void r200SaveHwState( r200ContextPtr rmesa )
111 {
112 struct r200_state_atom *atom;
113 char * dest = rmesa->backup_store.cmd_buf;
114
115 rmesa->backup_store.cmd_used = 0;
116
117 foreach( atom, &rmesa->hw.atomlist ) {
118 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
119 int size = atom->cmd_size * 4;
120 memcpy( dest, atom->cmd, size);
121 dest += size;
122 rmesa->backup_store.cmd_used += size;
123 }
124 }
125
126 assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
127 }
128
129 void r200EmitState( r200ContextPtr rmesa )
130 {
131 char *dest;
132 int mtu;
133 struct r200_state_atom *atom;
134
135 if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
136 fprintf(stderr, "%s\n", __FUNCTION__);
137
138 if (rmesa->save_on_next_emit) {
139 r200SaveHwState(rmesa);
140 rmesa->save_on_next_emit = GL_FALSE;
141 }
142
143 if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
144 return;
145
146 mtu = rmesa->glCtx->Const.MaxTextureUnits;
147
148 /* To avoid going across the entire set of states multiple times, just check
149 * for enough space for the case of emitting all state, and inline the
150 * r200AllocCmdBuf code here without all the checks.
151 */
152 r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
153
154 /* we need to calculate dest after EnsureCmdBufSpace
155 as we may flush the buffer - airlied */
156 dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
157 if (R200_DEBUG & DEBUG_STATE) {
158 foreach( atom, &rmesa->hw.atomlist ) {
159 if ( atom->dirty || rmesa->hw.all_dirty ) {
160 if ( atom->check( rmesa->glCtx, atom->idx ) )
161 print_state_atom( atom );
162 else
163 fprintf(stderr, "skip state %s\n", atom->name);
164 }
165 }
166 }
167
168 foreach( atom, &rmesa->hw.atomlist ) {
169 if ( rmesa->hw.all_dirty )
170 atom->dirty = GL_TRUE;
171 if ( atom->dirty ) {
172 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
173 int size = atom->cmd_size * 4;
174 memcpy( dest, atom->cmd, size);
175 dest += size;
176 rmesa->store.cmd_used += size;
177 atom->dirty = GL_FALSE;
178 }
179 }
180 }
181
182 assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
183
184 rmesa->hw.is_dirty = GL_FALSE;
185 rmesa->hw.all_dirty = GL_FALSE;
186 }
187
188 /* Fire a section of the retained (indexed_verts) buffer as a regular
189 * primtive.
190 */
191 extern void r200EmitVbufPrim( r200ContextPtr rmesa,
192 GLuint primitive,
193 GLuint vertex_nr )
194 {
195 drm_radeon_cmd_header_t *cmd;
196
197 assert(!(primitive & R200_VF_PRIM_WALK_IND));
198
199 r200EmitState( rmesa );
200
201 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
202 fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
203 rmesa->store.cmd_used/4, primitive, vertex_nr);
204
205 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
206 __FUNCTION__ );
207 cmd[0].i = 0;
208 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
209 cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2;
210 cmd[2].i = (primitive |
211 R200_VF_PRIM_WALK_LIST |
212 R200_VF_COLOR_ORDER_RGBA |
213 (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
214 }
215
216
217 void r200FlushElts( r200ContextPtr rmesa )
218 {
219 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
220 int dwords;
221 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
222
223 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
224 fprintf(stderr, "%s\n", __FUNCTION__);
225
226 assert( rmesa->dma.flush == r200FlushElts );
227 rmesa->dma.flush = 0;
228
229 /* Cope with odd number of elts:
230 */
231 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
232 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
233
234 cmd[1] |= (dwords - 3) << 16;
235 cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
236
237 if (R200_DEBUG & DEBUG_SYNC) {
238 fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
239 r200Finish( rmesa->glCtx );
240 }
241 }
242
243
244 GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
245 GLuint primitive,
246 GLuint min_nr )
247 {
248 drm_radeon_cmd_header_t *cmd;
249 GLushort *retval;
250
251 if (R200_DEBUG & DEBUG_IOCTL)
252 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
253
254 assert((primitive & R200_VF_PRIM_WALK_IND));
255
256 r200EmitState( rmesa );
257
258 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
259 __FUNCTION__ );
260 cmd[0].i = 0;
261 cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
262 cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2;
263 cmd[2].i = (primitive |
264 R200_VF_PRIM_WALK_IND |
265 R200_VF_COLOR_ORDER_RGBA);
266
267
268 retval = (GLushort *)(cmd+3);
269
270 if (R200_DEBUG & DEBUG_PRIMS)
271 fprintf(stderr, "%s: header 0x%x prim %x \n",
272 __FUNCTION__,
273 cmd[1].i, primitive);
274
275 assert(!rmesa->dma.flush);
276 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
277 rmesa->dma.flush = r200FlushElts;
278
279 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
280
281 return retval;
282 }
283
284
285
286 void r200EmitVertexAOS( r200ContextPtr rmesa,
287 GLuint vertex_size,
288 GLuint offset )
289 {
290 drm_radeon_cmd_header_t *cmd;
291
292 if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
293 fprintf(stderr, "%s: vertex_size 0x%x offset 0x%x \n",
294 __FUNCTION__, vertex_size, offset);
295
296 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
297 __FUNCTION__ );
298
299 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
300 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
301 cmd[2].i = 1;
302 cmd[3].i = vertex_size | (vertex_size << 8);
303 cmd[4].i = offset;
304 }
305
306
307 void r200EmitAOS( r200ContextPtr rmesa,
308 struct r200_dma_region **component,
309 GLuint nr,
310 GLuint offset )
311 {
312 drm_radeon_cmd_header_t *cmd;
313 int sz = AOS_BUFSZ(nr);
314 int i;
315 int *tmp;
316
317 if (R200_DEBUG & DEBUG_IOCTL)
318 fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
319
320 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
321 cmd[0].i = 0;
322 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
323 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
324 cmd[2].i = nr;
325 tmp = &cmd[0].i;
326 cmd += 3;
327
328 for (i = 0 ; i < nr ; i++) {
329 if (i & 1) {
330 cmd[0].i |= ((component[i]->aos_stride << 24) |
331 (component[i]->aos_size << 16));
332 cmd[2].i = (component[i]->aos_start +
333 offset * component[i]->aos_stride * 4);
334 cmd += 3;
335 }
336 else {
337 cmd[0].i = ((component[i]->aos_stride << 8) |
338 (component[i]->aos_size << 0));
339 cmd[1].i = (component[i]->aos_start +
340 offset * component[i]->aos_stride * 4);
341 }
342 }
343
344 if (R200_DEBUG & DEBUG_VERTS) {
345 fprintf(stderr, "%s:\n", __FUNCTION__);
346 for (i = 0 ; i < sz ; i++)
347 fprintf(stderr, " %d: %x\n", i, tmp[i]);
348 }
349 }
350
351 void r200EmitBlit( r200ContextPtr rmesa,
352 GLuint color_fmt,
353 GLuint src_pitch,
354 GLuint src_offset,
355 GLuint dst_pitch,
356 GLuint dst_offset,
357 GLint srcx, GLint srcy,
358 GLint dstx, GLint dsty,
359 GLuint w, GLuint h )
360 {
361 drm_radeon_cmd_header_t *cmd;
362
363 if (R200_DEBUG & DEBUG_IOCTL)
364 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
365 __FUNCTION__,
366 src_pitch, src_offset, srcx, srcy,
367 dst_pitch, dst_offset, dstx, dsty,
368 w, h);
369
370 assert( (src_pitch & 63) == 0 );
371 assert( (dst_pitch & 63) == 0 );
372 assert( (src_offset & 1023) == 0 );
373 assert( (dst_offset & 1023) == 0 );
374 assert( w < (1<<16) );
375 assert( h < (1<<16) );
376
377 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
378 __FUNCTION__ );
379
380
381 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
382 cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
383 cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
384 RADEON_GMC_DST_PITCH_OFFSET_CNTL |
385 RADEON_GMC_BRUSH_NONE |
386 (color_fmt << 8) |
387 RADEON_GMC_SRC_DATATYPE_COLOR |
388 RADEON_ROP3_S |
389 RADEON_DP_SRC_SOURCE_MEMORY |
390 RADEON_GMC_CLR_CMP_CNTL_DIS |
391 RADEON_GMC_WR_MSK_DIS );
392
393 cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
394 cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
395 cmd[5].i = (srcx << 16) | srcy;
396 cmd[6].i = (dstx << 16) | dsty; /* dst */
397 cmd[7].i = (w << 16) | h;
398 }
399
400
401 void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
402 {
403 if (rmesa->dri.drmMinor >= 6) {
404 drm_radeon_cmd_header_t *cmd;
405
406 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
407
408 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
409 __FUNCTION__ );
410 cmd[0].i = 0;
411 cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
412 cmd[0].wait.flags = flags;
413 }
414 }