1/**************************************************************************
2
3Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                     Tungsten Graphics Inc., Cedar Park, 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#include "main/macros.h"
39
40#include "swrast_setup/swrast_setup.h"
41#include "math/m_translate.h"
42#include "tnl/tnl.h"
43
44#include "radeon_context.h"
45#include "radeon_ioctl.h"
46#include "radeon_state.h"
47#include "radeon_swtcl.h"
48#include "radeon_maos.h"
49#include "radeon_tcl.h"
50
51static void emit_s0_vec(uint32_t *out, GLvoid *data, int stride, int count)
52{
53   int i;
54   if (RADEON_DEBUG & RADEON_VERTS)
55      fprintf(stderr, "%s count %d stride %d\n",
56	      __FUNCTION__, count, stride);
57
58   for (i = 0; i < count; i++) {
59      out[0] = *(int *)data;
60      out[1] = 0;
61      out += 2;
62      data += stride;
63   }
64}
65
66static void emit_stq_vec(uint32_t *out, GLvoid *data, int stride, int count)
67{
68   int i;
69
70   if (RADEON_DEBUG & RADEON_VERTS)
71      fprintf(stderr, "%s count %d stride %d\n",
72	      __FUNCTION__, count, stride);
73
74   for (i = 0; i < count; i++) {
75      out[0] = *(int *)data;
76      out[1] = *(int *)(data+4);
77      out[2] = *(int *)(data+12);
78      out += 3;
79      data += stride;
80   }
81}
82
83static void emit_tex_vector(struct gl_context *ctx, struct radeon_aos *aos,
84			    GLvoid *data, int size, int stride, int count)
85{
86   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
87   int emitsize;
88   uint32_t *out;
89
90   if (RADEON_DEBUG & RADEON_VERTS)
91      fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
92
93   switch (size) {
94   case 4: emitsize = 3; break;
95   case 3: emitsize = 3; break;
96   default: emitsize = 2; break;
97   }
98
99
100   if (stride == 0) {
101      radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * 4, 32);
102      count = 1;
103      aos->stride = 0;
104   }
105   else {
106      radeonAllocDmaRegion(rmesa, &aos->bo, &aos->offset, emitsize * count * 4, 32);
107      aos->stride = emitsize;
108   }
109
110   aos->components = emitsize;
111   aos->count = count;
112
113   /* Emit the data
114    */
115   radeon_bo_map(aos->bo, 1);
116   out = (uint32_t*)((char*)aos->bo->ptr + aos->offset);
117   switch (size) {
118   case 1:
119      emit_s0_vec( out, data, stride, count );
120      break;
121   case 2:
122      radeonEmitVec8( out, data, stride, count );
123      break;
124   case 3:
125      radeonEmitVec12( out, data, stride, count );
126      break;
127   case 4:
128      emit_stq_vec( out, data, stride, count );
129      break;
130   default:
131      assert(0);
132      exit(1);
133      break;
134   }
135   radeon_bo_unmap(aos->bo);
136}
137
138
139
140
141/* Emit any changed arrays to new GART memory, re-emit a packet to
142 * update the arrays.
143 */
144void radeonEmitArrays( struct gl_context *ctx, GLuint inputs )
145{
146   r100ContextPtr rmesa = R100_CONTEXT( ctx );
147   struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
148   GLuint nr = 0;
149   GLuint vfmt = 0;
150   GLuint count = VB->Count;
151   GLuint vtx, unit;
152
153#if 0
154   if (RADEON_DEBUG & RADEON_VERTS)
155      _tnl_print_vert_flags( __FUNCTION__, inputs );
156#endif
157
158   if (1) {
159      if (!rmesa->tcl.obj.buf)
160	rcommon_emit_vector( ctx,
161			     &(rmesa->tcl.aos[nr]),
162			     (char *)VB->AttribPtr[_TNL_ATTRIB_POS]->data,
163			     VB->AttribPtr[_TNL_ATTRIB_POS]->size,
164			     VB->AttribPtr[_TNL_ATTRIB_POS]->stride,
165			     count);
166
167      switch( VB->AttribPtr[_TNL_ATTRIB_POS]->size ) {
168      case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
169      case 3: vfmt |= RADEON_CP_VC_FRMT_Z;
170      case 2: vfmt |= RADEON_CP_VC_FRMT_XY;
171      default:
172         break;
173      }
174      nr++;
175   }
176
177
178   if (inputs & VERT_BIT_NORMAL) {
179      if (!rmesa->tcl.norm.buf)
180	 rcommon_emit_vector( ctx,
181			      &(rmesa->tcl.aos[nr]),
182			      (char *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data,
183			      3,
184			      VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride,
185			      count);
186
187      vfmt |= RADEON_CP_VC_FRMT_N0;
188      nr++;
189   }
190
191   if (inputs & VERT_BIT_COLOR0) {
192      int emitsize;
193      if (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->size == 4 &&
194	  (VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride != 0 ||
195	   VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data[0][3] != 1.0)) {
196	 vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA;
197	 emitsize = 4;
198      }
199
200      else {
201	 vfmt |= RADEON_CP_VC_FRMT_FPCOLOR;
202	 emitsize = 3;
203      }
204
205      if (!rmesa->tcl.rgba.buf)
206	rcommon_emit_vector( ctx,
207			     &(rmesa->tcl.aos[nr]),
208			     (char *)VB->AttribPtr[_TNL_ATTRIB_COLOR0]->data,
209			     emitsize,
210			     VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride,
211			     count);
212
213      nr++;
214   }
215
216
217   if (inputs & VERT_BIT_COLOR1) {
218      if (!rmesa->tcl.spec.buf) {
219
220	rcommon_emit_vector( ctx,
221			     &(rmesa->tcl.aos[nr]),
222			     (char *)VB->AttribPtr[_TNL_ATTRIB_COLOR1]->data,
223			     3,
224			     VB->AttribPtr[_TNL_ATTRIB_COLOR1]->stride,
225			     count);
226      }
227
228      vfmt |= RADEON_CP_VC_FRMT_FPSPEC;
229      nr++;
230   }
231
232/* FIXME: not sure if this is correct. May need to stitch this together with
233   secondary color. It seems odd that for primary color color and alpha values
234   are emitted together but for secondary color not. */
235   if (inputs & VERT_BIT_FOG) {
236      if (!rmesa->tcl.fog.buf)
237	 rcommon_emit_vecfog( ctx,
238			      &(rmesa->tcl.aos[nr]),
239			      (char *)VB->AttribPtr[_TNL_ATTRIB_FOG]->data,
240			      VB->AttribPtr[_TNL_ATTRIB_FOG]->stride,
241			      count);
242
243      vfmt |= RADEON_CP_VC_FRMT_FPFOG;
244      nr++;
245   }
246
247
248   vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
249	  ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1|RADEON_TCL_VTX_Q2));
250
251   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
252      if (inputs & VERT_BIT_TEX(unit)) {
253	 if (!rmesa->tcl.tex[unit].buf)
254	    emit_tex_vector( ctx,
255			     &(rmesa->tcl.aos[nr]),
256			     (char *)VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->data,
257			     VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size,
258			     VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->stride,
259			     count );
260	 nr++;
261
262	 vfmt |= RADEON_ST_BIT(unit);
263         /* assume we need the 3rd coord if texgen is active for r/q OR at least
264	    3 coords are submitted. This may not be 100% correct */
265         if (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) {
266	    vtx |= RADEON_Q_BIT(unit);
267	    vfmt |= RADEON_Q_BIT(unit);
268	 }
269	 if ( (ctx->Texture.Unit[unit].TexGenEnabled & (R_BIT | Q_BIT)) )
270	    vtx |= RADEON_Q_BIT(unit);
271	 else if ((VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size >= 3) &&
272	          ((ctx->Texture.Unit[unit]._ReallyEnabled & (TEXTURE_CUBE_BIT)) == 0)) {
273	    GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3);
274	    if (((rmesa->NeedTexMatrix >> unit) & 1) &&
275		 (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
276	       radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
277	 }
278      }
279   }
280
281   if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
282      RADEON_STATECHANGE( rmesa, tcl );
283      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
284   }
285
286   rmesa->tcl.nr_aos_components = nr;
287   rmesa->tcl.vertex_format = vfmt;
288}
289
290