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