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