1 /**************************************************************************
2 
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4                      VMware, Inc.
5 
6 All Rights Reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH 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/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 
emit_s0_vec(uint32_t * out,GLvoid * data,int stride,int count)51 static 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 	      __func__, 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 
emit_stq_vec(uint32_t * out,GLvoid * data,int stride,int count)66 static 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 	      __func__, 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 
emit_tex_vector(struct gl_context * ctx,struct radeon_aos * aos,GLvoid * data,int size,int stride,int count)83 static 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", __func__, 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  */
radeonEmitArrays(struct gl_context * ctx,GLuint inputs)144 void 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( __func__, 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]._Current ||
273                    ctx->Texture.Unit[unit]._Current->Target != GL_TEXTURE_CUBE_MAP)) {
274 	    GLuint swaptexmatcol = (VB->AttribPtr[_TNL_ATTRIB_TEX0 + unit]->size - 3);
275 	    if (((rmesa->NeedTexMatrix >> unit) & 1) &&
276 		 (swaptexmatcol != ((rmesa->TexMatColSwap >> unit) & 1)))
277 	       radeonUploadTexMatrix( rmesa, unit, swaptexmatcol ) ;
278 	 }
279       }
280    }
281 
282    if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
283       RADEON_STATECHANGE( rmesa, tcl );
284       rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
285    }
286 
287    rmesa->tcl.nr_aos_components = nr;
288    rmesa->tcl.vertex_format = vfmt;
289 }
290 
291