Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * Version: 6.5 |
||
4 | * |
||
5 | * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. |
||
6 | * |
||
7 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
8 | * copy of this software and associated documentation files (the "Software"), |
||
9 | * to deal in the Software without restriction, including without limitation |
||
10 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
11 | * and/or sell copies of the Software, and to permit persons to whom the |
||
12 | * Software is furnished to do so, subject to the following conditions: |
||
13 | * |
||
14 | * The above copyright notice and this permission notice shall be included |
||
15 | * in all copies or substantial portions of the Software. |
||
16 | * |
||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
18 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
20 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
||
21 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
||
22 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Brian Paul |
||
26 | * Keith Whitwell |
||
27 | */ |
||
28 | |||
29 | /* |
||
30 | * Regarding GL_NV_texgen_reflection: |
||
31 | * |
||
32 | * Portions of this software may use or implement intellectual |
||
33 | * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims |
||
34 | * any and all warranties with respect to such intellectual property, |
||
35 | * including any use thereof or modifications thereto. |
||
36 | */ |
||
37 | |||
38 | #include "main/glheader.h" |
||
39 | #include "main/colormac.h" |
||
40 | #include "main/macros.h" |
||
41 | #include "main/imports.h" |
||
42 | #include "main/mtypes.h" |
||
43 | |||
44 | #include "math/m_xform.h" |
||
45 | |||
46 | #include "t_context.h" |
||
47 | #include "t_pipeline.h" |
||
48 | |||
49 | |||
50 | /*********************************************************************** |
||
51 | * Automatic texture coordinate generation (texgen) code. |
||
52 | */ |
||
53 | |||
54 | |||
55 | struct texgen_stage_data; |
||
56 | |||
57 | typedef void (*texgen_func)( struct gl_context *ctx, |
||
58 | struct texgen_stage_data *store, |
||
59 | GLuint unit); |
||
60 | |||
61 | |||
62 | struct texgen_stage_data { |
||
63 | |||
64 | /* Per-texunit derived state. |
||
65 | */ |
||
66 | GLuint TexgenSize[MAX_TEXTURE_COORD_UNITS]; |
||
67 | texgen_func TexgenFunc[MAX_TEXTURE_COORD_UNITS]; |
||
68 | |||
69 | /* Temporary values used in texgen. |
||
70 | */ |
||
71 | GLfloat (*tmp_f)[3]; |
||
72 | GLfloat *tmp_m; |
||
73 | |||
74 | /* Buffered outputs of the stage. |
||
75 | */ |
||
76 | GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS]; |
||
77 | }; |
||
78 | |||
79 | |||
80 | #define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr) |
||
81 | |||
82 | |||
83 | |||
84 | static GLuint all_bits[5] = { |
||
85 | 0, |
||
86 | VEC_SIZE_1, |
||
87 | VEC_SIZE_2, |
||
88 | VEC_SIZE_3, |
||
89 | VEC_SIZE_4, |
||
90 | }; |
||
91 | |||
92 | #define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4) |
||
93 | |||
94 | #define TEXGEN_NEED_M (TEXGEN_SPHERE_MAP) |
||
95 | #define TEXGEN_NEED_F (TEXGEN_SPHERE_MAP | \ |
||
96 | TEXGEN_REFLECTION_MAP_NV) |
||
97 | |||
98 | |||
99 | |||
100 | static void build_m3( GLfloat f[][3], GLfloat m[], |
||
101 | const GLvector4f *normal, |
||
102 | const GLvector4f *eye ) |
||
103 | { |
||
104 | GLuint stride = eye->stride; |
||
105 | GLfloat *coord = (GLfloat *)eye->start; |
||
106 | GLuint count = eye->count; |
||
107 | const GLfloat *norm = normal->start; |
||
108 | GLuint i; |
||
109 | |||
110 | for (i=0;i |
||
111 | GLfloat u[3], two_nu, fx, fy, fz; |
||
112 | COPY_3V( u, coord ); |
||
113 | NORMALIZE_3FV( u ); |
||
114 | two_nu = 2.0F * DOT3(norm,u); |
||
115 | fx = f[i][0] = u[0] - norm[0] * two_nu; |
||
116 | fy = f[i][1] = u[1] - norm[1] * two_nu; |
||
117 | fz = f[i][2] = u[2] - norm[2] * two_nu; |
||
118 | m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); |
||
119 | if (m[i] != 0.0F) { |
||
120 | m[i] = 0.5F * _mesa_inv_sqrtf(m[i]); |
||
121 | } |
||
122 | } |
||
123 | } |
||
124 | |||
125 | |||
126 | |||
127 | static void build_m2( GLfloat f[][3], GLfloat m[], |
||
128 | const GLvector4f *normal, |
||
129 | const GLvector4f *eye ) |
||
130 | { |
||
131 | GLuint stride = eye->stride; |
||
132 | GLfloat *coord = eye->start; |
||
133 | GLuint count = eye->count; |
||
134 | |||
135 | GLfloat *norm = normal->start; |
||
136 | GLuint i; |
||
137 | |||
138 | for (i=0;i |
||
139 | GLfloat u[3], two_nu, fx, fy, fz; |
||
140 | COPY_2V( u, coord ); |
||
141 | u[2] = 0; |
||
142 | NORMALIZE_3FV( u ); |
||
143 | two_nu = 2.0F * DOT3(norm,u); |
||
144 | fx = f[i][0] = u[0] - norm[0] * two_nu; |
||
145 | fy = f[i][1] = u[1] - norm[1] * two_nu; |
||
146 | fz = f[i][2] = u[2] - norm[2] * two_nu; |
||
147 | m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); |
||
148 | if (m[i] != 0.0F) { |
||
149 | m[i] = 0.5F * _mesa_inv_sqrtf(m[i]); |
||
150 | } |
||
151 | } |
||
152 | } |
||
153 | |||
154 | |||
155 | |||
156 | typedef void (*build_m_func)( GLfloat f[][3], |
||
157 | GLfloat m[], |
||
158 | const GLvector4f *normal, |
||
159 | const GLvector4f *eye ); |
||
160 | |||
161 | |||
162 | static build_m_func build_m_tab[5] = { |
||
163 | NULL, |
||
164 | NULL, |
||
165 | build_m2, |
||
166 | build_m3, |
||
167 | build_m3 |
||
168 | }; |
||
169 | |||
170 | |||
171 | /* This is unusual in that we respect the stride of the output vector |
||
172 | * (f). This allows us to pass in either a texcoord vector4f, or a |
||
173 | * temporary vector3f. |
||
174 | */ |
||
175 | static void build_f3( GLfloat *f, |
||
176 | GLuint fstride, |
||
177 | const GLvector4f *normal, |
||
178 | const GLvector4f *eye ) |
||
179 | { |
||
180 | GLuint stride = eye->stride; |
||
181 | GLfloat *coord = eye->start; |
||
182 | GLuint count = eye->count; |
||
183 | |||
184 | GLfloat *norm = normal->start; |
||
185 | GLuint i; |
||
186 | |||
187 | for (i=0;i |
||
188 | GLfloat u[3], two_nu; |
||
189 | COPY_3V( u, coord ); |
||
190 | NORMALIZE_3FV( u ); |
||
191 | two_nu = 2.0F * DOT3(norm,u); |
||
192 | f[0] = u[0] - norm[0] * two_nu; |
||
193 | f[1] = u[1] - norm[1] * two_nu; |
||
194 | f[2] = u[2] - norm[2] * two_nu; |
||
195 | STRIDE_F(coord,stride); |
||
196 | STRIDE_F(f,fstride); |
||
197 | STRIDE_F(norm, normal->stride); |
||
198 | } |
||
199 | } |
||
200 | |||
201 | |||
202 | static void build_f2( GLfloat *f, |
||
203 | GLuint fstride, |
||
204 | const GLvector4f *normal, |
||
205 | const GLvector4f *eye ) |
||
206 | { |
||
207 | GLuint stride = eye->stride; |
||
208 | GLfloat *coord = eye->start; |
||
209 | GLuint count = eye->count; |
||
210 | GLfloat *norm = normal->start; |
||
211 | GLuint i; |
||
212 | |||
213 | for (i=0;i |
||
214 | |||
215 | GLfloat u[3], two_nu; |
||
216 | COPY_2V( u, coord ); |
||
217 | u[2] = 0; |
||
218 | NORMALIZE_3FV( u ); |
||
219 | two_nu = 2.0F * DOT3(norm,u); |
||
220 | f[0] = u[0] - norm[0] * two_nu; |
||
221 | f[1] = u[1] - norm[1] * two_nu; |
||
222 | f[2] = u[2] - norm[2] * two_nu; |
||
223 | |||
224 | STRIDE_F(coord,stride); |
||
225 | STRIDE_F(f,fstride); |
||
226 | STRIDE_F(norm, normal->stride); |
||
227 | } |
||
228 | } |
||
229 | |||
230 | typedef void (*build_f_func)( GLfloat *f, |
||
231 | GLuint fstride, |
||
232 | const GLvector4f *normal_vec, |
||
233 | const GLvector4f *eye ); |
||
234 | |||
235 | |||
236 | |||
237 | /* Just treat 4-vectors as 3-vectors. |
||
238 | */ |
||
239 | static build_f_func build_f_tab[5] = { |
||
240 | NULL, |
||
241 | NULL, |
||
242 | build_f2, |
||
243 | build_f3, |
||
244 | build_f3 |
||
245 | }; |
||
246 | |||
247 | |||
248 | |||
249 | /* Special case texgen functions. |
||
250 | */ |
||
251 | static void texgen_reflection_map_nv( struct gl_context *ctx, |
||
252 | struct texgen_stage_data *store, |
||
253 | GLuint unit ) |
||
254 | { |
||
255 | struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
||
256 | GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; |
||
257 | GLvector4f *out = &store->texcoord[unit]; |
||
258 | |||
259 | build_f_tab[VB->EyePtr->size]( out->start, |
||
260 | out->stride, |
||
261 | VB->AttribPtr[_TNL_ATTRIB_NORMAL], |
||
262 | VB->EyePtr ); |
||
263 | |||
264 | out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; |
||
265 | out->count = VB->Count; |
||
266 | out->size = MAX2(in->size, 3); |
||
267 | if (in->size == 4) |
||
268 | _mesa_copy_tab[0x8]( out, in ); |
||
269 | } |
||
270 | |||
271 | |||
272 | |||
273 | static void texgen_normal_map_nv( struct gl_context *ctx, |
||
274 | struct texgen_stage_data *store, |
||
275 | GLuint unit ) |
||
276 | { |
||
277 | struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
||
278 | GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; |
||
279 | GLvector4f *out = &store->texcoord[unit]; |
||
280 | GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; |
||
281 | GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start; |
||
282 | GLuint count = VB->Count; |
||
283 | GLuint i; |
||
284 | const GLfloat *norm = normal->start; |
||
285 | |||
286 | for (i=0;i |
||
287 | texcoord[i][0] = norm[0]; |
||
288 | texcoord[i][1] = norm[1]; |
||
289 | texcoord[i][2] = norm[2]; |
||
290 | } |
||
291 | |||
292 | |||
293 | out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; |
||
294 | out->count = count; |
||
295 | out->size = MAX2(in->size, 3); |
||
296 | if (in->size == 4) |
||
297 | _mesa_copy_tab[0x8]( out, in ); |
||
298 | } |
||
299 | |||
300 | |||
301 | static void texgen_sphere_map( struct gl_context *ctx, |
||
302 | struct texgen_stage_data *store, |
||
303 | GLuint unit ) |
||
304 | { |
||
305 | struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
||
306 | GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; |
||
307 | GLvector4f *out = &store->texcoord[unit]; |
||
308 | GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start; |
||
309 | GLuint count = VB->Count; |
||
310 | GLuint i; |
||
311 | GLfloat (*f)[3] = store->tmp_f; |
||
312 | GLfloat *m = store->tmp_m; |
||
313 | |||
314 | (build_m_tab[VB->EyePtr->size])( store->tmp_f, |
||
315 | store->tmp_m, |
||
316 | VB->AttribPtr[_TNL_ATTRIB_NORMAL], |
||
317 | VB->EyePtr ); |
||
318 | |||
319 | out->size = MAX2(in->size,2); |
||
320 | |||
321 | for (i=0;i |
||
322 | texcoord[i][0] = f[i][0] * m[i] + 0.5F; |
||
323 | texcoord[i][1] = f[i][1] * m[i] + 0.5F; |
||
324 | } |
||
325 | |||
326 | out->count = count; |
||
327 | out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2; |
||
328 | if (in->size > 2) |
||
329 | _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in ); |
||
330 | } |
||
331 | |||
332 | |||
333 | |||
334 | static void texgen( struct gl_context *ctx, |
||
335 | struct texgen_stage_data *store, |
||
336 | GLuint unit ) |
||
337 | { |
||
338 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
339 | struct vertex_buffer *VB = &tnl->vb; |
||
340 | GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; |
||
341 | GLvector4f *out = &store->texcoord[unit]; |
||
342 | const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
||
343 | const GLvector4f *obj = VB->AttribPtr[_TNL_ATTRIB_POS]; |
||
344 | const GLvector4f *eye = VB->EyePtr; |
||
345 | const GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; |
||
346 | const GLfloat *m = store->tmp_m; |
||
347 | const GLuint count = VB->Count; |
||
348 | GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data; |
||
349 | GLfloat (*f)[3] = store->tmp_f; |
||
350 | GLuint copy; |
||
351 | |||
352 | if (texUnit->_GenFlags & TEXGEN_NEED_M) { |
||
353 | build_m_tab[eye->size]( store->tmp_f, store->tmp_m, normal, eye ); |
||
354 | } else if (texUnit->_GenFlags & TEXGEN_NEED_F) { |
||
355 | build_f_tab[eye->size]( (GLfloat *)store->tmp_f, 3, normal, eye ); |
||
356 | } |
||
357 | |||
358 | |||
359 | out->size = MAX2(in->size, store->TexgenSize[unit]); |
||
360 | out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled; |
||
361 | out->count = count; |
||
362 | |||
363 | copy = (all_bits[in->size] & ~texUnit->TexGenEnabled); |
||
364 | if (copy) |
||
365 | _mesa_copy_tab[copy]( out, in ); |
||
366 | |||
367 | if (texUnit->TexGenEnabled & S_BIT) { |
||
368 | GLuint i; |
||
369 | switch (texUnit->GenS.Mode) { |
||
370 | case GL_OBJECT_LINEAR: |
||
371 | _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data, |
||
372 | sizeof(out->data[0]), obj, |
||
373 | texUnit->GenS.ObjectPlane ); |
||
374 | break; |
||
375 | case GL_EYE_LINEAR: |
||
376 | _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data, |
||
377 | sizeof(out->data[0]), eye, |
||
378 | texUnit->GenS.EyePlane ); |
||
379 | break; |
||
380 | case GL_SPHERE_MAP: |
||
381 | for (i = 0; i < count; i++) |
||
382 | texcoord[i][0] = f[i][0] * m[i] + 0.5F; |
||
383 | break; |
||
384 | case GL_REFLECTION_MAP_NV: |
||
385 | for (i=0;i |
||
386 | texcoord[i][0] = f[i][0]; |
||
387 | break; |
||
388 | case GL_NORMAL_MAP_NV: { |
||
389 | const GLfloat *norm = normal->start; |
||
390 | for (i=0;i |
||
391 | texcoord[i][0] = norm[0]; |
||
392 | } |
||
393 | break; |
||
394 | } |
||
395 | default: |
||
396 | _mesa_problem(ctx, "Bad S texgen"); |
||
397 | } |
||
398 | } |
||
399 | |||
400 | if (texUnit->TexGenEnabled & T_BIT) { |
||
401 | GLuint i; |
||
402 | switch (texUnit->GenT.Mode) { |
||
403 | case GL_OBJECT_LINEAR: |
||
404 | _mesa_dotprod_tab[obj->size]( &(out->data[0][1]), |
||
405 | sizeof(out->data[0]), obj, |
||
406 | texUnit->GenT.ObjectPlane ); |
||
407 | break; |
||
408 | case GL_EYE_LINEAR: |
||
409 | _mesa_dotprod_tab[eye->size]( &(out->data[0][1]), |
||
410 | sizeof(out->data[0]), eye, |
||
411 | texUnit->GenT.EyePlane ); |
||
412 | break; |
||
413 | case GL_SPHERE_MAP: |
||
414 | for (i = 0; i < count; i++) |
||
415 | texcoord[i][1] = f[i][1] * m[i] + 0.5F; |
||
416 | break; |
||
417 | case GL_REFLECTION_MAP_NV: |
||
418 | for (i=0;i |
||
419 | texcoord[i][1] = f[i][1]; |
||
420 | break; |
||
421 | case GL_NORMAL_MAP_NV: { |
||
422 | const GLfloat *norm = normal->start; |
||
423 | for (i=0;i |
||
424 | texcoord[i][1] = norm[1]; |
||
425 | } |
||
426 | break; |
||
427 | } |
||
428 | default: |
||
429 | _mesa_problem(ctx, "Bad T texgen"); |
||
430 | } |
||
431 | } |
||
432 | |||
433 | if (texUnit->TexGenEnabled & R_BIT) { |
||
434 | GLuint i; |
||
435 | switch (texUnit->GenR.Mode) { |
||
436 | case GL_OBJECT_LINEAR: |
||
437 | _mesa_dotprod_tab[obj->size]( &(out->data[0][2]), |
||
438 | sizeof(out->data[0]), obj, |
||
439 | texUnit->GenR.ObjectPlane ); |
||
440 | break; |
||
441 | case GL_EYE_LINEAR: |
||
442 | _mesa_dotprod_tab[eye->size]( &(out->data[0][2]), |
||
443 | sizeof(out->data[0]), eye, |
||
444 | texUnit->GenR.EyePlane ); |
||
445 | break; |
||
446 | case GL_REFLECTION_MAP_NV: |
||
447 | for (i=0;i |
||
448 | texcoord[i][2] = f[i][2]; |
||
449 | break; |
||
450 | case GL_NORMAL_MAP_NV: { |
||
451 | const GLfloat *norm = normal->start; |
||
452 | for (i=0;i |
||
453 | texcoord[i][2] = norm[2]; |
||
454 | } |
||
455 | break; |
||
456 | } |
||
457 | default: |
||
458 | _mesa_problem(ctx, "Bad R texgen"); |
||
459 | } |
||
460 | } |
||
461 | |||
462 | if (texUnit->TexGenEnabled & Q_BIT) { |
||
463 | switch (texUnit->GenQ.Mode) { |
||
464 | case GL_OBJECT_LINEAR: |
||
465 | _mesa_dotprod_tab[obj->size]( &(out->data[0][3]), |
||
466 | sizeof(out->data[0]), obj, |
||
467 | texUnit->GenQ.ObjectPlane ); |
||
468 | break; |
||
469 | case GL_EYE_LINEAR: |
||
470 | _mesa_dotprod_tab[eye->size]( &(out->data[0][3]), |
||
471 | sizeof(out->data[0]), eye, |
||
472 | texUnit->GenQ.EyePlane ); |
||
473 | break; |
||
474 | default: |
||
475 | _mesa_problem(ctx, "Bad Q texgen"); |
||
476 | } |
||
477 | } |
||
478 | } |
||
479 | |||
480 | |||
481 | |||
482 | |||
483 | static GLboolean run_texgen_stage( struct gl_context *ctx, |
||
484 | struct tnl_pipeline_stage *stage ) |
||
485 | { |
||
486 | struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
||
487 | struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); |
||
488 | GLuint i; |
||
489 | |||
490 | if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) |
||
491 | return GL_TRUE; |
||
492 | |||
493 | for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { |
||
494 | struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; |
||
495 | |||
496 | if (texUnit->TexGenEnabled) { |
||
497 | |||
498 | store->TexgenFunc[i]( ctx, store, i ); |
||
499 | |||
500 | VB->AttribPtr[VERT_ATTRIB_TEX0 + i] = &store->texcoord[i]; |
||
501 | } |
||
502 | } |
||
503 | |||
504 | return GL_TRUE; |
||
505 | } |
||
506 | |||
507 | |||
508 | static void validate_texgen_stage( struct gl_context *ctx, |
||
509 | struct tnl_pipeline_stage *stage ) |
||
510 | { |
||
511 | struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); |
||
512 | GLuint i; |
||
513 | |||
514 | if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) |
||
515 | return; |
||
516 | |||
517 | for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { |
||
518 | struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; |
||
519 | |||
520 | if (texUnit->TexGenEnabled) { |
||
521 | GLuint sz; |
||
522 | |||
523 | if (texUnit->TexGenEnabled & Q_BIT) |
||
524 | sz = 4; |
||
525 | else if (texUnit->TexGenEnabled & R_BIT) |
||
526 | sz = 3; |
||
527 | else if (texUnit->TexGenEnabled & T_BIT) |
||
528 | sz = 2; |
||
529 | else |
||
530 | sz = 1; |
||
531 | |||
532 | store->TexgenSize[i] = sz; |
||
533 | store->TexgenFunc[i] = texgen; /* general solution */ |
||
534 | |||
535 | /* look for special texgen cases */ |
||
536 | if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) { |
||
537 | if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) { |
||
538 | store->TexgenFunc[i] = texgen_reflection_map_nv; |
||
539 | } |
||
540 | else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) { |
||
541 | store->TexgenFunc[i] = texgen_normal_map_nv; |
||
542 | } |
||
543 | } |
||
544 | else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) && |
||
545 | texUnit->_GenFlags == TEXGEN_SPHERE_MAP) { |
||
546 | store->TexgenFunc[i] = texgen_sphere_map; |
||
547 | } |
||
548 | } |
||
549 | } |
||
550 | } |
||
551 | |||
552 | |||
553 | |||
554 | |||
555 | |||
556 | /* Called the first time stage->run() is invoked. |
||
557 | */ |
||
558 | static GLboolean alloc_texgen_data( struct gl_context *ctx, |
||
559 | struct tnl_pipeline_stage *stage ) |
||
560 | { |
||
561 | struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
||
562 | struct texgen_stage_data *store; |
||
563 | GLuint i; |
||
564 | |||
565 | stage->privatePtr = CALLOC(sizeof(*store)); |
||
566 | store = TEXGEN_STAGE_DATA(stage); |
||
567 | if (!store) |
||
568 | return GL_FALSE; |
||
569 | |||
570 | for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) |
||
571 | _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); |
||
572 | |||
573 | store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3); |
||
574 | store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat)); |
||
575 | |||
576 | return GL_TRUE; |
||
577 | } |
||
578 | |||
579 | |||
580 | static void free_texgen_data( struct tnl_pipeline_stage *stage ) |
||
581 | |||
582 | { |
||
583 | struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); |
||
584 | GLuint i; |
||
585 | |||
586 | if (store) { |
||
587 | for (i = 0 ; i < MAX_TEXTURE_COORD_UNITS ; i++) |
||
588 | if (store->texcoord[i].data) |
||
589 | _mesa_vector4f_free( &store->texcoord[i] ); |
||
590 | |||
591 | |||
592 | if (store->tmp_f) FREE( store->tmp_f ); |
||
593 | if (store->tmp_m) FREE( store->tmp_m ); |
||
594 | FREE( store ); |
||
595 | stage->privatePtr = NULL; |
||
596 | } |
||
597 | } |
||
598 | |||
599 | |||
600 | |||
601 | const struct tnl_pipeline_stage _tnl_texgen_stage = |
||
602 | { |
||
603 | "texgen", /* name */ |
||
604 | NULL, /* private data */ |
||
605 | alloc_texgen_data, /* destructor */ |
||
606 | free_texgen_data, /* destructor */ |
||
607 | validate_texgen_stage, /* check */ |
||
608 | run_texgen_stage /* run -- initially set to alloc data */ |
||
609 | };>>>> |