Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
135 giacomo 1
/* $Id: t_vb_gentex.c,v 1.1 2003-04-24 14:24:01 giacomo Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  3.5
6
 *
7
 * Copyright (C) 1999-2001  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
 * Authors:
27
 *    Brian Paul
28
 *    Keith Whitwell <keith@tungstengraphics.com>
29
 */
30
 
31
 
32
#include "glheader.h"
33
#include "colormac.h"
34
#include "context.h"
35
#include "macros.h"
36
#include "mmath.h"
37
#include "imports.h"
38
#include "mtypes.h"
39
 
40
#include "math/m_xform.h"
41
 
42
#include "t_context.h"
43
#include "t_pipeline.h"
44
 
45
 
46
/***********************************************************************
47
 * Automatic texture coordinate generation (texgen) code.
48
 */
49
 
50
 
51
struct texgen_stage_data;
52
 
53
typedef void (*texgen_func)( GLcontext *ctx,
54
                             struct texgen_stage_data *store,
55
                             GLuint unit);
56
 
57
 
58
struct texgen_stage_data {
59
 
60
   /* Per-texunit derived state.
61
    */
62
   GLuint TexgenSize[MAX_TEXTURE_UNITS];
63
   GLuint TexgenHoles[MAX_TEXTURE_UNITS];
64
   texgen_func TexgenFunc[MAX_TEXTURE_UNITS];
65
 
66
   /* Temporary values used in texgen.
67
    */
68
   GLfloat (*tmp_f)[3];
69
   GLfloat *tmp_m;
70
 
71
   /* Buffered outputs of the stage.
72
    */
73
   GLvector4f texcoord[MAX_TEXTURE_UNITS];
74
};
75
 
76
 
77
#define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr)
78
 
79
 
80
 
81
static GLuint all_bits[5] = {
82
   0,
83
   VEC_SIZE_1,
84
   VEC_SIZE_2,
85
   VEC_SIZE_3,
86
   VEC_SIZE_4,
87
};
88
 
89
#define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4)
90
 
91
#define TEXGEN_NEED_M            (TEXGEN_SPHERE_MAP)
92
#define TEXGEN_NEED_F            (TEXGEN_SPHERE_MAP        | \
93
                                  TEXGEN_REFLECTION_MAP_NV)
94
 
95
 
96
 
97
static void build_m3( GLfloat f[][3], GLfloat m[],
98
                      const GLvector4f *normal,
99
                      const GLvector4f *eye )
100
{
101
   GLuint stride = eye->stride;
102
   GLfloat *coord = (GLfloat *)eye->start;
103
   GLuint count = eye->count;
104
   const GLfloat *norm = normal->start;
105
   GLuint i;
106
 
107
   for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
108
      GLfloat u[3], two_nu, fx, fy, fz;
109
      COPY_3V( u, coord );
110
      NORMALIZE_3FV( u );
111
      two_nu = 2.0F * DOT3(norm,u);
112
      fx = f[i][0] = u[0] - norm[0] * two_nu;
113
      fy = f[i][1] = u[1] - norm[1] * two_nu;
114
      fz = f[i][2] = u[2] - norm[2] * two_nu;
115
      m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
116
      if (m[i] != 0.0F) {
117
         m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
118
      }
119
   }
120
}
121
 
122
 
123
 
124
static void build_m2( GLfloat f[][3], GLfloat m[],
125
                      const GLvector4f *normal,
126
                      const GLvector4f *eye )
127
{
128
   GLuint stride = eye->stride;
129
   GLfloat *coord = eye->start;
130
   GLuint count = eye->count;
131
 
132
   GLfloat *norm = normal->start;
133
   GLuint i;
134
 
135
   for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
136
      GLfloat u[3], two_nu, fx, fy, fz;
137
      COPY_2V( u, coord );
138
      u[2] = 0;
139
      NORMALIZE_3FV( u );
140
      two_nu = 2.0F * DOT3(norm,u);
141
      fx = f[i][0] = u[0] - norm[0] * two_nu;
142
      fy = f[i][1] = u[1] - norm[1] * two_nu;
143
      fz = f[i][2] = u[2] - norm[2] * two_nu;
144
      m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
145
      if (m[i] != 0.0F) {
146
         m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
147
      }
148
   }
149
}
150
 
151
 
152
 
153
typedef void (*build_m_func)( GLfloat f[][3],
154
                              GLfloat m[],
155
                              const GLvector4f *normal,
156
                              const GLvector4f *eye );
157
 
158
 
159
static build_m_func build_m_tab[5] = {
160
   0,
161
   0,
162
   build_m2,
163
   build_m3,
164
   build_m3
165
};
166
 
167
 
168
/* This is unusual in that we respect the stride of the output vector
169
 * (f).  This allows us to pass in either a texcoord vector4f, or a
170
 * temporary vector3f.
171
 */
172
static void build_f3( GLfloat *f,
173
                      GLuint fstride,
174
                      const GLvector4f *normal,
175
                      const GLvector4f *eye )
176
{
177
   GLuint stride = eye->stride;
178
   GLfloat *coord = eye->start;
179
   GLuint count = eye->count;
180
 
181
   GLfloat *norm = normal->start;
182
   GLuint i;
183
 
184
   for (i=0;i<count;i++) {
185
      GLfloat u[3], two_nu;
186
      COPY_3V( u, coord );
187
      NORMALIZE_3FV( u );
188
      two_nu = 2.0F * DOT3(norm,u);
189
      f[0] = u[0] - norm[0] * two_nu;
190
      f[1] = u[1] - norm[1] * two_nu;
191
      f[2] = u[2] - norm[2] * two_nu;
192
      STRIDE_F(coord,stride);
193
      STRIDE_F(f,fstride);
194
      STRIDE_F(norm, normal->stride);
195
   }
196
}
197
 
198
 
199
static void build_f2( GLfloat *f,
200
                      GLuint fstride,
201
                      const GLvector4f *normal,
202
                      const GLvector4f *eye )
203
{
204
   GLuint stride = eye->stride;
205
   GLfloat *coord = eye->start;
206
   GLuint count = eye->count;
207
   GLfloat *norm = normal->start;
208
   GLuint i;
209
 
210
   for (i=0;i<count;i++) {
211
 
212
      GLfloat u[3], two_nu;
213
      COPY_2V( u, coord );
214
      u[2] = 0;
215
      NORMALIZE_3FV( u );
216
      two_nu = 2.0F * DOT3(norm,u);
217
      f[0] = u[0] - norm[0] * two_nu;
218
      f[1] = u[1] - norm[1] * two_nu;
219
      f[2] = u[2] - norm[2] * two_nu;
220
 
221
      STRIDE_F(coord,stride);
222
      STRIDE_F(f,fstride);
223
      STRIDE_F(norm, normal->stride);
224
   }
225
}
226
 
227
typedef void (*build_f_func)( GLfloat *f,
228
                              GLuint fstride,
229
                              const GLvector4f *normal_vec,
230
                              const GLvector4f *eye );
231
 
232
 
233
 
234
/* Just treat 4-vectors as 3-vectors.
235
 */
236
static build_f_func build_f_tab[5] = {
237
   0,
238
   0,
239
   build_f2,
240
   build_f3,
241
   build_f3
242
};
243
 
244
 
245
/* Special case texgen functions.
246
 */
247
static void texgen_reflection_map_nv( GLcontext *ctx,
248
                                      struct texgen_stage_data *store,
249
                                      GLuint unit )
250
{
251
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
252
   GLvector4f *in = VB->TexCoordPtr[unit];
253
   GLvector4f *out = &store->texcoord[unit];
254
 
255
   build_f_tab[VB->EyePtr->size]( out->start,
256
                                  out->stride,
257
                                  VB->NormalPtr,
258
                                  VB->EyePtr );
259
 
260
   if (in) {
261
      out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
262
      out->count = in->count;
263
      out->size = MAX2(in->size, 3);
264
      if (in->size == 4)
265
         _mesa_copy_tab[0x8]( out, in );
266
   }
267
   else {
268
      out->flags |= VEC_SIZE_3;
269
      out->size = 3;
270
      out->count = in->count;
271
   }
272
 
273
}
274
 
275
 
276
 
277
static void texgen_normal_map_nv( GLcontext *ctx,
278
                                  struct texgen_stage_data *store,
279
                                  GLuint unit )
280
{
281
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
282
   GLvector4f *in = VB->TexCoordPtr[unit];
283
   GLvector4f *out = &store->texcoord[unit];
284
   GLvector4f *normal = VB->NormalPtr;
285
   GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start;
286
   GLuint count = VB->Count;
287
   GLuint i;
288
   const GLfloat *norm = normal->start;
289
 
290
   for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
291
      texcoord[i][0] = norm[0];
292
      texcoord[i][1] = norm[1];
293
      texcoord[i][2] = norm[2];
294
   }
295
 
296
 
297
   if (in) {
298
      out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
299
      out->count = in->count;
300
      out->size = MAX2(in->size, 3);
301
      if (in->size == 4)
302
         _mesa_copy_tab[0x8]( out, in );
303
   }
304
   else {
305
      out->flags |= VEC_SIZE_3;
306
      out->size = 3;
307
      out->count = in->count;
308
   }
309
}
310
 
311
 
312
static void texgen_sphere_map( GLcontext *ctx,
313
                               struct texgen_stage_data *store,
314
                               GLuint unit )
315
{
316
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
317
   GLvector4f *in = VB->TexCoordPtr[unit];
318
   GLvector4f *out = &store->texcoord[unit];
319
   GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start;
320
   GLuint count = VB->Count;
321
   GLuint i;
322
   GLfloat (*f)[3] = store->tmp_f;
323
   GLfloat *m = store->tmp_m;
324
 
325
/*     _mesa_debug(NULL, "%s normstride %d eyestride %d\n",  */
326
/*         __FUNCTION__, VB->NormalPtr->stride, */
327
/*         VB->EyePtr->stride); */
328
 
329
   (build_m_tab[VB->EyePtr->size])( store->tmp_f,
330
                                    store->tmp_m,
331
                                    VB->NormalPtr,
332
                                    VB->EyePtr );
333
 
334
   for (i=0;i<count;i++) {
335
      texcoord[i][0] = f[i][0] * m[i] + 0.5F;
336
      texcoord[i][1] = f[i][1] * m[i] + 0.5F;
337
   }
338
 
339
   if (in) {
340
      out->size = MAX2(in->size,2);
341
      out->count = in->count;
342
      out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2;
343
      if (in->size > 2)
344
         _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in );
345
   } else {
346
      out->size = 2;
347
      out->flags |= VEC_SIZE_2;
348
      out->count = in->count;
349
   }
350
}
351
 
352
 
353
 
354
static void texgen( GLcontext *ctx,
355
                    struct texgen_stage_data *store,
356
                    GLuint unit )
357
{
358
   TNLcontext *tnl = TNL_CONTEXT(ctx);
359
   struct vertex_buffer *VB = &tnl->vb;
360
   GLvector4f *in = VB->TexCoordPtr[unit];
361
   GLvector4f *out = &store->texcoord[unit];
362
   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
363
   const GLvector4f *obj = VB->ObjPtr;
364
   const GLvector4f *eye = VB->EyePtr;
365
   const GLvector4f *normal = VB->NormalPtr;
366
   GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
367
   GLfloat *indata;
368
   GLuint count = VB->Count;
369
   GLfloat (*f)[3] = store->tmp_f;
370
   GLfloat *m = store->tmp_m;
371
         GLuint holes = 0;
372
 
373
 
374
   if (texUnit->_GenFlags & TEXGEN_NEED_M) {
375
      build_m_tab[in->size]( store->tmp_f, store->tmp_m, normal, eye );
376
   } else if (texUnit->_GenFlags & TEXGEN_NEED_F) {
377
      build_f_tab[in->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
378
   }
379
 
380
   if (!in) {
381
      ASSERT(0);
382
      in = out;
383
      in->count = VB->Count;
384
 
385
      out->size = store->TexgenSize[unit];
386
      out->flags |= texUnit->TexGenEnabled;
387
      out->count = VB->Count;
388
      holes = store->TexgenHoles[unit];
389
   }
390
   else {
391
      GLuint copy = (all_bits[in->size] & ~texUnit->TexGenEnabled);
392
      if (copy)
393
         _mesa_copy_tab[copy]( out, in );
394
 
395
      out->size = MAX2(in->size, store->TexgenSize[unit]);
396
      out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled;
397
      out->count = in->count;
398
 
399
      holes = ~all_bits[in->size] & store->TexgenHoles[unit];
400
   }
401
 
402
   if (holes) {
403
      if (holes & VEC_DIRTY_2) _mesa_vector4f_clean_elem(out, count, 2);
404
      if (holes & VEC_DIRTY_1) _mesa_vector4f_clean_elem(out, count, 1);
405
      if (holes & VEC_DIRTY_0) _mesa_vector4f_clean_elem(out, count, 0);
406
   }
407
 
408
   if (texUnit->TexGenEnabled & S_BIT) {
409
      GLuint i;
410
      switch (texUnit->GenModeS) {
411
      case GL_OBJECT_LINEAR:
412
         _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data,
413
                                       sizeof(out->data[0]), obj,
414
                                       texUnit->ObjectPlaneS );
415
         break;
416
      case GL_EYE_LINEAR:
417
         _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data,
418
                                       sizeof(out->data[0]), eye,
419
                                       texUnit->EyePlaneS );
420
         break;
421
      case GL_SPHERE_MAP:
422
         for (indata=in->start,i=0 ; i<count ;i++, STRIDE_F(indata,in->stride))
423
            texcoord[i][0] = indata[0] * m[i] + 0.5F;
424
         break;
425
      case GL_REFLECTION_MAP_NV:
426
         for (i=0;i<count;i++)
427
             texcoord[i][0] = f[i][0];
428
         break;
429
      case GL_NORMAL_MAP_NV: {
430
         const GLfloat *norm = normal->start;
431
         for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
432
             texcoord[i][0] = norm[0];
433
         }
434
         break;
435
      }
436
      default:
437
         _mesa_problem(ctx, "Bad S texgen");
438
      }
439
   }
440
 
441
   if (texUnit->TexGenEnabled & T_BIT) {
442
      GLuint i;
443
      switch (texUnit->GenModeT) {
444
      case GL_OBJECT_LINEAR:
445
         _mesa_dotprod_tab[obj->size]( &(out->data[0][1]),
446
                                       sizeof(out->data[0]), obj,
447
                                       texUnit->ObjectPlaneT );
448
         break;
449
      case GL_EYE_LINEAR:
450
         _mesa_dotprod_tab[eye->size]( &(out->data[0][1]),
451
                                       sizeof(out->data[0]), eye,
452
                                       texUnit->EyePlaneT );
453
         break;
454
      case GL_SPHERE_MAP:
455
         for (indata=in->start,i=0; i<count ;i++,STRIDE_F(indata,in->stride))
456
             texcoord[i][1] = indata[1] * m[i] + 0.5F;
457
         break;
458
      case GL_REFLECTION_MAP_NV:
459
         for (i=0;i<count;i++)
460
             texcoord[i][0] = f[i][0];
461
         break;
462
      case GL_NORMAL_MAP_NV: {
463
         const GLfloat *norm = normal->start;
464
         for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
465
             texcoord[i][1] = norm[1];
466
         }
467
         break;
468
      }
469
      default:
470
         _mesa_problem(ctx, "Bad T texgen");
471
      }
472
   }
473
 
474
   if (texUnit->TexGenEnabled & R_BIT) {
475
      GLuint i;
476
      switch (texUnit->GenModeR) {
477
      case GL_OBJECT_LINEAR:
478
         _mesa_dotprod_tab[obj->size]( &(out->data[0][2]),
479
                                       sizeof(out->data[0]), obj,
480
                                       texUnit->ObjectPlaneR );
481
         break;
482
      case GL_EYE_LINEAR:
483
         _mesa_dotprod_tab[eye->size]( &(out->data[0][2]),
484
                                       sizeof(out->data[0]), eye,
485
                                       texUnit->EyePlaneR );
486
         break;
487
      case GL_REFLECTION_MAP_NV:
488
         for (i=0;i<count;i++)
489
             texcoord[i][2] = f[i][2];
490
         break;
491
      case GL_NORMAL_MAP_NV: {
492
         const GLfloat *norm = normal->start;
493
         for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) {
494
             texcoord[i][2] = norm[2];
495
         }
496
         break;
497
      }
498
      default:
499
         _mesa_problem(ctx, "Bad R texgen");
500
      }
501
   }
502
 
503
   if (texUnit->TexGenEnabled & Q_BIT) {
504
      switch (texUnit->GenModeQ) {
505
      case GL_OBJECT_LINEAR:
506
         _mesa_dotprod_tab[obj->size]( &(out->data[0][3]),
507
                                       sizeof(out->data[0]), obj,
508
                                       texUnit->ObjectPlaneQ );
509
         break;
510
      case GL_EYE_LINEAR:
511
         _mesa_dotprod_tab[eye->size]( &(out->data[0][3]),
512
                                       sizeof(out->data[0]), eye,
513
                                       texUnit->EyePlaneQ );
514
         break;
515
      default:
516
         _mesa_problem(ctx, "Bad Q texgen");
517
      }
518
   }
519
}
520
 
521
 
522
 
523
static GLboolean run_texgen_stage( GLcontext *ctx,
524
                                   struct gl_pipeline_stage *stage )
525
{
526
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
527
   struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage );
528
   GLuint i;
529
 
530
   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
531
      if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) {
532
         if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i)))
533
            store->TexgenFunc[i]( ctx, store, i );
534
 
535
         VB->TexCoordPtr[i] = &store->texcoord[i];
536
      }
537
 
538
   return GL_TRUE;
539
}
540
 
541
 
542
 
543
 
544
static GLboolean run_validate_texgen_stage( GLcontext *ctx,
545
                                            struct gl_pipeline_stage *stage )
546
{
547
   struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
548
   GLuint i;
549
 
550
   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
551
      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
552
 
553
      if (texUnit->TexGenEnabled) {
554
         GLuint sz;
555
 
556
         if (texUnit->TexGenEnabled & R_BIT)
557
            sz = 4;
558
         else if (texUnit->TexGenEnabled & Q_BIT)
559
            sz = 3;
560
         else if (texUnit->TexGenEnabled & T_BIT)
561
            sz = 2;
562
         else
563
            sz = 1;
564
 
565
         store->TexgenSize[i] = sz;
566
         store->TexgenHoles[i] = (all_bits[sz] & ~texUnit->TexGenEnabled);
567
         store->TexgenFunc[i] = texgen;
568
 
569
         if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
570
            if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) {
571
               store->TexgenFunc[i] = texgen_reflection_map_nv;
572
            }
573
            else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) {
574
               store->TexgenFunc[i] = texgen_normal_map_nv;
575
            }
576
         }
577
         else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
578
                  texUnit->_GenFlags == TEXGEN_SPHERE_MAP) {
579
            store->TexgenFunc[i] = texgen_sphere_map;
580
         }
581
      }
582
   }
583
 
584
   stage->run = run_texgen_stage;
585
   return stage->run( ctx, stage );
586
}
587
 
588
 
589
static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
590
{
591
   GLuint i;
592
   stage->active = 0;
593
 
594
   if (ctx->Texture._TexGenEnabled && !ctx->VertexProgram.Enabled) {
595
      GLuint inputs = 0;
596
      GLuint outputs = 0;
597
 
598
      if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR)
599
         inputs |= VERT_BIT_POS;
600
 
601
      if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)
602
         inputs |= VERT_BIT_EYE;
603
 
604
      if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
605
         inputs |= VERT_BIT_NORMAL;
606
 
607
      for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
608
         if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i))
609
         {
610
            outputs |= VERT_BIT_TEX(i);
611
 
612
            /* Need the original input in case it contains a Q coord:
613
             * (sigh)
614
             */
615
            inputs |= VERT_BIT_TEX(i);
616
 
617
            /* Something for Feedback? */
618
         }
619
 
620
      if (stage->privatePtr)
621
         stage->run = run_validate_texgen_stage;
622
      stage->active = 1;
623
      stage->inputs = inputs;
624
      stage->outputs = outputs;
625
   }
626
}
627
 
628
 
629
 
630
 
631
/* Called the first time stage->run() is invoked.
632
 */
633
static GLboolean alloc_texgen_data( GLcontext *ctx,
634
                                    struct gl_pipeline_stage *stage )
635
{
636
   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
637
   struct texgen_stage_data *store;
638
   GLuint i;
639
 
640
   stage->privatePtr = CALLOC(sizeof(*store));
641
   store = TEXGEN_STAGE_DATA(stage);
642
   if (!store)
643
      return GL_FALSE;
644
 
645
   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
646
      _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
647
 
648
   store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
649
   store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat));
650
 
651
   /* Now validate and run the stage.
652
    */
653
   stage->run = run_validate_texgen_stage;
654
   return stage->run( ctx, stage );
655
}
656
 
657
 
658
static void free_texgen_data( struct gl_pipeline_stage *stage )
659
 
660
{
661
   struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
662
   GLuint i;
663
 
664
   if (store) {
665
      for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
666
         if (store->texcoord[i].data)
667
            _mesa_vector4f_free( &store->texcoord[i] );
668
 
669
 
670
      if (store->tmp_f) FREE( store->tmp_f );
671
      if (store->tmp_m) FREE( store->tmp_m );
672
      FREE( store );
673
      stage->privatePtr = NULL;
674
   }
675
}
676
 
677
 
678
 
679
const struct gl_pipeline_stage _tnl_texgen_stage =
680
{
681
   "texgen",                    /* name */
682
   _NEW_TEXTURE,                /* when to call check() */
683
   _NEW_TEXTURE,                /* when to invalidate stored data */
684
   GL_FALSE,                    /* active? */
685
   0,                           /* inputs */
686
   0,                           /* outputs */
687
   0,                           /* changed_inputs */
688
   NULL,                        /* private data */
689
   free_texgen_data,            /* destructor */
690
   check_texgen,                /* check */
691
   alloc_texgen_data            /* run -- initially set to alloc data */
692
};