r200_cmdbuf.c revision 44dace86eaf9eded8e6465adfadf6345658686dd
1/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_cmdbuf.c,v 1.1 2002/10/30 12:51:51 alanh Exp $ */
2/*
3Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
4
5The Weather Channel (TM) funded Tungsten Graphics to develop the
6initial release of the Radeon 8500 driver under the XFree86 license.
7This notice must be preserved.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial
19portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27WITH 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
49static 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 */
64void 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   /* FIXME: is this a good place to insert that atom ? */
111   insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.spr );
112   insert_at_tail( &rmesa->hw.atomlist, &rmesa->hw.prf );
113}
114
115static void r200SaveHwState( r200ContextPtr rmesa )
116{
117   struct r200_state_atom *atom;
118   char * dest = rmesa->backup_store.cmd_buf;
119
120   if (R200_DEBUG & DEBUG_STATE)
121      fprintf(stderr, "%s\n", __FUNCTION__);
122
123   rmesa->backup_store.cmd_used = 0;
124
125   foreach( atom, &rmesa->hw.atomlist ) {
126      if ( atom->check( rmesa->glCtx, atom->idx ) ) {
127	 int size = atom->cmd_size * 4;
128	 memcpy( dest, atom->cmd, size);
129	 dest += size;
130	 rmesa->backup_store.cmd_used += size;
131	 if (R200_DEBUG & DEBUG_STATE)
132	    print_state_atom( atom );
133      }
134   }
135
136   assert( rmesa->backup_store.cmd_used <= R200_CMD_BUF_SZ );
137   if (R200_DEBUG & DEBUG_STATE)
138      fprintf(stderr, "Returning to r200EmitState\n");
139}
140
141void r200EmitState( r200ContextPtr rmesa )
142{
143   char *dest;
144   int mtu;
145   struct r200_state_atom *atom;
146
147   if (R200_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
148      fprintf(stderr, "%s\n", __FUNCTION__);
149
150   if (rmesa->save_on_next_emit) {
151      r200SaveHwState(rmesa);
152      rmesa->save_on_next_emit = GL_FALSE;
153   }
154
155   if (!rmesa->hw.is_dirty && !rmesa->hw.all_dirty)
156      return;
157
158   mtu = rmesa->glCtx->Const.MaxTextureUnits;
159
160   /* To avoid going across the entire set of states multiple times, just check
161    * for enough space for the case of emitting all state, and inline the
162    * r200AllocCmdBuf code here without all the checks.
163    */
164   r200EnsureCmdBufSpace( rmesa, rmesa->hw.max_state_size );
165
166   /* we need to calculate dest after EnsureCmdBufSpace
167      as we may flush the buffer - airlied */
168   dest = rmesa->store.cmd_buf + rmesa->store.cmd_used;
169   if (R200_DEBUG & DEBUG_STATE) {
170      foreach( atom, &rmesa->hw.atomlist ) {
171	 if ( atom->dirty || rmesa->hw.all_dirty ) {
172	    if ( atom->check( rmesa->glCtx, atom->idx ) )
173	       print_state_atom( atom );
174	    else
175	       fprintf(stderr, "skip state %s\n", atom->name);
176	 }
177      }
178   }
179
180   foreach( atom, &rmesa->hw.atomlist ) {
181      if ( rmesa->hw.all_dirty )
182	 atom->dirty = GL_TRUE;
183      if ( atom->dirty ) {
184	 if ( atom->check( rmesa->glCtx, atom->idx ) ) {
185	    int size = atom->cmd_size * 4;
186	    memcpy( dest, atom->cmd, size);
187	    dest += size;
188	    rmesa->store.cmd_used += size;
189	    atom->dirty = GL_FALSE;
190	 }
191      }
192   }
193
194   assert( rmesa->store.cmd_used <= R200_CMD_BUF_SZ );
195
196   rmesa->hw.is_dirty = GL_FALSE;
197   rmesa->hw.all_dirty = GL_FALSE;
198}
199
200/* Fire a section of the retained (indexed_verts) buffer as a regular
201 * primtive.
202 */
203void r200EmitVbufPrim( r200ContextPtr rmesa,
204                       GLuint primitive,
205                       GLuint vertex_nr )
206{
207   drm_radeon_cmd_header_t *cmd;
208
209   assert(!(primitive & R200_VF_PRIM_WALK_IND));
210
211   r200EmitState( rmesa );
212
213   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
214      fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
215	      rmesa->store.cmd_used/4, primitive, vertex_nr);
216
217   cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VBUF_BUFSZ,
218						  __FUNCTION__ );
219   cmd[0].i = 0;
220   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
221   cmd[1].i = R200_CP_CMD_3D_DRAW_VBUF_2;
222   cmd[2].i = (primitive |
223	       R200_VF_PRIM_WALK_LIST |
224	       R200_VF_COLOR_ORDER_RGBA |
225	       (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
226}
227
228
229void r200FlushElts( r200ContextPtr rmesa )
230{
231   int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
232   int dwords;
233   int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 12)) / 2;
234
235   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
236      fprintf(stderr, "%s\n", __FUNCTION__);
237
238   assert( rmesa->dma.flush == r200FlushElts );
239   rmesa->dma.flush = NULL;
240
241   /* Cope with odd number of elts:
242    */
243   rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
244   dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
245
246   cmd[1] |= (dwords - 3) << 16;
247   cmd[2] |= nr << R200_VF_VERTEX_NUMBER_SHIFT;
248
249   if (R200_DEBUG & DEBUG_SYNC) {
250      fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
251      r200Finish( rmesa->glCtx );
252   }
253}
254
255
256GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
257				    GLuint primitive,
258				    GLuint min_nr )
259{
260   drm_radeon_cmd_header_t *cmd;
261   GLushort *retval;
262
263   if (R200_DEBUG & DEBUG_IOCTL)
264      fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
265
266   assert((primitive & R200_VF_PRIM_WALK_IND));
267
268   r200EmitState( rmesa );
269
270   cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, ELTS_BUFSZ(min_nr),
271						__FUNCTION__ );
272   cmd[0].i = 0;
273   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
274   cmd[1].i = R200_CP_CMD_3D_DRAW_INDX_2;
275   cmd[2].i = (primitive |
276	       R200_VF_PRIM_WALK_IND |
277	       R200_VF_COLOR_ORDER_RGBA);
278
279
280   retval = (GLushort *)(cmd+3);
281
282   if (R200_DEBUG & DEBUG_PRIMS)
283      fprintf(stderr, "%s: header 0x%x prim %x \n",
284	      __FUNCTION__,
285	      cmd[1].i, primitive);
286
287   assert(!rmesa->dma.flush);
288   rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
289   rmesa->dma.flush = r200FlushElts;
290
291   rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
292
293   return retval;
294}
295
296
297
298void r200EmitVertexAOS( r200ContextPtr rmesa,
299			  GLuint vertex_size,
300			  GLuint offset )
301{
302   drm_radeon_cmd_header_t *cmd;
303
304   if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
305      fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
306	      __FUNCTION__, vertex_size, offset);
307
308   cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, VERT_AOS_BUFSZ,
309						  __FUNCTION__ );
310
311   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
312   cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (2 << 16);
313   cmd[2].i = 1;
314   cmd[3].i = vertex_size | (vertex_size << 8);
315   cmd[4].i = offset;
316}
317
318
319void r200EmitAOS( r200ContextPtr rmesa,
320		    struct r200_dma_region **component,
321		    GLuint nr,
322		    GLuint offset )
323{
324   drm_radeon_cmd_header_t *cmd;
325   int sz = AOS_BUFSZ(nr);
326   int i;
327   int *tmp;
328
329   if (R200_DEBUG & DEBUG_IOCTL)
330      fprintf(stderr, "%s nr arrays: %d\n", __FUNCTION__, nr);
331
332   cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, sz, __FUNCTION__ );
333   cmd[0].i = 0;
334   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
335   cmd[1].i = R200_CP_CMD_3D_LOAD_VBPNTR | (((sz / sizeof(int)) - 3) << 16);
336   cmd[2].i = nr;
337   tmp = &cmd[0].i;
338   cmd += 3;
339
340   for (i = 0 ; i < nr ; i++) {
341      if (i & 1) {
342	 cmd[0].i |= ((component[i]->aos_stride << 24) |
343		      (component[i]->aos_size << 16));
344	 cmd[2].i = (component[i]->aos_start +
345		     offset * component[i]->aos_stride * 4);
346	 cmd += 3;
347      }
348      else {
349	 cmd[0].i = ((component[i]->aos_stride << 8) |
350		     (component[i]->aos_size << 0));
351	 cmd[1].i = (component[i]->aos_start +
352		     offset * component[i]->aos_stride * 4);
353      }
354   }
355
356   if (R200_DEBUG & DEBUG_VERTS) {
357      fprintf(stderr, "%s:\n", __FUNCTION__);
358      for (i = 0 ; i < sz ; i++)
359	 fprintf(stderr, "   %d: %x\n", i, tmp[i]);
360   }
361}
362
363void r200EmitBlit( r200ContextPtr rmesa,
364		   GLuint color_fmt,
365		   GLuint src_pitch,
366		   GLuint src_offset,
367		   GLuint dst_pitch,
368		   GLuint dst_offset,
369		   GLint srcx, GLint srcy,
370		   GLint dstx, GLint dsty,
371		   GLuint w, GLuint h )
372{
373   drm_radeon_cmd_header_t *cmd;
374
375   if (R200_DEBUG & DEBUG_IOCTL)
376      fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
377	      __FUNCTION__,
378	      src_pitch, src_offset, srcx, srcy,
379	      dst_pitch, dst_offset, dstx, dsty,
380	      w, h);
381
382   assert( (src_pitch & 63) == 0 );
383   assert( (dst_pitch & 63) == 0 );
384   assert( (src_offset & 1023) == 0 );
385   assert( (dst_offset & 1023) == 0 );
386   assert( w < (1<<16) );
387   assert( h < (1<<16) );
388
389   cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 8 * sizeof(int),
390						  __FUNCTION__ );
391
392
393   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
394   cmd[1].i = R200_CP_CMD_BITBLT_MULTI | (5 << 16);
395   cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
396	       RADEON_GMC_DST_PITCH_OFFSET_CNTL |
397	       RADEON_GMC_BRUSH_NONE |
398	       (color_fmt << 8) |
399	       RADEON_GMC_SRC_DATATYPE_COLOR |
400	       RADEON_ROP3_S |
401	       RADEON_DP_SRC_SOURCE_MEMORY |
402	       RADEON_GMC_CLR_CMP_CNTL_DIS |
403	       RADEON_GMC_WR_MSK_DIS );
404
405   cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
406   cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
407   cmd[5].i = (srcx << 16) | srcy;
408   cmd[6].i = (dstx << 16) | dsty; /* dst */
409   cmd[7].i = (w << 16) | h;
410}
411
412
413void r200EmitWait( r200ContextPtr rmesa, GLuint flags )
414{
415   if (rmesa->dri.drmMinor >= 6) {
416      drm_radeon_cmd_header_t *cmd;
417
418      assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
419
420      cmd = (drm_radeon_cmd_header_t *)r200AllocCmdBuf( rmesa, 1 * sizeof(int),
421						   __FUNCTION__ );
422      cmd[0].i = 0;
423      cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
424      cmd[0].wait.flags = flags;
425   }
426}
427