1 | /* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */
|
---|
2 |
|
---|
3 | /*
|
---|
4 | * Mesa 3-D graphics library
|
---|
5 | * Version: 3.3
|
---|
6 | *
|
---|
7 | * Copyright (C) 1999 Brian Paul All Rights Reserved.
|
---|
8 | *
|
---|
9 | * Permission is hereby granted, free of charge, to any person obtaining a
|
---|
10 | * copy of this software and associated documentation files (the "Software"),
|
---|
11 | * to deal in the Software without restriction, including without limitation
|
---|
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
---|
13 | * and/or sell copies of the Software, and to permit persons to whom the
|
---|
14 | * Software is furnished to do so, subject to the following conditions:
|
---|
15 | *
|
---|
16 | * The above copyright notice and this permission notice shall be included
|
---|
17 | * in all copies or substantial portions of the Software.
|
---|
18 | *
|
---|
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
---|
22 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
---|
23 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
---|
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
---|
25 | *
|
---|
26 | *
|
---|
27 | * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
|
---|
28 | * terms stated above.
|
---|
29 | *
|
---|
30 | * Thank you for your contribution, David!
|
---|
31 | *
|
---|
32 | * Please make note of the above copyright/license statement. If you
|
---|
33 | * contributed code or bug fixes to this code under the previous (GNU
|
---|
34 | * Library) license and object to the new license, your code will be
|
---|
35 | * removed at your request. Please see the Mesa docs/COPYRIGHT file
|
---|
36 | * for more information.
|
---|
37 | *
|
---|
38 | * Additional Mesa/3Dfx driver developers:
|
---|
39 | * Daryll Strauss <daryll@precisioninsight.com>
|
---|
40 | * Keith Whitwell <keith@precisioninsight.com>
|
---|
41 | *
|
---|
42 | * See fxapi.h for more revision/author details.
|
---|
43 | */
|
---|
44 |
|
---|
45 |
|
---|
46 | /* Build clip space vertices from object space data.
|
---|
47 | */
|
---|
48 | static void TAG(fx_setup_full)( struct vertex_buffer *VB, GLuint do_clip )
|
---|
49 | {
|
---|
50 | GLcontext *ctx = VB->ctx;
|
---|
51 | GLfloat *f = (GLfloat *) FX_DRIVER_DATA(VB)->verts;
|
---|
52 | fxMesaContext fxMesa = FX_CONTEXT(VB->ctx);
|
---|
53 | GLuint count = VB->Count;
|
---|
54 | GLuint i;
|
---|
55 |
|
---|
56 | const GLfloat * const m = ctx->ModelProjectMatrix.m;
|
---|
57 |
|
---|
58 | #if (TYPE & SETUP_RGBA)
|
---|
59 | GLubyte *color = (GLubyte *)VB->ColorPtr->data;
|
---|
60 | GLuint color_stride = VB->ColorPtr->stride;
|
---|
61 | #endif
|
---|
62 |
|
---|
63 | #if (TYPE & SETUP_TMU0)
|
---|
64 | GLuint tmu0_source = fxMesa->tmu_source[0];
|
---|
65 | struct gl_texture_unit *t0 = &ctx->Texture.Unit[tmu0_source];
|
---|
66 | GLint s0scale = FX_TEXTURE_DATA(t0)->int_sScale;
|
---|
67 | GLint t0scale = FX_TEXTURE_DATA(t0)->int_tScale;
|
---|
68 | GLint *tmu0_int_data = (GLint *)VB->TexCoordPtr[tmu0_source]->data;
|
---|
69 | GLuint tmu0_stride = VB->TexCoordPtr[tmu0_source]->stride;
|
---|
70 | #endif
|
---|
71 |
|
---|
72 | #if (TYPE & SETUP_TMU1)
|
---|
73 | GLuint tmu1_source = fxMesa->tmu_source[1];
|
---|
74 | struct gl_texture_unit *t1 = &ctx->Texture.Unit[tmu1_source];
|
---|
75 | GLint s1scale = FX_TEXTURE_DATA(t1)->int_sScale;
|
---|
76 | GLint t1scale = FX_TEXTURE_DATA(t1)->int_tScale;
|
---|
77 | GLint *tmu1_int_data = (GLint *)VB->TexCoordPtr[tmu1_source]->data;
|
---|
78 | GLuint tmu1_stride = VB->TexCoordPtr[tmu1_source]->stride;
|
---|
79 | #endif
|
---|
80 |
|
---|
81 | (void) fxMesa;
|
---|
82 | (void) ctx;
|
---|
83 | (void) i;
|
---|
84 | (void) f;
|
---|
85 |
|
---|
86 | /* Use 3 seperate loops because it's easier for assembly. A
|
---|
87 | * best-case solution might be to do all three in a single assembly
|
---|
88 | * loop.
|
---|
89 | */
|
---|
90 | gl_xform_points3_v16_general(FX_DRIVER_DATA(VB)->verts[0].f,
|
---|
91 | m,
|
---|
92 | VB->ObjPtr->start,
|
---|
93 | VB->ObjPtr->stride,
|
---|
94 | count);
|
---|
95 |
|
---|
96 | if (do_clip)
|
---|
97 | {
|
---|
98 | VB->ClipAndMask = ~0;
|
---|
99 | VB->ClipOrMask = 0;
|
---|
100 | gl_cliptest_points4_v16(FX_DRIVER_DATA(VB)->verts[0].f,
|
---|
101 | FX_DRIVER_DATA(VB)->verts[count].f,
|
---|
102 | &(VB->ClipOrMask),
|
---|
103 | &(VB->ClipAndMask),
|
---|
104 | VB->ClipMask);
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | #if (TYPE)
|
---|
109 | for (i = 0 ; i < count ; i++, f += 16) {
|
---|
110 | #if (TYPE & SETUP_RGBA)
|
---|
111 | GLubyte *col = color; color += color_stride;
|
---|
112 | UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_R], col[0] );
|
---|
113 | UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_G], col[1] );
|
---|
114 | UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_B], col[2] );
|
---|
115 | UBYTE_COLOR_TO_FLOAT_255_COLOR2( f[CLIP_A], col[3] );
|
---|
116 | #endif
|
---|
117 | #if (TYPE & SETUP_TMU0)
|
---|
118 | * (int *) &f[CLIP_S0] = s0scale + tmu0_int_data[0];
|
---|
119 | * (int *) &f[CLIP_T0] = t0scale + tmu0_int_data[1];
|
---|
120 | STRIDE_T(tmu0_int_data, GLint, tmu0_stride);
|
---|
121 | #endif
|
---|
122 | #if (TYPE & SETUP_TMU1)
|
---|
123 | * (int *) &f[CLIP_S1] = s1scale + tmu1_int_data[0];
|
---|
124 | * (int *) &f[CLIP_T1] = t1scale + tmu1_int_data[1];
|
---|
125 | STRIDE_T(tmu1_int_data, GLint, tmu1_stride);
|
---|
126 | #endif
|
---|
127 | }
|
---|
128 | #endif
|
---|
129 |
|
---|
130 | FX_DRIVER_DATA(VB)->last_vert = &(FX_DRIVER_DATA(VB)->verts[count]);
|
---|
131 | }
|
---|
132 |
|
---|
133 |
|
---|
134 | /* Do viewport map, device scale and perspective projection.
|
---|
135 | *
|
---|
136 | * Rearrange fxVertices to look like grVertices.
|
---|
137 | */
|
---|
138 | static void TAG(fx_project_vertices)( GLfloat *first,
|
---|
139 | GLfloat *last,
|
---|
140 | const GLfloat *mat,
|
---|
141 | GLuint stride )
|
---|
142 | {
|
---|
143 | GLfloat *f;
|
---|
144 | VARS_XYZ;
|
---|
145 |
|
---|
146 | for ( f = first ; f != last ; STRIDE_F(f, stride))
|
---|
147 | {
|
---|
148 | GLfloat oow = 1.0f/f[CLIP_WCOORD]; /* urp! */
|
---|
149 |
|
---|
150 | #if FX_USE_PARGB
|
---|
151 | if (TYPE & SETUP_RGBA) {
|
---|
152 | PACK_4F_ARGB(GET_PARGB(f),f[CLIP_A],f[CLIP_R],f[CLIP_G],f[CLIP_B]);
|
---|
153 | }
|
---|
154 | #else
|
---|
155 | if (TYPE & SETUP_RGBA) {
|
---|
156 | f[RCOORD]=f[CLIP_R];
|
---|
157 | }
|
---|
158 | #endif
|
---|
159 | if (TYPE & SETUP_TMU1) {
|
---|
160 | f[S1COORD] = f[CLIP_S1] * oow;
|
---|
161 | f[T1COORD] = f[CLIP_T1] * oow;
|
---|
162 | }
|
---|
163 |
|
---|
164 | if (TYPE & SETUP_TMU0) {
|
---|
165 | f[T0COORD] = f[CLIP_T0] * oow;
|
---|
166 | f[S0COORD] = f[CLIP_S0] * oow;
|
---|
167 | }
|
---|
168 |
|
---|
169 | DO_SETUP_XYZ;
|
---|
170 |
|
---|
171 | f[OOWCOORD] = oow;
|
---|
172 | }
|
---|
173 | }
|
---|
174 |
|
---|
175 | static void TAG(fx_project_clipped_vertices)( GLfloat *first,
|
---|
176 | GLfloat *last,
|
---|
177 | const GLfloat *mat,
|
---|
178 | GLuint stride,
|
---|
179 | const GLubyte *mask )
|
---|
180 | {
|
---|
181 | GLfloat *f;
|
---|
182 | VARS_XYZ;
|
---|
183 |
|
---|
184 | for ( f = first ; f != last ; STRIDE_F(f, stride), mask++) {
|
---|
185 | if (!*mask) {
|
---|
186 |
|
---|
187 | GLfloat oow = 1.0f / f[CLIP_WCOORD];
|
---|
188 | #if FX_USE_PARGB
|
---|
189 | if (TYPE & SETUP_RGBA) {
|
---|
190 | const GLuint r = f[CLIP_R];
|
---|
191 | const GLuint g = f[CLIP_G];
|
---|
192 | const GLuint b = f[CLIP_B];
|
---|
193 | const GLuint a = f[CLIP_A];
|
---|
194 | /* ToDo Optimize */
|
---|
195 | GET_PARGB(f) = a << 24 | r << 16 | g << 8 | b;
|
---|
196 | }
|
---|
197 | #else
|
---|
198 | if (TYPE & SETUP_RGBA) {
|
---|
199 | f[RCOORD]=f[CLIP_R];
|
---|
200 | }
|
---|
201 | #endif
|
---|
202 |
|
---|
203 | if (TYPE & SETUP_TMU1) {
|
---|
204 | f[S1COORD] = f[CLIP_S1] * oow;
|
---|
205 | f[T1COORD] = f[CLIP_T1] * oow;
|
---|
206 | }
|
---|
207 |
|
---|
208 | if (TYPE & SETUP_TMU0) {
|
---|
209 | f[T0COORD] = f[CLIP_T0] * oow;
|
---|
210 | f[S0COORD] = f[CLIP_S0] * oow;
|
---|
211 | }
|
---|
212 |
|
---|
213 | DO_SETUP_XYZ;
|
---|
214 |
|
---|
215 | f[OOWCOORD] = oow;
|
---|
216 | }
|
---|
217 | }
|
---|
218 | }
|
---|
219 |
|
---|
220 |
|
---|
221 | static
|
---|
222 | #if (SIZE <= 8)
|
---|
223 | INLINE
|
---|
224 | #endif
|
---|
225 | void TAG(fx_tri_clip)( GLuint **p_elts,
|
---|
226 | fxVertex *verts,
|
---|
227 | GLubyte *clipmask,
|
---|
228 | GLuint *p_next_vert,
|
---|
229 | GLubyte mask )
|
---|
230 | {
|
---|
231 | GLuint *elts = *p_elts;
|
---|
232 | GLuint next_vert = *p_next_vert;
|
---|
233 | GLuint vlist1[VB_MAX_CLIPPED_VERTS];
|
---|
234 | GLuint vlist2[VB_MAX_CLIPPED_VERTS];
|
---|
235 | GLuint *inlist[2];
|
---|
236 | GLuint *out;
|
---|
237 | GLuint in = 0;
|
---|
238 | GLuint n = 3;
|
---|
239 | GLuint i;
|
---|
240 |
|
---|
241 | inlist[0] = elts;
|
---|
242 | inlist[1] = vlist2;
|
---|
243 |
|
---|
244 | CLIP(-,0,CLIP_RIGHT_BIT);
|
---|
245 | CLIP(+,0,CLIP_LEFT_BIT);
|
---|
246 | CLIP(-,1,CLIP_TOP_BIT);
|
---|
247 | CLIP(+,1,CLIP_BOTTOM_BIT);
|
---|
248 | CLIP(-,2,CLIP_FAR_BIT);
|
---|
249 | CLIP(+,2,CLIP_NEAR_BIT);
|
---|
250 |
|
---|
251 | /* Convert the planar polygon to a list of triangles.
|
---|
252 | */
|
---|
253 | out = inlist[in];
|
---|
254 |
|
---|
255 | for (i = 2 ; i < n ; i++) {
|
---|
256 | elts[0] = out[0];
|
---|
257 | elts[1] = out[i-1];
|
---|
258 | elts[2] = out[i];
|
---|
259 | elts += 3;
|
---|
260 | }
|
---|
261 |
|
---|
262 | *p_next_vert = next_vert;
|
---|
263 | *p_elts = elts;
|
---|
264 | }
|
---|
265 |
|
---|
266 |
|
---|
267 | static INLINE void TAG(fx_line_clip)( GLuint **p_elts,
|
---|
268 | fxVertex *verts,
|
---|
269 | GLubyte *clipmask,
|
---|
270 | GLuint *p_next_vert,
|
---|
271 | GLubyte mask )
|
---|
272 | {
|
---|
273 | GLuint *elts = *p_elts;
|
---|
274 | GLfloat *I = verts[elts[0]].f;
|
---|
275 | GLfloat *J = verts[elts[1]].f;
|
---|
276 | GLuint next_vert = *p_next_vert;
|
---|
277 |
|
---|
278 | LINE_CLIP(1,0,0,-1,CLIP_LEFT_BIT);
|
---|
279 | LINE_CLIP(-1,0,0,1,CLIP_RIGHT_BIT);
|
---|
280 | LINE_CLIP(0,1,0,-1,CLIP_TOP_BIT);
|
---|
281 | LINE_CLIP(0,-1,0,1,CLIP_BOTTOM_BIT);
|
---|
282 | LINE_CLIP(0,0,1,-1,CLIP_FAR_BIT);
|
---|
283 | LINE_CLIP(0,0,-1,1,CLIP_NEAR_BIT);
|
---|
284 |
|
---|
285 | *p_next_vert = next_vert;
|
---|
286 | *p_elts += 2;
|
---|
287 | }
|
---|
288 |
|
---|
289 |
|
---|
290 | /* Build a table of functions to clip each primitive type.
|
---|
291 | */
|
---|
292 | #define LOCAL_VARS \
|
---|
293 | GLuint *elt = VB->EltPtr->data; \
|
---|
294 | fxVertex *verts = FX_DRIVER_DATA(VB)->verts; \
|
---|
295 | GLuint next_vert = VB->Count; \
|
---|
296 | GLuint *out = FX_DRIVER_DATA(VB)->clipped_elements.data; \
|
---|
297 | GLubyte *mask = VB->ClipMask; \
|
---|
298 |
|
---|
299 |
|
---|
300 | #define POSTFIX \
|
---|
301 | FX_DRIVER_DATA(VB)->clipped_elements.count = \
|
---|
302 | out - FX_DRIVER_DATA(VB)->clipped_elements.data; \
|
---|
303 | FX_DRIVER_DATA(VB)->last_vert = &verts[next_vert];
|
---|
304 |
|
---|
305 | #define INIT(x)
|
---|
306 |
|
---|
307 | #define RENDER_POINTS(start, count) \
|
---|
308 | do { \
|
---|
309 | GLuint i; \
|
---|
310 | for (i = start ; i < count ; i++ ) \
|
---|
311 | CLIP_POINT( elt[i] ); \
|
---|
312 | } while (0)
|
---|
313 |
|
---|
314 | #define RENDER_LINE(i1, i0) \
|
---|
315 | CLIP_LINE(elt[i1], elt[i0])
|
---|
316 |
|
---|
317 | #define RENDER_TRI(i2, i1, i0, pv, parroty) \
|
---|
318 | do { \
|
---|
319 | GLuint e2 = elt[i2], e1 = elt[i1], e0 = elt[i0]; \
|
---|
320 | if (parroty) e2 = elt[i1], e1 = elt[i2]; \
|
---|
321 | CLIP_TRIANGLE( e2, e1, e0 ); \
|
---|
322 | } while (0)
|
---|
323 |
|
---|
324 | #define RENDER_QUAD(i3, i2, i1, i0, pv) \
|
---|
325 | CLIP_TRIANGLE(elt[i3], elt[i2], elt[i0]); \
|
---|
326 | CLIP_TRIANGLE(elt[i2], elt[i1], elt[i0])
|
---|
327 |
|
---|
328 | #define PRESERVE_TAG
|
---|
329 | #include "render_tmp.h"
|
---|
330 |
|
---|
331 |
|
---|
332 | static void TAG(fx_init_fastpath)( struct fx_fast_tab *tab )
|
---|
333 | {
|
---|
334 | GLuint i;
|
---|
335 |
|
---|
336 | /* Use the render templates to do clipping.
|
---|
337 | */
|
---|
338 | TAG(render_init)();
|
---|
339 | for (i = 0 ; i < GL_POLYGON+2 ; i++)
|
---|
340 | tab->clip[i] = TAG(render_tab)[i];
|
---|
341 |
|
---|
342 | tab->build_vertices = TAG(fx_setup_full);
|
---|
343 | tab->project_vertices = TAG(fx_project_vertices);
|
---|
344 | tab->project_clipped_vertices = TAG(fx_project_clipped_vertices);
|
---|
345 |
|
---|
346 | #if defined(USE_3DNOW_ASM)
|
---|
347 | if (gl_x86_cpu_features & GL_CPU_3Dnow) {
|
---|
348 | extern void TAG(fx_3dnow_project_vertices)( GLfloat *first,
|
---|
349 | GLfloat *last,
|
---|
350 | const GLfloat *mat,
|
---|
351 | GLuint stride );
|
---|
352 |
|
---|
353 | extern void TAG(fx_3dnow_project_clipped_vertices)( GLfloat *first,
|
---|
354 | GLfloat *last,
|
---|
355 | const GLfloat *mat,
|
---|
356 | GLuint stride,
|
---|
357 | const GLubyte *mask );
|
---|
358 |
|
---|
359 | tab->project_vertices = TAG(fx_3dnow_project_vertices);
|
---|
360 | tab->project_clipped_vertices = TAG(fx_3dnow_project_clipped_vertices);
|
---|
361 | }
|
---|
362 | #endif
|
---|
363 | }
|
---|
364 |
|
---|
365 | #undef TYPE
|
---|
366 | #undef TAG
|
---|
367 | #undef SIZE
|
---|