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