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