db13ec70b426ec7e9db6a213ba68acccab55e2d3
[mesa.git] / src / mesa / drivers / dri / nouveau / nv30_state.c
1 /**************************************************************************
2
3 Copyright 2006 Nouveau
4 All Rights Reserved.
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 on the rights to use, copy, modify, merge, publish, distribute, sub
10 license, and/or sell copies of the Software, and to permit persons to whom
11 the Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice (including the next
14 paragraph) shall be included in all copies or substantial portions of the
15 Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
21 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
23 USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 **************************************************************************/
26
27 #include "nouveau_context.h"
28 #include "nouveau_object.h"
29 #include "nouveau_fifo.h"
30 #include "nouveau_reg.h"
31 #include "nouveau_state.h"
32
33 #include "tnl/t_pipeline.h"
34
35 #include "mtypes.h"
36 #include "colormac.h"
37
38 #define NOUVEAU_CARD_USING_SHADERS (nmesa->screen->card->type >= NV_40)
39
40 static void nv30AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
41 {
42 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
43 GLubyte ubRef;
44 CLAMPED_FLOAT_TO_UBYTE(ubRef, ref);
45
46 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC, 2);
47 OUT_RING_CACHE(func); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_FUNC */
48 OUT_RING_CACHE(ubRef); /* NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_REF */
49 }
50
51 static void nv30BlendColor(GLcontext *ctx, const GLfloat color[4])
52 {
53 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
54 GLubyte cf[4];
55
56 CLAMPED_FLOAT_TO_UBYTE(cf[0], color[0]);
57 CLAMPED_FLOAT_TO_UBYTE(cf[1], color[1]);
58 CLAMPED_FLOAT_TO_UBYTE(cf[2], color[2]);
59 CLAMPED_FLOAT_TO_UBYTE(cf[3], color[3]);
60
61 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_COLOR, 1);
62 OUT_RING_CACHE(PACK_COLOR_8888(cf[3], cf[1], cf[2], cf[0]));
63 }
64
65 static void nv30BlendEquationSeparate(GLcontext *ctx, GLenum modeRGB, GLenum modeA)
66 {
67 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
68 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_EQUATION, 1);
69 OUT_RING_CACHE((modeA<<16) | modeRGB);
70 }
71
72
73 static void nv30BlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
74 GLenum sfactorA, GLenum dfactorA)
75 {
76 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
77 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_SRC, 2);
78 OUT_RING_CACHE((sfactorA<<16) | sfactorRGB);
79 OUT_RING_CACHE((dfactorA<<16) | dfactorRGB);
80 }
81
82 static void nv30Clear(GLcontext *ctx, GLbitfield mask)
83 {
84 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
85 GLuint hw_bufs = 0;
86
87 if (mask & (BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT))
88 hw_bufs |= 0xf0;
89 if (mask & (BUFFER_BIT_DEPTH))
90 hw_bufs |= 0x03;
91
92 if (hw_bufs) {
93 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_WHICH_BUFFERS, 1);
94 OUT_RING(hw_bufs);
95 }
96 }
97
98 static void nv30ClearColor(GLcontext *ctx, const GLfloat color[4])
99 {
100 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
101 GLubyte c[4];
102 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,color);
103 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_ARGB, 1);
104 OUT_RING_CACHE(PACK_COLOR_8888(c[3],c[0],c[1],c[2]));
105 }
106
107 static void nv30ClearDepth(GLcontext *ctx, GLclampd d)
108 {
109 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
110 nmesa->clear_value=((nmesa->clear_value&0x000000FF)|(((uint32_t)(d*0xFFFFFF))<<8));
111 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
112 OUT_RING_CACHE(nmesa->clear_value);
113 }
114
115 /* we're don't support indexed buffers
116 void (*ClearIndex)(GLcontext *ctx, GLuint index)
117 */
118
119 static void nv30ClearStencil(GLcontext *ctx, GLint s)
120 {
121 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
122 nmesa->clear_value=((nmesa->clear_value&0xFFFFFF00)|(s&0x000000FF));
123 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLEAR_VALUE_DEPTH, 1);
124 OUT_RING_CACHE(nmesa->clear_value);
125 }
126
127 static void nv30ClipPlane(GLcontext *ctx, GLenum plane, const GLfloat *equation)
128 {
129 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
130
131 if (NOUVEAU_CARD_USING_SHADERS)
132 return;
133
134 plane -= GL_CLIP_PLANE0;
135 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_A(plane), 4);
136 OUT_RING_CACHEf(equation[0]);
137 OUT_RING_CACHEf(equation[1]);
138 OUT_RING_CACHEf(equation[2]);
139 OUT_RING_CACHEf(equation[3]);
140 }
141
142 static void nv30ColorMask(GLcontext *ctx, GLboolean rmask, GLboolean gmask,
143 GLboolean bmask, GLboolean amask )
144 {
145 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
146 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_MASK, 1);
147 OUT_RING_CACHE(((amask && 0x01) << 24) | ((rmask && 0x01) << 16) | ((gmask && 0x01)<< 8) | ((bmask && 0x01) << 0));
148 }
149
150 static void nv30ColorMaterial(GLcontext *ctx, GLenum face, GLenum mode)
151 {
152 // TODO I need love
153 }
154
155 static void nv30CullFace(GLcontext *ctx, GLenum mode)
156 {
157 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
158 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE, 1);
159 OUT_RING_CACHE(mode);
160 }
161
162 static void nv30FrontFace(GLcontext *ctx, GLenum mode)
163 {
164 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
165 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FRONT_FACE, 1);
166 OUT_RING_CACHE(mode);
167 }
168
169 static void nv30DepthFunc(GLcontext *ctx, GLenum func)
170 {
171 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
172 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_FUNC, 1);
173 OUT_RING_CACHE(func);
174 }
175
176 static void nv30DepthMask(GLcontext *ctx, GLboolean flag)
177 {
178 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
179 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_WRITE_ENABLE, 1);
180 OUT_RING_CACHE(flag);
181 }
182
183 static void nv30DepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
184 {
185 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
186 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_RANGE_NEAR, 2);
187 OUT_RING_CACHEf(nearval);
188 OUT_RING_CACHEf(farval);
189 }
190
191 /** Specify the current buffer for writing */
192 //void (*DrawBuffer)( GLcontext *ctx, GLenum buffer );
193 /** Specify the buffers for writing for fragment programs*/
194 //void (*DrawBuffers)( GLcontext *ctx, GLsizei n, const GLenum *buffers );
195
196 static void nv30Enable(GLcontext *ctx, GLenum cap, GLboolean state)
197 {
198 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
199 switch(cap)
200 {
201 case GL_ALPHA_TEST:
202 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ALPHA_FUNC_ENABLE, 1);
203 OUT_RING_CACHE(state);
204 break;
205 // case GL_AUTO_NORMAL:
206 case GL_BLEND:
207 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_BLEND_FUNC_ENABLE, 1);
208 OUT_RING_CACHE(state);
209 break;
210 case GL_CLIP_PLANE0:
211 case GL_CLIP_PLANE1:
212 case GL_CLIP_PLANE2:
213 case GL_CLIP_PLANE3:
214 case GL_CLIP_PLANE4:
215 case GL_CLIP_PLANE5:
216 if (NOUVEAU_CARD_USING_SHADERS) {
217 nouveauShader *nvs = (nouveauShader *)ctx->VertexProgram._Current;
218 if (nvs)
219 nvs->translated = GL_FALSE;
220 } else {
221 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CLIP_PLANE_ENABLE(cap-GL_CLIP_PLANE0), 1);
222 OUT_RING_CACHE(state);
223 }
224 break;
225 case GL_COLOR_LOGIC_OP:
226 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_ENABLE, 1);
227 OUT_RING_CACHE(state);
228 break;
229 // case GL_COLOR_MATERIAL:
230 // case GL_COLOR_SUM_EXT:
231 // case GL_COLOR_TABLE:
232 // case GL_CONVOLUTION_1D:
233 // case GL_CONVOLUTION_2D:
234 case GL_CULL_FACE:
235 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_CULL_FACE_ENABLE, 1);
236 OUT_RING_CACHE(state);
237 break;
238 case GL_DEPTH_TEST:
239 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_TEST_ENABLE, 1);
240 OUT_RING_CACHE(state);
241 break;
242 case GL_DITHER:
243 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DITHER_ENABLE, 1);
244 OUT_RING_CACHE(state);
245 break;
246 case GL_FOG:
247 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_ENABLE, 1);
248 OUT_RING_CACHE(state);
249 break;
250 // case GL_HISTOGRAM:
251 // case GL_INDEX_LOGIC_OP:
252 case GL_LIGHT0:
253 case GL_LIGHT1:
254 case GL_LIGHT2:
255 case GL_LIGHT3:
256 case GL_LIGHT4:
257 case GL_LIGHT5:
258 case GL_LIGHT6:
259 case GL_LIGHT7:
260 {
261 uint32_t mask=0x11<<(2*(cap-GL_LIGHT0));
262
263 if (NOUVEAU_CARD_USING_SHADERS)
264 break;
265
266 nmesa->enabled_lights=((nmesa->enabled_lights&mask)|(mask*state));
267 if (nmesa->lighting_enabled)
268 {
269 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
270 OUT_RING_CACHE(nmesa->enabled_lights);
271 }
272 break;
273 }
274 case GL_LIGHTING:
275 if (NOUVEAU_CARD_USING_SHADERS)
276 break;
277
278 nmesa->lighting_enabled=state;
279 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_ENABLED_LIGHTS, 1);
280 if (nmesa->lighting_enabled)
281 OUT_RING_CACHE(nmesa->enabled_lights);
282 else
283 OUT_RING_CACHE(0x0);
284 break;
285 // case GL_LINE_SMOOTH:
286 // case GL_LINE_STIPPLE:
287 // case GL_MAP1_COLOR_4:
288 // case GL_MAP1_INDEX:
289 // case GL_MAP1_NORMAL:
290 // case GL_MAP1_TEXTURE_COORD_1:
291 // case GL_MAP1_TEXTURE_COORD_2:
292 // case GL_MAP1_TEXTURE_COORD_3:
293 // case GL_MAP1_TEXTURE_COORD_4:
294 // case GL_MAP1_VERTEX_3:
295 // case GL_MAP1_VERTEX_4:
296 // case GL_MAP2_COLOR_4:
297 // case GL_MAP2_INDEX:
298 // case GL_MAP2_NORMAL:
299 // case GL_MAP2_TEXTURE_COORD_1:
300 // case GL_MAP2_TEXTURE_COORD_2:
301 // case GL_MAP2_TEXTURE_COORD_3:
302 // case GL_MAP2_TEXTURE_COORD_4:
303 // case GL_MAP2_VERTEX_3:
304 // case GL_MAP2_VERTEX_4:
305 // case GL_MINMAX:
306 case GL_NORMALIZE:
307 if (nmesa->screen->card->type != NV_44) {
308 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_NORMALIZE_ENABLE, 1);
309 OUT_RING_CACHE(state);
310 }
311 break;
312 // case GL_POINT_SMOOTH:
313 case GL_POLYGON_OFFSET_POINT:
314 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_POINT_ENABLE, 1);
315 OUT_RING_CACHE(state);
316 break;
317 case GL_POLYGON_OFFSET_LINE:
318 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_LINE_ENABLE, 1);
319 OUT_RING_CACHE(state);
320 break;
321 case GL_POLYGON_OFFSET_FILL:
322 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FILL_ENABLE, 1);
323 OUT_RING_CACHE(state);
324 break;
325 case GL_POLYGON_SMOOTH:
326 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_SMOOTH_ENABLE, 1);
327 OUT_RING_CACHE(state);
328 break;
329 case GL_POLYGON_STIPPLE:
330 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_ENABLE, 1);
331 OUT_RING_CACHE(state);
332 break;
333 // case GL_POST_COLOR_MATRIX_COLOR_TABLE:
334 // case GL_POST_CONVOLUTION_COLOR_TABLE:
335 // case GL_RESCALE_NORMAL:
336 case GL_SCISSOR_TEST:
337 /* No enable bit, nv30Scissor will adjust to max range */
338 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
339 ctx->Scissor.Width, ctx->Scissor.Height);
340 break;
341 // case GL_SEPARABLE_2D:
342 case GL_STENCIL_TEST:
343 // TODO BACK and FRONT ?
344 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_ENABLE, 1);
345 OUT_RING_CACHE(state);
346 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_ENABLE, 1);
347 OUT_RING_CACHE(state);
348 break;
349 // case GL_TEXTURE_GEN_Q:
350 // case GL_TEXTURE_GEN_R:
351 // case GL_TEXTURE_GEN_S:
352 // case GL_TEXTURE_GEN_T:
353 // case GL_TEXTURE_1D:
354 // case GL_TEXTURE_2D:
355 // case GL_TEXTURE_3D:
356 }
357 }
358
359 static void nv30Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
360 {
361 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
362
363 if (NOUVEAU_CARD_USING_SHADERS)
364 return;
365
366 switch(pname)
367 {
368 case GL_FOG_MODE:
369 {
370 int mode = 0;
371 /* The modes are different in GL and the card. */
372 switch(ctx->Fog.Mode)
373 {
374 case GL_LINEAR:
375 mode = 0x804;
376 break;
377 case GL_EXP:
378 mode = 0x802;
379 break;
380 case GL_EXP2:
381 mode = 0x803;
382 break;
383 }
384 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_MODE, 1);
385 OUT_RING_CACHE (mode);
386 break;
387 }
388 case GL_FOG_COLOR:
389 {
390 GLubyte c[4];
391 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c,params);
392 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_COLOR, 1);
393 /* nvidia ignores the alpha channel */
394 OUT_RING_CACHE(PACK_COLOR_8888_REV(c[0],c[1],c[2],c[3]));
395 break;
396 }
397 case GL_FOG_DENSITY:
398 case GL_FOG_START:
399 case GL_FOG_END:
400 {
401 GLfloat f=0., c=0.;
402 switch(ctx->Fog.Mode)
403 {
404 case GL_LINEAR:
405 f = -1.0/(ctx->Fog.End - ctx->Fog.Start);
406 c = ctx->Fog.Start/(ctx->Fog.End - ctx->Fog.Start) + 2.001953;
407 break;
408 case GL_EXP:
409 f = -0.090168*ctx->Fog.Density;
410 c = 1.5;
411 case GL_EXP2:
412 f = -0.212330*ctx->Fog.Density;
413 c = 1.5;
414 }
415 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_LINEAR, 1);
416 OUT_RING_CACHE(f);
417 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_CONSTANT, 1);
418 OUT_RING_CACHE(c);
419 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FOG_EQUATION_QUADRATIC, 1);
420 OUT_RING_CACHE(0); /* Is this always the same? */
421 break;
422 }
423 // case GL_FOG_COORD_SRC:
424 default:
425 break;
426 }
427 }
428
429 static void nv30Hint(GLcontext *ctx, GLenum target, GLenum mode)
430 {
431 // TODO I need love (fog and line_smooth hints)
432 }
433
434 // void (*IndexMask)(GLcontext *ctx, GLuint mask);
435
436 enum {
437 SPOTLIGHT_NO_UPDATE,
438 SPOTLIGHT_UPDATE_EXPONENT,
439 SPOTLIGHT_UPDATE_DIRECTION,
440 SPOTLIGHT_UPDATE_ALL
441 };
442
443 static void nv30Lightfv(GLcontext *ctx, GLenum light, GLenum pname, const GLfloat *params )
444 {
445 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
446 GLint p = light - GL_LIGHT0;
447 struct gl_light *l = &ctx->Light.Light[p];
448 int spotlight_update = SPOTLIGHT_NO_UPDATE;
449
450 if (NOUVEAU_CARD_USING_SHADERS)
451 return;
452
453 /* not sure where the fourth param value goes...*/
454 switch(pname)
455 {
456 case GL_AMBIENT:
457 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_AMBIENT_R(p), 3);
458 OUT_RING_CACHEf(params[0]);
459 OUT_RING_CACHEf(params[1]);
460 OUT_RING_CACHEf(params[2]);
461 break;
462 case GL_DIFFUSE:
463 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_DIFFUSE_R(p), 3);
464 OUT_RING_CACHEf(params[0]);
465 OUT_RING_CACHEf(params[1]);
466 OUT_RING_CACHEf(params[2]);
467 break;
468 case GL_SPECULAR:
469 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_FRONT_SIDE_PRODUCT_SPECULAR_R(p), 3);
470 OUT_RING_CACHEf(params[0]);
471 OUT_RING_CACHEf(params[1]);
472 OUT_RING_CACHEf(params[2]);
473 break;
474 case GL_POSITION:
475 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_POSITION_X(p), 3);
476 OUT_RING_CACHEf(params[0]);
477 OUT_RING_CACHEf(params[1]);
478 OUT_RING_CACHEf(params[2]);
479 break;
480 case GL_SPOT_DIRECTION:
481 spotlight_update = SPOTLIGHT_UPDATE_DIRECTION;
482 break;
483 case GL_SPOT_EXPONENT:
484 spotlight_update = SPOTLIGHT_UPDATE_EXPONENT;
485 break;
486 case GL_SPOT_CUTOFF:
487 spotlight_update = SPOTLIGHT_UPDATE_ALL;
488 break;
489 case GL_CONSTANT_ATTENUATION:
490 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_CONSTANT_ATTENUATION(p), 1);
491 OUT_RING_CACHEf(*params);
492 break;
493 case GL_LINEAR_ATTENUATION:
494 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_LINEAR_ATTENUATION(p), 1);
495 OUT_RING_CACHEf(*params);
496 break;
497 case GL_QUADRATIC_ATTENUATION:
498 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_QUADRATIC_ATTENUATION(p), 1);
499 OUT_RING_CACHEf(*params);
500 break;
501 default:
502 break;
503 }
504
505 switch(spotlight_update) {
506 case SPOTLIGHT_UPDATE_DIRECTION:
507 {
508 GLfloat x,y,z;
509 GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
510 x = spot_light_coef_a * l->_NormDirection[0];
511 y = spot_light_coef_a * l->_NormDirection[1];
512 z = spot_light_coef_a * l->_NormDirection[2];
513 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_DIR_X(p), 3);
514 OUT_RING_CACHEf(x);
515 OUT_RING_CACHEf(y);
516 OUT_RING_CACHEf(z);
517 }
518 break;
519 case SPOTLIGHT_UPDATE_EXPONENT:
520 {
521 GLfloat cc,lc,qc;
522 cc = 1.0; /* FIXME: These need to be correctly computed */
523 lc = 0.0;
524 qc = 2.0;
525 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 3);
526 OUT_RING_CACHEf(cc);
527 OUT_RING_CACHEf(lc);
528 OUT_RING_CACHEf(qc);
529 }
530 break;
531 case SPOTLIGHT_UPDATE_ALL:
532 {
533 GLfloat cc,lc,qc, x,y,z, c;
534 GLfloat spot_light_coef_a = 1.0 / (l->_CosCutoff - 1.0);
535 cc = 1.0; /* FIXME: These need to be correctly computed */
536 lc = 0.0;
537 qc = 2.0;
538 x = spot_light_coef_a * l->_NormDirection[0];
539 y = spot_light_coef_a * l->_NormDirection[1];
540 z = spot_light_coef_a * l->_NormDirection[2];
541 c = spot_light_coef_a + 1.0;
542 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LIGHT_SPOT_CUTOFF_A(p), 7);
543 OUT_RING_CACHEf(cc);
544 OUT_RING_CACHEf(lc);
545 OUT_RING_CACHEf(qc);
546 OUT_RING_CACHEf(x);
547 OUT_RING_CACHEf(y);
548 OUT_RING_CACHEf(z);
549 OUT_RING_CACHEf(c);
550 }
551 break;
552 default:
553 break;
554 }
555 }
556
557 /** Set the lighting model parameters */
558 void (*LightModelfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
559
560
561 static void nv30LineStipple(GLcontext *ctx, GLint factor, GLushort pattern )
562 {
563 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
564 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_STIPPLE_PATTERN, 1);
565 OUT_RING_CACHE((pattern << 16) | factor);
566 }
567
568 static void nv30LineWidth(GLcontext *ctx, GLfloat width)
569 {
570 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
571 GLubyte ubWidth;
572
573 ubWidth = (GLubyte)(width * 8.0) & 0xFF;
574
575 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LINE_WIDTH_SMOOTH, 1);
576 OUT_RING_CACHE(ubWidth);
577 }
578
579 static void nv30LogicOpcode(GLcontext *ctx, GLenum opcode)
580 {
581 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
582 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_COLOR_LOGIC_OP_OP, 1);
583 OUT_RING_CACHE(opcode);
584 }
585
586 static void nv30PointParameterfv(GLcontext *ctx, GLenum pname, const GLfloat *params)
587 {
588 /*TODO: not sure what goes here. */
589 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
590
591 }
592
593 /** Specify the diameter of rasterized points */
594 static void nv30PointSize(GLcontext *ctx, GLfloat size)
595 {
596 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
597 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POINT_SIZE, 1);
598 OUT_RING_CACHEf(size);
599 }
600
601 /** Select a polygon rasterization mode */
602 static void nv30PolygonMode(GLcontext *ctx, GLenum face, GLenum mode)
603 {
604 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
605
606 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
607 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_FRONT, 1);
608 OUT_RING_CACHE(mode);
609 }
610 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
611 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_MODE_BACK, 1);
612 OUT_RING_CACHE(mode);
613 }
614 }
615
616 /** Set the scale and units used to calculate depth values */
617 static void nv30PolygonOffset(GLcontext *ctx, GLfloat factor, GLfloat units)
618 {
619 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
620 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_OFFSET_FACTOR, 2);
621 OUT_RING_CACHEf(factor);
622
623 /* Looks like we always multiply units by 2.0... according to the dumps.*/
624 OUT_RING_CACHEf(units * 2.0);
625 }
626
627 /** Set the polygon stippling pattern */
628 static void nv30PolygonStipple(GLcontext *ctx, const GLubyte *mask )
629 {
630 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
631 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_POLYGON_STIPPLE_PATTERN(0), 32);
632 OUT_RING_CACHEp(mask, 32);
633 }
634
635 /* Specifies the current buffer for reading */
636 void (*ReadBuffer)( GLcontext *ctx, GLenum buffer );
637 /** Set rasterization mode */
638 void (*RenderMode)(GLcontext *ctx, GLenum mode );
639
640 /** Define the scissor box */
641 static void nv30Scissor(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h)
642 {
643 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
644
645 /* There's no scissor enable bit, so adjust the scissor to cover the
646 * maximum draw buffer bounds
647 */
648 if (!ctx->Scissor.Enabled) {
649 x = y = 0;
650 w = h = 4095;
651 } else {
652 x += nmesa->drawX;
653 y += nmesa->drawY;
654 }
655
656 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SCISSOR_WIDTH_XPOS, 2);
657 OUT_RING_CACHE(((w) << 16) | x);
658 OUT_RING_CACHE(((h) << 16) | y);
659 }
660
661 /** Select flat or smooth shading */
662 static void nv30ShadeModel(GLcontext *ctx, GLenum mode)
663 {
664 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
665
666 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SHADE_MODEL, 1);
667 OUT_RING_CACHE(mode);
668 }
669
670 /** OpenGL 2.0 two-sided StencilFunc */
671 static void nv30StencilFuncSeparate(GLcontext *ctx, GLenum face, GLenum func,
672 GLint ref, GLuint mask)
673 {
674 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
675
676 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
677 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_FUNC_FUNC, 3);
678 OUT_RING_CACHE(func);
679 OUT_RING_CACHE(ref);
680 OUT_RING_CACHE(mask);
681 }
682 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
683 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_FUNC_FUNC, 3);
684 OUT_RING_CACHE(func);
685 OUT_RING_CACHE(ref);
686 OUT_RING_CACHE(mask);
687 }
688 }
689
690 /** OpenGL 2.0 two-sided StencilMask */
691 static void nv30StencilMaskSeparate(GLcontext *ctx, GLenum face, GLuint mask)
692 {
693 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
694
695 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
696 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_MASK, 1);
697 OUT_RING_CACHE(mask);
698 }
699 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
700 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_MASK, 1);
701 OUT_RING_CACHE(mask);
702 }
703 }
704
705 /** OpenGL 2.0 two-sided StencilOp */
706 static void nv30StencilOpSeparate(GLcontext *ctx, GLenum face, GLenum fail,
707 GLenum zfail, GLenum zpass)
708 {
709 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
710
711 if (face == GL_FRONT || face == GL_FRONT_AND_BACK) {
712 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_FRONT_OP_FAIL, 3);
713 OUT_RING_CACHE(fail);
714 OUT_RING_CACHE(zfail);
715 OUT_RING_CACHE(zpass);
716 }
717 if (face == GL_BACK || face == GL_FRONT_AND_BACK) {
718 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_STENCIL_BACK_OP_FAIL, 3);
719 OUT_RING_CACHE(fail);
720 OUT_RING_CACHE(zfail);
721 OUT_RING_CACHE(zpass);
722 }
723 }
724
725 /** Control the generation of texture coordinates */
726 void (*TexGen)(GLcontext *ctx, GLenum coord, GLenum pname,
727 const GLfloat *params);
728 /** Set texture environment parameters */
729 void (*TexEnv)(GLcontext *ctx, GLenum target, GLenum pname,
730 const GLfloat *param);
731 /** Set texture parameters */
732 void (*TexParameter)(GLcontext *ctx, GLenum target,
733 struct gl_texture_object *texObj,
734 GLenum pname, const GLfloat *params);
735
736 static void nv30TextureMatrix(GLcontext *ctx, GLuint unit, const GLmatrix *mat)
737 {
738 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
739 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_TX_MATRIX(unit, 0), 16);
740 /*XXX: This SHOULD work.*/
741 OUT_RING_CACHEp(mat->m, 16);
742 }
743
744 static void nv30WindowMoved(nouveauContextPtr nmesa)
745 {
746 GLcontext *ctx = nmesa->glCtx;
747 GLfloat *v = nmesa->viewport.m;
748 GLuint w = ctx->Viewport.Width;
749 GLuint h = ctx->Viewport.Height;
750 GLuint x = ctx->Viewport.X + nmesa->drawX;
751 GLuint y = ctx->Viewport.Y + nmesa->drawY;
752
753 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_DIMS_0, 2);
754 OUT_RING_CACHE((w << 16) | x);
755 OUT_RING_CACHE((h << 16) | y);
756 /* something to do with clears, possibly doesn't belong here */
757 BEGIN_RING_CACHE(NvSub3D,
758 NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_OFS0, 2);
759 OUT_RING_CACHE(((w+x) << 16) | x);
760 OUT_RING_CACHE(((h+y) << 16) | y);
761 /* viewport transform */
762 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_XFRM_OX, 8);
763 OUT_RING_CACHEf (v[MAT_TX]);
764 OUT_RING_CACHEf (v[MAT_TY]);
765 OUT_RING_CACHEf (v[MAT_TZ]);
766 OUT_RING_CACHEf (0.0);
767 OUT_RING_CACHEf (v[MAT_SX]);
768 OUT_RING_CACHEf (v[MAT_SY]);
769 OUT_RING_CACHEf (v[MAT_SZ]);
770 OUT_RING_CACHEf (0.0);
771
772 ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
773 ctx->Scissor.Width, ctx->Scissor.Height);
774 }
775
776 static GLboolean nv30InitCard(nouveauContextPtr nmesa)
777 {
778 int i;
779 nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
780
781 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 3);
782 OUT_RING(NvDmaFB);
783 OUT_RING(NvDmaAGP);
784 OUT_RING(NvDmaFB);
785 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
786 OUT_RING(NvDmaFB);
787 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
788 OUT_RING(NvDmaFB);
789 OUT_RING(NvDmaFB);
790 BEGIN_RING_SIZE(NvSub3D, 0x1b0, 1); /* SET_OBJECT8B*/
791 OUT_RING(NvDmaFB);
792
793 for(i = 0x2c8; i <= 0x2fc; i += 4)
794 {
795 BEGIN_RING_SIZE(NvSub3D, i, 1);
796 OUT_RING(0x0);
797 }
798
799 BEGIN_RING_SIZE(NvSub3D, 0x0220, 1);
800 OUT_RING(1);
801
802 BEGIN_RING_SIZE(NvSub3D, 0x03b0, 1);
803 OUT_RING(0x00100000);
804 BEGIN_RING_SIZE(NvSub3D, 0x1454, 1);
805 OUT_RING(0);
806 BEGIN_RING_SIZE(NvSub3D, 0x1d80, 1);
807 OUT_RING(3);
808 BEGIN_RING_SIZE(NvSub3D, 0x1450, 1);
809 OUT_RING(0x00030004);
810
811 /* NEW */
812 BEGIN_RING_SIZE(NvSub3D, 0x1e98, 1);
813 OUT_RING(0);
814 BEGIN_RING_SIZE(NvSub3D, 0x17e0, 3);
815 OUT_RING(0);
816 OUT_RING(0);
817 OUT_RING(0x3f800000);
818 BEGIN_RING_SIZE(NvSub3D, 0x1f80, 16);
819 OUT_RING(0); OUT_RING(0); OUT_RING(0); OUT_RING(0);
820 OUT_RING(0); OUT_RING(0); OUT_RING(0); OUT_RING(0);
821 OUT_RING(0x0000ffff);
822 OUT_RING(0); OUT_RING(0); OUT_RING(0); OUT_RING(0);
823 OUT_RING(0); OUT_RING(0); OUT_RING(0);
824 /*
825 BEGIN_RING_SIZE(NvSub3D, 0x100, 2);
826 OUT_RING(0);
827 OUT_RING(0);
828 */
829 BEGIN_RING_SIZE(NvSub3D, 0x120, 3);
830 OUT_RING(0);
831 OUT_RING(1);
832 OUT_RING(2);
833
834 BEGIN_RING_SIZE(NvSub3D, 0x1d88, 1);
835 OUT_RING(0x00001200);
836
837 return GL_TRUE;
838 }
839
840 static GLboolean nv40InitCard(nouveauContextPtr nmesa)
841 {
842 nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
843
844 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT1, 2);
845 OUT_RING(NvDmaFB);
846 OUT_RING(NvDmaFB);
847 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT8, 1);
848 OUT_RING(NvDmaFB);
849 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_OBJECT4, 2);
850 OUT_RING(NvDmaFB);
851 OUT_RING(NvDmaFB);
852 BEGIN_RING_SIZE(NvSub3D, 0x0220, 1);
853 OUT_RING(1);
854
855 BEGIN_RING_SIZE(NvSub3D, 0x1ea4, 3);
856 OUT_RING(0x00000010);
857 OUT_RING(0x01000100);
858 OUT_RING(0xff800006);
859 BEGIN_RING_SIZE(NvSub3D, 0x1fc4, 1);
860 OUT_RING(0x06144321);
861 BEGIN_RING_SIZE(NvSub3D, 0x1fc8, 2);
862 OUT_RING(0xedcba987);
863 OUT_RING(0x00000021);
864 BEGIN_RING_SIZE(NvSub3D, 0x1fd0, 1);
865 OUT_RING(0x00171615);
866 BEGIN_RING_SIZE(NvSub3D, 0x1fd4, 1);
867 OUT_RING(0x001b1a19);
868
869 BEGIN_RING_SIZE(NvSub3D, 0x1ef8, 1);
870 OUT_RING(0x0020ffff);
871 BEGIN_RING_SIZE(NvSub3D, 0x1d64, 1);
872 OUT_RING(0x00d30000);
873 BEGIN_RING_SIZE(NvSub3D, 0x1e94, 1);
874 OUT_RING(0x00000001);
875
876 return GL_TRUE;
877 }
878
879 static GLboolean nv30BindBuffers(nouveauContextPtr nmesa, int num_color,
880 nouveau_renderbuffer **color,
881 nouveau_renderbuffer *depth)
882 {
883 GLuint x, y, w, h;
884
885 w = color[0]->mesa.Width;
886 h = color[0]->mesa.Height;
887 x = nmesa->drawX;
888 y = nmesa->drawY;
889
890 if (num_color != 1)
891 return GL_FALSE;
892 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VIEWPORT_COLOR_BUFFER_DIM0, 5);
893 OUT_RING (((w+x)<<16)|x);
894 OUT_RING (((h+y)<<16)|y);
895 if (color[0]->mesa._ActualFormat == GL_RGBA8)
896 OUT_RING (0x148);
897 else
898 OUT_RING (0x143);
899 if (nmesa->screen->card->type >= NV_40)
900 OUT_RING (color[0]->pitch);
901 else
902 OUT_RING (color[0]->pitch | (depth ? (depth->pitch << 16): 0));
903 OUT_RING (color[0]->offset);
904
905 if (depth) {
906 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_DEPTH_OFFSET, 1);
907 OUT_RING (depth->offset);
908 if (nmesa->screen->card->type >= NV_40) {
909 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_LMA_DEPTH_BUFFER_PITCH, 1);
910 OUT_RING (depth->pitch);
911 }
912 }
913
914 return GL_TRUE;
915 }
916
917 void nv30InitStateFuncs(GLcontext *ctx, struct dd_function_table *func)
918 {
919 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
920
921 func->AlphaFunc = nv30AlphaFunc;
922 func->BlendColor = nv30BlendColor;
923 func->BlendEquationSeparate = nv30BlendEquationSeparate;
924 func->BlendFuncSeparate = nv30BlendFuncSeparate;
925 func->Clear = nv30Clear;
926 func->ClearColor = nv30ClearColor;
927 func->ClearDepth = nv30ClearDepth;
928 func->ClearStencil = nv30ClearStencil;
929 func->ClipPlane = nv30ClipPlane;
930 func->ColorMask = nv30ColorMask;
931 func->ColorMaterial = nv30ColorMaterial;
932 func->CullFace = nv30CullFace;
933 func->FrontFace = nv30FrontFace;
934 func->DepthFunc = nv30DepthFunc;
935 func->DepthMask = nv30DepthMask;
936 func->DepthRange = nv30DepthRange;
937 func->Enable = nv30Enable;
938 func->Fogfv = nv30Fogfv;
939 func->Hint = nv30Hint;
940 func->Lightfv = nv30Lightfv;
941 /* func->LightModelfv = nv30LightModelfv; */
942 func->LineStipple = nv30LineStipple;
943 func->LineWidth = nv30LineWidth;
944 func->LogicOpcode = nv30LogicOpcode;
945 func->PointParameterfv = nv30PointParameterfv;
946 func->PointSize = nv30PointSize;
947 func->PolygonMode = nv30PolygonMode;
948 func->PolygonOffset = nv30PolygonOffset;
949 func->PolygonStipple = nv30PolygonStipple;
950 #if 0
951 func->ReadBuffer = nv30ReadBuffer;
952 func->RenderMode = nv30RenderMode;
953 #endif
954 func->Scissor = nv30Scissor;
955 func->ShadeModel = nv30ShadeModel;
956 func->StencilFuncSeparate = nv30StencilFuncSeparate;
957 func->StencilMaskSeparate = nv30StencilMaskSeparate;
958 func->StencilOpSeparate = nv30StencilOpSeparate;
959 #if 0
960 func->TexGen = nv30TexGen;
961 func->TexParameter = nv30TexParameter;
962 #endif
963 func->TextureMatrix = nv30TextureMatrix;
964
965
966 if (nmesa->screen->card->type >= NV_40)
967 nmesa->hw_func.InitCard = nv40InitCard;
968 else
969 nmesa->hw_func.InitCard = nv30InitCard;
970 nmesa->hw_func.BindBuffers = nv30BindBuffers;
971 nmesa->hw_func.WindowMoved = nv30WindowMoved;
972 }
973