Subversion Repositories shark

Rev

Rev 56 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
135 giacomo 1
/* $Id: t_imm_exec.c,v 1.2 2003-04-24 14:22:20 giacomo Exp $ */
56 pj 2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  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
/**
28
 * \file tnl/t_imm_exec.c
29
 * \brief Setup to execute immediate-mode vertex data.
30
 * \author Keith Whitwell
31
 */
32
 
33
#include "glheader.h"
34
#include "colormac.h"
35
#include "context.h"
36
#include "enums.h"
37
#include "dlist.h"
38
#include "macros.h"
39
#include "imports.h"
40
#include "mmath.h"
41
#include "light.h"
42
#include "state.h"
43
#include "mtypes.h"
44
 
45
#include "math/m_matrix.h"
46
#include "math/m_xform.h"
47
 
48
#include "t_context.h"
135 giacomo 49
#include "t_import_array.h"
56 pj 50
#include "t_imm_alloc.h"
51
#include "t_imm_api.h"
52
#include "t_imm_debug.h"
53
#include "t_imm_dlist.h"
54
#include "t_imm_eval.h"
55
#include "t_imm_elt.h"
56
#include "t_imm_exec.h"
57
#include "t_imm_fixup.h"
58
#include "t_pipeline.h"
59
 
60
 
61
 
62
static void reset_input( GLcontext *ctx,
63
                         GLuint start,
64
                         GLuint beginstate,
65
                         GLuint savedbeginstate )
66
{
67
   struct immediate *IM = TNL_CURRENT_IM(ctx);
68
 
69
   /* Clear the dirty part of the flag array.
70
    */
71
   if (start < IM->Count+2)
72
      MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start));
73
 
74
   if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
75
      _mesa_debug(ctx, "reset_input: IM(%d) new %x\n", IM->id, beginstate);
76
 
77
   IM->Start = start;
78
   IM->Count = start;
79
   IM->LastMaterial = start;
80
   IM->BeginState = beginstate;
81
   IM->SavedBeginState = savedbeginstate;
82
   IM->TexSize = 0;
83
   IM->MaterialOrMask = 0;
84
 
85
   if (IM->MaterialMask)
86
      IM->MaterialMask[IM->Start] = 0;
87
 
88
   IM->ArrayEltFlags = ~ctx->Array._Enabled;
89
   IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0;
90
   IM->ArrayEltFlush = ctx->Array.LockCount ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER;
91
}
92
 
93
void _tnl_reset_exec_input( GLcontext *ctx,
94
                            GLuint start,
95
                            GLuint beginstate,
96
                            GLuint savedbeginstate )
97
{
98
   TNLcontext *tnl = TNL_CONTEXT(ctx);
99
   struct immediate *IM = TNL_CURRENT_IM(ctx);
100
 
101
   reset_input( ctx, start, beginstate, savedbeginstate );
102
 
103
   IM->CopyStart = start - tnl->ExecCopyCount;
104
 
105
   IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
106
   if (tnl->ExecParity)
107
      IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
108
 
109
   IM->LastPrimitive = IM->CopyStart;
110
}
111
 
112
 
113
void _tnl_reset_compile_input( GLcontext *ctx,
114
                            GLuint start,
115
                            GLuint beginstate,
116
                            GLuint savedbeginstate )
117
{
118
   struct immediate *IM = TNL_CURRENT_IM(ctx);
119
 
120
   reset_input( ctx, start, beginstate, savedbeginstate );
121
   IM->CopyStart = start;
122
   IM->LastPrimitive = IM->Start;
123
}
124
 
125
 
126
/**
127
 * Copy the last specified normal, color, texcoord, edge flag, etc
128
 * from the immediate struct into the ctx->Current attribute group.
129
 */
130
void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
131
                           GLuint flag, GLuint count )
132
{
133
   if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
134
      _tnl_print_vert_flags("copy to current", flag);
135
 
136
   /* XXX should be able to replace these conditions with a loop over
137
    * the 16 vertex attributes.
138
    */
139
   if (flag & VERT_BIT_NORMAL)
140
      COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL],
141
                IM->Attrib[VERT_ATTRIB_NORMAL][count]);
142
 
143
   if (flag & VERT_BIT_INDEX)
144
      ctx->Current.Index = IM->Index[count];
145
 
146
   if (flag & VERT_BIT_EDGEFLAG)
147
      ctx->Current.EdgeFlag = IM->EdgeFlag[count];
148
 
149
   if (flag & VERT_BIT_COLOR0) {
150
      COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR0],
151
               IM->Attrib[VERT_ATTRIB_COLOR0][count]);
152
      if (ctx->Light.ColorMaterialEnabled) {
153
         _mesa_update_color_material( ctx,
154
                                   ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
155
         TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
156
      }
157
   }
158
 
159
   if (flag & VERT_BIT_COLOR1)
160
      COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR1],
161
               IM->Attrib[VERT_ATTRIB_COLOR1][count]);
162
 
163
   if (flag & VERT_BIT_FOG)
164
      ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = IM->Attrib[VERT_ATTRIB_FOG][count][0];
165
 
166
   if (flag & VERT_BITS_TEX_ANY) {
167
      GLuint i;
168
      for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
169
         if (flag & VERT_BIT_TEX(i)) {
170
            COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i],
171
                      IM->Attrib[VERT_ATTRIB_TEX0 + i][count]);
172
         }
173
      }
174
   }
175
 
176
   if (flag & VERT_BIT_MATERIAL) {
177
      _mesa_update_material( ctx,
178
                          IM->Material[IM->LastMaterial],
179
                          IM->MaterialOrMask );
180
 
181
      TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
182
   }
183
}
184
 
185
 
186
 
187
void _tnl_compute_orflag( struct immediate *IM, GLuint start )
188
{
189
   GLuint count = IM->Count;
190
   GLuint orflag = 0;
191
   GLuint andflag = ~0U;
192
   GLuint i;
193
 
194
   IM->LastData = count-1;
195
 
196
 
197
   /* Compute the flags for the whole buffer.
198
    */
199
   for (i = start ; i < count ; i++) {
200
      andflag &= IM->Flag[i];
201
      orflag |= IM->Flag[i];
202
   }
203
 
204
   /* It is possible there will be data in the buffer arising from
205
    * calls like 'glNormal', 'glMaterial' that occur after the final
206
    * glVertex, glEval, etc.  Additionally, a buffer can consist of
207
    * eg. a single glMaterial call, in which case IM->Start ==
208
    * IM->Count, but the buffer is definitely not empty.
209
    */
210
   if (IM->Flag[i] & VERT_BITS_DATA) {
211
      IM->LastData++;
212
      orflag |= IM->Flag[i];
213
   }
214
 
215
   IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB;
216
   IM->CopyAndFlag = IM->AndFlag = andflag;
217
   IM->OrFlag = orflag;
218
   IM->CopyOrFlag = orflag;
219
   IM->Evaluated = 0;
220
}
221
 
222
 
223
/**
224
 * This is where the vertex data is transfered from the 'struct immediate
225
 * into the 'struct vertex_buffer'.
226
 *
227
 * Note: The 'start' member of the GLvector structs is now redundant
228
 * because we always re-transform copied vertices, and the vectors
229
 * below are set up so that the first copied vertex (if any) appears
230
 * at position zero.
231
 */
232
static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM )
233
{
234
   TNLcontext *tnl = TNL_CONTEXT(ctx);
235
   struct vertex_buffer *VB = &tnl->vb;
236
   struct vertex_arrays *tmp = &tnl->imm_inputs;
237
   GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */
238
   const GLuint start = IM->CopyStart;
239
   const GLuint count = IM->Count - start;
240
 
241
   /* TODO: optimize the case where nothing has changed.  (Just bind
242
    * tmp to vb).
243
    */
244
 
245
   /* Setup constant data in the VB.
246
    */
247
   VB->Count = count;
248
   VB->FirstClipped = IMM_MAXDATA - IM->CopyStart;
249
   VB->import_data = NULL;
250
   VB->importable_data = 0;
251
 
252
   /* Need an IM->FirstPrimitive?
253
    */
254
   VB->Primitive = IM->Primitive + IM->CopyStart;
255
   VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
256
   VB->FirstPrimitive = 0;
257
 
258
   VB->Flag = IM->Flag + start;
259
 
260
   /* TexCoordPtr's are zeroed in loop below.
261
    */
262
   VB->NormalPtr = NULL;
263
   VB->NormalLengthPtr = NULL;
264
   VB->EdgeFlag = NULL;
265
   VB->IndexPtr[0] = NULL;
266
   VB->IndexPtr[1] = NULL;
267
   VB->ColorPtr[0] = NULL;
268
   VB->ColorPtr[1] = NULL;
269
   VB->SecondaryColorPtr[0] = NULL;
270
   VB->SecondaryColorPtr[1] = NULL;
271
   VB->Elts = NULL;
272
   VB->MaterialMask = NULL;
273
   VB->Material = NULL;
274
 
275
/*     _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */
276
/*     _tnl_print_vert_flags("orflag", IM->OrFlag); */
277
/*     _tnl_print_vert_flags("inputs", inputs); */
278
 
279
   /* Setup the initial values of array pointers in the vb.
280
    */
281
   if (inputs & VERT_BIT_POS) {
282
      tmp->Obj.data = IM->Attrib[VERT_ATTRIB_POS] + start;
283
      tmp->Obj.start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_POS] + start);
284
      tmp->Obj.count = count;
285
      VB->ObjPtr = &tmp->Obj;
286
      if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_234)
287
         tmp->Obj.size = 4;
288
      else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23)
289
         tmp->Obj.size = 3;
290
      else
291
         tmp->Obj.size = 2;
292
   }
293
 
294
   if (inputs & VERT_BIT_NORMAL) {
295
      tmp->Normal.data = IM->Attrib[VERT_ATTRIB_NORMAL] + start;
296
      tmp->Normal.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_NORMAL] + start);
297
      tmp->Normal.count = count;
298
      tmp->Normal.size = 3; /* just to be safe */
299
      VB->NormalPtr = &tmp->Normal;
300
      if (IM->NormalLengthPtr)
301
         VB->NormalLengthPtr = IM->NormalLengthPtr + start;
302
   }
303
 
304
   if (inputs & VERT_BIT_INDEX) {
305
      tmp->Index.count = count;
306
      tmp->Index.data = IM->Index + start;
307
      tmp->Index.start = IM->Index + start;
308
      VB->IndexPtr[0] = &tmp->Index;
309
   }
310
 
311
   if (inputs & VERT_BIT_FOG) {
312
      tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start;
313
      tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start);
314
      tmp->FogCoord.count = count;
315
      VB->FogCoordPtr = &tmp->FogCoord;
316
   }
317
 
318
   if (inputs & VERT_BIT_COLOR1) {
319
      tmp->SecondaryColor.Ptr = IM->Attrib[VERT_ATTRIB_COLOR1] + start;
320
      VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
321
   }
322
 
323
   if (inputs & VERT_BIT_EDGEFLAG) {
324
      VB->EdgeFlag = IM->EdgeFlag + start;
325
   }
326
 
327
   if (inputs & VERT_BIT_COLOR0) {
328
      if (IM->CopyOrFlag & VERT_BIT_COLOR0) {
329
         tmp->Color.Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start;
330
         tmp->Color.StrideB = 4 * sizeof(GLfloat);
331
         tmp->Color.Flags = 0;
332
      }
333
      else {
334
         tmp->Color.Ptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
335
         tmp->Color.StrideB = 0;
336
         tmp->Color.Flags = CA_CLIENT_DATA; /* hack */
337
         VB->import_source = IM;
338
         VB->importable_data |= VERT_BIT_COLOR0;
339
         VB->import_data = _tnl_upgrade_current_data;
340
      }
341
      VB->ColorPtr[0] = &tmp->Color;
342
   }
343
 
344
   if (inputs & VERT_BITS_TEX_ANY) {
345
      GLuint i;
346
      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
347
         VB->TexCoordPtr[i] = NULL;
348
         if (inputs & VERT_BIT_TEX(i)) {
349
            tmp->TexCoord[i].count = count;
350
            tmp->TexCoord[i].data = IM->Attrib[VERT_ATTRIB_TEX0 + i] + start;
351
            tmp->TexCoord[i].start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_TEX0 + i] + start);
352
            tmp->TexCoord[i].size = 2;
353
            if (IM->TexSize & TEX_SIZE_3(i)) {
354
               tmp->TexCoord[i].size = 3;
355
               if (IM->TexSize & TEX_SIZE_4(i))
356
                  tmp->TexCoord[i].size = 4;
357
            }
358
            VB->TexCoordPtr[i] = &tmp->TexCoord[i];
359
         }
360
      }
361
   }
362
 
363
   if ((inputs & IM->OrFlag & VERT_BIT_MATERIAL) && IM->Material) {
364
      VB->MaterialMask = IM->MaterialMask + start;
365
      VB->Material = IM->Material + start;
366
   }
367
 
368
   /* GL_NV_vertex_program */
369
   if (ctx->VertexProgram.Enabled) {
370
      GLuint attr;
371
      for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
372
         tmp->Attribs[attr].count = count;
373
         tmp->Attribs[attr].data = IM->Attrib[attr] + start;
374
         tmp->Attribs[attr].start = (GLfloat *) (IM->Attrib[attr] + start);
375
         tmp->Attribs[attr].size = 4;
376
         VB->AttribPtr[attr] = &(tmp->Attribs[attr]);
377
      }
378
   }
379
}
380
 
381
 
382
 
383
 
384
/**
385
 * Called by exec_vert_cassette, execute_compiled_cassette, but not
386
 * exec_elt_cassette.
387
 */
388
void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM )
389
{
390
   TNLcontext *tnl = TNL_CONTEXT(ctx);
391
 
392
   _tnl_vb_bind_immediate( ctx, IM );
393
 
394
   if (IM->OrFlag & VERT_BITS_EVAL_ANY)
395
      _tnl_eval_immediate( ctx, IM );
396
 
397
   /* Invalidate all stored data before and after run:
398
    */
399
   tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
400
   tnl->Driver.RunPipeline( ctx );
401
   tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
402
 
403
   _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
404
}
405
 
406
 
407
/**
408
 * Called for regular vertex cassettes.
409
 */
410
static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
411
{
412
   if (IM->FlushElt) {
413
      /* Orflag is computed twice, but only reach this code if app is
414
       * using a mixture of glArrayElement() and glVertex() while
415
       * arrays are locked (else would be in exec_elt_cassette now).
416
       */
417
      ASSERT(ctx->Array.LockCount);
418
      ASSERT(IM->FlushElt == FLUSH_ELT_LAZY);
419
      _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Count );
420
      _tnl_compute_orflag( IM, IM->CopyStart );
421
   }
422
 
423
   _tnl_fixup_input( ctx, IM );
424
/*     _tnl_print_cassette( IM ); */
425
   _tnl_run_cassette( ctx, IM );
426
}
427
 
428
 
429
/* Called for pure, locked VERT_BIT_ELT cassettes instead of
430
 * _tnl_run_cassette.
431
 */
432
static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
433
{
434
   TNLcontext *tnl = TNL_CONTEXT(ctx);
435
   struct vertex_buffer *VB = &tnl->vb;
436
 
437
   _tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
438
 
439
   /* Take only elements and primitive information from the immediate:
440
    */
441
   VB->Elts = IM->Elt + IM->CopyStart;
442
   VB->Primitive = IM->Primitive + IM->CopyStart;
443
   VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
444
   VB->FirstPrimitive = 0;
445
 
446
   /* Run the pipeline.  No input changes as a result of this action.
447
    */
448
   tnl->Driver.RunPipeline( ctx );
449
 
450
   /* Still need to update current values:  
451
    */
452
   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
453
      _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
454
      _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData );
455
   }
456
}
457
 
458
 
459
static void
460
exec_empty_cassette( GLcontext *ctx, struct immediate *IM )
461
{
462
   if (IM->FlushElt)
463
      _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
464
 
465
   _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
466
}
467
 
468
 
469
 
470
/**
471
 * Called for all cassettes when not compiling or playing a display
472
 * list.
473
 */
474
void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM )
475
{
476
   TNLcontext *tnl = TNL_CONTEXT(ctx);
477
 
478
   _tnl_compute_orflag( IM, IM->Start );
479
   _tnl_copy_immediate_vertices( ctx, IM );
480
   _tnl_get_exec_copy_verts( ctx, IM );
481
 
482
   if (tnl->pipeline.build_state_changes)
483
      _tnl_validate_pipeline( ctx );
484
 
485
   if (IM->CopyStart == IM->Count) {
486
      exec_empty_cassette( ctx, IM );
487
   }
488
   else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
489
            ctx->Array.LockCount &&
490
            ctx->Array.Vertex.Enabled) {
491
      exec_elt_cassette( ctx, IM );
492
   }
493
   else {
494
      exec_vert_cassette( ctx, IM );
495
   }
496
 
497
   /* Only reuse the immediate if there are no copied vertices living
498
    * inside it:
499
    */
500
   {
501
      GLuint begin_state = IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
502
      GLuint saved_begin_state = IM->SavedBeginState;
503
 
504
      if (--IM->ref_count != 0) {
505
         IM = _tnl_alloc_immediate( ctx );
506
         SET_IMMEDIATE( ctx, IM );
507
      }
508
 
509
      IM->ref_count++;
510
 
511
      _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS,
512
                             begin_state, saved_begin_state );
513
   }
514
 
515
   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
516
      ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
517
}
518
 
519
 
520
 
521
 
522
/**
523
 * Setup vector pointers that will be used to bind immediates to VB's.
524
 */
525
void _tnl_imm_init( GLcontext *ctx )
526
{
527
   TNLcontext *tnl = TNL_CONTEXT(ctx);
528
   struct vertex_arrays *tmp = &tnl->imm_inputs;
529
   GLuint i;
530
   static int firsttime = 1;
531
 
532
   if (firsttime) {
533
      firsttime = 0;
534
      _tnl_imm_elt_init();
535
   }
536
 
537
   ctx->swtnl_im = _tnl_alloc_immediate( ctx );
538
   TNL_CURRENT_IM(ctx)->ref_count++;
539
 
540
   tnl->ExecCopyTexSize = 0;
541
   tnl->ExecCopyCount = 0;
542
   tnl->ExecCopySource = 0;
543
 
544
   TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS;
545
 
546
   _mesa_vector4f_init( &tmp->Obj, 0, 0 );
547
   _mesa_vector4f_init( &tmp->Normal, 0, 0 );
548
 
549
   tmp->Color.Ptr = NULL;
550
   tmp->Color.Type = GL_FLOAT;
551
   tmp->Color.Size = 4;
552
   tmp->Color.Stride = 0;
553
   tmp->Color.StrideB = 4 * sizeof(GLfloat);
554
   tmp->Color.Flags = 0;
555
 
556
   tmp->SecondaryColor.Ptr = NULL;
557
   tmp->SecondaryColor.Type = GL_FLOAT;
558
   tmp->SecondaryColor.Size = 4;
559
   tmp->SecondaryColor.Stride = 0;
560
   tmp->SecondaryColor.StrideB = 4 * sizeof(GLfloat);
561
   tmp->SecondaryColor.Flags = 0;
562
 
563
   _mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
564
   _mesa_vector1ui_init( &tmp->Index, 0, 0 );
565
   _mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
566
 
567
   for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
568
      _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
569
 
570
   /* Install the first immediate.  Intially outside begin/end.
571
    */
572
   _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
573
   tnl->ReplayHardBeginEnd = 0;
574
 
575
   _tnl_imm_vtxfmt_init( ctx );
576
}
577
 
578
 
579
/**
580
 * Deallocate the immediate-mode buffer for the given context, if
581
 * its reference count goes to zero.
582
 */
583
void _tnl_imm_destroy( GLcontext *ctx )
584
{
585
   if (TNL_CURRENT_IM(ctx)) {
586
      TNL_CURRENT_IM(ctx)->ref_count--;
587
      if (TNL_CURRENT_IM(ctx)->ref_count == 0)
588
         _tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) );
589
      /*
590
       * Don't use SET_IMMEDIATE here, or else we'll whack the
591
       * _tnl_CurrentInput pointer - not good when another
592
       * context has already been made current.
593
       * So we just set the context's own tnl immediate pointer
594
       * to 0.
595
       */
596
      ctx->swtnl_im = NULL;
597
   }
598
}