1/**************************************************************************
2
3Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                     Tungsten Graphics Inc., Austin, Texas.
5
6All Rights Reserved.
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/*
31 * Authors:
32 *   Keith Whitwell <keith@tungstengraphics.com>
33 */
34
35#include "main/glheader.h"
36#include "main/imports.h"
37#include "main/mtypes.h"
38
39#include "vbo/vbo.h"
40#include "math/m_translate.h"
41#include "tnl/tnl.h"
42#include "tnl/t_pipeline.h"
43#include "radeon_context.h"
44#include "radeon_state.h"
45#include "radeon_ioctl.h"
46#include "radeon_tex.h"
47#include "radeon_tcl.h"
48#include "radeon_swtcl.h"
49#include "radeon_maos.h"
50#include "radeon_fog.h"
51
52#define RADEON_TCL_MAX_SETUP 19
53
54union emit_union { float f; GLuint ui; radeon_color_t rgba; };
55
56static struct {
57   void   (*emit)( struct gl_context *, GLuint, GLuint, void * );
58   GLuint vertex_size;
59   GLuint vertex_format;
60} setup_tab[RADEON_TCL_MAX_SETUP];
61
62#define DO_W    (IND & RADEON_CP_VC_FRMT_W0)
63#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR)
64#define DO_SPEC_OR_FOG (IND & RADEON_CP_VC_FRMT_PKSPEC)
65#define DO_SPEC ((IND & RADEON_CP_VC_FRMT_PKSPEC) && \
66		 (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
67#define DO_FOG  ((IND & RADEON_CP_VC_FRMT_PKSPEC) && ctx->Fog.Enabled && \
68		 (ctx->Fog.FogCoordinateSource == GL_FOG_COORD))
69#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
70#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
71#define DO_TEX2 (IND & RADEON_CP_VC_FRMT_ST2)
72#define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0)
73#define DO_NORM (IND & RADEON_CP_VC_FRMT_N0)
74
75#define DO_TEX3 0
76
77#define GET_TEXSOURCE(n)  n
78
79/***********************************************************************
80 *             Generate vertex emit functions               *
81 ***********************************************************************/
82
83
84/* Defined in order of increasing vertex size:
85 */
86#define IDX 0
87#define IND (RADEON_CP_VC_FRMT_XY|		\
88	     RADEON_CP_VC_FRMT_Z|		\
89	     RADEON_CP_VC_FRMT_PKCOLOR)
90#define TAG(x) x##_rgba
91#include "radeon_maos_vbtmp.h"
92
93#define IDX 1
94#define IND (RADEON_CP_VC_FRMT_XY|		\
95	     RADEON_CP_VC_FRMT_Z|		\
96	     RADEON_CP_VC_FRMT_N0)
97#define TAG(x) x##_n
98#include "radeon_maos_vbtmp.h"
99
100#define IDX 2
101#define IND (RADEON_CP_VC_FRMT_XY|		\
102	     RADEON_CP_VC_FRMT_Z|		\
103	     RADEON_CP_VC_FRMT_PKCOLOR|		\
104	     RADEON_CP_VC_FRMT_ST0)
105#define TAG(x) x##_rgba_st
106#include "radeon_maos_vbtmp.h"
107
108#define IDX 3
109#define IND (RADEON_CP_VC_FRMT_XY|		\
110	     RADEON_CP_VC_FRMT_Z|		\
111	     RADEON_CP_VC_FRMT_PKCOLOR|		\
112	     RADEON_CP_VC_FRMT_N0)
113#define TAG(x) x##_rgba_n
114#include "radeon_maos_vbtmp.h"
115
116#define IDX 4
117#define IND (RADEON_CP_VC_FRMT_XY|		\
118	     RADEON_CP_VC_FRMT_Z|		\
119	     RADEON_CP_VC_FRMT_ST0|		\
120	     RADEON_CP_VC_FRMT_N0)
121#define TAG(x) x##_st_n
122#include "radeon_maos_vbtmp.h"
123
124#define IDX 5
125#define IND (RADEON_CP_VC_FRMT_XY|		\
126	     RADEON_CP_VC_FRMT_Z|		\
127	     RADEON_CP_VC_FRMT_PKCOLOR|		\
128	     RADEON_CP_VC_FRMT_ST0|		\
129	     RADEON_CP_VC_FRMT_ST1)
130#define TAG(x) x##_rgba_st_st
131#include "radeon_maos_vbtmp.h"
132
133#define IDX 6
134#define IND (RADEON_CP_VC_FRMT_XY|		\
135	     RADEON_CP_VC_FRMT_Z|		\
136	     RADEON_CP_VC_FRMT_PKCOLOR|		\
137	     RADEON_CP_VC_FRMT_ST0|		\
138	     RADEON_CP_VC_FRMT_N0)
139#define TAG(x) x##_rgba_st_n
140#include "radeon_maos_vbtmp.h"
141
142#define IDX 7
143#define IND (RADEON_CP_VC_FRMT_XY|		\
144	     RADEON_CP_VC_FRMT_Z|		\
145	     RADEON_CP_VC_FRMT_PKCOLOR|		\
146	     RADEON_CP_VC_FRMT_PKSPEC|		\
147	     RADEON_CP_VC_FRMT_ST0|		\
148	     RADEON_CP_VC_FRMT_ST1)
149#define TAG(x) x##_rgba_spec_st_st
150#include "radeon_maos_vbtmp.h"
151
152#define IDX 8
153#define IND (RADEON_CP_VC_FRMT_XY|		\
154	     RADEON_CP_VC_FRMT_Z|		\
155	     RADEON_CP_VC_FRMT_ST0|		\
156	     RADEON_CP_VC_FRMT_ST1|		\
157	     RADEON_CP_VC_FRMT_N0)
158#define TAG(x) x##_st_st_n
159#include "radeon_maos_vbtmp.h"
160
161#define IDX 9
162#define IND (RADEON_CP_VC_FRMT_XY|		\
163	     RADEON_CP_VC_FRMT_Z|		\
164	     RADEON_CP_VC_FRMT_PKCOLOR|		\
165	     RADEON_CP_VC_FRMT_PKSPEC|		\
166	     RADEON_CP_VC_FRMT_ST0|		\
167	     RADEON_CP_VC_FRMT_ST1|		\
168	     RADEON_CP_VC_FRMT_N0)
169#define TAG(x) x##_rgba_spec_st_st_n
170#include "radeon_maos_vbtmp.h"
171
172#define IDX 10
173#define IND (RADEON_CP_VC_FRMT_XY|		\
174	     RADEON_CP_VC_FRMT_Z|		\
175	     RADEON_CP_VC_FRMT_PKCOLOR|		\
176	     RADEON_CP_VC_FRMT_ST0|		\
177	     RADEON_CP_VC_FRMT_Q0)
178#define TAG(x) x##_rgba_stq
179#include "radeon_maos_vbtmp.h"
180
181#define IDX 11
182#define IND (RADEON_CP_VC_FRMT_XY|		\
183	     RADEON_CP_VC_FRMT_Z|		\
184	     RADEON_CP_VC_FRMT_PKCOLOR|		\
185	     RADEON_CP_VC_FRMT_ST1|		\
186	     RADEON_CP_VC_FRMT_Q1|		\
187	     RADEON_CP_VC_FRMT_ST0|		\
188	     RADEON_CP_VC_FRMT_Q0)
189#define TAG(x) x##_rgba_stq_stq
190#include "radeon_maos_vbtmp.h"
191
192#define IDX 12
193#define IND (RADEON_CP_VC_FRMT_XY|		\
194	     RADEON_CP_VC_FRMT_Z|		\
195	     RADEON_CP_VC_FRMT_W0|		\
196	     RADEON_CP_VC_FRMT_PKCOLOR|		\
197	     RADEON_CP_VC_FRMT_PKSPEC|		\
198	     RADEON_CP_VC_FRMT_ST0|		\
199	     RADEON_CP_VC_FRMT_Q0|		\
200	     RADEON_CP_VC_FRMT_ST1|		\
201	     RADEON_CP_VC_FRMT_Q1|		\
202	     RADEON_CP_VC_FRMT_N0)
203#define TAG(x) x##_w_rgba_spec_stq_stq_n
204#include "radeon_maos_vbtmp.h"
205
206#define IDX 13
207#define IND (RADEON_CP_VC_FRMT_XY|		\
208	     RADEON_CP_VC_FRMT_Z|		\
209	     RADEON_CP_VC_FRMT_PKCOLOR|		\
210	     RADEON_CP_VC_FRMT_ST0|		\
211	     RADEON_CP_VC_FRMT_ST1|		\
212	     RADEON_CP_VC_FRMT_ST2)
213#define TAG(x) x##_rgba_st_st_st
214#include "radeon_maos_vbtmp.h"
215
216#define IDX 14
217#define IND (RADEON_CP_VC_FRMT_XY|		\
218	     RADEON_CP_VC_FRMT_Z|		\
219	     RADEON_CP_VC_FRMT_PKCOLOR|		\
220	     RADEON_CP_VC_FRMT_PKSPEC|		\
221	     RADEON_CP_VC_FRMT_ST0|		\
222	     RADEON_CP_VC_FRMT_ST1|		\
223	     RADEON_CP_VC_FRMT_ST2)
224#define TAG(x) x##_rgba_spec_st_st_st
225#include "radeon_maos_vbtmp.h"
226
227#define IDX 15
228#define IND (RADEON_CP_VC_FRMT_XY|		\
229	     RADEON_CP_VC_FRMT_Z|		\
230	     RADEON_CP_VC_FRMT_ST0|		\
231	     RADEON_CP_VC_FRMT_ST1|		\
232	     RADEON_CP_VC_FRMT_ST2|		\
233	     RADEON_CP_VC_FRMT_N0)
234#define TAG(x) x##_st_st_st_n
235#include "radeon_maos_vbtmp.h"
236
237#define IDX 16
238#define IND (RADEON_CP_VC_FRMT_XY|		\
239	     RADEON_CP_VC_FRMT_Z|		\
240	     RADEON_CP_VC_FRMT_PKCOLOR|		\
241	     RADEON_CP_VC_FRMT_PKSPEC|		\
242	     RADEON_CP_VC_FRMT_ST0|		\
243	     RADEON_CP_VC_FRMT_ST1|		\
244	     RADEON_CP_VC_FRMT_ST2|		\
245	     RADEON_CP_VC_FRMT_N0)
246#define TAG(x) x##_rgba_spec_st_st_st_n
247#include "radeon_maos_vbtmp.h"
248
249#define IDX 17
250#define IND (RADEON_CP_VC_FRMT_XY|		\
251	     RADEON_CP_VC_FRMT_Z|		\
252	     RADEON_CP_VC_FRMT_PKCOLOR|		\
253	     RADEON_CP_VC_FRMT_ST0|		\
254	     RADEON_CP_VC_FRMT_Q0|		\
255	     RADEON_CP_VC_FRMT_ST1|		\
256	     RADEON_CP_VC_FRMT_Q1|		\
257	     RADEON_CP_VC_FRMT_ST2|		\
258	     RADEON_CP_VC_FRMT_Q2)
259#define TAG(x) x##_rgba_stq_stq_stq
260#include "radeon_maos_vbtmp.h"
261
262#define IDX 18
263#define IND (RADEON_CP_VC_FRMT_XY|		\
264	     RADEON_CP_VC_FRMT_Z|		\
265	     RADEON_CP_VC_FRMT_W0|		\
266	     RADEON_CP_VC_FRMT_PKCOLOR|		\
267	     RADEON_CP_VC_FRMT_PKSPEC|		\
268	     RADEON_CP_VC_FRMT_ST0|		\
269	     RADEON_CP_VC_FRMT_Q0|		\
270	     RADEON_CP_VC_FRMT_ST1|		\
271	     RADEON_CP_VC_FRMT_Q1|		\
272	     RADEON_CP_VC_FRMT_ST2|		\
273	     RADEON_CP_VC_FRMT_Q2|		\
274	     RADEON_CP_VC_FRMT_N0)
275#define TAG(x) x##_w_rgba_spec_stq_stq_stq_n
276#include "radeon_maos_vbtmp.h"
277
278
279
280
281/***********************************************************************
282 *                         Initialization
283 ***********************************************************************/
284
285
286static void init_tcl_verts( void )
287{
288   init_rgba();
289   init_n();
290   init_rgba_n();
291   init_rgba_st();
292   init_st_n();
293   init_rgba_st_st();
294   init_rgba_st_n();
295   init_rgba_spec_st_st();
296   init_st_st_n();
297   init_rgba_spec_st_st_n();
298   init_rgba_stq();
299   init_rgba_stq_stq();
300   init_w_rgba_spec_stq_stq_n();
301   init_rgba_st_st_st();
302   init_rgba_spec_st_st_st();
303   init_st_st_st_n();
304   init_rgba_spec_st_st_st_n();
305   init_rgba_stq_stq_stq();
306   init_w_rgba_spec_stq_stq_stq_n();
307}
308
309
310void radeonEmitArrays( struct gl_context *ctx, GLuint inputs )
311{
312   r100ContextPtr rmesa = R100_CONTEXT(ctx);
313   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
314   GLuint req = 0;
315   GLuint unit;
316   GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
317		 ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2));
318   int i;
319   static int firsttime = 1;
320
321   if (firsttime) {
322      init_tcl_verts();
323      firsttime = 0;
324   }
325
326   if (1) {
327      req |= RADEON_CP_VC_FRMT_Z;
328      if (VB->AttribPtr[_TNL_ATTRIB_POS]->size == 4) {
329	 req |= RADEON_CP_VC_FRMT_W0;
330      }
331   }
332
333   if (inputs & VERT_BIT_NORMAL) {
334      req |= RADEON_CP_VC_FRMT_N0;
335   }
336
337   if (inputs & VERT_BIT_COLOR0) {
338      req |= RADEON_CP_VC_FRMT_PKCOLOR;
339   }
340
341   if (inputs & (VERT_BIT_COLOR1|VERT_BIT_FOG)) {
342      req |= RADEON_CP_VC_FRMT_PKSPEC;
343   }
344
345   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
346      if (inputs & VERT_BIT_TEX(unit)) {
347	 req |= RADEON_ST_BIT(unit);
348	 /* assume we need the 3rd coord if texgen is active for r/q OR at least
349	    3 coords are submitted. This may not be 100% correct */
350	 if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) {
351	    req |= RADEON_Q_BIT(unit);
352	    vtx |= RADEON_Q_BIT(unit);
353	 }
354	 if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) )
355	    vtx |= RADEON_Q_BIT(unit);
356	 else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) &&
357	          ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) {
358	    GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3);
359	    if (((rmesa->NeedTexMatrix >> unit) & 1) &&
360		 (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
361	       radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
362	 }
363      }
364   }
365
366   if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
367      RADEON_STATECHANGE( rmesa, tcl );
368      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
369   }
370
371   for (i = 0 ; i < RADEON_TCL_MAX_SETUP ; i++)
372      if ((setup_tab[i].vertex_format & req) == req)
373	 break;
374
375   if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format &&
376       rmesa->radeon.tcl.aos[0].bo)
377      return;
378
379   if (rmesa->radeon.tcl.aos[0].bo)
380      radeonReleaseArrays( ctx, ~0 );
381
382   radeonAllocDmaRegion( &rmesa->radeon,
383			 &rmesa->radeon.tcl.aos[0].bo,
384			 &rmesa->radeon.tcl.aos[0].offset,
385			 VB->Count * setup_tab[i].vertex_size * 4,
386			 4);
387
388   /* The vertex code expects Obj to be clean to element 3.  To fix
389    * this, add more vertex code (for obj-2, obj-3) or preferably move
390    * to maos.
391    */
392   if (VB->AttribPtr[_TNL_ATTRIB_POS]->size < 3 ||
393       (VB->AttribPtr[_TNL_ATTRIB_POS]->size == 3 &&
394	(setup_tab[i].vertex_format & RADEON_CP_VC_FRMT_W0))) {
395
396      _math_trans_4f( rmesa->tcl.ObjClean.data,
397		      VB->AttribPtr[_TNL_ATTRIB_POS]->data,
398		      VB->AttribPtr[_TNL_ATTRIB_POS]->stride,
399		      GL_FLOAT,
400		      VB->AttribPtr[_TNL_ATTRIB_POS]->size,
401		      0,
402		      VB->Count );
403
404      switch (VB->AttribPtr[_TNL_ATTRIB_POS]->size) {
405      case 1:
406	    _mesa_vector4f_clean_elem(&rmesa->tcl.ObjClean, VB->Count, 1);
407      case 2:
408	    _mesa_vector4f_clean_elem(&rmesa->tcl.ObjClean, VB->Count, 2);
409      case 3:
410	 if (setup_tab[i].vertex_format & RADEON_CP_VC_FRMT_W0) {
411	    _mesa_vector4f_clean_elem(&rmesa->tcl.ObjClean, VB->Count, 3);
412	 }
413      case 4:
414      default:
415	 break;
416      }
417
418      VB->AttribPtr[_TNL_ATTRIB_POS] = &rmesa->tcl.ObjClean;
419   }
420
421
422   radeon_bo_map(rmesa->radeon.tcl.aos[0].bo, 1);
423   setup_tab[i].emit( ctx, 0, VB->Count,
424		      rmesa->radeon.tcl.aos[0].bo->ptr + rmesa->radeon.tcl.aos[0].offset);
425   radeon_bo_unmap(rmesa->radeon.tcl.aos[0].bo);
426   //   rmesa->radeon.tcl.aos[0].size = setup_tab[i].vertex_size;
427   rmesa->radeon.tcl.aos[0].stride = setup_tab[i].vertex_size;
428   rmesa->tcl.vertex_format = setup_tab[i].vertex_format;
429   rmesa->radeon.tcl.aos_count = 1;
430}
431
432
433