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