r200_cmdbuf.c revision 1090d206de011a67d236d8c4ae32d2d42b2f6337
1/*
2Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4The Weather Channel (TM) funded Tungsten Graphics to develop the
5initial release of the Radeon 8500 driver under the XFree86 license.
6This notice must be preserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27*/
28
29/*
30 * Authors:
31 *   Keith Whitwell <keith@tungstengraphics.com>
32 */
33
34#include "main/glheader.h"
35#include "main/imports.h"
36#include "main/macros.h"
37#include "main/context.h"
38#include "swrast/swrast.h"
39#include "main/simple_list.h"
40
41#include "radeon_cs.h"
42#include "r200_context.h"
43#include "common_cmdbuf.h"
44#include "r200_state.h"
45#include "r200_ioctl.h"
46#include "r200_tcl.h"
47#include "r200_sanity.h"
48#include "radeon_reg.h"
49
50/* The state atoms will be emitted in the order they appear in the atom list,
51 * so this step is important.
52 */
53void r200SetUpAtomList( r200ContextPtr rmesa )
54{
55   int i, mtu;
56
57   mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
58
59   make_empty_list(&rmesa->radeon.hw.atomlist);
60   rmesa->radeon.hw.atomlist.name = "atom-list";
61
62   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.ctx );
63   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.set );
64   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.lin );
65   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.msk );
66   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpt );
67   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vtx );
68   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vap );
69   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vte );
70   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.msc );
71   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.cst );
72   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.zbs );
73   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcl );
74   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.msl );
75   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcg );
76   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.grd );
77   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.fog );
78   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tam );
79   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tf );
80   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.atf );
81   for (i = 0; i < mtu; ++i)
82       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i] );
83   for (i = 0; i < mtu; ++i)
84       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i] );
85   for (i = 0; i < 6; ++i)
86       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] );
87   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] );
88   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] );
89   for (i = 0; i < 8; ++i)
90       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] );
91   for (i = 0; i < 3 + mtu; ++i)
92       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i] );
93   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.eye );
94   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.glt );
95   for (i = 0; i < 2; ++i)
96      insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.mtl[i] );
97   for (i = 0; i < 6; ++i)
98       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i] );
99   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.spr );
100   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.ptp );
101   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.prf );
102   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.pvs );
103   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[0] );
104   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[1] );
105   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[0] );
106   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[1] );
107}
108
109/* Fire a section of the retained (indexed_verts) buffer as a regular
110 * primtive.
111 */
112void r200EmitVbufPrim( r200ContextPtr rmesa,
113                       GLuint primitive,
114                       GLuint vertex_nr )
115{
116   drm_radeon_cmd_header_t *cmd;
117   BATCH_LOCALS(&rmesa->radeon);
118
119   assert(!(primitive & R200_VF_PRIM_WALK_IND));
120
121   radeonEmitState(&rmesa->radeon);
122
123   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
124      fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
125	      rmesa->store.cmd_used/4, primitive, vertex_nr);
126
127   BEGIN_BATCH(3);
128   OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_VBUF_2, 0);
129   OUT_BATCH(primitive | R200_VF_PRIM_WALK_LIST | R200_VF_COLOR_ORDER_RGBA |
130	     (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
131   END_BATCH();
132}
133
134static void r200FireEB(r200ContextPtr rmesa, int vertex_count, int type)
135{
136	BATCH_LOCALS(&rmesa->radeon);
137
138	if (vertex_count > 0) {
139		BEGIN_BATCH(8);
140		OUT_BATCH_PACKET3(R200_CP_CMD_3D_DRAW_INDX_2, 0);
141		OUT_BATCH(R200_VF_PRIM_WALK_IND |
142			  ((vertex_count + 0) << 16) |
143			  type);
144
145		if (!rmesa->radeon.radeonScreen->kernel_mm) {
146			OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
147			OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
148			OUT_BATCH_RELOC(rmesa->tcl.elt_dma_offset,
149					rmesa->tcl.elt_dma_bo,
150					rmesa->tcl.elt_dma_offset,
151					RADEON_GEM_DOMAIN_GTT, 0, 0);
152			OUT_BATCH(vertex_count/2);
153		} else {
154			OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
155			OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
156			OUT_BATCH(rmesa->tcl.elt_dma_offset);
157			OUT_BATCH(vertex_count/2);
158			radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
159					      rmesa->tcl.elt_dma_bo,
160					      RADEON_GEM_DOMAIN_GTT, 0, 0);
161		}
162		END_BATCH();
163	}
164}
165
166void r200FlushElts(GLcontext *ctx)
167{
168  r200ContextPtr rmesa = R200_CONTEXT(ctx);
169   int dwords;
170   int nr, elt_used = rmesa->tcl.elt_used;
171
172   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
173     fprintf(stderr, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used);
174
175   assert( rmesa->radeon.dma.flush == r200FlushElts );
176   rmesa->radeon.dma.flush = NULL;
177
178   elt_used = (elt_used + 2) & ~2;
179
180   nr = elt_used / 2;
181
182   radeon_bo_unmap(rmesa->tcl.elt_dma_bo);
183
184   r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive);
185
186   radeon_bo_unref(rmesa->tcl.elt_dma_bo);
187   rmesa->tcl.elt_dma_bo = NULL;
188
189   if (R200_DEBUG & DEBUG_SYNC) {
190      fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
191      r200Finish( rmesa->radeon.glCtx );
192   }
193}
194
195
196GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
197				    GLuint primitive,
198				    GLuint min_nr )
199{
200   GLushort *retval;
201
202   if (R200_DEBUG & DEBUG_IOCTL)
203      fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
204
205   assert((primitive & R200_VF_PRIM_WALK_IND));
206
207   radeonEmitState(&rmesa->radeon);
208
209   rmesa->tcl.elt_dma_bo = radeon_bo_open(rmesa->radeon.radeonScreen->bom,
210					  0, R200_ELT_BUF_SZ, 4,
211					  RADEON_GEM_DOMAIN_GTT, 0);
212   rmesa->tcl.elt_dma_offset = 0;
213   rmesa->tcl.elt_used = min_nr * 2;
214
215   radeon_bo_map(rmesa->tcl.elt_dma_bo, 1);
216   retval = rmesa->tcl.elt_dma_bo->ptr + rmesa->tcl.elt_dma_offset;
217
218
219   if (R200_DEBUG & DEBUG_PRIMS)
220      fprintf(stderr, "%s: header prim %x \n",
221	      __FUNCTION__, primitive);
222
223   assert(!rmesa->radeon.dma.flush);
224   rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
225   rmesa->radeon.dma.flush = r200FlushElts;
226
227   return retval;
228}
229
230
231
232void r200EmitVertexAOS( r200ContextPtr rmesa,
233			GLuint vertex_size,
234 			struct radeon_bo *bo,
235			GLuint offset )
236{
237   BATCH_LOCALS(&rmesa->radeon);
238
239   if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
240      fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
241	      __FUNCTION__, vertex_size, offset);
242
243
244   BEGIN_BATCH(5);
245   OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, 2);
246   OUT_BATCH(1);
247   OUT_BATCH(vertex_size | (vertex_size << 8));
248   OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
249   END_BATCH();
250}
251
252void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset)
253{
254   BATCH_LOCALS(&rmesa->radeon);
255   uint32_t voffset;
256   int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
257   int i;
258
259   if (RADEON_DEBUG & DEBUG_VERTS)
260      fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
261	      offset);
262
263   BEGIN_BATCH(sz+2);
264   OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, sz - 1);
265   OUT_BATCH(nr);
266
267
268   if (!rmesa->radeon.radeonScreen->kernel_mm) {
269      for (i = 0; i + 1 < nr; i += 2) {
270	 OUT_BATCH((rmesa->tcl.aos[i].components << 0) |
271		   (rmesa->tcl.aos[i].stride << 8) |
272		   (rmesa->tcl.aos[i + 1].components << 16) |
273		   (rmesa->tcl.aos[i + 1].stride << 24));
274
275	 voffset =  rmesa->tcl.aos[i + 0].offset +
276	    offset * 4 * rmesa->tcl.aos[i + 0].stride;
277	 OUT_BATCH_RELOC(voffset,
278			 rmesa->tcl.aos[i].bo,
279			 voffset,
280			 RADEON_GEM_DOMAIN_GTT,
281			 0, 0);
282	 voffset =  rmesa->tcl.aos[i + 1].offset +
283	    offset * 4 * rmesa->tcl.aos[i + 1].stride;
284	 OUT_BATCH_RELOC(voffset,
285			 rmesa->tcl.aos[i+1].bo,
286			 voffset,
287			 RADEON_GEM_DOMAIN_GTT,
288			 0, 0);
289      }
290
291      if (nr & 1) {
292	 OUT_BATCH((rmesa->tcl.aos[nr - 1].components << 0) |
293		   (rmesa->tcl.aos[nr - 1].stride << 8));
294	 voffset =  rmesa->tcl.aos[nr - 1].offset +
295	    offset * 4 * rmesa->tcl.aos[nr - 1].stride;
296	 OUT_BATCH_RELOC(voffset,
297			 rmesa->tcl.aos[nr - 1].bo,
298			 voffset,
299			 RADEON_GEM_DOMAIN_GTT,
300			 0, 0);
301      }
302   } else {
303      for (i = 0; i + 1 < nr; i += 2) {
304	 OUT_BATCH((rmesa->tcl.aos[i].components << 0) |
305		   (rmesa->tcl.aos[i].stride << 8) |
306		   (rmesa->tcl.aos[i + 1].components << 16) |
307		   (rmesa->tcl.aos[i + 1].stride << 24));
308
309	 voffset =  rmesa->tcl.aos[i + 0].offset +
310	    offset * 4 * rmesa->tcl.aos[i + 0].stride;
311	 OUT_BATCH(voffset);
312	 voffset =  rmesa->tcl.aos[i + 1].offset +
313	    offset * 4 * rmesa->tcl.aos[i + 1].stride;
314	 OUT_BATCH(voffset);
315      }
316
317      if (nr & 1) {
318	 OUT_BATCH((rmesa->tcl.aos[nr - 1].components << 0) |
319		   (rmesa->tcl.aos[nr - 1].stride << 8));
320	 voffset =  rmesa->tcl.aos[nr - 1].offset +
321	    offset * 4 * rmesa->tcl.aos[nr - 1].stride;
322	 OUT_BATCH(voffset);
323      }
324      for (i = 0; i + 1 < nr; i += 2) {
325	 voffset =  rmesa->tcl.aos[i + 0].offset +
326	    offset * 4 * rmesa->tcl.aos[i + 0].stride;
327	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
328			       rmesa->tcl.aos[i+0].bo,
329			       RADEON_GEM_DOMAIN_GTT,
330			       0, 0);
331	 voffset =  rmesa->tcl.aos[i + 1].offset +
332	    offset * 4 * rmesa->tcl.aos[i + 1].stride;
333	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
334			       rmesa->tcl.aos[i+1].bo,
335			       RADEON_GEM_DOMAIN_GTT,
336			       0, 0);
337      }
338      if (nr & 1) {
339	 voffset =  rmesa->tcl.aos[nr - 1].offset +
340	    offset * 4 * rmesa->tcl.aos[nr - 1].stride;
341	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
342			       rmesa->tcl.aos[nr-1].bo,
343			       RADEON_GEM_DOMAIN_GTT,
344			       0, 0);
345      }
346   }
347   END_BATCH();
348}
349
350void r200FireAOS(r200ContextPtr rmesa, int vertex_count, int type)
351{
352	BATCH_LOCALS(&rmesa->radeon);
353
354	BEGIN_BATCH(3);
355	OUT_BATCH_PACKET3(R200_CP_CMD_3D_DRAW_VBUF_2, 0);
356	OUT_BATCH(R200_VF_PRIM_WALK_LIST | (vertex_count << 16) | type);
357	END_BATCH();
358}
359
360