r200_cmdbuf.c revision 714f5e689fb1a69142995260e3c8908c12407b47
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_common.h"
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/* The state atoms will be emitted in the order they appear in the atom list,
50 * so this step is important.
51 */
52void r200SetUpAtomList( r200ContextPtr rmesa )
53{
54   int i, mtu;
55
56   mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
57
58   make_empty_list(&rmesa->radeon.hw.atomlist);
59   rmesa->radeon.hw.atomlist.name = "atom-list";
60
61   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.ctx );
62   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.set );
63   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.lin );
64   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.msk );
65   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpt );
66   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vtx );
67   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vap );
68   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vte );
69   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.msc );
70   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.cst );
71   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.zbs );
72   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcl );
73   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.msl );
74   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcg );
75   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.grd );
76   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.fog );
77   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tam );
78   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tf );
79   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.atf );
80   for (i = 0; i < mtu; ++i)
81       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i] );
82   for (i = 0; i < mtu; ++i)
83       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i] );
84   for (i = 0; i < 6; ++i)
85       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] );
86   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] );
87   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] );
88   for (i = 0; i < 8; ++i)
89       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] );
90   for (i = 0; i < 3 + mtu; ++i)
91       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i] );
92   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.eye );
93   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.glt );
94   for (i = 0; i < 2; ++i)
95      insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.mtl[i] );
96   for (i = 0; i < 6; ++i)
97       insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i] );
98   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.spr );
99   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.ptp );
100   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.prf );
101   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.pvs );
102   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[0] );
103   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[1] );
104   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[0] );
105   insert_at_tail( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[1] );
106}
107
108void r200EmitScissor(r200ContextPtr rmesa)
109{
110    BATCH_LOCALS(&rmesa->radeon);
111    if (!rmesa->radeon.radeonScreen->kernel_mm) {
112       return;
113    }
114    if (rmesa->radeon.state.scissor.enabled) {
115        BEGIN_BATCH(8);
116        OUT_BATCH(CP_PACKET0(R200_RE_CNTL, 0));
117        OUT_BATCH(R200_SCISSOR_ENABLE | rmesa->hw.set.cmd[SET_RE_CNTL]);
118        OUT_BATCH(CP_PACKET0(R200_RE_AUX_SCISSOR_CNTL, 0));
119        OUT_BATCH(R200_SCISSOR_ENABLE_0);
120        OUT_BATCH(CP_PACKET0(R200_RE_SCISSOR_TL_0, 0));
121        OUT_BATCH((rmesa->radeon.state.scissor.rect.y1 << 16) |
122                  rmesa->radeon.state.scissor.rect.x1);
123        OUT_BATCH(CP_PACKET0(R200_RE_SCISSOR_BR_0, 0));
124        OUT_BATCH(((rmesa->radeon.state.scissor.rect.y2 - 1) << 16) |
125                  (rmesa->radeon.state.scissor.rect.x2 - 1));
126        END_BATCH();
127    } else {
128        BEGIN_BATCH(4);
129        OUT_BATCH(CP_PACKET0(R200_RE_CNTL, 0));
130        OUT_BATCH(rmesa->hw.set.cmd[SET_RE_CNTL] & ~R200_SCISSOR_ENABLE);
131        OUT_BATCH(CP_PACKET0(R200_RE_AUX_SCISSOR_CNTL, 0));
132        OUT_BATCH(0);
133        END_BATCH();
134    }
135}
136
137/* Fire a section of the retained (indexed_verts) buffer as a regular
138 * primtive.
139 */
140void r200EmitVbufPrim( r200ContextPtr rmesa,
141                       GLuint primitive,
142                       GLuint vertex_nr )
143{
144   BATCH_LOCALS(&rmesa->radeon);
145
146   assert(!(primitive & R200_VF_PRIM_WALK_IND));
147
148   radeonEmitState(&rmesa->radeon);
149
150   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
151      fprintf(stderr, "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
152	      rmesa->store.cmd_used/4, primitive, vertex_nr);
153   r200EmitScissor(rmesa);
154
155   BEGIN_BATCH(3);
156   OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_VBUF_2, 0);
157   OUT_BATCH(primitive | R200_VF_PRIM_WALK_LIST | R200_VF_COLOR_ORDER_RGBA |
158	     (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
159   END_BATCH();
160}
161
162static void r200FireEB(r200ContextPtr rmesa, int vertex_count, int type)
163{
164	BATCH_LOCALS(&rmesa->radeon);
165
166	if (vertex_count > 0) {
167        r200EmitScissor(rmesa);
168		BEGIN_BATCH(8+2);
169		OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_INDX_2, 0);
170		OUT_BATCH(R200_VF_PRIM_WALK_IND |
171			  R200_VF_COLOR_ORDER_RGBA |
172			  ((vertex_count + 0) << 16) |
173			  type);
174
175		if (!rmesa->radeon.radeonScreen->kernel_mm) {
176			OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
177			OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
178			OUT_BATCH_RELOC(rmesa->radeon.tcl.elt_dma_offset,
179					rmesa->radeon.tcl.elt_dma_bo,
180					rmesa->radeon.tcl.elt_dma_offset,
181					RADEON_GEM_DOMAIN_GTT, 0, 0);
182			OUT_BATCH((vertex_count + 1)/2);
183		} else {
184			OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
185			OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
186			OUT_BATCH(rmesa->radeon.tcl.elt_dma_offset);
187			OUT_BATCH((vertex_count + 1)/2);
188			radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
189					      rmesa->radeon.tcl.elt_dma_bo,
190					      RADEON_GEM_DOMAIN_GTT, 0, 0);
191		}
192		END_BATCH();
193	}
194}
195
196void r200FlushElts(GLcontext *ctx)
197{
198   r200ContextPtr rmesa = R200_CONTEXT(ctx);
199   int nr, elt_used = rmesa->tcl.elt_used;
200
201   if (R200_DEBUG & (DEBUG_IOCTL|DEBUG_PRIMS))
202     fprintf(stderr, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used);
203
204   assert( rmesa->radeon.dma.flush == r200FlushElts );
205   rmesa->radeon.dma.flush = NULL;
206
207   nr = elt_used / 2;
208
209   radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo);
210
211   r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive);
212
213   radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo);
214   rmesa->radeon.tcl.elt_dma_bo = NULL;
215
216   if (R200_DEBUG & DEBUG_SYNC) {
217      fprintf(stderr, "%s: Syncing\n", __FUNCTION__);
218      radeonFinish( rmesa->radeon.glCtx );
219   }
220}
221
222
223GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
224				    GLuint primitive,
225				    GLuint min_nr )
226{
227   GLushort *retval;
228
229   if (R200_DEBUG & DEBUG_IOCTL)
230      fprintf(stderr, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
231
232   assert((primitive & R200_VF_PRIM_WALK_IND));
233
234   radeonEmitState(&rmesa->radeon);
235
236   rmesa->radeon.tcl.elt_dma_bo = radeon_bo_open(rmesa->radeon.radeonScreen->bom,
237					  0, R200_ELT_BUF_SZ, 4,
238					  RADEON_GEM_DOMAIN_GTT, 0);
239   rmesa->radeon.tcl.elt_dma_offset = 0;
240   rmesa->tcl.elt_used = min_nr * 2;
241
242   radeon_validate_bo(&rmesa->radeon, rmesa->radeon.tcl.elt_dma_bo,
243                      RADEON_GEM_DOMAIN_GTT, 0);
244   if (radeon_revalidate_bos(rmesa->radeon.glCtx) == GL_FALSE)
245      fprintf(stderr,"failure to revalidate BOs - badness\n");
246
247   radeon_bo_map(rmesa->radeon.tcl.elt_dma_bo, 1);
248   retval = rmesa->radeon.tcl.elt_dma_bo->ptr + rmesa->radeon.tcl.elt_dma_offset;
249
250
251   if (R200_DEBUG & DEBUG_PRIMS)
252      fprintf(stderr, "%s: header prim %x \n",
253	      __FUNCTION__, primitive);
254
255   assert(!rmesa->radeon.dma.flush);
256   rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
257   rmesa->radeon.dma.flush = r200FlushElts;
258
259   return retval;
260}
261
262
263
264void r200EmitVertexAOS( r200ContextPtr rmesa,
265			GLuint vertex_size,
266 			struct radeon_bo *bo,
267			GLuint offset )
268{
269   BATCH_LOCALS(&rmesa->radeon);
270
271   if (R200_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
272      fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
273	      __FUNCTION__, vertex_size, offset);
274
275
276   BEGIN_BATCH(7);
277   OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, 2);
278   OUT_BATCH(1);
279   OUT_BATCH(vertex_size | (vertex_size << 8));
280   OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
281   END_BATCH();
282}
283
284void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset)
285{
286   BATCH_LOCALS(&rmesa->radeon);
287   uint32_t voffset;
288   int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
289   int i;
290
291   if (RADEON_DEBUG & DEBUG_VERTS)
292      fprintf(stderr, "%s: nr=%d, ofs=0x%08x\n", __FUNCTION__, nr,
293	      offset);
294
295   BEGIN_BATCH(sz+2+ (nr*2));
296   OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, sz - 1);
297   OUT_BATCH(nr);
298
299
300   if (!rmesa->radeon.radeonScreen->kernel_mm) {
301      for (i = 0; i + 1 < nr; i += 2) {
302	 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
303		   (rmesa->radeon.tcl.aos[i].stride << 8) |
304		   (rmesa->radeon.tcl.aos[i + 1].components << 16) |
305		   (rmesa->radeon.tcl.aos[i + 1].stride << 24));
306
307	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
308	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
309	 OUT_BATCH_RELOC(voffset,
310			 rmesa->radeon.tcl.aos[i].bo,
311			 voffset,
312			 RADEON_GEM_DOMAIN_GTT,
313			 0, 0);
314	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
315	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
316	 OUT_BATCH_RELOC(voffset,
317			 rmesa->radeon.tcl.aos[i+1].bo,
318			 voffset,
319			 RADEON_GEM_DOMAIN_GTT,
320			 0, 0);
321      }
322
323      if (nr & 1) {
324	 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
325		   (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
326	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
327	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
328	 OUT_BATCH_RELOC(voffset,
329			 rmesa->radeon.tcl.aos[nr - 1].bo,
330			 voffset,
331			 RADEON_GEM_DOMAIN_GTT,
332			 0, 0);
333      }
334   } else {
335      for (i = 0; i + 1 < nr; i += 2) {
336	 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
337		   (rmesa->radeon.tcl.aos[i].stride << 8) |
338		   (rmesa->radeon.tcl.aos[i + 1].components << 16) |
339		   (rmesa->radeon.tcl.aos[i + 1].stride << 24));
340
341	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
342	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
343	 OUT_BATCH(voffset);
344	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
345	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
346	 OUT_BATCH(voffset);
347      }
348
349      if (nr & 1) {
350	 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
351		   (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
352	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
353	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
354	 OUT_BATCH(voffset);
355      }
356      for (i = 0; i + 1 < nr; i += 2) {
357	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
358	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
359	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
360			       rmesa->radeon.tcl.aos[i+0].bo,
361			       RADEON_GEM_DOMAIN_GTT,
362			       0, 0);
363	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
364	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
365	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
366			       rmesa->radeon.tcl.aos[i+1].bo,
367			       RADEON_GEM_DOMAIN_GTT,
368			       0, 0);
369      }
370      if (nr & 1) {
371	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
372	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
373	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
374			       rmesa->radeon.tcl.aos[nr-1].bo,
375			       RADEON_GEM_DOMAIN_GTT,
376			       0, 0);
377      }
378   }
379   END_BATCH();
380}
381