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 "nv20_3d.xml.h" 32 #include "nv10_driver.h" 33 #include "nv20_driver.h" 34 #include "util/bitscan.h" 35 36 #define LIGHT_MODEL_AMBIENT_R(side) \ 37 ((side) ? NV20_3D_LIGHT_MODEL_BACK_AMBIENT_R : \ 38 NV20_3D_LIGHT_MODEL_FRONT_AMBIENT_R) 39 #define LIGHT_AMBIENT_R(side, i) \ 40 ((side) ? NV20_3D_LIGHT_BACK_AMBIENT_R(i) : \ 41 NV20_3D_LIGHT_FRONT_AMBIENT_R(i)) 42 #define LIGHT_DIFFUSE_R(side, i) \ 43 ((side) ? NV20_3D_LIGHT_BACK_DIFFUSE_R(i) : \ 44 NV20_3D_LIGHT_FRONT_DIFFUSE_R(i)) 45 #define LIGHT_SPECULAR_R(side, i) \ 46 ((side) ? NV20_3D_LIGHT_BACK_SPECULAR_R(i) : \ 47 NV20_3D_LIGHT_FRONT_SPECULAR_R(i)) 48 #define MATERIAL_FACTOR_R(side) \ 49 ((side) ? NV20_3D_MATERIAL_FACTOR_BACK_R : \ 50 NV20_3D_MATERIAL_FACTOR_FRONT_R) 51 #define MATERIAL_FACTOR_A(side) \ 52 ((side) ? NV20_3D_MATERIAL_FACTOR_BACK_A : \ 53 NV20_3D_MATERIAL_FACTOR_FRONT_A) 54 #define MATERIAL_SHININESS(side) \ 55 ((side) ? NV20_3D_BACK_MATERIAL_SHININESS(0) : \ 56 NV20_3D_FRONT_MATERIAL_SHININESS(0)) 57 58 void 59 nv20_emit_clip_plane(struct gl_context *ctx, int emit) 60 { 61 } 62 63 static inline unsigned 64 get_material_bitmask(unsigned m) 65 { 66 unsigned ret = 0; 67 68 if (m & MAT_BIT_FRONT_EMISSION) 69 ret |= NV20_3D_COLOR_MATERIAL_FRONT_EMISSION_COL1; 70 if (m & MAT_BIT_FRONT_AMBIENT) 71 ret |= NV20_3D_COLOR_MATERIAL_FRONT_AMBIENT_COL1; 72 if (m & MAT_BIT_FRONT_DIFFUSE) 73 ret |= NV20_3D_COLOR_MATERIAL_FRONT_DIFFUSE_COL1; 74 if (m & MAT_BIT_FRONT_SPECULAR) 75 ret |= NV20_3D_COLOR_MATERIAL_FRONT_SPECULAR_COL1; 76 77 if (m & MAT_BIT_BACK_EMISSION) 78 ret |= NV20_3D_COLOR_MATERIAL_BACK_EMISSION_COL1; 79 if (m & MAT_BIT_BACK_AMBIENT) 80 ret |= NV20_3D_COLOR_MATERIAL_BACK_AMBIENT_COL1; 81 if (m & MAT_BIT_BACK_DIFFUSE) 82 ret |= NV20_3D_COLOR_MATERIAL_BACK_DIFFUSE_COL1; 83 if (m & MAT_BIT_BACK_SPECULAR) 84 ret |= NV20_3D_COLOR_MATERIAL_BACK_SPECULAR_COL1; 85 86 return ret; 87 } 88 89 void 90 nv20_emit_color_material(struct gl_context *ctx, int emit) 91 { 92 struct nouveau_pushbuf *push = context_push(ctx); 93 unsigned mask = get_material_bitmask(ctx->Light._ColorMaterialBitmask); 94 95 BEGIN_NV04(push, NV20_3D(COLOR_MATERIAL), 1); 96 PUSH_DATA (push, ctx->Light.ColorMaterialEnabled ? mask : 0); 97 } 98 99 static unsigned 100 get_fog_mode_signed(unsigned mode) 101 { 102 switch (mode) { 103 case GL_LINEAR: 104 return NV20_3D_FOG_MODE_LINEAR_SIGNED; 105 case GL_EXP: 106 return NV20_3D_FOG_MODE_EXP_SIGNED; 107 case GL_EXP2: 108 return NV20_3D_FOG_MODE_EXP2_SIGNED; 109 default: 110 assert(0); 111 } 112 } 113 114 static unsigned 115 get_fog_mode_unsigned(unsigned mode) 116 { 117 switch (mode) { 118 case GL_LINEAR: 119 return NV20_3D_FOG_MODE_LINEAR_UNSIGNED; 120 case GL_EXP: 121 return NV20_3D_FOG_MODE_EXP_UNSIGNED; 122 case GL_EXP2: 123 return NV20_3D_FOG_MODE_EXP2_UNSIGNED; 124 default: 125 assert(0); 126 } 127 } 128 129 static unsigned 130 get_fog_source(unsigned source, unsigned distance_mode) 131 { 132 switch (source) { 133 case GL_FOG_COORDINATE_EXT: 134 return NV20_3D_FOG_COORD_FOG; 135 case GL_FRAGMENT_DEPTH_EXT: 136 switch (distance_mode) { 137 case GL_EYE_PLANE_ABSOLUTE_NV: 138 return NV20_3D_FOG_COORD_DIST_ORTHOGONAL_ABS; 139 case GL_EYE_PLANE: 140 return NV20_3D_FOG_COORD_DIST_ORTHOGONAL; 141 case GL_EYE_RADIAL_NV: 142 return NV20_3D_FOG_COORD_DIST_RADIAL; 143 default: 144 assert(0); 145 } 146 default: 147 assert(0); 148 } 149 } 150 151 void 152 nv20_emit_fog(struct gl_context *ctx, int emit) 153 { 154 struct nouveau_context *nctx = to_nouveau_context(ctx); 155 struct nouveau_pushbuf *push = context_push(ctx); 156 struct gl_fog_attrib *f = &ctx->Fog; 157 unsigned source = nctx->fallback == HWTNL ? 158 f->FogCoordinateSource : GL_FOG_COORDINATE_EXT; 159 float k[3]; 160 161 nv10_get_fog_coeff(ctx, k); 162 163 BEGIN_NV04(push, NV20_3D(FOG_MODE), 4); 164 PUSH_DATA (push, ((source == GL_FRAGMENT_DEPTH_EXT && 165 f->FogDistanceMode == GL_EYE_PLANE_ABSOLUTE_NV) ? 166 get_fog_mode_unsigned(f->Mode) : 167 get_fog_mode_signed(f->Mode))); 168 PUSH_DATA (push, get_fog_source(source, f->FogDistanceMode)); 169 PUSH_DATAb(push, f->Enabled); 170 PUSH_DATA (push, pack_rgba_f(MESA_FORMAT_R8G8B8A8_UNORM, f->Color)); 171 172 BEGIN_NV04(push, NV20_3D(FOG_COEFF(0)), 3); 173 PUSH_DATAp(push, k, 3); 174 } 175 176 void 177 nv20_emit_light_model(struct gl_context *ctx, int emit) 178 { 179 struct nouveau_pushbuf *push = context_push(ctx); 180 struct gl_lightmodel *m = &ctx->Light.Model; 181 182 BEGIN_NV04(push, NV20_3D(SEPARATE_SPECULAR_ENABLE), 1); 183 PUSH_DATAb(push, m->ColorControl == GL_SEPARATE_SPECULAR_COLOR); 184 185 BEGIN_NV04(push, NV20_3D(LIGHT_MODEL), 1); 186 PUSH_DATA (push, ((m->LocalViewer ? 187 NV20_3D_LIGHT_MODEL_VIEWER_LOCAL : 188 NV20_3D_LIGHT_MODEL_VIEWER_NONLOCAL) | 189 (_mesa_need_secondary_color(ctx) ? 190 NV20_3D_LIGHT_MODEL_SEPARATE_SPECULAR : 191 0))); 192 193 BEGIN_NV04(push, NV20_3D(LIGHT_MODEL_TWO_SIDE_ENABLE), 1); 194 PUSH_DATAb(push, ctx->Light.Model.TwoSide); 195 } 196 197 void 198 nv20_emit_light_source(struct gl_context *ctx, int emit) 199 { 200 const int i = emit - NOUVEAU_STATE_LIGHT_SOURCE0; 201 struct nouveau_pushbuf *push = context_push(ctx); 202 struct gl_light *l = &ctx->Light.Light[i]; 203 204 if (l->_Flags & LIGHT_POSITIONAL) { 205 BEGIN_NV04(push, NV20_3D(LIGHT_POSITION_X(i)), 3); 206 PUSH_DATAp(push, l->_Position, 3); 207 208 BEGIN_NV04(push, NV20_3D(LIGHT_ATTENUATION_CONSTANT(i)), 3); 209 PUSH_DATAf(push, l->ConstantAttenuation); 210 PUSH_DATAf(push, l->LinearAttenuation); 211 PUSH_DATAf(push, l->QuadraticAttenuation); 212 213 } else { 214 BEGIN_NV04(push, NV20_3D(LIGHT_DIRECTION_X(i)), 3); 215 PUSH_DATAp(push, l->_VP_inf_norm, 3); 216 217 BEGIN_NV04(push, NV20_3D(LIGHT_HALF_VECTOR_X(i)), 3); 218 PUSH_DATAp(push, l->_h_inf_norm, 3); 219 } 220 221 if (l->_Flags & LIGHT_SPOT) { 222 float k[7]; 223 224 nv10_get_spot_coeff(l, k); 225 226 BEGIN_NV04(push, NV20_3D(LIGHT_SPOT_CUTOFF(i, 0)), 7); 227 PUSH_DATAp(push, k, 7); 228 } 229 } 230 231 #define USE_COLOR_MATERIAL(attr, side) \ 232 (ctx->Light.ColorMaterialEnabled && \ 233 ctx->Light._ColorMaterialBitmask & (1 << MAT_ATTRIB_##attr(side))) 234 235 void 236 nv20_emit_material_ambient(struct gl_context *ctx, int emit) 237 { 238 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT; 239 struct nouveau_pushbuf *push = context_push(ctx); 240 float (*mat)[4] = ctx->Light.Material.Attrib; 241 float c_scene[3], c_factor[3]; 242 GLbitfield mask; 243 244 if (USE_COLOR_MATERIAL(AMBIENT, side)) { 245 COPY_3V(c_scene, mat[MAT_ATTRIB_EMISSION(side)]); 246 COPY_3V(c_factor, ctx->Light.Model.Ambient); 247 248 } else if (USE_COLOR_MATERIAL(EMISSION, side)) { 249 SCALE_3V(c_scene, mat[MAT_ATTRIB_AMBIENT(side)], 250 ctx->Light.Model.Ambient); 251 ASSIGN_3V(c_factor, 1, 1, 1); 252 253 } else { 254 COPY_3V(c_scene, ctx->Light._BaseColor[side]); 255 ZERO_3V(c_factor); 256 } 257 258 BEGIN_NV04(push, SUBC_3D(LIGHT_MODEL_AMBIENT_R(side)), 3); 259 PUSH_DATAp(push, c_scene, 3); 260 261 if (ctx->Light.ColorMaterialEnabled) { 262 BEGIN_NV04(push, SUBC_3D(MATERIAL_FACTOR_R(side)), 3); 263 PUSH_DATAp(push, c_factor, 3); 264 } 265 266 mask = ctx->Light._EnabledLights; 267 while (mask) { 268 const int i = u_bit_scan(&mask); 269 struct gl_light *l = &ctx->Light.Light[i]; 270 float *c_light = (USE_COLOR_MATERIAL(AMBIENT, side) ? 271 l->Ambient : 272 l->_MatAmbient[side]); 273 274 BEGIN_NV04(push, SUBC_3D(LIGHT_AMBIENT_R(side, i)), 3); 275 PUSH_DATAp(push, c_light, 3); 276 } 277 } 278 279 void 280 nv20_emit_material_diffuse(struct gl_context *ctx, int emit) 281 { 282 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE; 283 struct nouveau_pushbuf *push = context_push(ctx); 284 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 285 GLbitfield mask; 286 287 BEGIN_NV04(push, SUBC_3D(MATERIAL_FACTOR_A(side)), 1); 288 PUSH_DATAf(push, mat[MAT_ATTRIB_DIFFUSE(side)][3]); 289 290 mask = ctx->Light._EnabledLights; 291 while (mask) { 292 const int i = u_bit_scan(&mask); 293 struct gl_light *l = &ctx->Light.Light[i]; 294 float *c_light = (USE_COLOR_MATERIAL(DIFFUSE, side) ? 295 l->Diffuse : 296 l->_MatDiffuse[side]); 297 298 BEGIN_NV04(push, SUBC_3D(LIGHT_DIFFUSE_R(side, i)), 3); 299 PUSH_DATAp(push, c_light, 3); 300 } 301 } 302 303 void 304 nv20_emit_material_specular(struct gl_context *ctx, int emit) 305 { 306 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR; 307 struct nouveau_pushbuf *push = context_push(ctx); 308 GLbitfield mask; 309 310 mask = ctx->Light._EnabledLights; 311 while (mask) { 312 const int i = u_bit_scan(&mask); 313 struct gl_light *l = &ctx->Light.Light[i]; 314 float *c_light = (USE_COLOR_MATERIAL(SPECULAR, side) ? 315 l->Specular : 316 l->_MatSpecular[side]); 317 318 BEGIN_NV04(push, SUBC_3D(LIGHT_SPECULAR_R(side, i)), 3); 319 PUSH_DATAp(push, c_light, 3); 320 } 321 } 322 323 void 324 nv20_emit_material_shininess(struct gl_context *ctx, int emit) 325 { 326 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SHININESS; 327 struct nouveau_pushbuf *push = context_push(ctx); 328 float (*mat)[4] = ctx->Light.Material.Attrib; 329 float k[6]; 330 331 nv10_get_shininess_coeff( 332 CLAMP(mat[MAT_ATTRIB_SHININESS(side)][0], 0, 1024), 333 k); 334 335 BEGIN_NV04(push, SUBC_3D(MATERIAL_SHININESS(side)), 6); 336 PUSH_DATAp(push, k, 6); 337 } 338 339 void 340 nv20_emit_modelview(struct gl_context *ctx, int emit) 341 { 342 struct nouveau_context *nctx = to_nouveau_context(ctx); 343 struct nouveau_pushbuf *push = context_push(ctx); 344 GLmatrix *m = ctx->ModelviewMatrixStack.Top; 345 346 if (nctx->fallback != HWTNL) 347 return; 348 349 if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || 350 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { 351 BEGIN_NV04(push, NV20_3D(MODELVIEW_MATRIX(0, 0)), 16); 352 PUSH_DATAm(push, m->m); 353 } 354 355 if (ctx->Light.Enabled || 356 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { 357 int i, j; 358 359 BEGIN_NV04(push, NV20_3D(INVERSE_MODELVIEW_MATRIX(0, 0)), 12); 360 for (i = 0; i < 3; i++) 361 for (j = 0; j < 4; j++) 362 PUSH_DATAf(push, m->inv[4*i + j]); 363 } 364 } 365 366 void 367 nv20_emit_projection(struct gl_context *ctx, int emit) 368 { 369 struct nouveau_context *nctx = to_nouveau_context(ctx); 370 struct nouveau_pushbuf *push = context_push(ctx); 371 GLmatrix m; 372 373 _math_matrix_ctr(&m); 374 get_viewport_scale(ctx, m.m); 375 376 if (nctx->fallback == HWTNL) 377 _math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix); 378 379 BEGIN_NV04(push, NV20_3D(PROJECTION_MATRIX(0)), 16); 380 PUSH_DATAm(push, m.m); 381 382 _math_matrix_dtr(&m); 383 } 384