1 /* 2 * Copyright (C) 2009-2010 Francisco Jerez. 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial 15 * portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 */ 26 27 #include "nouveau_driver.h" 28 #include "nouveau_context.h" 29 #include "nouveau_gldefs.h" 30 #include "nouveau_util.h" 31 #include "nv10_3d.xml.h" 32 #include "nv10_driver.h" 33 34 void 35 nv10_emit_clip_plane(struct gl_context *ctx, int emit) 36 { 37 } 38 39 static inline unsigned 40 get_material_bitmask(unsigned m) 41 { 42 unsigned ret = 0; 43 44 if (m & MAT_BIT_FRONT_EMISSION) 45 ret |= NV10_3D_COLOR_MATERIAL_EMISSION; 46 if (m & MAT_BIT_FRONT_AMBIENT) 47 ret |= NV10_3D_COLOR_MATERIAL_AMBIENT; 48 if (m & MAT_BIT_FRONT_DIFFUSE) 49 ret |= NV10_3D_COLOR_MATERIAL_DIFFUSE; 50 if (m & MAT_BIT_FRONT_SPECULAR) 51 ret |= NV10_3D_COLOR_MATERIAL_SPECULAR; 52 53 return ret; 54 } 55 56 void 57 nv10_emit_color_material(struct gl_context *ctx, int emit) 58 { 59 struct nouveau_pushbuf *push = context_push(ctx); 60 unsigned mask = get_material_bitmask(ctx->Light._ColorMaterialBitmask); 61 62 BEGIN_NV04(push, NV10_3D(COLOR_MATERIAL), 1); 63 PUSH_DATA (push, ctx->Light.ColorMaterialEnabled ? mask : 0); 64 } 65 66 static unsigned 67 get_fog_mode(unsigned mode) 68 { 69 switch (mode) { 70 case GL_LINEAR: 71 return NV10_3D_FOG_MODE_LINEAR; 72 case GL_EXP: 73 return NV10_3D_FOG_MODE_EXP; 74 case GL_EXP2: 75 return NV10_3D_FOG_MODE_EXP2; 76 default: 77 assert(0); 78 } 79 } 80 81 static unsigned 82 get_fog_source(unsigned source, unsigned distance_mode) 83 { 84 switch (source) { 85 case GL_FOG_COORDINATE_EXT: 86 return NV10_3D_FOG_COORD_FOG; 87 case GL_FRAGMENT_DEPTH_EXT: 88 switch (distance_mode) { 89 case GL_EYE_PLANE_ABSOLUTE_NV: 90 return NV10_3D_FOG_COORD_DIST_ORTHOGONAL_ABS; 91 case GL_EYE_PLANE: 92 return NV10_3D_FOG_COORD_DIST_ORTHOGONAL; 93 case GL_EYE_RADIAL_NV: 94 return NV10_3D_FOG_COORD_DIST_RADIAL; 95 default: 96 assert(0); 97 } 98 default: 99 assert(0); 100 } 101 } 102 103 void 104 nv10_get_fog_coeff(struct gl_context *ctx, float k[3]) 105 { 106 struct gl_fog_attrib *f = &ctx->Fog; 107 108 switch (f->Mode) { 109 case GL_LINEAR: 110 k[0] = 2 + f->Start / (f->End - f->Start); 111 k[1] = -1 / (f->End - f->Start); 112 break; 113 114 case GL_EXP: 115 k[0] = 1.5; 116 k[1] = -0.09 * f->Density; 117 break; 118 119 case GL_EXP2: 120 k[0] = 1.5; 121 k[1] = -0.21 * f->Density; 122 break; 123 124 default: 125 assert(0); 126 } 127 128 k[2] = 0; 129 } 130 131 void 132 nv10_emit_fog(struct gl_context *ctx, int emit) 133 { 134 struct nouveau_context *nctx = to_nouveau_context(ctx); 135 struct nouveau_pushbuf *push = context_push(ctx); 136 struct gl_fog_attrib *f = &ctx->Fog; 137 unsigned source = nctx->fallback == HWTNL ? 138 f->FogCoordinateSource : GL_FOG_COORDINATE_EXT; 139 float k[3]; 140 141 nv10_get_fog_coeff(ctx, k); 142 143 BEGIN_NV04(push, NV10_3D(FOG_MODE), 4); 144 PUSH_DATA (push, get_fog_mode(f->Mode)); 145 PUSH_DATA (push, get_fog_source(source, f->FogDistanceMode)); 146 PUSH_DATAb(push, f->Enabled); 147 PUSH_DATA (push, pack_rgba_f(MESA_FORMAT_RGBA8888_REV, f->Color)); 148 149 BEGIN_NV04(push, NV10_3D(FOG_COEFF(0)), 3); 150 PUSH_DATAp(push, k, 3); 151 152 context_dirty(ctx, FRAG); 153 } 154 155 static inline unsigned 156 get_light_mode(struct gl_light *l) 157 { 158 if (l->Enabled) { 159 if (l->_Flags & LIGHT_SPOT) 160 return NV10_3D_ENABLED_LIGHTS_0_DIRECTIONAL; 161 else if (l->_Flags & LIGHT_POSITIONAL) 162 return NV10_3D_ENABLED_LIGHTS_0_POSITIONAL; 163 else 164 return NV10_3D_ENABLED_LIGHTS_0_NONPOSITIONAL; 165 } else { 166 return NV10_3D_ENABLED_LIGHTS_0_DISABLED; 167 } 168 } 169 170 void 171 nv10_emit_light_enable(struct gl_context *ctx, int emit) 172 { 173 struct nouveau_context *nctx = to_nouveau_context(ctx); 174 struct nouveau_pushbuf *push = context_push(ctx); 175 uint32_t en_lights = 0; 176 int i; 177 178 if (nctx->fallback != HWTNL) { 179 BEGIN_NV04(push, NV10_3D(LIGHTING_ENABLE), 1); 180 PUSH_DATA (push, 0); 181 return; 182 } 183 184 for (i = 0; i < MAX_LIGHTS; i++) 185 en_lights |= get_light_mode(&ctx->Light.Light[i]) << 2 * i; 186 187 BEGIN_NV04(push, NV10_3D(ENABLED_LIGHTS), 1); 188 PUSH_DATA (push, en_lights); 189 BEGIN_NV04(push, NV10_3D(LIGHTING_ENABLE), 1); 190 PUSH_DATAb(push, ctx->Light.Enabled); 191 BEGIN_NV04(push, NV10_3D(NORMALIZE_ENABLE), 1); 192 PUSH_DATAb(push, ctx->Transform.Normalize); 193 } 194 195 void 196 nv10_emit_light_model(struct gl_context *ctx, int emit) 197 { 198 struct nouveau_pushbuf *push = context_push(ctx); 199 struct gl_lightmodel *m = &ctx->Light.Model; 200 201 BEGIN_NV04(push, NV10_3D(SEPARATE_SPECULAR_ENABLE), 1); 202 PUSH_DATAb(push, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR); 203 204 BEGIN_NV04(push, NV10_3D(LIGHT_MODEL), 1); 205 PUSH_DATA (push, ((m->LocalViewer ? 206 NV10_3D_LIGHT_MODEL_LOCAL_VIEWER : 0) | 207 (_mesa_need_secondary_color(ctx) ? 208 NV10_3D_LIGHT_MODEL_SEPARATE_SPECULAR : 0) | 209 (!ctx->Light.Enabled && ctx->Fog.ColorSumEnabled ? 210 NV10_3D_LIGHT_MODEL_VERTEX_SPECULAR : 0))); 211 } 212 213 static float 214 get_shine(const float p[], float x) 215 { 216 const int n = 15; 217 const float *y = &p[1]; 218 float f = (n - 1) * (1 - 1 / (1 + p[0] * x)) 219 / (1 - 1 / (1 + p[0] * 1024)); 220 int i = f; 221 222 /* Linear interpolation in f-space (Faster and somewhat more 223 * accurate than x-space). */ 224 if (x == 0) 225 return y[0]; 226 else if (i > n - 2) 227 return y[n - 1]; 228 else 229 return y[i] + (y[i + 1] - y[i]) * (f - i); 230 } 231 232 static const float nv10_spot_params[2][16] = { 233 { 0.02, -3.80e-05, -1.77, -2.41, -2.71, -2.88, -2.98, -3.06, 234 -3.11, -3.17, -3.23, -3.28, -3.37, -3.47, -3.83, -5.11 }, 235 { 0.02, -0.01, 1.77, 2.39, 2.70, 2.87, 2.98, 3.06, 236 3.10, 3.16, 3.23, 3.27, 3.37, 3.47, 3.83, 5.11 }, 237 }; 238 239 void 240 nv10_get_spot_coeff(struct gl_light *l, float k[7]) 241 { 242 float e = l->SpotExponent; 243 float a0, b0, a1, a2, b2, a3; 244 245 if (e > 0) 246 a0 = -1 - 5.36e-3 / sqrt(e); 247 else 248 a0 = -1; 249 b0 = 1 / (1 + 0.273 * e); 250 251 a1 = get_shine(nv10_spot_params[0], e); 252 253 a2 = get_shine(nv10_spot_params[1], e); 254 b2 = 1 / (1 + 0.273 * e); 255 256 a3 = 0.9 + 0.278 * e; 257 258 if (l->SpotCutoff > 0) { 259 float cutoff = MAX2(a3, 1 / (1 - l->_CosCutoff)); 260 261 k[0] = MAX2(0, a0 + b0 * cutoff); 262 k[1] = a1; 263 k[2] = a2 + b2 * cutoff; 264 k[3] = - cutoff * l->_NormSpotDirection[0]; 265 k[4] = - cutoff * l->_NormSpotDirection[1]; 266 k[5] = - cutoff * l->_NormSpotDirection[2]; 267 k[6] = 1 - cutoff; 268 269 } else { 270 k[0] = b0; 271 k[1] = a1; 272 k[2] = a2 + b2; 273 k[3] = - l->_NormSpotDirection[0]; 274 k[4] = - l->_NormSpotDirection[1]; 275 k[5] = - l->_NormSpotDirection[2]; 276 k[6] = -1; 277 } 278 } 279 280 void 281 nv10_emit_light_source(struct gl_context *ctx, int emit) 282 { 283 const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0; 284 struct nouveau_pushbuf *push = context_push(ctx); 285 struct gl_light *l = &ctx->Light.Light[i]; 286 287 if (l->_Flags & LIGHT_POSITIONAL) { 288 BEGIN_NV04(push, NV10_3D(LIGHT_POSITION_X(i)), 3); 289 PUSH_DATAp(push, l->_Position, 3); 290 291 BEGIN_NV04(push, NV10_3D(LIGHT_ATTENUATION_CONSTANT(i)), 3); 292 PUSH_DATAf(push, l->ConstantAttenuation); 293 PUSH_DATAf(push, l->LinearAttenuation); 294 PUSH_DATAf(push, l->QuadraticAttenuation); 295 296 } else { 297 BEGIN_NV04(push, NV10_3D(LIGHT_DIRECTION_X(i)), 3); 298 PUSH_DATAp(push, l->_VP_inf_norm, 3); 299 300 BEGIN_NV04(push, NV10_3D(LIGHT_HALF_VECTOR_X(i)), 3); 301 PUSH_DATAp(push, l->_h_inf_norm, 3); 302 } 303 304 if (l->_Flags & LIGHT_SPOT) { 305 float k[7]; 306 307 nv10_get_spot_coeff(l, k); 308 309 BEGIN_NV04(push, NV10_3D(LIGHT_SPOT_CUTOFF(i, 0)), 7); 310 PUSH_DATAp(push, k, 7); 311 } 312 } 313 314 #define USE_COLOR_MATERIAL(attr) \ 315 (ctx->Light.ColorMaterialEnabled && \ 316 ctx->Light._ColorMaterialBitmask & (1 << MAT_ATTRIB_FRONT_##attr)) 317 318 void 319 nv10_emit_material_ambient(struct gl_context *ctx, int emit) 320 { 321 struct nouveau_pushbuf *push = context_push(ctx); 322 float (*mat)[4] = ctx->Light.Material.Attrib; 323 float c_scene[3], c_factor[3]; 324 struct gl_light *l; 325 326 if (USE_COLOR_MATERIAL(AMBIENT)) { 327 COPY_3V(c_scene, ctx->Light.Model.Ambient); 328 COPY_3V(c_factor, mat[MAT_ATTRIB_FRONT_EMISSION]); 329 330 } else if (USE_COLOR_MATERIAL(EMISSION)) { 331 SCALE_3V(c_scene, mat[MAT_ATTRIB_FRONT_AMBIENT], 332 ctx->Light.Model.Ambient); 333 ZERO_3V(c_factor); 334 335 } else { 336 COPY_3V(c_scene, ctx->Light._BaseColor[0]); 337 ZERO_3V(c_factor); 338 } 339 340 BEGIN_NV04(push, NV10_3D(LIGHT_MODEL_AMBIENT_R), 3); 341 PUSH_DATAp(push, c_scene, 3); 342 343 if (ctx->Light.ColorMaterialEnabled) { 344 BEGIN_NV04(push, NV10_3D(MATERIAL_FACTOR_R), 3); 345 PUSH_DATAp(push, c_factor, 3); 346 } 347 348 foreach(l, &ctx->Light.EnabledList) { 349 const int i = l - ctx->Light.Light; 350 float *c_light = (USE_COLOR_MATERIAL(AMBIENT) ? 351 l->Ambient : 352 l->_MatAmbient[0]); 353 354 BEGIN_NV04(push, NV10_3D(LIGHT_AMBIENT_R(i)), 3); 355 PUSH_DATAp(push, c_light, 3); 356 } 357 } 358 359 void 360 nv10_emit_material_diffuse(struct gl_context *ctx, int emit) 361 { 362 struct nouveau_pushbuf *push = context_push(ctx); 363 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 364 struct gl_light *l; 365 366 BEGIN_NV04(push, NV10_3D(MATERIAL_FACTOR_A), 1); 367 PUSH_DATAf(push, mat[MAT_ATTRIB_FRONT_DIFFUSE][3]); 368 369 foreach(l, &ctx->Light.EnabledList) { 370 const int i = l - ctx->Light.Light; 371 float *c_light = (USE_COLOR_MATERIAL(DIFFUSE) ? 372 l->Diffuse : 373 l->_MatDiffuse[0]); 374 375 BEGIN_NV04(push, NV10_3D(LIGHT_DIFFUSE_R(i)), 3); 376 PUSH_DATAp(push, c_light, 3); 377 } 378 } 379 380 void 381 nv10_emit_material_specular(struct gl_context *ctx, int emit) 382 { 383 struct nouveau_pushbuf *push = context_push(ctx); 384 struct gl_light *l; 385 386 foreach(l, &ctx->Light.EnabledList) { 387 const int i = l - ctx->Light.Light; 388 float *c_light = (USE_COLOR_MATERIAL(SPECULAR) ? 389 l->Specular : 390 l->_MatSpecular[0]); 391 392 BEGIN_NV04(push, NV10_3D(LIGHT_SPECULAR_R(i)), 3); 393 PUSH_DATAp(push, c_light, 3); 394 } 395 } 396 397 static const float nv10_shininess_param[6][16] = { 398 { 0.70, 0.00, 0.06, 0.06, 0.05, 0.04, 0.02, 0.00, 399 -0.06, -0.13, -0.24, -0.36, -0.51, -0.66, -0.82, -1.00 }, 400 { 0.01, 1.00, -2.29, -2.77, -2.96, -3.06, -3.12, -3.18, 401 -3.24, -3.29, -3.36, -3.43, -3.51, -3.75, -4.33, -5.11 }, 402 { 0.02, 0.00, 2.28, 2.75, 2.94, 3.04, 3.1, 3.15, 403 3.18, 3.22, 3.27, 3.32, 3.39, 3.48, 3.84, 5.11 }, 404 { 0.70, 0.00, 0.05, 0.06, 0.06, 0.06, 0.05, 0.04, 405 0.02, 0.01, -0.03, -0.12, -0.25, -0.43, -0.68, -0.99 }, 406 { 0.01, 1.00, -1.61, -2.35, -2.67, -2.84, -2.96, -3.05, 407 -3.08, -3.14, -3.2, -3.26, -3.32, -3.42, -3.54, -4.21 }, 408 { 0.01, 0.00, 2.25, 2.73, 2.92, 3.03, 3.09, 3.15, 409 3.16, 3.21, 3.25, 3.29, 3.35, 3.43, 3.56, 4.22 }, 410 }; 411 412 void 413 nv10_get_shininess_coeff(float s, float k[6]) 414 { 415 int i; 416 417 for (i = 0; i < 6; i++) 418 k[i] = get_shine(nv10_shininess_param[i], s); 419 } 420 421 void 422 nv10_emit_material_shininess(struct gl_context *ctx, int emit) 423 { 424 struct nouveau_pushbuf *push = context_push(ctx); 425 float (*mat)[4] = ctx->Light.Material.Attrib; 426 float k[6]; 427 428 nv10_get_shininess_coeff( 429 CLAMP(mat[MAT_ATTRIB_FRONT_SHININESS][0], 0, 1024), 430 k); 431 432 BEGIN_NV04(push, NV10_3D(MATERIAL_SHININESS(0)), 6); 433 PUSH_DATAp(push, k, 6); 434 } 435 436 void 437 nv10_emit_modelview(struct gl_context *ctx, int emit) 438 { 439 struct nouveau_context *nctx = to_nouveau_context(ctx); 440 struct nouveau_pushbuf *push = context_push(ctx); 441 GLmatrix *m = ctx->ModelviewMatrixStack.Top; 442 443 if (nctx->fallback != HWTNL) 444 return; 445 446 if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || 447 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { 448 BEGIN_NV04(push, NV10_3D(MODELVIEW_MATRIX(0, 0)), 16); 449 PUSH_DATAm(push, m->m); 450 } 451 452 if (ctx->Light.Enabled || 453 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { 454 int i, j; 455 456 BEGIN_NV04(push, NV10_3D(INVERSE_MODELVIEW_MATRIX(0, 0)), 12); 457 for (i = 0; i < 3; i++) 458 for (j = 0; j < 4; j++) 459 PUSH_DATAf(push, m->inv[4*i + j]); 460 } 461 } 462 463 void 464 nv10_emit_point_parameter(struct gl_context *ctx, int emit) 465 { 466 } 467 468 void 469 nv10_emit_projection(struct gl_context *ctx, int emit) 470 { 471 struct nouveau_context *nctx = to_nouveau_context(ctx); 472 struct nouveau_pushbuf *push = context_push(ctx); 473 GLmatrix m; 474 475 _math_matrix_ctr(&m); 476 get_viewport_scale(ctx, m.m); 477 478 if (nv10_use_viewport_zclear(ctx)) 479 m.m[MAT_SZ] /= 8; 480 481 if (nctx->fallback == HWTNL) 482 _math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix); 483 484 BEGIN_NV04(push, NV10_3D(PROJECTION_MATRIX(0)), 16); 485 PUSH_DATAm(push, m.m); 486 487 _math_matrix_dtr(&m); 488 } 489