Fix a refcounting mistake with first_swap_fence.
[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 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] );
118 }
119
120 static void r200SaveHwState( r200ContextPtr rmesa )
121 {
122 struct r200_state_atom *atom;
123 char * dest = rmesa->backup_store.cmd_buf;
124
125 if (R200_DEBUG & DEBUG_STATE)
126 fprintf(stderr, "%s\n", __FUNCTION__);
127
128 rmesa->backup_store.cmd_used = 0;
129
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);
134 dest += size;
135 rmesa->backup_store.cmd_used += size;
136 if (R200_DEBUG & DEBUG_STATE)
137 print_state_atom( atom );
138 }
139 }
140
141 assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
142 if (R200_DEBUG & DEBUG_STATE)
143 fprintf(stderr, "Returning to r200EmitState\n");
144 }
145
146 void r200EmitState( r200ContextPtr rmesa )
147 {
148 char *dest;
149 int mtu;
150 struct r200_state_atom *atom;
151
152 if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
153 fprintf(stderr, "%s\n", __FUNCTION__);
154
155 if (rmesa->save_on_next_emit) {
156 r200SaveHwState(rmesa);
157 rmesa->save_on_next_emit = GL_FALSE;
158 }
159
160 if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
161 return;
162
163 mtu = rmesa->glCtx->Const.MaxTextureUnits;
164
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.
168 */
169 r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
170
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 );
179 else
180 fprintf(stderr, "skip state %s\n", atom->name);
181 }
182 }
183 }
184
185 foreach( atom, &rmesa->hw.atomlist ) {
186 if ( rmesa->hw.all_dirty )
187 atom->dirty = GL_TRUE;
188 if ( atom->dirty ) {
189 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
190 int size = atom->cmd_size * 4;
191 memcpy( dest, atom->cmd, size);
192 dest += size;
193 rmesa->store.cmd_used += size;
194 atom->dirty = GL_FALSE;
195 }
196 }
197 }
198
199 assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
200
201 rmesa->hw.is_dirty = GL_FALSE;
202 rmesa->hw.all_dirty = GL_FALSE;
203 }
204
205 /* Fire a section of the retained (indexed_verts) buffer as a regular
206 * primtive.
207 */
208 void r200EmitVbufPrim( r200ContextPtr rmesa,
209 GLuint primitive,
210 GLuint vertex_nr )
211 {
212 drm_radeon_cmd_header_t *cmd;
213
214 assert(!(primitive & R200_VF_PRIM_WALK_IND));
215
216 r200EmitState( rmesa );
217
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);
221
222 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
223 __FUNCTION__ );
224 cmd[0].i = 0;
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));
231 }
232
233
234 void r200FlushElts( r200ContextPtr rmesa )
235 {
236 int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
237 int dwords;
238 int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
239
240 if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
241 fprintf(stderr, "%s\n", __FUNCTION__);
242
243 assert( rmesa->dma.flush == r200FlushElts );
244 rmesa->dma.flush = NULL;
245
246 /* Cope with odd number of elts:
247 */
248 rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
249 dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
250
251 cmd[1] |= (dwords - 3) << 16;
252 cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
253
254 if (R200_DEBUG & DEBUG_SYNC) {
255 fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
256 r200Finish( rmesa->glCtx );
257 }
258 }
259
260
261 GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
262 GLuint primitive,
263 GLuint min_nr )
264 {
265 drm_radeon_cmd_header_t *cmd;
266 GLushort *retval;
267
268 if (R200_DEBUG & DEBUG_IOCTL)
269 fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
270
271 assert((primitive & R200_VF_PRIM_WALK_IND));
272
273 r200EmitState( rmesa );
274
275 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
276 __FUNCTION__ );
277 cmd[0].i = 0;
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);
283
284
285 retval = (GLushort *)(cmd+3);
286
287 if (R200_DEBUG & DEBUG_PRIMS)
288 fprintf(stderr, "%s: header 0x%x prim %x \n",
289 __FUNCTION__,
290 cmd[1].i, primitive);
291
292 assert(!rmesa->dma.flush);
293 rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
294 rmesa->dma.flush = r200FlushElts;
295
296 rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
297
298 return retval;
299 }
300
301
302
303 void r200EmitVertexAOS( r200ContextPtr rmesa,
304 GLuint vertex_size,
305 GLuint offset )
306 {
307 drm_radeon_cmd_header_t *cmd;
308
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);
312
313 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
314 __FUNCTION__ );
315
316 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
317 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
318 cmd[2].i = 1;
319 cmd[3].i = vertex_size | (vertex_size << 8);
320 cmd[4].i = offset;
321 }
322
323
324 void r200EmitAOS( r200ContextPtr rmesa,
325 struct r200_dma_region **component,
326 GLuint nr,
327 GLuint offset )
328 {
329 drm_radeon_cmd_header_t *cmd;
330 int sz = AOS_BUFSZ(nr);
331 int i;
332 int *tmp;
333
334 if (R200_DEBUG & DEBUG_IOCTL)
335 fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
336
337 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
338 cmd[0].i = 0;
339 cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
340 cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
341 cmd[2].i = nr;
342 tmp = &cmd[0].i;
343 cmd += 3;
344
345 for (i = 0 ; i < nr ; i++) {
346 if (i & 1) {
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);
351 cmd += 3;
352 }
353 else {
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);
358 }
359 }
360
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]);
365 }
366 }
367
368 void r200EmitBlit( r200ContextPtr rmesa,
369 GLuint color_fmt,
370 GLuint src_pitch,
371 GLuint src_offset,
372 GLuint dst_pitch,
373 GLuint dst_offset,
374 GLint srcx, GLint srcy,
375 GLint dstx, GLint dsty,
376 GLuint w, GLuint h )
377 {
378 drm_radeon_cmd_header_t *cmd;
379
380 if (R200_DEBUG & DEBUG_IOCTL)
381 fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
382 __FUNCTION__,
383 src_pitch, src_offset, srcx, srcy,
384 dst_pitch, dst_offset, dstx, dsty,
385 w, h);
386
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) );
393
394 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
395 __FUNCTION__ );
396
397
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 |
403 (color_fmt << 8) |
404 RADEON_GMC_SRC_DATATYPE_COLOR |
405 RADEON_ROP3_S |
406 RADEON_DP_SRC_SOURCE_MEMORY |
407 RADEON_GMC_CLR_CMP_CNTL_DIS |
408 RADEON_GMC_WR_MSK_DIS );
409
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;
415 }
416
417
418 void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
419 {
420 drm_radeon_cmd_header_t *cmd;
421
422 assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
423
424 cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
425 __FUNCTION__ );
426 cmd[0].i = 0;
427 cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
428 cmd[0].wait.flags = flags;
429 }