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 "main/simple_list.h"
39
40#include "radeon_common.h"
41#include "r200_context.h"
42#include "r200_ioctl.h"
43#include "radeon_reg.h"
44
45/* The state atoms will be emitted in the order they appear in the atom list,
46 * so this step is important.
47 */
48#define insert_at_tail_if(atom_list, atom) \
49   do { \
50      struct radeon_state_atom* current_atom = (atom); \
51      if (current_atom->check) \
52	 insert_at_tail((atom_list), current_atom); \
53   } while(0)
54
55void r200SetUpAtomList( r200ContextPtr rmesa )
56{
57   int i, mtu;
58
59   mtu = rmesa->radeon.glCtx->Const.MaxTextureUnits;
60
61   make_empty_list(&rmesa->radeon.hw.atomlist);
62   rmesa->radeon.hw.atomlist.name = "atom-list";
63
64   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ctx );
65   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.set );
66   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lin );
67   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msk );
68   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpt );
69   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vtx );
70   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vap );
71   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vte );
72   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msc );
73   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cst );
74   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.zbs );
75   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcl );
76   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.msl );
77   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tcg );
78   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.grd );
79   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.fog );
80   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tam );
81   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tf );
82   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.atf );
83   for (i = 0; i < mtu; ++i)
84       insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.tex[i] );
85   for (i = 0; i < mtu; ++i)
86       insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.cube[i] );
87   for (i = 0; i < 6; ++i)
88       insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pix[i] );
89   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[0] );
90   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.afs[1] );
91   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.stp );
92   for (i = 0; i < 8; ++i)
93       insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.lit[i] );
94   for (i = 0; i < 3 + mtu; ++i)
95       insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mat[i] );
96   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.eye );
97   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.glt );
98   for (i = 0; i < 2; ++i)
99      insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.mtl[i] );
100   for (i = 0; i < 6; ++i)
101       insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ucp[i] );
102   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.spr );
103   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.ptp );
104   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.prf );
105   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.pvs );
106   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[0] );
107   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpp[1] );
108   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[0] );
109   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.vpi[1] );
110   insert_at_tail_if( &rmesa->radeon.hw.atomlist, &rmesa->hw.sci );
111}
112
113/* Fire a section of the retained (indexed_verts) buffer as a regular
114 * primtive.
115 */
116void r200EmitVbufPrim( r200ContextPtr rmesa,
117                       GLuint primitive,
118                       GLuint vertex_nr )
119{
120   BATCH_LOCALS(&rmesa->radeon);
121
122   assert(!(primitive & R200_VF_PRIM_WALK_IND));
123
124   radeonEmitState(&rmesa->radeon);
125
126   radeon_print(RADEON_RENDER|RADEON_SWRENDER,RADEON_VERBOSE,
127           "%s cmd_used/4: %d prim %x nr %d\n", __FUNCTION__,
128           rmesa->store.cmd_used/4, primitive, vertex_nr);
129
130   BEGIN_BATCH(3);
131   OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_VBUF_2, 0);
132   OUT_BATCH(primitive | R200_VF_PRIM_WALK_LIST | R200_VF_COLOR_ORDER_RGBA |
133	     (vertex_nr << R200_VF_VERTEX_NUMBER_SHIFT));
134   END_BATCH();
135}
136
137static void r200FireEB(r200ContextPtr rmesa, int vertex_count, int type)
138{
139	BATCH_LOCALS(&rmesa->radeon);
140
141	if (vertex_count > 0) {
142		BEGIN_BATCH(8+2);
143		OUT_BATCH_PACKET3_CLIP(R200_CP_CMD_3D_DRAW_INDX_2, 0);
144		OUT_BATCH(R200_VF_PRIM_WALK_IND |
145			  R200_VF_COLOR_ORDER_RGBA |
146			  ((vertex_count + 0) << 16) |
147			  type);
148
149		OUT_BATCH_PACKET3(R200_CP_CMD_INDX_BUFFER, 2);
150		OUT_BATCH((0x80 << 24) | (0 << 16) | 0x810);
151		OUT_BATCH(rmesa->radeon.tcl.elt_dma_offset);
152		OUT_BATCH((vertex_count + 1)/2);
153		radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
154				      rmesa->radeon.tcl.elt_dma_bo,
155				      RADEON_GEM_DOMAIN_GTT, 0, 0);
156		END_BATCH();
157	}
158}
159
160void r200FlushElts(struct gl_context *ctx)
161{
162   r200ContextPtr rmesa = R200_CONTEXT(ctx);
163   int nr, elt_used = rmesa->tcl.elt_used;
164
165   radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %x %d\n", __FUNCTION__, rmesa->tcl.hw_primitive, elt_used);
166
167   assert( rmesa->radeon.dma.flush == r200FlushElts );
168   rmesa->radeon.dma.flush = NULL;
169
170   nr = elt_used / 2;
171
172   radeon_bo_unmap(rmesa->radeon.tcl.elt_dma_bo);
173
174   r200FireEB(rmesa, nr, rmesa->tcl.hw_primitive);
175
176   radeon_bo_unref(rmesa->radeon.tcl.elt_dma_bo);
177   rmesa->radeon.tcl.elt_dma_bo = NULL;
178
179   if (R200_ELT_BUF_SZ > elt_used)
180     radeonReturnDmaRegion(&rmesa->radeon, R200_ELT_BUF_SZ - elt_used);
181}
182
183
184GLushort *r200AllocEltsOpenEnded( r200ContextPtr rmesa,
185				    GLuint primitive,
186				    GLuint min_nr )
187{
188   GLushort *retval;
189
190   radeon_print(RADEON_RENDER, RADEON_VERBOSE, "%s %d prim %x\n", __FUNCTION__, min_nr, primitive);
191
192   assert((primitive & R200_VF_PRIM_WALK_IND));
193
194   radeonEmitState(&rmesa->radeon);
195
196   radeonAllocDmaRegion(&rmesa->radeon, &rmesa->radeon.tcl.elt_dma_bo,
197			&rmesa->radeon.tcl.elt_dma_offset, R200_ELT_BUF_SZ, 4);
198   rmesa->tcl.elt_used = min_nr * 2;
199
200   radeon_bo_map(rmesa->radeon.tcl.elt_dma_bo, 1);
201   retval = rmesa->radeon.tcl.elt_dma_bo->ptr + rmesa->radeon.tcl.elt_dma_offset;
202
203   assert(!rmesa->radeon.dma.flush);
204   rmesa->radeon.glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
205   rmesa->radeon.dma.flush = r200FlushElts;
206
207   return retval;
208}
209
210void r200EmitMaxVtxIndex(r200ContextPtr rmesa, int count)
211{
212   BATCH_LOCALS(&rmesa->radeon);
213
214   BEGIN_BATCH_NO_AUTOSTATE(2);
215   OUT_BATCH(CP_PACKET0(R200_SE_VF_MAX_VTX_INDX, 0));
216   OUT_BATCH(count);
217   END_BATCH();
218}
219
220void r200EmitVertexAOS( r200ContextPtr rmesa,
221			GLuint vertex_size,
222 			struct radeon_bo *bo,
223			GLuint offset )
224{
225   BATCH_LOCALS(&rmesa->radeon);
226
227   radeon_print(RADEON_SWRENDER, RADEON_VERBOSE, "%s:  vertex_size 0x%x offset 0x%x \n",
228	      __FUNCTION__, vertex_size, offset);
229
230
231   BEGIN_BATCH(7);
232   OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, 2);
233   OUT_BATCH(1);
234   OUT_BATCH(vertex_size | (vertex_size << 8));
235   OUT_BATCH_RELOC(offset, bo, offset, RADEON_GEM_DOMAIN_GTT, 0, 0);
236   END_BATCH();
237}
238
239void r200EmitAOS(r200ContextPtr rmesa, GLuint nr, GLuint offset)
240{
241   BATCH_LOCALS(&rmesa->radeon);
242   uint32_t voffset;
243   int sz = 1 + (nr >> 1) * 3 + (nr & 1) * 2;
244   int i;
245
246   radeon_print(RADEON_RENDER, RADEON_VERBOSE,
247           "%s: nr=%d, ofs=0x%08x\n",
248           __FUNCTION__, nr, offset);
249
250   BEGIN_BATCH(sz+2+ (nr*2));
251   OUT_BATCH_PACKET3(R200_CP_CMD_3D_LOAD_VBPNTR, sz - 1);
252   OUT_BATCH(nr);
253
254   {
255      for (i = 0; i + 1 < nr; i += 2) {
256	 OUT_BATCH((rmesa->radeon.tcl.aos[i].components << 0) |
257		   (rmesa->radeon.tcl.aos[i].stride << 8) |
258		   (rmesa->radeon.tcl.aos[i + 1].components << 16) |
259		   (rmesa->radeon.tcl.aos[i + 1].stride << 24));
260
261	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
262	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
263	 OUT_BATCH(voffset);
264	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
265	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
266	 OUT_BATCH(voffset);
267      }
268
269      if (nr & 1) {
270	 OUT_BATCH((rmesa->radeon.tcl.aos[nr - 1].components << 0) |
271		   (rmesa->radeon.tcl.aos[nr - 1].stride << 8));
272	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
273	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
274	 OUT_BATCH(voffset);
275      }
276      for (i = 0; i + 1 < nr; i += 2) {
277	 voffset =  rmesa->radeon.tcl.aos[i + 0].offset +
278	    offset * 4 * rmesa->radeon.tcl.aos[i + 0].stride;
279	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
280			       rmesa->radeon.tcl.aos[i+0].bo,
281			       RADEON_GEM_DOMAIN_GTT,
282			       0, 0);
283	 voffset =  rmesa->radeon.tcl.aos[i + 1].offset +
284	    offset * 4 * rmesa->radeon.tcl.aos[i + 1].stride;
285	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
286			       rmesa->radeon.tcl.aos[i+1].bo,
287			       RADEON_GEM_DOMAIN_GTT,
288			       0, 0);
289      }
290      if (nr & 1) {
291	 voffset =  rmesa->radeon.tcl.aos[nr - 1].offset +
292	    offset * 4 * rmesa->radeon.tcl.aos[nr - 1].stride;
293	 radeon_cs_write_reloc(rmesa->radeon.cmdbuf.cs,
294			       rmesa->radeon.tcl.aos[nr-1].bo,
295			       RADEON_GEM_DOMAIN_GTT,
296			       0, 0);
297      }
298   }
299   END_BATCH();
300}
301