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