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 58void 59nv20_emit_clip_plane(struct gl_context *ctx, int emit) 60{ 61} 62 63static inline unsigned 64get_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 89void 90nv20_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 99static unsigned 100get_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 114static unsigned 115get_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 129static unsigned 130get_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 151void 152nv20_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 176void 177nv20_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 197void 198nv20_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 struct gl_light_uniforms *lu = &ctx->Light.LightSource[i]; 204 205 if (l->_Flags & LIGHT_POSITIONAL) { 206 BEGIN_NV04(push, NV20_3D(LIGHT_POSITION_X(i)), 3); 207 PUSH_DATAp(push, l->_Position, 3); 208 209 BEGIN_NV04(push, NV20_3D(LIGHT_ATTENUATION_CONSTANT(i)), 3); 210 PUSH_DATAf(push, lu->ConstantAttenuation); 211 PUSH_DATAf(push, lu->LinearAttenuation); 212 PUSH_DATAf(push, lu->QuadraticAttenuation); 213 214 } else { 215 BEGIN_NV04(push, NV20_3D(LIGHT_DIRECTION_X(i)), 3); 216 PUSH_DATAp(push, l->_VP_inf_norm, 3); 217 218 BEGIN_NV04(push, NV20_3D(LIGHT_HALF_VECTOR_X(i)), 3); 219 PUSH_DATAp(push, l->_h_inf_norm, 3); 220 } 221 222 if (l->_Flags & LIGHT_SPOT) { 223 float k[7]; 224 225 nv10_get_spot_coeff(l, lu, k); 226 227 BEGIN_NV04(push, NV20_3D(LIGHT_SPOT_CUTOFF(i, 0)), 7); 228 PUSH_DATAp(push, k, 7); 229 } 230} 231 232#define USE_COLOR_MATERIAL(attr, side) \ 233 (ctx->Light.ColorMaterialEnabled && \ 234 ctx->Light._ColorMaterialBitmask & (1 << MAT_ATTRIB_##attr(side))) 235 236void 237nv20_emit_material_ambient(struct gl_context *ctx, int emit) 238{ 239 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_AMBIENT; 240 struct nouveau_pushbuf *push = context_push(ctx); 241 float (*mat)[4] = ctx->Light.Material.Attrib; 242 float c_scene[3], c_factor[3]; 243 GLbitfield mask; 244 245 if (USE_COLOR_MATERIAL(AMBIENT, side)) { 246 COPY_3V(c_scene, mat[MAT_ATTRIB_EMISSION(side)]); 247 COPY_3V(c_factor, ctx->Light.Model.Ambient); 248 249 } else if (USE_COLOR_MATERIAL(EMISSION, side)) { 250 SCALE_3V(c_scene, mat[MAT_ATTRIB_AMBIENT(side)], 251 ctx->Light.Model.Ambient); 252 ASSIGN_3V(c_factor, 1, 1, 1); 253 254 } else { 255 COPY_3V(c_scene, ctx->Light._BaseColor[side]); 256 ZERO_3V(c_factor); 257 } 258 259 BEGIN_NV04(push, SUBC_3D(LIGHT_MODEL_AMBIENT_R(side)), 3); 260 PUSH_DATAp(push, c_scene, 3); 261 262 if (ctx->Light.ColorMaterialEnabled) { 263 BEGIN_NV04(push, SUBC_3D(MATERIAL_FACTOR_R(side)), 3); 264 PUSH_DATAp(push, c_factor, 3); 265 } 266 267 mask = ctx->Light._EnabledLights; 268 while (mask) { 269 const int i = u_bit_scan(&mask); 270 struct gl_light *l = &ctx->Light.Light[i]; 271 struct gl_light_uniforms *lu = &ctx->Light.LightSource[i]; 272 float *c_light = (USE_COLOR_MATERIAL(AMBIENT, side) ? 273 lu->Ambient : 274 l->_MatAmbient[side]); 275 276 BEGIN_NV04(push, SUBC_3D(LIGHT_AMBIENT_R(side, i)), 3); 277 PUSH_DATAp(push, c_light, 3); 278 } 279} 280 281void 282nv20_emit_material_diffuse(struct gl_context *ctx, int emit) 283{ 284 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_DIFFUSE; 285 struct nouveau_pushbuf *push = context_push(ctx); 286 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 287 GLbitfield mask; 288 289 BEGIN_NV04(push, SUBC_3D(MATERIAL_FACTOR_A(side)), 1); 290 PUSH_DATAf(push, mat[MAT_ATTRIB_DIFFUSE(side)][3]); 291 292 mask = ctx->Light._EnabledLights; 293 while (mask) { 294 const int i = u_bit_scan(&mask); 295 struct gl_light *l = &ctx->Light.Light[i]; 296 struct gl_light_uniforms *lu = &ctx->Light.LightSource[i]; 297 float *c_light = (USE_COLOR_MATERIAL(DIFFUSE, side) ? 298 lu->Diffuse : 299 l->_MatDiffuse[side]); 300 301 BEGIN_NV04(push, SUBC_3D(LIGHT_DIFFUSE_R(side, i)), 3); 302 PUSH_DATAp(push, c_light, 3); 303 } 304} 305 306void 307nv20_emit_material_specular(struct gl_context *ctx, int emit) 308{ 309 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SPECULAR; 310 struct nouveau_pushbuf *push = context_push(ctx); 311 GLbitfield mask; 312 313 mask = ctx->Light._EnabledLights; 314 while (mask) { 315 const int i = u_bit_scan(&mask); 316 struct gl_light *l = &ctx->Light.Light[i]; 317 struct gl_light_uniforms *lu = &ctx->Light.LightSource[i]; 318 float *c_light = (USE_COLOR_MATERIAL(SPECULAR, side) ? 319 lu->Specular : 320 l->_MatSpecular[side]); 321 322 BEGIN_NV04(push, SUBC_3D(LIGHT_SPECULAR_R(side, i)), 3); 323 PUSH_DATAp(push, c_light, 3); 324 } 325} 326 327void 328nv20_emit_material_shininess(struct gl_context *ctx, int emit) 329{ 330 const int side = emit - NOUVEAU_STATE_MATERIAL_FRONT_SHININESS; 331 struct nouveau_pushbuf *push = context_push(ctx); 332 float (*mat)[4] = ctx->Light.Material.Attrib; 333 float k[6]; 334 335 nv10_get_shininess_coeff( 336 CLAMP(mat[MAT_ATTRIB_SHININESS(side)][0], 0, 1024), 337 k); 338 339 BEGIN_NV04(push, SUBC_3D(MATERIAL_SHININESS(side)), 6); 340 PUSH_DATAp(push, k, 6); 341} 342 343void 344nv20_emit_modelview(struct gl_context *ctx, int emit) 345{ 346 struct nouveau_context *nctx = to_nouveau_context(ctx); 347 struct nouveau_pushbuf *push = context_push(ctx); 348 GLmatrix *m = ctx->ModelviewMatrixStack.Top; 349 350 if (nctx->fallback != HWTNL) 351 return; 352 353 if (ctx->Light._NeedEyeCoords || ctx->Fog.Enabled || 354 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { 355 BEGIN_NV04(push, NV20_3D(MODELVIEW_MATRIX(0, 0)), 16); 356 PUSH_DATAm(push, m->m); 357 } 358 359 if (ctx->Light.Enabled || 360 (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)) { 361 int i, j; 362 363 BEGIN_NV04(push, NV20_3D(INVERSE_MODELVIEW_MATRIX(0, 0)), 12); 364 for (i = 0; i < 3; i++) 365 for (j = 0; j < 4; j++) 366 PUSH_DATAf(push, m->inv[4*i + j]); 367 } 368} 369 370void 371nv20_emit_projection(struct gl_context *ctx, int emit) 372{ 373 struct nouveau_context *nctx = to_nouveau_context(ctx); 374 struct nouveau_pushbuf *push = context_push(ctx); 375 GLmatrix m; 376 377 _math_matrix_ctr(&m); 378 get_viewport_scale(ctx, m.m); 379 380 if (nctx->fallback == HWTNL) 381 _math_matrix_mul_matrix(&m, &m, &ctx->_ModelProjectMatrix); 382 383 BEGIN_NV04(push, NV20_3D(PROJECTION_MATRIX(0)), 16); 384 PUSH_DATAm(push, m.m); 385} 386