Home | History | Annotate | Download | only in nouveau
      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