~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mesa/main/light.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Mesa 3-D graphics library
3
 
 *
4
 
 * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5
 
 * Copyright (C) 2009  VMware, Inc.  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
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21
 
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22
 
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23
 
 * OTHER DEALINGS IN THE SOFTWARE.
24
 
 */
25
 
 
26
 
 
27
 
#include "c99_math.h"
28
 
#include "glheader.h"
29
 
#include "context.h"
30
 
#include "enums.h"
31
 
#include "light.h"
32
 
#include "macros.h"
33
 
#include "mtypes.h"
34
 
#include "math/m_matrix.h"
35
 
#include "util/bitscan.h"
36
 
#include "api_exec_decl.h"
37
 
 
38
 
 
39
 
void GLAPIENTRY
40
 
_mesa_ShadeModel( GLenum mode )
41
 
{
42
 
   GET_CURRENT_CONTEXT(ctx);
43
 
 
44
 
   if (MESA_VERBOSE & VERBOSE_API)
45
 
      _mesa_debug(ctx, "glShadeModel %s\n", _mesa_enum_to_string(mode));
46
 
 
47
 
   if (ctx->Light.ShadeModel == mode)
48
 
      return;
49
 
 
50
 
   if (mode != GL_FLAT && mode != GL_SMOOTH) {
51
 
      _mesa_error(ctx, GL_INVALID_ENUM, "glShadeModel");
52
 
      return;
53
 
   }
54
 
 
55
 
   FLUSH_VERTICES(ctx, _NEW_LIGHT_STATE, GL_LIGHTING_BIT);
56
 
   ctx->Light.ShadeModel = mode;
57
 
}
58
 
 
59
 
 
60
 
/**
61
 
 * Set the provoking vertex (the vertex which specifies the prim's
62
 
 * color when flat shading) to either the first or last vertex of the
63
 
 * triangle or line.
64
 
 */
65
 
void GLAPIENTRY
66
 
_mesa_ProvokingVertex(GLenum mode)
67
 
{
68
 
   GET_CURRENT_CONTEXT(ctx);
69
 
 
70
 
   if (MESA_VERBOSE&VERBOSE_API)
71
 
      _mesa_debug(ctx, "glProvokingVertexEXT 0x%x\n", mode);
72
 
 
73
 
   if (ctx->Light.ProvokingVertex == mode)
74
 
      return;
75
 
 
76
 
   switch (mode) {
77
 
   case GL_FIRST_VERTEX_CONVENTION_EXT:
78
 
   case GL_LAST_VERTEX_CONVENTION_EXT:
79
 
      break;
80
 
   default:
81
 
      _mesa_error(ctx, GL_INVALID_ENUM, "glProvokingVertexEXT(0x%x)", mode);
82
 
      return;
83
 
   }
84
 
 
85
 
   FLUSH_VERTICES(ctx, _NEW_LIGHT_STATE, GL_LIGHTING_BIT);
86
 
   ctx->Light.ProvokingVertex = mode;
87
 
}
88
 
 
89
 
 
90
 
/**
91
 
 * Helper function called by _mesa_Lightfv and _mesa_PopAttrib to set
92
 
 * per-light state.
93
 
 * For GL_POSITION and GL_SPOT_DIRECTION the params position/direction
94
 
 * will have already been transformed by the modelview matrix!
95
 
 * Also, all error checking should have already been done.
96
 
 */
97
 
static void
98
 
do_light(struct gl_context *ctx, GLuint lnum, GLenum pname, const GLfloat *params)
99
 
{
100
 
   struct gl_light *light;
101
 
 
102
 
   assert(lnum < MAX_LIGHTS);
103
 
   light = &ctx->Light.Light[lnum];
104
 
 
105
 
   struct gl_light_uniforms *lu = &ctx->Light.LightSource[lnum];
106
 
 
107
 
   switch (pname) {
108
 
   case GL_AMBIENT:
109
 
      if (TEST_EQ_4V(lu->Ambient, params))
110
 
         return;
111
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
112
 
      COPY_4V( lu->Ambient, params );
113
 
      break;
114
 
   case GL_DIFFUSE:
115
 
      if (TEST_EQ_4V(lu->Diffuse, params))
116
 
         return;
117
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
118
 
      COPY_4V( lu->Diffuse, params );
119
 
      break;
120
 
   case GL_SPECULAR:
121
 
      if (TEST_EQ_4V(lu->Specular, params))
122
 
         return;
123
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
124
 
      COPY_4V( lu->Specular, params );
125
 
      break;
126
 
   case GL_POSITION: {
127
 
      /* NOTE: position has already been transformed by ModelView! */
128
 
      if (TEST_EQ_4V(lu->EyePosition, params))
129
 
         return;
130
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
131
 
 
132
 
      bool old_positional = lu->EyePosition[3] != 0.0f;
133
 
      bool positional = params[3] != 0.0f;
134
 
      COPY_4V(lu->EyePosition, params);
135
 
 
136
 
      if (positional != old_positional) {
137
 
         if (positional)
138
 
            light->_Flags |= LIGHT_POSITIONAL;
139
 
         else
140
 
            light->_Flags &= ~LIGHT_POSITIONAL;
141
 
 
142
 
         /* Used by fixed-func vertex program. */
143
 
         ctx->NewState |= _NEW_FF_VERT_PROGRAM;
144
 
      }
145
 
 
146
 
      static const GLfloat eye_z[] = {0, 0, 1};
147
 
      GLfloat p[3];
148
 
      /* Compute infinite half angle vector:
149
 
       *   halfVector = normalize(normalize(lightPos) + (0, 0, 1))
150
 
       * light.EyePosition.w should be 0 for infinite lights.
151
 
       */
152
 
      COPY_3V(p, params);
153
 
      NORMALIZE_3FV(p);
154
 
      ADD_3V(p, p, eye_z);
155
 
      NORMALIZE_3FV(p);
156
 
      COPY_3V(lu->_HalfVector, p);
157
 
      lu->_HalfVector[3] = 1.0;
158
 
      break;
159
 
   }
160
 
   case GL_SPOT_DIRECTION:
161
 
      /* NOTE: Direction already transformed by inverse ModelView! */
162
 
      if (TEST_EQ_3V(lu->SpotDirection, params))
163
 
         return;
164
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
165
 
      COPY_3V(lu->SpotDirection, params);
166
 
      break;
167
 
   case GL_SPOT_EXPONENT:
168
 
      assert(params[0] >= 0.0F);
169
 
      assert(params[0] <= ctx->Const.MaxSpotExponent);
170
 
      if (lu->SpotExponent == params[0])
171
 
         return;
172
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
173
 
      lu->SpotExponent = params[0];
174
 
      break;
175
 
   case GL_SPOT_CUTOFF: {
176
 
      assert(params[0] == 180.0F || (params[0] >= 0.0F && params[0] <= 90.0F));
177
 
      if (lu->SpotCutoff == params[0])
178
 
         return;
179
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
180
 
 
181
 
      bool old_is_180 = lu->SpotCutoff == 180.0f;
182
 
      bool is_180 = params[0] == 180.0f;
183
 
      lu->SpotCutoff = params[0];
184
 
      lu->_CosCutoff = (cosf(lu->SpotCutoff * M_PI / 180.0));
185
 
      if (lu->_CosCutoff < 0)
186
 
         lu->_CosCutoff = 0;
187
 
 
188
 
      if (is_180 != old_is_180) {
189
 
         if (!is_180)
190
 
            light->_Flags |= LIGHT_SPOT;
191
 
         else
192
 
            light->_Flags &= ~LIGHT_SPOT;
193
 
 
194
 
         /* Used by fixed-func vertex program. */
195
 
         ctx->NewState |= _NEW_FF_VERT_PROGRAM;
196
 
      }
197
 
      break;
198
 
   }
199
 
   case GL_CONSTANT_ATTENUATION: {
200
 
      assert(params[0] >= 0.0F);
201
 
      if (lu->ConstantAttenuation == params[0])
202
 
         return;
203
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
204
 
 
205
 
      bool old_is_one = lu->ConstantAttenuation == 1.0f;
206
 
      bool is_one = params[0] == 1.0f;
207
 
      lu->ConstantAttenuation = params[0];
208
 
 
209
 
      if (old_is_one != is_one) {
210
 
         /* Used by fixed-func vertex program. */
211
 
         ctx->NewState |= _NEW_FF_VERT_PROGRAM;
212
 
      }
213
 
      break;
214
 
   }
215
 
   case GL_LINEAR_ATTENUATION: {
216
 
      assert(params[0] >= 0.0F);
217
 
      if (lu->LinearAttenuation == params[0])
218
 
         return;
219
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
220
 
 
221
 
      bool old_is_zero = lu->LinearAttenuation == 0.0f;
222
 
      bool is_zero = params[0] == 0.0f;
223
 
      lu->LinearAttenuation = params[0];
224
 
 
225
 
      if (old_is_zero != is_zero) {
226
 
         /* Used by fixed-func vertex program. */
227
 
         ctx->NewState |= _NEW_FF_VERT_PROGRAM;
228
 
      }
229
 
      break;
230
 
   }
231
 
   case GL_QUADRATIC_ATTENUATION: {
232
 
      assert(params[0] >= 0.0F);
233
 
      if (lu->QuadraticAttenuation == params[0])
234
 
         return;
235
 
      FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
236
 
 
237
 
      bool old_is_zero = lu->QuadraticAttenuation == 0.0f;
238
 
      bool is_zero = params[0] == 0.0f;
239
 
      lu->QuadraticAttenuation = params[0];
240
 
 
241
 
      if (old_is_zero != is_zero) {
242
 
         /* Used by fixed-func vertex program. */
243
 
         ctx->NewState |= _NEW_FF_VERT_PROGRAM;
244
 
      }
245
 
      break;
246
 
   }
247
 
   default:
248
 
      unreachable("Unexpected pname in do_light()");
249
 
   }
250
 
}
251
 
 
252
 
 
253
 
void GLAPIENTRY
254
 
_mesa_Lightf( GLenum light, GLenum pname, GLfloat param )
255
 
{
256
 
   GLfloat fparam[4];
257
 
   fparam[0] = param;
258
 
   fparam[1] = fparam[2] = fparam[3] = 0.0F;
259
 
   _mesa_Lightfv( light, pname, fparam );
260
 
}
261
 
 
262
 
 
263
 
void GLAPIENTRY
264
 
_mesa_Lightfv( GLenum light, GLenum pname, const GLfloat *params )
265
 
{
266
 
   GET_CURRENT_CONTEXT(ctx);
267
 
   GLint i = (GLint) (light - GL_LIGHT0);
268
 
   GLfloat temp[4];
269
 
 
270
 
   if (i < 0 || i >= (GLint) ctx->Const.MaxLights) {
271
 
      _mesa_error( ctx, GL_INVALID_ENUM, "glLight(light=0x%x)", light );
272
 
      return;
273
 
   }
274
 
 
275
 
   /* do particular error checks, transformations */
276
 
   switch (pname) {
277
 
   case GL_AMBIENT:
278
 
   case GL_DIFFUSE:
279
 
   case GL_SPECULAR:
280
 
      /* nothing */
281
 
      break;
282
 
   case GL_POSITION:
283
 
      /* transform position by ModelView matrix */
284
 
      TRANSFORM_POINT(temp, ctx->ModelviewMatrixStack.Top->m, params);
285
 
      params = temp;
286
 
      break;
287
 
   case GL_SPOT_DIRECTION:
288
 
      /* transform direction by inverse modelview */
289
 
      if (_math_matrix_is_dirty(ctx->ModelviewMatrixStack.Top)) {
290
 
         _math_matrix_analyse(ctx->ModelviewMatrixStack.Top);
291
 
      }
292
 
      TRANSFORM_DIRECTION(temp, params, ctx->ModelviewMatrixStack.Top->m);
293
 
      params = temp;
294
 
      break;
295
 
   case GL_SPOT_EXPONENT:
296
 
      if (params[0] < 0.0F || params[0] > ctx->Const.MaxSpotExponent) {
297
 
         _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
298
 
         return;
299
 
      }
300
 
      break;
301
 
   case GL_SPOT_CUTOFF:
302
 
      if ((params[0] < 0.0F || params[0] > 90.0F) && params[0] != 180.0F) {
303
 
         _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
304
 
         return;
305
 
      }
306
 
      break;
307
 
   case GL_CONSTANT_ATTENUATION:
308
 
   case GL_LINEAR_ATTENUATION:
309
 
   case GL_QUADRATIC_ATTENUATION:
310
 
      if (params[0] < 0.0F) {
311
 
         _mesa_error(ctx, GL_INVALID_VALUE, "glLight");
312
 
         return;
313
 
      }
314
 
      break;
315
 
   default:
316
 
      _mesa_error(ctx, GL_INVALID_ENUM, "glLight(pname=0x%x)", pname);
317
 
      return;
318
 
   }
319
 
 
320
 
   do_light(ctx, i, pname, params);
321
 
}
322
 
 
323
 
 
324
 
void GLAPIENTRY
325
 
_mesa_Lighti( GLenum light, GLenum pname, GLint param )
326
 
{
327
 
   GLint iparam[4];
328
 
   iparam[0] = param;
329
 
   iparam[1] = iparam[2] = iparam[3] = 0;
330
 
   _mesa_Lightiv( light, pname, iparam );
331
 
}
332
 
 
333
 
 
334
 
void GLAPIENTRY
335
 
_mesa_Lightiv( GLenum light, GLenum pname, const GLint *params )
336
 
{
337
 
   GLfloat fparam[4];
338
 
 
339
 
   switch (pname) {
340
 
      case GL_AMBIENT:
341
 
      case GL_DIFFUSE:
342
 
      case GL_SPECULAR:
343
 
         fparam[0] = INT_TO_FLOAT( params[0] );
344
 
         fparam[1] = INT_TO_FLOAT( params[1] );
345
 
         fparam[2] = INT_TO_FLOAT( params[2] );
346
 
         fparam[3] = INT_TO_FLOAT( params[3] );
347
 
         break;
348
 
      case GL_POSITION:
349
 
         fparam[0] = (GLfloat) params[0];
350
 
         fparam[1] = (GLfloat) params[1];
351
 
         fparam[2] = (GLfloat) params[2];
352
 
         fparam[3] = (GLfloat) params[3];
353
 
         break;
354
 
      case GL_SPOT_DIRECTION:
355
 
         fparam[0] = (GLfloat) params[0];
356
 
         fparam[1] = (GLfloat) params[1];
357
 
         fparam[2] = (GLfloat) params[2];
358
 
         break;
359
 
      case GL_SPOT_EXPONENT:
360
 
      case GL_SPOT_CUTOFF:
361
 
      case GL_CONSTANT_ATTENUATION:
362
 
      case GL_LINEAR_ATTENUATION:
363
 
      case GL_QUADRATIC_ATTENUATION:
364
 
         fparam[0] = (GLfloat) params[0];
365
 
         break;
366
 
      default:
367
 
         /* error will be caught later in gl_Lightfv */
368
 
         ;
369
 
   }
370
 
 
371
 
   _mesa_Lightfv( light, pname, fparam );
372
 
}
373
 
 
374
 
 
375
 
 
376
 
void GLAPIENTRY
377
 
_mesa_GetLightfv( GLenum light, GLenum pname, GLfloat *params )
378
 
{
379
 
   GET_CURRENT_CONTEXT(ctx);
380
 
   GLint l = (GLint) (light - GL_LIGHT0);
381
 
 
382
 
   if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
383
 
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
384
 
      return;
385
 
   }
386
 
 
387
 
   switch (pname) {
388
 
      case GL_AMBIENT:
389
 
         COPY_4V( params, ctx->Light.LightSource[l].Ambient );
390
 
         break;
391
 
      case GL_DIFFUSE:
392
 
         COPY_4V( params, ctx->Light.LightSource[l].Diffuse );
393
 
         break;
394
 
      case GL_SPECULAR:
395
 
         COPY_4V( params, ctx->Light.LightSource[l].Specular );
396
 
         break;
397
 
      case GL_POSITION:
398
 
         COPY_4V( params, ctx->Light.LightSource[l].EyePosition );
399
 
         break;
400
 
      case GL_SPOT_DIRECTION:
401
 
         COPY_3V( params, ctx->Light.LightSource[l].SpotDirection );
402
 
         break;
403
 
      case GL_SPOT_EXPONENT:
404
 
         params[0] = ctx->Light.LightSource[l].SpotExponent;
405
 
         break;
406
 
      case GL_SPOT_CUTOFF:
407
 
         params[0] = ctx->Light.LightSource[l].SpotCutoff;
408
 
         break;
409
 
      case GL_CONSTANT_ATTENUATION:
410
 
         params[0] = ctx->Light.LightSource[l].ConstantAttenuation;
411
 
         break;
412
 
      case GL_LINEAR_ATTENUATION:
413
 
         params[0] = ctx->Light.LightSource[l].LinearAttenuation;
414
 
         break;
415
 
      case GL_QUADRATIC_ATTENUATION:
416
 
         params[0] = ctx->Light.LightSource[l].QuadraticAttenuation;
417
 
         break;
418
 
      default:
419
 
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
420
 
         break;
421
 
   }
422
 
}
423
 
 
424
 
 
425
 
void GLAPIENTRY
426
 
_mesa_GetLightiv( GLenum light, GLenum pname, GLint *params )
427
 
{
428
 
   GET_CURRENT_CONTEXT(ctx);
429
 
   GLint l = (GLint) (light - GL_LIGHT0);
430
 
 
431
 
   if (l < 0 || l >= (GLint) ctx->Const.MaxLights) {
432
 
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
433
 
      return;
434
 
   }
435
 
 
436
 
   switch (pname) {
437
 
      case GL_AMBIENT:
438
 
         params[0] = FLOAT_TO_INT(ctx->Light.LightSource[l].Ambient[0]);
439
 
         params[1] = FLOAT_TO_INT(ctx->Light.LightSource[l].Ambient[1]);
440
 
         params[2] = FLOAT_TO_INT(ctx->Light.LightSource[l].Ambient[2]);
441
 
         params[3] = FLOAT_TO_INT(ctx->Light.LightSource[l].Ambient[3]);
442
 
         break;
443
 
      case GL_DIFFUSE:
444
 
         params[0] = FLOAT_TO_INT(ctx->Light.LightSource[l].Diffuse[0]);
445
 
         params[1] = FLOAT_TO_INT(ctx->Light.LightSource[l].Diffuse[1]);
446
 
         params[2] = FLOAT_TO_INT(ctx->Light.LightSource[l].Diffuse[2]);
447
 
         params[3] = FLOAT_TO_INT(ctx->Light.LightSource[l].Diffuse[3]);
448
 
         break;
449
 
      case GL_SPECULAR:
450
 
         params[0] = FLOAT_TO_INT(ctx->Light.LightSource[l].Specular[0]);
451
 
         params[1] = FLOAT_TO_INT(ctx->Light.LightSource[l].Specular[1]);
452
 
         params[2] = FLOAT_TO_INT(ctx->Light.LightSource[l].Specular[2]);
453
 
         params[3] = FLOAT_TO_INT(ctx->Light.LightSource[l].Specular[3]);
454
 
         break;
455
 
      case GL_POSITION:
456
 
         params[0] = (GLint) ctx->Light.LightSource[l].EyePosition[0];
457
 
         params[1] = (GLint) ctx->Light.LightSource[l].EyePosition[1];
458
 
         params[2] = (GLint) ctx->Light.LightSource[l].EyePosition[2];
459
 
         params[3] = (GLint) ctx->Light.LightSource[l].EyePosition[3];
460
 
         break;
461
 
      case GL_SPOT_DIRECTION:
462
 
         params[0] = (GLint) ctx->Light.LightSource[l].SpotDirection[0];
463
 
         params[1] = (GLint) ctx->Light.LightSource[l].SpotDirection[1];
464
 
         params[2] = (GLint) ctx->Light.LightSource[l].SpotDirection[2];
465
 
         break;
466
 
      case GL_SPOT_EXPONENT:
467
 
         params[0] = (GLint) ctx->Light.LightSource[l].SpotExponent;
468
 
         break;
469
 
      case GL_SPOT_CUTOFF:
470
 
         params[0] = (GLint) ctx->Light.LightSource[l].SpotCutoff;
471
 
         break;
472
 
      case GL_CONSTANT_ATTENUATION:
473
 
         params[0] = (GLint) ctx->Light.LightSource[l].ConstantAttenuation;
474
 
         break;
475
 
      case GL_LINEAR_ATTENUATION:
476
 
         params[0] = (GLint) ctx->Light.LightSource[l].LinearAttenuation;
477
 
         break;
478
 
      case GL_QUADRATIC_ATTENUATION:
479
 
         params[0] = (GLint) ctx->Light.LightSource[l].QuadraticAttenuation;
480
 
         break;
481
 
      default:
482
 
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
483
 
         break;
484
 
   }
485
 
}
486
 
 
487
 
 
488
 
 
489
 
/**********************************************************************/
490
 
/***                        Light Model                             ***/
491
 
/**********************************************************************/
492
 
 
493
 
 
494
 
void GLAPIENTRY
495
 
_mesa_LightModelfv( GLenum pname, const GLfloat *params )
496
 
{
497
 
   GLenum newenum;
498
 
   GLboolean newbool;
499
 
   GET_CURRENT_CONTEXT(ctx);
500
 
 
501
 
   switch (pname) {
502
 
      case GL_LIGHT_MODEL_AMBIENT:
503
 
         if (TEST_EQ_4V( ctx->Light.Model.Ambient, params ))
504
 
            return;
505
 
         FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS, GL_LIGHTING_BIT);
506
 
         COPY_4V( ctx->Light.Model.Ambient, params );
507
 
         break;
508
 
      case GL_LIGHT_MODEL_LOCAL_VIEWER:
509
 
         if (ctx->API != API_OPENGL_COMPAT)
510
 
            goto invalid_pname;
511
 
         newbool = (params[0] != 0.0F);
512
 
         if (ctx->Light.Model.LocalViewer == newbool)
513
 
            return;
514
 
         FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS | _NEW_FF_VERT_PROGRAM,
515
 
                        GL_LIGHTING_BIT);
516
 
         ctx->Light.Model.LocalViewer = newbool;
517
 
         break;
518
 
      case GL_LIGHT_MODEL_TWO_SIDE:
519
 
         newbool = (params[0] != 0.0F);
520
 
         if (ctx->Light.Model.TwoSide == newbool)
521
 
            return;
522
 
         FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS | _NEW_FF_VERT_PROGRAM |
523
 
                        _NEW_LIGHT_STATE, GL_LIGHTING_BIT);
524
 
         ctx->Light.Model.TwoSide = newbool;
525
 
         break;
526
 
      case GL_LIGHT_MODEL_COLOR_CONTROL:
527
 
         if (ctx->API != API_OPENGL_COMPAT)
528
 
            goto invalid_pname;
529
 
         if (params[0] == (GLfloat) GL_SINGLE_COLOR)
530
 
            newenum = GL_SINGLE_COLOR;
531
 
         else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR)
532
 
            newenum = GL_SEPARATE_SPECULAR_COLOR;
533
 
         else {
534
 
            _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(param=0x0%x)",
535
 
                         (GLint) params[0] );
536
 
            return;
537
 
         }
538
 
         if (ctx->Light.Model.ColorControl == newenum)
539
 
            return;
540
 
         FLUSH_VERTICES(ctx, _NEW_LIGHT_CONSTANTS | _NEW_FF_VERT_PROGRAM |
541
 
                        _NEW_FF_FRAG_PROGRAM, GL_LIGHTING_BIT);
542
 
         ctx->Light.Model.ColorControl = newenum;
543
 
         break;
544
 
      default:
545
 
         goto invalid_pname;
546
 
   }
547
 
 
548
 
   return;
549
 
 
550
 
invalid_pname:
551
 
   _mesa_error( ctx, GL_INVALID_ENUM, "glLightModel(pname=0x%x)", pname );
552
 
   return;
553
 
}
554
 
 
555
 
 
556
 
void GLAPIENTRY
557
 
_mesa_LightModeliv( GLenum pname, const GLint *params )
558
 
{
559
 
   GLfloat fparam[4];
560
 
 
561
 
   switch (pname) {
562
 
      case GL_LIGHT_MODEL_AMBIENT:
563
 
         fparam[0] = INT_TO_FLOAT( params[0] );
564
 
         fparam[1] = INT_TO_FLOAT( params[1] );
565
 
         fparam[2] = INT_TO_FLOAT( params[2] );
566
 
         fparam[3] = INT_TO_FLOAT( params[3] );
567
 
         break;
568
 
      case GL_LIGHT_MODEL_LOCAL_VIEWER:
569
 
      case GL_LIGHT_MODEL_TWO_SIDE:
570
 
      case GL_LIGHT_MODEL_COLOR_CONTROL:
571
 
         fparam[0] = (GLfloat) params[0];
572
 
         break;
573
 
      default:
574
 
         /* Error will be caught later in gl_LightModelfv */
575
 
         ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
576
 
   }
577
 
   _mesa_LightModelfv( pname, fparam );
578
 
}
579
 
 
580
 
 
581
 
void GLAPIENTRY
582
 
_mesa_LightModeli( GLenum pname, GLint param )
583
 
{
584
 
   GLint iparam[4];
585
 
   iparam[0] = param;
586
 
   iparam[1] = iparam[2] = iparam[3] = 0;
587
 
   _mesa_LightModeliv( pname, iparam );
588
 
}
589
 
 
590
 
 
591
 
void GLAPIENTRY
592
 
_mesa_LightModelf( GLenum pname, GLfloat param )
593
 
{
594
 
   GLfloat fparam[4];
595
 
   fparam[0] = param;
596
 
   fparam[1] = fparam[2] = fparam[3] = 0.0F;
597
 
   _mesa_LightModelfv( pname, fparam );
598
 
}
599
 
 
600
 
 
601
 
 
602
 
/********** MATERIAL **********/
603
 
 
604
 
 
605
 
/*
606
 
 * Given a face and pname value (ala glColorMaterial), compute a bitmask
607
 
 * of the targeted material values.
608
 
 */
609
 
GLuint
610
 
_mesa_material_bitmask( struct gl_context *ctx, GLenum face, GLenum pname,
611
 
                        GLuint legal, const char *where )
612
 
{
613
 
   GLuint bitmask = 0;
614
 
 
615
 
   /* Make a bitmask indicating what material attribute(s) we're updating */
616
 
   switch (pname) {
617
 
      case GL_EMISSION:
618
 
         bitmask |= MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION;
619
 
         break;
620
 
      case GL_AMBIENT:
621
 
         bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
622
 
         break;
623
 
      case GL_DIFFUSE:
624
 
         bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
625
 
         break;
626
 
      case GL_SPECULAR:
627
 
         bitmask |= MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR;
628
 
         break;
629
 
      case GL_SHININESS:
630
 
         bitmask |= MAT_BIT_FRONT_SHININESS | MAT_BIT_BACK_SHININESS;
631
 
         break;
632
 
      case GL_AMBIENT_AND_DIFFUSE:
633
 
         bitmask |= MAT_BIT_FRONT_AMBIENT | MAT_BIT_BACK_AMBIENT;
634
 
         bitmask |= MAT_BIT_FRONT_DIFFUSE | MAT_BIT_BACK_DIFFUSE;
635
 
         break;
636
 
      case GL_COLOR_INDEXES:
637
 
         bitmask |= MAT_BIT_FRONT_INDEXES  | MAT_BIT_BACK_INDEXES;
638
 
         break;
639
 
      default:
640
 
         _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
641
 
         return 0;
642
 
   }
643
 
 
644
 
   if (face==GL_FRONT) {
645
 
      bitmask &= FRONT_MATERIAL_BITS;
646
 
   }
647
 
   else if (face==GL_BACK) {
648
 
      bitmask &= BACK_MATERIAL_BITS;
649
 
   }
650
 
   else if (face != GL_FRONT_AND_BACK) {
651
 
      _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
652
 
      return 0;
653
 
   }
654
 
 
655
 
   if (bitmask & ~legal) {
656
 
      _mesa_error( ctx, GL_INVALID_ENUM, "%s", where );
657
 
      return 0;
658
 
   }
659
 
 
660
 
   return bitmask;
661
 
}
662
 
 
663
 
 
664
 
 
665
 
/* Update derived values following a change in ctx->Light.Material
666
 
 */
667
 
void
668
 
_mesa_update_material( struct gl_context *ctx, GLuint bitmask )
669
 
{
670
 
   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
671
 
 
672
 
   if (MESA_VERBOSE & VERBOSE_MATERIAL)
673
 
      _mesa_debug(ctx, "_mesa_update_material, mask 0x%x\n", bitmask);
674
 
 
675
 
   if (!bitmask)
676
 
      return;
677
 
 
678
 
   /* update material ambience */
679
 
   if (bitmask & MAT_BIT_FRONT_AMBIENT) {
680
 
      GLbitfield mask = ctx->Light._EnabledLights;
681
 
      while (mask) {
682
 
         const int i = u_bit_scan(&mask);
683
 
         struct gl_light *light = &ctx->Light.Light[i];
684
 
         struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
685
 
         SCALE_3V( light->_MatAmbient[0], lu->Ambient,
686
 
                   mat[MAT_ATTRIB_FRONT_AMBIENT]);
687
 
      }
688
 
   }
689
 
 
690
 
   if (bitmask & MAT_BIT_BACK_AMBIENT) {
691
 
      GLbitfield mask = ctx->Light._EnabledLights;
692
 
      while (mask) {
693
 
         const int i = u_bit_scan(&mask);
694
 
         struct gl_light *light = &ctx->Light.Light[i];
695
 
         struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
696
 
         SCALE_3V( light->_MatAmbient[1], lu->Ambient,
697
 
                   mat[MAT_ATTRIB_BACK_AMBIENT]);
698
 
      }
699
 
   }
700
 
 
701
 
   /* update BaseColor = emission + scene's ambience * material's ambience */
702
 
   if (bitmask & (MAT_BIT_FRONT_EMISSION | MAT_BIT_FRONT_AMBIENT)) {
703
 
      COPY_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_EMISSION] );
704
 
      ACC_SCALE_3V( ctx->Light._BaseColor[0], mat[MAT_ATTRIB_FRONT_AMBIENT],
705
 
                    ctx->Light.Model.Ambient );
706
 
   }
707
 
 
708
 
   if (bitmask & (MAT_BIT_BACK_EMISSION | MAT_BIT_BACK_AMBIENT)) {
709
 
      COPY_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_EMISSION] );
710
 
      ACC_SCALE_3V( ctx->Light._BaseColor[1], mat[MAT_ATTRIB_BACK_AMBIENT],
711
 
                    ctx->Light.Model.Ambient );
712
 
   }
713
 
 
714
 
   /* update material diffuse values */
715
 
   if (bitmask & MAT_BIT_FRONT_DIFFUSE) {
716
 
      GLbitfield mask = ctx->Light._EnabledLights;
717
 
      while (mask) {
718
 
         const int i = u_bit_scan(&mask);
719
 
         struct gl_light *light = &ctx->Light.Light[i];
720
 
         struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
721
 
         SCALE_3V( light->_MatDiffuse[0], lu->Diffuse,
722
 
                   mat[MAT_ATTRIB_FRONT_DIFFUSE] );
723
 
      }
724
 
   }
725
 
 
726
 
   if (bitmask & MAT_BIT_BACK_DIFFUSE) {
727
 
      GLbitfield mask = ctx->Light._EnabledLights;
728
 
      while (mask) {
729
 
         const int i = u_bit_scan(&mask);
730
 
         struct gl_light *light = &ctx->Light.Light[i];
731
 
         struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
732
 
         SCALE_3V( light->_MatDiffuse[1], lu->Diffuse,
733
 
                   mat[MAT_ATTRIB_BACK_DIFFUSE] );
734
 
      }
735
 
   }
736
 
 
737
 
   /* update material specular values */
738
 
   if (bitmask & MAT_BIT_FRONT_SPECULAR) {
739
 
      GLbitfield mask = ctx->Light._EnabledLights;
740
 
      while (mask) {
741
 
         const int i = u_bit_scan(&mask);
742
 
         struct gl_light *light = &ctx->Light.Light[i];
743
 
         struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
744
 
         SCALE_3V( light->_MatSpecular[0], lu->Specular,
745
 
                   mat[MAT_ATTRIB_FRONT_SPECULAR]);
746
 
      }
747
 
   }
748
 
 
749
 
   if (bitmask & MAT_BIT_BACK_SPECULAR) {
750
 
      GLbitfield mask = ctx->Light._EnabledLights;
751
 
      while (mask) {
752
 
         const int i = u_bit_scan(&mask);
753
 
         struct gl_light *light = &ctx->Light.Light[i];
754
 
         struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
755
 
         SCALE_3V( light->_MatSpecular[1], lu->Specular,
756
 
                   mat[MAT_ATTRIB_BACK_SPECULAR]);
757
 
      }
758
 
   }
759
 
}
760
 
 
761
 
 
762
 
/*
763
 
 * Update the current materials from the given rgba color
764
 
 * according to the bitmask in _ColorMaterialBitmask, which is
765
 
 * set by glColorMaterial().
766
 
 */
767
 
void
768
 
_mesa_update_color_material( struct gl_context *ctx, const GLfloat color[4] )
769
 
{
770
 
   GLbitfield bitmask = ctx->Light._ColorMaterialBitmask;
771
 
   struct gl_material *mat = &ctx->Light.Material;
772
 
 
773
 
   while (bitmask) {
774
 
      const int i = u_bit_scan(&bitmask);
775
 
 
776
 
      if (memcmp(mat->Attrib[i], color, sizeof(mat->Attrib[i]))) {
777
 
         COPY_4FV(mat->Attrib[i], color);
778
 
         ctx->NewState |= _NEW_MATERIAL;
779
 
      }
780
 
   }
781
 
}
782
 
 
783
 
 
784
 
void GLAPIENTRY
785
 
_mesa_ColorMaterial( GLenum face, GLenum mode )
786
 
{
787
 
   GET_CURRENT_CONTEXT(ctx);
788
 
   GLuint bitmask;
789
 
   GLuint legal = (MAT_BIT_FRONT_EMISSION | MAT_BIT_BACK_EMISSION |
790
 
                   MAT_BIT_FRONT_SPECULAR | MAT_BIT_BACK_SPECULAR |
791
 
                   MAT_BIT_FRONT_DIFFUSE  | MAT_BIT_BACK_DIFFUSE  |
792
 
                   MAT_BIT_FRONT_AMBIENT  | MAT_BIT_BACK_AMBIENT);
793
 
 
794
 
   if (MESA_VERBOSE&VERBOSE_API)
795
 
      _mesa_debug(ctx, "glColorMaterial %s %s\n",
796
 
                  _mesa_enum_to_string(face),
797
 
                  _mesa_enum_to_string(mode));
798
 
 
799
 
   bitmask = _mesa_material_bitmask(ctx, face, mode, legal, "glColorMaterial");
800
 
   if (bitmask == 0)
801
 
      return; /* error was recorded */
802
 
 
803
 
   if (ctx->Light._ColorMaterialBitmask == bitmask &&
804
 
       ctx->Light.ColorMaterialFace == face &&
805
 
       ctx->Light.ColorMaterialMode == mode)
806
 
      return;
807
 
 
808
 
   FLUSH_VERTICES(ctx, 0, GL_LIGHTING_BIT);
809
 
   ctx->Light._ColorMaterialBitmask = bitmask;
810
 
   ctx->Light.ColorMaterialFace = face;
811
 
   ctx->Light.ColorMaterialMode = mode;
812
 
 
813
 
   if (ctx->Light.ColorMaterialEnabled) {
814
 
      /* Used by fixed-func vertex program. */
815
 
      FLUSH_CURRENT(ctx, _NEW_FF_VERT_PROGRAM);
816
 
      _mesa_update_color_material(ctx,ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
817
 
   }
818
 
}
819
 
 
820
 
 
821
 
void GLAPIENTRY
822
 
_mesa_GetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
823
 
{
824
 
   GET_CURRENT_CONTEXT(ctx);
825
 
   GLuint f;
826
 
   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
827
 
 
828
 
   FLUSH_VERTICES(ctx, 0, 0); /* update materials */
829
 
   FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
830
 
 
831
 
   if (face==GL_FRONT) {
832
 
      f = 0;
833
 
   }
834
 
   else if (face==GL_BACK) {
835
 
      f = 1;
836
 
   }
837
 
   else {
838
 
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
839
 
      return;
840
 
   }
841
 
 
842
 
   switch (pname) {
843
 
      case GL_AMBIENT:
844
 
         COPY_4FV( params, mat[MAT_ATTRIB_AMBIENT(f)] );
845
 
         break;
846
 
      case GL_DIFFUSE:
847
 
         COPY_4FV( params, mat[MAT_ATTRIB_DIFFUSE(f)] );
848
 
         break;
849
 
      case GL_SPECULAR:
850
 
         COPY_4FV( params, mat[MAT_ATTRIB_SPECULAR(f)] );
851
 
         break;
852
 
      case GL_EMISSION:
853
 
         COPY_4FV( params, mat[MAT_ATTRIB_EMISSION(f)] );
854
 
         break;
855
 
      case GL_SHININESS:
856
 
         *params = mat[MAT_ATTRIB_SHININESS(f)][0];
857
 
         break;
858
 
      case GL_COLOR_INDEXES:
859
 
         if (ctx->API != API_OPENGL_COMPAT) {
860
 
            _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
861
 
            return;
862
 
         }
863
 
         params[0] = mat[MAT_ATTRIB_INDEXES(f)][0];
864
 
         params[1] = mat[MAT_ATTRIB_INDEXES(f)][1];
865
 
         params[2] = mat[MAT_ATTRIB_INDEXES(f)][2];
866
 
         break;
867
 
      default:
868
 
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
869
 
   }
870
 
}
871
 
 
872
 
 
873
 
void GLAPIENTRY
874
 
_mesa_GetMaterialiv( GLenum face, GLenum pname, GLint *params )
875
 
{
876
 
   GET_CURRENT_CONTEXT(ctx);
877
 
   GLuint f;
878
 
   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
879
 
 
880
 
   assert(ctx->API == API_OPENGL_COMPAT);
881
 
 
882
 
   FLUSH_VERTICES(ctx, 0, 0); /* update materials */
883
 
   FLUSH_CURRENT(ctx, 0); /* update ctx->Light.Material from vertex buffer */
884
 
 
885
 
   if (face==GL_FRONT) {
886
 
      f = 0;
887
 
   }
888
 
   else if (face==GL_BACK) {
889
 
      f = 1;
890
 
   }
891
 
   else {
892
 
      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
893
 
      return;
894
 
   }
895
 
   switch (pname) {
896
 
      case GL_AMBIENT:
897
 
         params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][0] );
898
 
         params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][1] );
899
 
         params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][2] );
900
 
         params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_AMBIENT(f)][3] );
901
 
         break;
902
 
      case GL_DIFFUSE:
903
 
         params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][0] );
904
 
         params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][1] );
905
 
         params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][2] );
906
 
         params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_DIFFUSE(f)][3] );
907
 
         break;
908
 
      case GL_SPECULAR:
909
 
         params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][0] );
910
 
         params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][1] );
911
 
         params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][2] );
912
 
         params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_SPECULAR(f)][3] );
913
 
         break;
914
 
      case GL_EMISSION:
915
 
         params[0] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][0] );
916
 
         params[1] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][1] );
917
 
         params[2] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][2] );
918
 
         params[3] = FLOAT_TO_INT( mat[MAT_ATTRIB_EMISSION(f)][3] );
919
 
         break;
920
 
      case GL_SHININESS:
921
 
         *params = lroundf( mat[MAT_ATTRIB_SHININESS(f)][0] );
922
 
         break;
923
 
      case GL_COLOR_INDEXES:
924
 
         params[0] = lroundf( mat[MAT_ATTRIB_INDEXES(f)][0] );
925
 
         params[1] = lroundf( mat[MAT_ATTRIB_INDEXES(f)][1] );
926
 
         params[2] = lroundf( mat[MAT_ATTRIB_INDEXES(f)][2] );
927
 
         break;
928
 
      default:
929
 
         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
930
 
   }
931
 
}
932
 
 
933
 
 
934
 
 
935
 
/**
936
 
 * Examine current lighting parameters to determine if the optimized lighting
937
 
 * function can be used.
938
 
 * Also, precompute some lighting values such as the products of light
939
 
 * source and material ambient, diffuse and specular coefficients.
940
 
 */
941
 
GLbitfield
942
 
_mesa_update_lighting( struct gl_context *ctx )
943
 
{
944
 
   GLbitfield flags = 0;
945
 
   bool old_need_eye_coords = ctx->Light._NeedEyeCoords;
946
 
   ctx->Light._NeedEyeCoords = GL_FALSE;
947
 
 
948
 
   if (!ctx->Light.Enabled) {
949
 
      return old_need_eye_coords != ctx->Light._NeedEyeCoords ?
950
 
                                       _NEW_TNL_SPACES : 0;
951
 
   }
952
 
 
953
 
   GLbitfield mask = ctx->Light._EnabledLights;
954
 
   while (mask) {
955
 
      const int i = u_bit_scan(&mask);
956
 
      struct gl_light *light = &ctx->Light.Light[i];
957
 
      flags |= light->_Flags;
958
 
   }
959
 
 
960
 
   ctx->Light._NeedVertices =
961
 
      ((flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
962
 
       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR ||
963
 
       ctx->Light.Model.LocalViewer);
964
 
 
965
 
   ctx->Light._NeedEyeCoords = ((flags & LIGHT_POSITIONAL) ||
966
 
                                ctx->Light.Model.LocalViewer);
967
 
 
968
 
   /* XXX: This test is overkill & needs to be fixed both for software and
969
 
    * hardware t&l drivers.  The above should be sufficient & should
970
 
    * be tested to verify this.
971
 
    */
972
 
   if (ctx->Light._NeedVertices)
973
 
      ctx->Light._NeedEyeCoords = GL_TRUE;
974
 
 
975
 
   return old_need_eye_coords != ctx->Light._NeedEyeCoords ?
976
 
                                    _NEW_TNL_SPACES : 0;
977
 
}
978
 
 
979
 
void
980
 
_mesa_update_light_materials(struct gl_context *ctx)
981
 
{
982
 
   /* Precompute some shading values.  Although we reference
983
 
    * Light.Material here, we can get away without flushing
984
 
    * FLUSH_UPDATE_CURRENT, as when any outstanding material changes
985
 
    * are flushed, they will update the derived state at that time.
986
 
    */
987
 
   if (ctx->Light.Model.TwoSide)
988
 
      _mesa_update_material(ctx,
989
 
                            MAT_BIT_FRONT_EMISSION |
990
 
                            MAT_BIT_FRONT_AMBIENT |
991
 
                            MAT_BIT_FRONT_DIFFUSE |
992
 
                            MAT_BIT_FRONT_SPECULAR |
993
 
                            MAT_BIT_BACK_EMISSION |
994
 
                            MAT_BIT_BACK_AMBIENT |
995
 
                            MAT_BIT_BACK_DIFFUSE |
996
 
                            MAT_BIT_BACK_SPECULAR);
997
 
   else
998
 
      _mesa_update_material(ctx,
999
 
                            MAT_BIT_FRONT_EMISSION |
1000
 
                            MAT_BIT_FRONT_AMBIENT |
1001
 
                            MAT_BIT_FRONT_DIFFUSE |
1002
 
                            MAT_BIT_FRONT_SPECULAR);
1003
 
}
1004
 
 
1005
 
 
1006
 
/**
1007
 
 * Update state derived from light position, spot direction.
1008
 
 * Called upon:
1009
 
 *   _NEW_MODELVIEW
1010
 
 *   _NEW_LIGHT_CONSTANTS
1011
 
 *   _TNL_NEW_NEED_EYE_COORDS
1012
 
 *
1013
 
 * Update on (_NEW_MODELVIEW | _NEW_LIGHT_CONSTANTS) when lighting is enabled.
1014
 
 * Also update on lighting space changes.
1015
 
 */
1016
 
static void
1017
 
compute_light_positions( struct gl_context *ctx )
1018
 
{
1019
 
   static const GLfloat eye_z[3] = { 0, 0, 1 };
1020
 
 
1021
 
   if (!ctx->Light.Enabled)
1022
 
      return;
1023
 
 
1024
 
   if (ctx->_NeedEyeCoords) {
1025
 
      COPY_3V( ctx->_EyeZDir, eye_z );
1026
 
   }
1027
 
   else {
1028
 
      TRANSFORM_NORMAL( ctx->_EyeZDir, eye_z, ctx->ModelviewMatrixStack.Top->m );
1029
 
   }
1030
 
 
1031
 
   GLbitfield mask = ctx->Light._EnabledLights;
1032
 
   while (mask) {
1033
 
      const int i = u_bit_scan(&mask);
1034
 
      struct gl_light *light = &ctx->Light.Light[i];
1035
 
      struct gl_light_uniforms *lu = &ctx->Light.LightSource[i];
1036
 
 
1037
 
      if (ctx->_NeedEyeCoords) {
1038
 
         /* _Position is in eye coordinate space */
1039
 
         COPY_4FV( light->_Position, lu->EyePosition );
1040
 
      }
1041
 
      else {
1042
 
         /* _Position is in object coordinate space */
1043
 
         TRANSFORM_POINT( light->_Position, ctx->ModelviewMatrixStack.Top->inv,
1044
 
                          lu->EyePosition );
1045
 
      }
1046
 
 
1047
 
      if (!(light->_Flags & LIGHT_POSITIONAL)) {
1048
 
         /* VP (VP) = Normalize( Position ) */
1049
 
         COPY_3V( light->_VP_inf_norm, light->_Position );
1050
 
         NORMALIZE_3FV( light->_VP_inf_norm );
1051
 
 
1052
 
         if (!ctx->Light.Model.LocalViewer) {
1053
 
            /* _h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
1054
 
            ADD_3V( light->_h_inf_norm, light->_VP_inf_norm, ctx->_EyeZDir);
1055
 
            NORMALIZE_3FV( light->_h_inf_norm );
1056
 
         }
1057
 
         light->_VP_inf_spot_attenuation = 1.0;
1058
 
      }
1059
 
      else {
1060
 
         /* positional light w/ homogeneous coordinate, divide by W */
1061
 
         GLfloat wInv = 1.0F / light->_Position[3];
1062
 
         light->_Position[0] *= wInv;
1063
 
         light->_Position[1] *= wInv;
1064
 
         light->_Position[2] *= wInv;
1065
 
      }
1066
 
 
1067
 
      if (light->_Flags & LIGHT_SPOT) {
1068
 
         /* Note: we normalize the spot direction now */
1069
 
 
1070
 
         if (ctx->_NeedEyeCoords) {
1071
 
            COPY_3V( light->_NormSpotDirection, lu->SpotDirection );
1072
 
            NORMALIZE_3FV( light->_NormSpotDirection );
1073
 
         }
1074
 
         else {
1075
 
            GLfloat spotDir[3];
1076
 
            COPY_3V(spotDir, lu->SpotDirection);
1077
 
            NORMALIZE_3FV(spotDir);
1078
 
            TRANSFORM_NORMAL( light->_NormSpotDirection,
1079
 
                              spotDir,
1080
 
                              ctx->ModelviewMatrixStack.Top->m);
1081
 
         }
1082
 
 
1083
 
         NORMALIZE_3FV( light->_NormSpotDirection );
1084
 
 
1085
 
         if (!(light->_Flags & LIGHT_POSITIONAL)) {
1086
 
            GLfloat PV_dot_dir = - DOT3(light->_VP_inf_norm,
1087
 
                                        light->_NormSpotDirection);
1088
 
 
1089
 
            if (PV_dot_dir > lu->_CosCutoff) {
1090
 
               light->_VP_inf_spot_attenuation =
1091
 
                  powf(PV_dot_dir, lu->SpotExponent);
1092
 
            }
1093
 
            else {
1094
 
               light->_VP_inf_spot_attenuation = 0;
1095
 
            }
1096
 
         }
1097
 
      }
1098
 
   }
1099
 
}
1100
 
 
1101
 
 
1102
 
 
1103
 
static void
1104
 
update_modelview_scale( struct gl_context *ctx )
1105
 
{
1106
 
   ctx->_ModelViewInvScale = 1.0F;
1107
 
   ctx->_ModelViewInvScaleEyespace = 1.0F;
1108
 
   if (!_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top)) {
1109
 
      const GLfloat *m = ctx->ModelviewMatrixStack.Top->inv;
1110
 
      GLfloat f = m[2] * m[2] + m[6] * m[6] + m[10] * m[10];
1111
 
      if (f < 1e-12f) f = 1.0f;
1112
 
      if (ctx->_NeedEyeCoords)
1113
 
         ctx->_ModelViewInvScale = 1.0f / sqrtf(f);
1114
 
      else
1115
 
         ctx->_ModelViewInvScale = sqrtf(f);
1116
 
      ctx->_ModelViewInvScaleEyespace = 1.0f / sqrtf(f);
1117
 
   }
1118
 
}
1119
 
 
1120
 
 
1121
 
/**
1122
 
 * Bring up to date any state that relies on _NeedEyeCoords.
1123
 
 *
1124
 
 * Return true if ctx->_NeedEyeCoords has been changed.
1125
 
 */
1126
 
bool
1127
 
_mesa_update_tnl_spaces( struct gl_context *ctx, GLuint new_state )
1128
 
{
1129
 
   const GLuint oldneedeyecoords = ctx->_NeedEyeCoords;
1130
 
 
1131
 
   (void) new_state;
1132
 
   ctx->_NeedEyeCoords = GL_FALSE;
1133
 
 
1134
 
   if ((ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) ||
1135
 
       ctx->Point._Attenuated ||
1136
 
       ctx->Light._NeedEyeCoords)
1137
 
      ctx->_NeedEyeCoords = GL_TRUE;
1138
 
 
1139
 
   if (ctx->Light.Enabled &&
1140
 
       !_math_matrix_is_length_preserving(ctx->ModelviewMatrixStack.Top))
1141
 
      ctx->_NeedEyeCoords = GL_TRUE;
1142
 
 
1143
 
   /* Check if the truth-value interpretations of the bitfields have
1144
 
    * changed:
1145
 
    */
1146
 
   if (oldneedeyecoords != ctx->_NeedEyeCoords) {
1147
 
      /* Recalculate all state that depends on _NeedEyeCoords.
1148
 
       */
1149
 
      update_modelview_scale(ctx);
1150
 
      compute_light_positions( ctx );
1151
 
 
1152
 
      return true;
1153
 
   }
1154
 
   else {
1155
 
      GLuint new_state2 = ctx->NewState;
1156
 
 
1157
 
      /* Recalculate that same state only if it has been invalidated
1158
 
       * by other statechanges.
1159
 
       */
1160
 
      if (new_state2 & _NEW_MODELVIEW)
1161
 
         update_modelview_scale(ctx);
1162
 
 
1163
 
      if (new_state2 & (_NEW_LIGHT_CONSTANTS | _NEW_MODELVIEW))
1164
 
         compute_light_positions( ctx );
1165
 
 
1166
 
      return false;
1167
 
   }
1168
 
}
1169
 
 
1170
 
 
1171
 
/**********************************************************************/
1172
 
/*****                      Initialization                        *****/
1173
 
/**********************************************************************/
1174
 
 
1175
 
/**
1176
 
 * Initialize the n-th light data structure.
1177
 
 *
1178
 
 * \param l pointer to the gl_light structure to be initialized.
1179
 
 * \param n number of the light.
1180
 
 * \note The defaults for light 0 are different than the other lights.
1181
 
 */
1182
 
static void
1183
 
init_light( struct gl_light *l, struct gl_light_uniforms *lu, GLuint n )
1184
 
{
1185
 
   ASSIGN_4V( lu->Ambient, 0.0, 0.0, 0.0, 1.0 );
1186
 
   if (n==0) {
1187
 
      ASSIGN_4V( lu->Diffuse, 1.0, 1.0, 1.0, 1.0 );
1188
 
      ASSIGN_4V( lu->Specular, 1.0, 1.0, 1.0, 1.0 );
1189
 
   }
1190
 
   else {
1191
 
      ASSIGN_4V( lu->Diffuse, 0.0, 0.0, 0.0, 1.0 );
1192
 
      ASSIGN_4V( lu->Specular, 0.0, 0.0, 0.0, 1.0 );
1193
 
   }
1194
 
   ASSIGN_4V( lu->EyePosition, 0.0, 0.0, 1.0, 0.0 );
1195
 
   ASSIGN_3V( lu->SpotDirection, 0.0, 0.0, -1.0 );
1196
 
   lu->SpotExponent = 0.0;
1197
 
   lu->SpotCutoff = 180.0;
1198
 
   lu->_CosCutoff = 0.0;                /* KW: -ve values not admitted */
1199
 
   lu->ConstantAttenuation = 1.0;
1200
 
   lu->LinearAttenuation = 0.0;
1201
 
   lu->QuadraticAttenuation = 0.0;
1202
 
   l->Enabled = GL_FALSE;
1203
 
}
1204
 
 
1205
 
 
1206
 
/**
1207
 
 * Initialize the light model data structure.
1208
 
 *
1209
 
 * \param lm pointer to the gl_lightmodel structure to be initialized.
1210
 
 */
1211
 
static void
1212
 
init_lightmodel( struct gl_lightmodel *lm )
1213
 
{
1214
 
   ASSIGN_4V( lm->Ambient, 0.2F, 0.2F, 0.2F, 1.0F );
1215
 
   lm->LocalViewer = GL_FALSE;
1216
 
   lm->TwoSide = GL_FALSE;
1217
 
   lm->ColorControl = GL_SINGLE_COLOR;
1218
 
}
1219
 
 
1220
 
 
1221
 
/**
1222
 
 * Initialize the material data structure.
1223
 
 *
1224
 
 * \param m pointer to the gl_material structure to be initialized.
1225
 
 */
1226
 
static void
1227
 
init_material( struct gl_material *m )
1228
 
{
1229
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_AMBIENT],  0.2F, 0.2F, 0.2F, 1.0F );
1230
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_DIFFUSE],  0.8F, 0.8F, 0.8F, 1.0F );
1231
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
1232
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
1233
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
1234
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_FRONT_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
1235
 
 
1236
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_AMBIENT],  0.2F, 0.2F, 0.2F, 1.0F );
1237
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_DIFFUSE],  0.8F, 0.8F, 0.8F, 1.0F );
1238
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SPECULAR], 0.0F, 0.0F, 0.0F, 1.0F );
1239
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_EMISSION], 0.0F, 0.0F, 0.0F, 1.0F );
1240
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_SHININESS], 0.0F, 0.0F, 0.0F, 0.0F );
1241
 
   ASSIGN_4V( m->Attrib[MAT_ATTRIB_BACK_INDEXES], 0.0F, 1.0F, 1.0F, 0.0F );
1242
 
}
1243
 
 
1244
 
 
1245
 
/**
1246
 
 * Initialize all lighting state for the given context.
1247
 
 */
1248
 
void
1249
 
_mesa_init_lighting( struct gl_context *ctx )
1250
 
{
1251
 
   GLuint i;
1252
 
 
1253
 
   /* Lighting group */
1254
 
   ctx->Light._EnabledLights = 0;
1255
 
   for (i = 0; i < MAX_LIGHTS; i++) {
1256
 
      init_light( &ctx->Light.Light[i], &ctx->Light.LightSource[i], i );
1257
 
   }
1258
 
 
1259
 
   init_lightmodel( &ctx->Light.Model );
1260
 
   init_material( &ctx->Light.Material );
1261
 
   ctx->Light.ShadeModel = GL_SMOOTH;
1262
 
   ctx->Light.ProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
1263
 
   ctx->Light.Enabled = GL_FALSE;
1264
 
   ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
1265
 
   ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
1266
 
   ctx->Light._ColorMaterialBitmask = _mesa_material_bitmask( ctx,
1267
 
                                               GL_FRONT_AND_BACK,
1268
 
                                               GL_AMBIENT_AND_DIFFUSE, ~0,
1269
 
                                               NULL );
1270
 
 
1271
 
   ctx->Light.ColorMaterialEnabled = GL_FALSE;
1272
 
   ctx->Light.ClampVertexColor = ctx->API == API_OPENGL_COMPAT;
1273
 
   ctx->Light._ClampVertexColor = ctx->API == API_OPENGL_COMPAT;
1274
 
 
1275
 
   /* Miscellaneous */
1276
 
   ctx->Light._NeedEyeCoords = GL_FALSE;
1277
 
   ctx->_NeedEyeCoords = GL_FALSE;
1278
 
   ctx->_ModelViewInvScale = 1.0;
1279
 
   ctx->_ModelViewInvScaleEyespace = 1.0;
1280
 
}