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/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 
emit_s0_vec(uint32_t * out,GLvoid * data,int stride,int count)50 static 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 
emit_stq_vec(uint32_t * out,GLvoid * data,int stride,int count)65 static 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 
emit_tex_vector(struct gl_context * ctx,struct radeon_aos * aos,GLvoid * data,int size,int stride,int count)82 static 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  */
radeonEmitArrays(struct gl_context * ctx,GLuint inputs)143 void 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