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