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