3ad25282d90d599ad71aaba270e26ee91c51b26c
[mesa.git] / src / mesa / drivers / dri / i810 / i810state.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/i810/i810state.c,v 1.9 2002/10/30 12:51:33 alanh Exp $ */
2
3 #include <stdio.h>
4
5 #include "glheader.h"
6 #include "context.h"
7 #include "macros.h"
8 #include "dd.h"
9 #include "colormac.h"
10
11 #include "texmem.h"
12
13 #include "i810screen.h"
14 #include "i810_dri.h"
15
16 #include "i810context.h"
17 #include "i810state.h"
18 #include "i810tex.h"
19 #include "i810vb.h"
20 #include "i810tris.h"
21 #include "i810ioctl.h"
22
23 #include "swrast/swrast.h"
24 #include "tnl/tnl.h"
25 #include "vbo/vbo.h"
26 #include "swrast_setup/swrast_setup.h"
27
28 #include "tnl/t_pipeline.h"
29
30 static __inline__ GLuint i810PackColor(GLuint format,
31 GLubyte r, GLubyte g,
32 GLubyte b, GLubyte a)
33 {
34
35 if (I810_DEBUG&DEBUG_DRI)
36 fprintf(stderr, "%s\n", __FUNCTION__);
37
38 switch (format) {
39 case DV_PF_555:
40 return PACK_COLOR_1555( a, r, g, b );
41 case DV_PF_565:
42 return PACK_COLOR_565( r, g, b );
43 default:
44 fprintf(stderr, "unknown format %d\n", (int)format);
45 return 0;
46 }
47 }
48
49
50 static void i810AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
51 {
52 i810ContextPtr imesa = I810_CONTEXT(ctx);
53 GLuint a = (ZA_UPDATE_ALPHAFUNC|ZA_UPDATE_ALPHAREF);
54 GLubyte refByte;
55
56 CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
57
58 switch (ctx->Color.AlphaFunc) {
59 case GL_NEVER: a |= ZA_ALPHA_NEVER; break;
60 case GL_LESS: a |= ZA_ALPHA_LESS; break;
61 case GL_GEQUAL: a |= ZA_ALPHA_GEQUAL; break;
62 case GL_LEQUAL: a |= ZA_ALPHA_LEQUAL; break;
63 case GL_GREATER: a |= ZA_ALPHA_GREATER; break;
64 case GL_NOTEQUAL: a |= ZA_ALPHA_NOTEQUAL; break;
65 case GL_EQUAL: a |= ZA_ALPHA_EQUAL; break;
66 case GL_ALWAYS: a |= ZA_ALPHA_ALWAYS; break;
67 default: return;
68 }
69
70 a |= ((refByte & 0xfc) << ZA_ALPHAREF_SHIFT);
71
72 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
73 imesa->Setup[I810_CTXREG_ZA] &= ~(ZA_ALPHA_MASK|ZA_ALPHAREF_MASK);
74 imesa->Setup[I810_CTXREG_ZA] |= a;
75 }
76
77 static void i810BlendEquationSeparate(GLcontext *ctx,
78 GLenum modeRGB, GLenum modeA)
79 {
80 assert( modeRGB == modeA );
81
82 /* Can only do GL_ADD equation in hardware */
83 FALLBACK( I810_CONTEXT(ctx), I810_FALLBACK_BLEND_EQ,
84 modeRGB != GL_FUNC_ADD);
85
86 /* BlendEquation sets ColorLogicOpEnabled in an unexpected
87 * manner.
88 */
89 FALLBACK( I810_CONTEXT(ctx), I810_FALLBACK_LOGICOP,
90 (ctx->Color.ColorLogicOpEnabled &&
91 ctx->Color.LogicOp != GL_COPY));
92 }
93
94 static void i810BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB,
95 GLenum dfactorRGB, GLenum sfactorA,
96 GLenum dfactorA )
97 {
98 i810ContextPtr imesa = I810_CONTEXT(ctx);
99 GLuint a = SDM_UPDATE_SRC_BLEND | SDM_UPDATE_DST_BLEND;
100 GLboolean fallback = GL_FALSE;
101
102 switch (ctx->Color.BlendSrcRGB) {
103 case GL_ZERO: a |= SDM_SRC_ZERO; break;
104 case GL_ONE: a |= SDM_SRC_ONE; break;
105 case GL_SRC_COLOR: a |= SDM_SRC_SRC_COLOR; break;
106 case GL_ONE_MINUS_SRC_COLOR: a |= SDM_SRC_INV_SRC_COLOR; break;
107 case GL_SRC_ALPHA: a |= SDM_SRC_SRC_ALPHA; break;
108 case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_SRC_INV_SRC_ALPHA; break;
109 case GL_DST_ALPHA: a |= SDM_SRC_ONE; break;
110 case GL_ONE_MINUS_DST_ALPHA: a |= SDM_SRC_ZERO; break;
111 case GL_DST_COLOR: a |= SDM_SRC_DST_COLOR; break;
112 case GL_ONE_MINUS_DST_COLOR: a |= SDM_SRC_INV_DST_COLOR; break;
113
114 /* (f, f, f, 1), f = min(As, 1 - Ad) = min(As, 1 - 1) = 0
115 * So (f, f, f, 1) = (0, 0, 0, 1). Since there is no destination alpha and
116 * the only supported alpha operation is GL_FUNC_ADD, the result modulating
117 * the source alpha with the alpha factor is largely irrelevant.
118 */
119 case GL_SRC_ALPHA_SATURATE: a |= SDM_SRC_ZERO; break;
120
121 case GL_CONSTANT_COLOR:
122 case GL_ONE_MINUS_CONSTANT_COLOR:
123 case GL_CONSTANT_ALPHA:
124 case GL_ONE_MINUS_CONSTANT_ALPHA:
125 fallback = GL_TRUE;
126 break;
127 default:
128 return;
129 }
130
131 switch (ctx->Color.BlendDstRGB) {
132 case GL_ZERO: a |= SDM_DST_ZERO; break;
133 case GL_ONE: a |= SDM_DST_ONE; break;
134 case GL_SRC_COLOR: a |= SDM_DST_SRC_COLOR; break;
135 case GL_ONE_MINUS_SRC_COLOR: a |= SDM_DST_INV_SRC_COLOR; break;
136 case GL_SRC_ALPHA: a |= SDM_DST_SRC_ALPHA; break;
137 case GL_ONE_MINUS_SRC_ALPHA: a |= SDM_DST_INV_SRC_ALPHA; break;
138 case GL_DST_ALPHA: a |= SDM_DST_ONE; break;
139 case GL_ONE_MINUS_DST_ALPHA: a |= SDM_DST_ZERO; break;
140 case GL_DST_COLOR: a |= SDM_DST_DST_COLOR; break;
141 case GL_ONE_MINUS_DST_COLOR: a |= SDM_DST_INV_DST_COLOR; break;
142
143 case GL_CONSTANT_COLOR:
144 case GL_ONE_MINUS_CONSTANT_COLOR:
145 case GL_CONSTANT_ALPHA:
146 case GL_ONE_MINUS_CONSTANT_ALPHA:
147 fallback = GL_TRUE;
148 break;
149 default:
150 return;
151 }
152
153 FALLBACK( imesa, I810_FALLBACK_BLEND_FUNC, fallback);
154 if (!fallback) {
155 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
156 imesa->Setup[I810_CTXREG_SDM] &= ~(SDM_SRC_MASK|SDM_DST_MASK);
157 imesa->Setup[I810_CTXREG_SDM] |= a;
158 }
159 }
160
161
162
163 static void i810DepthFunc(GLcontext *ctx, GLenum func)
164 {
165 i810ContextPtr imesa = I810_CONTEXT(ctx);
166 int zmode;
167
168 switch(func) {
169 case GL_NEVER: zmode = LCS_Z_NEVER; break;
170 case GL_ALWAYS: zmode = LCS_Z_ALWAYS; break;
171 case GL_LESS: zmode = LCS_Z_LESS; break;
172 case GL_LEQUAL: zmode = LCS_Z_LEQUAL; break;
173 case GL_EQUAL: zmode = LCS_Z_EQUAL; break;
174 case GL_GREATER: zmode = LCS_Z_GREATER; break;
175 case GL_GEQUAL: zmode = LCS_Z_GEQUAL; break;
176 case GL_NOTEQUAL: zmode = LCS_Z_NOTEQUAL; break;
177 default: return;
178 }
179
180 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
181 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_Z_MASK;
182 imesa->Setup[I810_CTXREG_LCS] |= zmode;
183 }
184
185 static void i810DepthMask(GLcontext *ctx, GLboolean flag)
186 {
187 i810ContextPtr imesa = I810_CONTEXT(ctx);
188 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
189
190 if (flag)
191 imesa->Setup[I810_CTXREG_B2] |= B2_ZB_WRITE_ENABLE;
192 else
193 imesa->Setup[I810_CTXREG_B2] &= ~B2_ZB_WRITE_ENABLE;
194 }
195
196
197 /* =============================================================
198 * Polygon stipple
199 *
200 * The i810 supports a 4x4 stipple natively, GL wants 32x32.
201 * Fortunately stipple is usually a repeating pattern.
202 */
203 static void i810PolygonStipple( GLcontext *ctx, const GLubyte *mask )
204 {
205 i810ContextPtr imesa = I810_CONTEXT(ctx);
206 const GLubyte *m = mask;
207 GLubyte p[4];
208 int i,j,k;
209 int active = (ctx->Polygon.StippleFlag &&
210 imesa->reduced_primitive == GL_TRIANGLES);
211 GLuint newMask;
212
213 if (active) {
214 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
215 imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE;
216 }
217
218 p[0] = mask[12] & 0xf; p[0] |= p[0] << 4;
219 p[1] = mask[8] & 0xf; p[1] |= p[1] << 4;
220 p[2] = mask[4] & 0xf; p[2] |= p[2] << 4;
221 p[3] = mask[0] & 0xf; p[3] |= p[3] << 4;
222
223 for (k = 0 ; k < 8 ; k++)
224 for (j = 0 ; j < 4; j++)
225 for (i = 0 ; i < 4 ; i++)
226 if (*m++ != p[j]) {
227 imesa->stipple_in_hw = 0;
228 return;
229 }
230
231 newMask = ((p[0] & 0xf) << 0) |
232 ((p[1] & 0xf) << 4) |
233 ((p[2] & 0xf) << 8) |
234 ((p[3] & 0xf) << 12);
235
236 if (newMask == 0xffff) {
237 /* this is needed to make conform pass */
238 imesa->stipple_in_hw = 0;
239 return;
240 }
241
242 imesa->Setup[I810_CTXREG_ST1] &= ~0xffff;
243 imesa->Setup[I810_CTXREG_ST1] |= newMask;
244 imesa->stipple_in_hw = 1;
245
246 if (active)
247 imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE;
248 }
249
250
251
252 /* =============================================================
253 * Hardware clipping
254 */
255
256
257 static void i810Scissor( GLcontext *ctx, GLint x, GLint y,
258 GLsizei w, GLsizei h )
259 {
260 i810ContextPtr imesa = I810_CONTEXT(ctx);
261
262 if (ctx->Scissor.Enabled) {
263 I810_FIREVERTICES(imesa); /* don't pipeline cliprect changes */
264 imesa->upload_cliprects = GL_TRUE;
265 }
266
267 imesa->scissor_rect.x1 = x;
268 imesa->scissor_rect.y1 = imesa->driDrawable->h - (y + h);
269 imesa->scissor_rect.x2 = x + w;
270 imesa->scissor_rect.y2 = imesa->driDrawable->h - y;
271 }
272
273
274 static void i810LogicOp( GLcontext *ctx, GLenum opcode )
275 {
276 i810ContextPtr imesa = I810_CONTEXT(ctx);
277 FALLBACK( imesa, I810_FALLBACK_LOGICOP,
278 (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) );
279 }
280
281 /* Fallback to swrast for select and feedback.
282 */
283 static void i810RenderMode( GLcontext *ctx, GLenum mode )
284 {
285 i810ContextPtr imesa = I810_CONTEXT(ctx);
286 FALLBACK( imesa, I810_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
287 }
288
289
290 void i810DrawBuffer(GLcontext *ctx, GLenum mode )
291 {
292 i810ContextPtr imesa = I810_CONTEXT(ctx);
293 int front = 0;
294
295 /*
296 * _DrawDestMask is easier to cope with than <mode>.
297 */
298 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0]) {
299 case BUFFER_BIT_FRONT_LEFT:
300 front = 1;
301 break;
302 case BUFFER_BIT_BACK_LEFT:
303 front = 0;
304 break;
305 default:
306 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
307 FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_TRUE );
308 return;
309 }
310
311 if ( imesa->sarea->pf_current_page == 1 )
312 front ^= 1;
313
314 FALLBACK( imesa, I810_FALLBACK_DRAW_BUFFER, GL_FALSE );
315 I810_FIREVERTICES(imesa);
316 I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS);
317
318 if (front)
319 {
320 imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->fbOffset |
321 imesa->i810Screen->backPitchBits);
322 i810XMesaSetFrontClipRects( imesa );
323 }
324 else
325 {
326 imesa->BufferSetup[I810_DESTREG_DI1] = (imesa->i810Screen->backOffset |
327 imesa->i810Screen->backPitchBits);
328 i810XMesaSetBackClipRects( imesa );
329 }
330 }
331
332
333 static void i810ReadBuffer(GLcontext *ctx, GLenum mode )
334 {
335 /* XXX anything? */
336 }
337
338
339 static void i810ClearColor(GLcontext *ctx, const GLfloat color[4] )
340 {
341 i810ContextPtr imesa = I810_CONTEXT(ctx);
342 GLubyte c[4];
343 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
344 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
345 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
346 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
347 imesa->ClearColor = i810PackColor( imesa->i810Screen->fbFormat,
348 c[0], c[1], c[2], c[3] );
349 }
350
351
352 /* =============================================================
353 * Culling - the i810 isn't quite as clean here as the rest of
354 * its interfaces, but it's not bad.
355 */
356 static void i810CullFaceFrontFace(GLcontext *ctx, GLenum unused)
357 {
358 i810ContextPtr imesa = I810_CONTEXT(ctx);
359 GLuint mode = LCS_CULL_BOTH;
360
361 if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
362 mode = LCS_CULL_CW;
363 if (ctx->Polygon.CullFaceMode == GL_FRONT)
364 mode ^= (LCS_CULL_CW ^ LCS_CULL_CCW);
365 if (ctx->Polygon.FrontFace != GL_CCW)
366 mode ^= (LCS_CULL_CW ^ LCS_CULL_CCW);
367 }
368
369 imesa->LcsCullMode = mode;
370
371 if (ctx->Polygon.CullFlag)
372 {
373 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
374 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK;
375 imesa->Setup[I810_CTXREG_LCS] |= mode;
376 }
377 }
378
379
380 static void i810LineWidth( GLcontext *ctx, GLfloat widthf )
381 {
382 i810ContextPtr imesa = I810_CONTEXT( ctx );
383 int width = (int)ctx->Line._Width;
384
385 imesa->LcsLineWidth = 0;
386 if (width & 1) imesa->LcsLineWidth |= LCS_LINEWIDTH_1_0;
387 if (width & 2) imesa->LcsLineWidth |= LCS_LINEWIDTH_2_0;
388
389 if (imesa->reduced_primitive == GL_LINES) {
390 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
391 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_3_0;
392 imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsLineWidth;
393 }
394 }
395
396 static void i810PointSize( GLcontext *ctx, GLfloat sz )
397 {
398 i810ContextPtr imesa = I810_CONTEXT( ctx );
399 int size = (int)ctx->Point._Size;
400
401 imesa->LcsPointSize = 0;
402 if (size & 1) imesa->LcsPointSize |= LCS_LINEWIDTH_1_0;
403 if (size & 2) imesa->LcsPointSize |= LCS_LINEWIDTH_2_0;
404
405 if (imesa->reduced_primitive == GL_POINTS) {
406 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
407 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_3_0;
408 imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsPointSize;
409 }
410 }
411
412 /* =============================================================
413 * Color masks
414 */
415
416 static void i810ColorMask(GLcontext *ctx,
417 GLboolean r, GLboolean g,
418 GLboolean b, GLboolean a )
419 {
420 i810ContextPtr imesa = I810_CONTEXT( ctx );
421 GLuint tmp = 0;
422
423 if (r && g && b) {
424 tmp = imesa->Setup[I810_CTXREG_B2] | B2_FB_WRITE_ENABLE;
425 FALLBACK( imesa, I810_FALLBACK_COLORMASK, GL_FALSE );
426 } else if (!r && !g && !b) {
427 tmp = imesa->Setup[I810_CTXREG_B2] & ~B2_FB_WRITE_ENABLE;
428 FALLBACK( imesa, I810_FALLBACK_COLORMASK, GL_FALSE );
429 } else {
430 FALLBACK( imesa, I810_FALLBACK_COLORMASK, GL_TRUE );
431 return;
432 }
433
434 if (tmp != imesa->Setup[I810_CTXREG_B2]) {
435 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
436 imesa->Setup[I810_CTXREG_B2] = tmp;
437 imesa->dirty |= I810_UPLOAD_CTX;
438 }
439 }
440
441 /* Seperate specular not fully implemented on the i810.
442 */
443 static void i810LightModelfv(GLcontext *ctx, GLenum pname,
444 const GLfloat *param)
445 {
446 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL)
447 {
448 i810ContextPtr imesa = I810_CONTEXT( ctx );
449 FALLBACK( imesa, I810_FALLBACK_SPECULAR,
450 (ctx->Light.Enabled &&
451 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR));
452 }
453 }
454
455 /* But the 815 has it...
456 */
457 static void i810LightModelfv_i815(GLcontext *ctx, GLenum pname,
458 const GLfloat *param)
459 {
460 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL)
461 {
462 i810ContextPtr imesa = I810_CONTEXT( ctx );
463
464 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
465 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
466 imesa->Setup[I810_CTXREG_B1] |= B1_SPEC_ENABLE;
467 else
468 imesa->Setup[I810_CTXREG_B1] &= ~B1_SPEC_ENABLE;
469 }
470 }
471
472 /* In Mesa 3.5 we can reliably do native flatshading.
473 */
474 static void i810ShadeModel(GLcontext *ctx, GLenum mode)
475 {
476 i810ContextPtr imesa = I810_CONTEXT(ctx);
477 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
478 if (mode == GL_FLAT)
479 imesa->Setup[I810_CTXREG_LCS] |= LCS_INTERP_FLAT;
480 else
481 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_INTERP_FLAT;
482 }
483
484
485
486 /* =============================================================
487 * Fog
488 */
489 static void i810Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
490 {
491 i810ContextPtr imesa = I810_CONTEXT(ctx);
492
493 if (pname == GL_FOG_COLOR) {
494 GLuint color = (((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
495 ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
496 ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
497
498 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
499 imesa->Setup[I810_CTXREG_FOG] = ((GFX_OP_FOG_COLOR | color) &
500 ~FOG_RESERVED_MASK);
501 }
502 }
503
504
505 /* =============================================================
506 */
507 static void i810Enable(GLcontext *ctx, GLenum cap, GLboolean state)
508 {
509 i810ContextPtr imesa = I810_CONTEXT(ctx);
510
511 switch(cap) {
512 case GL_ALPHA_TEST:
513 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
514 imesa->Setup[I810_CTXREG_B1] &= ~B1_ALPHA_TEST_ENABLE;
515 if (state)
516 imesa->Setup[I810_CTXREG_B1] |= B1_ALPHA_TEST_ENABLE;
517 break;
518 case GL_BLEND:
519 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
520 imesa->Setup[I810_CTXREG_B1] &= ~B1_BLEND_ENABLE;
521 if (state)
522 imesa->Setup[I810_CTXREG_B1] |= B1_BLEND_ENABLE;
523
524 /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
525 */
526 FALLBACK( imesa, I810_FALLBACK_LOGICOP,
527 (ctx->Color.ColorLogicOpEnabled &&
528 ctx->Color.LogicOp != GL_COPY));
529 break;
530 case GL_DEPTH_TEST:
531 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
532 imesa->Setup[I810_CTXREG_B1] &= ~B1_Z_TEST_ENABLE;
533 if (state)
534 imesa->Setup[I810_CTXREG_B1] |= B1_Z_TEST_ENABLE;
535 break;
536 case GL_SCISSOR_TEST:
537 /* XXX without these next two lines, conform's scissor test fails */
538 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
539 I810_STATECHANGE(imesa, I810_UPLOAD_BUFFERS);
540 I810_FIREVERTICES(imesa); /* don't pipeline cliprect changes */
541 imesa->upload_cliprects = GL_TRUE;
542 imesa->scissor = state;
543 break;
544 case GL_POLYGON_STIPPLE:
545 if (imesa->stipple_in_hw && imesa->reduced_primitive == GL_TRIANGLES)
546 {
547 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
548 imesa->Setup[I810_CTXREG_ST1] &= ~ST1_ENABLE;
549 if (state)
550 imesa->Setup[I810_CTXREG_ST1] |= ST1_ENABLE;
551 }
552 break;
553 case GL_LINE_SMOOTH:
554 /* Need to fatten the lines by .5, or they disappear...
555 */
556 if (imesa->reduced_primitive == GL_LINES) {
557 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
558 imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE;
559 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5;
560 if (state) {
561 imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE;
562 imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5;
563 }
564 }
565 break;
566 case GL_POINT_SMOOTH:
567 if (imesa->reduced_primitive == GL_POINTS) {
568 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
569 imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE;
570 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_LINEWIDTH_0_5;
571 if (state) {
572 imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE;
573 imesa->Setup[I810_CTXREG_LCS] |= LCS_LINEWIDTH_0_5;
574 }
575 }
576 break;
577 case GL_POLYGON_SMOOTH:
578 if (imesa->reduced_primitive == GL_TRIANGLES) {
579 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
580 imesa->Setup[I810_CTXREG_AA] &= ~AA_ENABLE;
581 if (state)
582 imesa->Setup[I810_CTXREG_AA] |= AA_ENABLE;
583 }
584 break;
585 case GL_FOG:
586 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
587 imesa->Setup[I810_CTXREG_B1] &= ~B1_FOG_ENABLE;
588 if (state)
589 imesa->Setup[I810_CTXREG_B1] |= B1_FOG_ENABLE;
590 break;
591 case GL_CULL_FACE:
592 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
593 imesa->Setup[I810_CTXREG_LCS] &= ~LCS_CULL_MASK;
594 if (state)
595 imesa->Setup[I810_CTXREG_LCS] |= imesa->LcsCullMode;
596 else
597 imesa->Setup[I810_CTXREG_LCS] |= LCS_CULL_DISABLE;
598 break;
599 case GL_TEXTURE_2D:
600 case GL_TEXTURE_RECTANGLE_NV:
601 I810_STATECHANGE(imesa, I810_UPLOAD_CTX);
602 if (ctx->Texture.CurrentUnit == 0) {
603 imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL0_ENABLE;
604 if (state)
605 imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL0_ENABLE;
606 } else {
607 imesa->Setup[I810_CTXREG_MT] &= ~MT_TEXEL1_ENABLE;
608 if (state)
609 imesa->Setup[I810_CTXREG_MT] |= MT_TEXEL1_ENABLE;
610 }
611 break;
612 case GL_COLOR_LOGIC_OP:
613 FALLBACK( imesa, I810_FALLBACK_LOGICOP,
614 (state && ctx->Color.LogicOp != GL_COPY));
615 break;
616 case GL_STENCIL_TEST:
617 FALLBACK( imesa, I810_FALLBACK_STENCIL, state );
618 break;
619 default:
620 ;
621 }
622 }
623
624
625
626
627
628
629
630 /* =============================================================
631 */
632
633
634
635
636 void i810EmitDrawingRectangle( i810ContextPtr imesa )
637 {
638 __DRIdrawablePrivate *dPriv = imesa->driDrawable;
639 i810ScreenPrivate *i810Screen = imesa->i810Screen;
640 int x0 = imesa->drawX;
641 int y0 = imesa->drawY;
642 int x1 = x0 + dPriv->w;
643 int y1 = y0 + dPriv->h;
644 GLuint dr2, dr3, dr4;
645
646
647 /* Coordinate origin of the window - may be offscreen.
648 */
649 dr4 = imesa->BufferSetup[I810_DESTREG_DR4] = ((y0<<16) |
650 (((unsigned)x0)&0xFFFF));
651
652 /* Clip to screen.
653 */
654 if (x0 < 0) x0 = 0;
655 if (y0 < 0) y0 = 0;
656 if (x1 > i810Screen->width-1) x1 = i810Screen->width-1;
657 if (y1 > i810Screen->height-1) y1 = i810Screen->height-1;
658
659
660 /* Onscreen drawing rectangle.
661 */
662 dr2 = imesa->BufferSetup[I810_DESTREG_DR2] = ((y0<<16) | x0);
663 dr3 = imesa->BufferSetup[I810_DESTREG_DR3] = (((y1+1)<<16) | (x1+1));
664
665
666 imesa->dirty |= I810_UPLOAD_BUFFERS;
667 }
668
669
670
671 static void i810CalcViewport( GLcontext *ctx )
672 {
673 i810ContextPtr imesa = I810_CONTEXT(ctx);
674 const GLfloat *v = ctx->Viewport._WindowMap.m;
675 GLfloat *m = imesa->ViewportMatrix.m;
676
677 /* See also i810_translate_vertex. SUBPIXEL adjustments can be done
678 * via state vars, too.
679 */
680 m[MAT_SX] = v[MAT_SX];
681 m[MAT_TX] = v[MAT_TX] + SUBPIXEL_X;
682 m[MAT_SY] = - v[MAT_SY];
683 m[MAT_TY] = - v[MAT_TY] + imesa->driDrawable->h + SUBPIXEL_Y;
684 m[MAT_SZ] = v[MAT_SZ] * (1.0 / 0xffff);
685 m[MAT_TZ] = v[MAT_TZ] * (1.0 / 0xffff);
686 }
687
688 static void i810Viewport( GLcontext *ctx,
689 GLint x, GLint y,
690 GLsizei width, GLsizei height )
691 {
692 i810CalcViewport( ctx );
693 }
694
695 static void i810DepthRange( GLcontext *ctx,
696 GLclampd nearval, GLclampd farval )
697 {
698 i810CalcViewport( ctx );
699 }
700
701
702
703 void i810PrintDirty( const char *msg, GLuint state )
704 {
705 fprintf(stderr, "%s (0x%x): %s%s%s%s\n",
706 msg,
707 (unsigned int) state,
708 (state & I810_UPLOAD_TEX0) ? "upload-tex0, " : "",
709 (state & I810_UPLOAD_TEX1) ? "upload-tex1, " : "",
710 (state & I810_UPLOAD_CTX) ? "upload-ctx, " : "",
711 (state & I810_UPLOAD_BUFFERS) ? "upload-bufs, " : ""
712 );
713 }
714
715
716
717 void i810InitState( GLcontext *ctx )
718 {
719 i810ContextPtr imesa = I810_CONTEXT(ctx);
720 i810ScreenPrivate *i810Screen = imesa->i810Screen;
721
722 memset(imesa->Setup, 0, sizeof(imesa->Setup));
723
724 imesa->Setup[I810_CTXREG_VF] = 0;
725
726 imesa->Setup[I810_CTXREG_MT] = (GFX_OP_MAP_TEXELS |
727 MT_UPDATE_TEXEL1_STATE |
728 MT_TEXEL1_COORD1 |
729 MT_TEXEL1_MAP1 |
730 MT_TEXEL1_DISABLE |
731 MT_UPDATE_TEXEL0_STATE |
732 MT_TEXEL0_COORD0 |
733 MT_TEXEL0_MAP0 |
734 MT_TEXEL0_DISABLE);
735
736 imesa->Setup[I810_CTXREG_MC0] = ( GFX_OP_MAP_COLOR_STAGES |
737 MC_STAGE_0 |
738 MC_UPDATE_DEST |
739 MC_DEST_CURRENT |
740 MC_UPDATE_ARG1 |
741 ((MC_ARG_ITERATED_COLOR |
742 MC_ARG_DONT_REPLICATE_ALPHA |
743 MC_ARG_DONT_INVERT) << MC_ARG1_SHIFT) |
744 MC_UPDATE_ARG2 |
745 ((MC_ARG_ONE |
746 MC_ARG_DONT_REPLICATE_ALPHA |
747 MC_ARG_DONT_INVERT) << MC_ARG2_SHIFT) |
748 MC_UPDATE_OP |
749 MC_OP_ARG1 );
750
751 imesa->Setup[I810_CTXREG_MC1] = ( GFX_OP_MAP_COLOR_STAGES |
752 MC_STAGE_1 |
753 MC_UPDATE_DEST |
754 MC_DEST_CURRENT |
755 MC_UPDATE_ARG1 |
756 ((MC_ARG_ONE |
757 MC_ARG_DONT_REPLICATE_ALPHA |
758 MC_ARG_DONT_INVERT) << MC_ARG1_SHIFT) |
759 MC_UPDATE_ARG2 |
760 ((MC_ARG_ONE |
761 MC_ARG_DONT_REPLICATE_ALPHA |
762 MC_ARG_DONT_INVERT) << MC_ARG2_SHIFT) |
763 MC_UPDATE_OP |
764 MC_OP_DISABLE );
765
766
767 imesa->Setup[I810_CTXREG_MC2] = ( GFX_OP_MAP_COLOR_STAGES |
768 MC_STAGE_2 |
769 MC_UPDATE_DEST |
770 MC_DEST_CURRENT |
771 MC_UPDATE_ARG1 |
772 ((MC_ARG_CURRENT_COLOR |
773 MC_ARG_REPLICATE_ALPHA |
774 MC_ARG_DONT_INVERT) << MC_ARG1_SHIFT) |
775 MC_UPDATE_ARG2 |
776 ((MC_ARG_ONE |
777 MC_ARG_DONT_REPLICATE_ALPHA |
778 MC_ARG_DONT_INVERT) << MC_ARG2_SHIFT) |
779 MC_UPDATE_OP |
780 MC_OP_DISABLE );
781
782
783 imesa->Setup[I810_CTXREG_MA0] = ( GFX_OP_MAP_ALPHA_STAGES |
784 MA_STAGE_0 |
785 MA_UPDATE_ARG1 |
786 ((MA_ARG_ITERATED_ALPHA |
787 MA_ARG_DONT_INVERT) << MA_ARG1_SHIFT) |
788 MA_UPDATE_ARG2 |
789 ((MA_ARG_CURRENT_ALPHA |
790 MA_ARG_DONT_INVERT) << MA_ARG2_SHIFT) |
791 MA_UPDATE_OP |
792 MA_OP_ARG1 );
793
794
795 imesa->Setup[I810_CTXREG_MA1] = ( GFX_OP_MAP_ALPHA_STAGES |
796 MA_STAGE_1 |
797 MA_UPDATE_ARG1 |
798 ((MA_ARG_CURRENT_ALPHA |
799 MA_ARG_DONT_INVERT) << MA_ARG1_SHIFT) |
800 MA_UPDATE_ARG2 |
801 ((MA_ARG_CURRENT_ALPHA |
802 MA_ARG_DONT_INVERT) << MA_ARG2_SHIFT) |
803 MA_UPDATE_OP |
804 MA_OP_ARG1 );
805
806
807 imesa->Setup[I810_CTXREG_MA2] = ( GFX_OP_MAP_ALPHA_STAGES |
808 MA_STAGE_2 |
809 MA_UPDATE_ARG1 |
810 ((MA_ARG_CURRENT_ALPHA |
811 MA_ARG_DONT_INVERT) << MA_ARG1_SHIFT) |
812 MA_UPDATE_ARG2 |
813 ((MA_ARG_CURRENT_ALPHA |
814 MA_ARG_DONT_INVERT) << MA_ARG2_SHIFT) |
815 MA_UPDATE_OP |
816 MA_OP_ARG1 );
817
818
819 imesa->Setup[I810_CTXREG_SDM] = ( GFX_OP_SRC_DEST_MONO |
820 SDM_UPDATE_MONO_ENABLE |
821 0 |
822 SDM_UPDATE_SRC_BLEND |
823 SDM_SRC_ONE |
824 SDM_UPDATE_DST_BLEND |
825 SDM_DST_ZERO );
826
827 /* Use for colormask:
828 */
829 imesa->Setup[I810_CTXREG_CF0] = GFX_OP_COLOR_FACTOR;
830 imesa->Setup[I810_CTXREG_CF1] = 0xffffffff;
831
832 imesa->Setup[I810_CTXREG_ZA] = (GFX_OP_ZBIAS_ALPHAFUNC |
833 ZA_UPDATE_ALPHAFUNC |
834 ZA_ALPHA_ALWAYS |
835 ZA_UPDATE_ZBIAS |
836 0 |
837 ZA_UPDATE_ALPHAREF |
838 0x0);
839
840 imesa->Setup[I810_CTXREG_FOG] = (GFX_OP_FOG_COLOR |
841 (0xffffff & ~FOG_RESERVED_MASK));
842
843 /* Choose a pipe
844 */
845 imesa->Setup[I810_CTXREG_B1] = ( GFX_OP_BOOL_1 |
846 B1_UPDATE_SPEC_SETUP_ENABLE |
847 0 |
848 B1_UPDATE_ALPHA_SETUP_ENABLE |
849 B1_ALPHA_SETUP_ENABLE |
850 B1_UPDATE_CI_KEY_ENABLE |
851 0 |
852 B1_UPDATE_CHROMAKEY_ENABLE |
853 0 |
854 B1_UPDATE_Z_BIAS_ENABLE |
855 0 |
856 B1_UPDATE_SPEC_ENABLE |
857 0 |
858 B1_UPDATE_FOG_ENABLE |
859 0 |
860 B1_UPDATE_ALPHA_TEST_ENABLE |
861 0 |
862 B1_UPDATE_BLEND_ENABLE |
863 0 |
864 B1_UPDATE_Z_TEST_ENABLE |
865 0 );
866
867 imesa->Setup[I810_CTXREG_B2] = ( GFX_OP_BOOL_2 |
868 B2_UPDATE_MAP_CACHE_ENABLE |
869 B2_MAP_CACHE_ENABLE |
870 B2_UPDATE_ALPHA_DITHER_ENABLE |
871 0 |
872 B2_UPDATE_FOG_DITHER_ENABLE |
873 0 |
874 B2_UPDATE_SPEC_DITHER_ENABLE |
875 0 |
876 B2_UPDATE_RGB_DITHER_ENABLE |
877 B2_RGB_DITHER_ENABLE |
878 B2_UPDATE_FB_WRITE_ENABLE |
879 B2_FB_WRITE_ENABLE |
880 B2_UPDATE_ZB_WRITE_ENABLE |
881 B2_ZB_WRITE_ENABLE );
882
883 imesa->Setup[I810_CTXREG_LCS] = ( GFX_OP_LINEWIDTH_CULL_SHADE_MODE |
884 LCS_UPDATE_ZMODE |
885 LCS_Z_LESS |
886 LCS_UPDATE_LINEWIDTH |
887 LCS_LINEWIDTH_1_0 |
888 LCS_UPDATE_ALPHA_INTERP |
889 LCS_ALPHA_INTERP |
890 LCS_UPDATE_FOG_INTERP |
891 0 |
892 LCS_UPDATE_SPEC_INTERP |
893 0 |
894 LCS_UPDATE_RGB_INTERP |
895 LCS_RGB_INTERP |
896 LCS_UPDATE_CULL_MODE |
897 LCS_CULL_DISABLE);
898
899 imesa->LcsCullMode = LCS_CULL_CW;
900 imesa->LcsLineWidth = LCS_LINEWIDTH_1_0;
901 imesa->LcsPointSize = LCS_LINEWIDTH_1_0;
902
903 imesa->Setup[I810_CTXREG_PV] = ( GFX_OP_PV_RULE |
904 PV_UPDATE_PIXRULE |
905 PV_PIXRULE_ENABLE |
906 PV_UPDATE_LINELIST |
907 PV_LINELIST_PV1 |
908 PV_UPDATE_TRIFAN |
909 PV_TRIFAN_PV2 |
910 PV_UPDATE_TRISTRIP |
911 PV_TRISTRIP_PV2 );
912
913
914 imesa->Setup[I810_CTXREG_ST0] = GFX_OP_STIPPLE;
915 imesa->Setup[I810_CTXREG_ST1] = 0;
916
917 imesa->Setup[I810_CTXREG_AA] = ( GFX_OP_ANTIALIAS |
918 AA_UPDATE_EDGEFLAG |
919 0 |
920 AA_UPDATE_POLYWIDTH |
921 AA_POLYWIDTH_05 |
922 AA_UPDATE_LINEWIDTH |
923 AA_LINEWIDTH_05 |
924 AA_UPDATE_BB_EXPANSION |
925 0 |
926 AA_UPDATE_AA_ENABLE |
927 0 );
928
929 memset(imesa->BufferSetup, 0, sizeof(imesa->BufferSetup));
930 imesa->BufferSetup[I810_DESTREG_DI0] = CMD_OP_DESTBUFFER_INFO;
931
932 if (imesa->glCtx->Visual.doubleBufferMode && imesa->sarea->pf_current_page == 0) {
933 /* use back buffer by default */
934 imesa->BufferSetup[I810_DESTREG_DI1] = (i810Screen->backOffset |
935 i810Screen->backPitchBits);
936 } else {
937 /* use front buffer by default */
938 imesa->BufferSetup[I810_DESTREG_DI1] = (i810Screen->fbOffset |
939 i810Screen->backPitchBits);
940 }
941
942 imesa->BufferSetup[I810_DESTREG_DV0] = GFX_OP_DESTBUFFER_VARS;
943 imesa->BufferSetup[I810_DESTREG_DV1] = (DV_HORG_BIAS_OGL |
944 DV_VORG_BIAS_OGL |
945 i810Screen->fbFormat);
946
947 imesa->BufferSetup[I810_DESTREG_DR0] = GFX_OP_DRAWRECT_INFO;
948 imesa->BufferSetup[I810_DESTREG_DR1] = DR1_RECT_CLIP_ENABLE;
949 }
950
951
952 static void i810InvalidateState( GLcontext *ctx, GLuint new_state )
953 {
954 _swrast_InvalidateState( ctx, new_state );
955 _swsetup_InvalidateState( ctx, new_state );
956 _vbo_InvalidateState( ctx, new_state );
957 _tnl_InvalidateState( ctx, new_state );
958 I810_CONTEXT(ctx)->new_state |= new_state;
959 }
960
961
962 void i810InitStateFuncs(GLcontext *ctx)
963 {
964 /* Callbacks for internal Mesa events.
965 */
966 ctx->Driver.UpdateState = i810InvalidateState;
967
968 /* API callbacks
969 */
970 ctx->Driver.AlphaFunc = i810AlphaFunc;
971 ctx->Driver.BlendEquationSeparate = i810BlendEquationSeparate;
972 ctx->Driver.BlendFuncSeparate = i810BlendFuncSeparate;
973 ctx->Driver.ClearColor = i810ClearColor;
974 ctx->Driver.ColorMask = i810ColorMask;
975 ctx->Driver.CullFace = i810CullFaceFrontFace;
976 ctx->Driver.DepthFunc = i810DepthFunc;
977 ctx->Driver.DepthMask = i810DepthMask;
978 ctx->Driver.Enable = i810Enable;
979 ctx->Driver.Fogfv = i810Fogfv;
980 ctx->Driver.FrontFace = i810CullFaceFrontFace;
981 ctx->Driver.LineWidth = i810LineWidth;
982 ctx->Driver.LogicOpcode = i810LogicOp;
983 ctx->Driver.PolygonStipple = i810PolygonStipple;
984 ctx->Driver.RenderMode = i810RenderMode;
985 ctx->Driver.Scissor = i810Scissor;
986 ctx->Driver.DrawBuffer = i810DrawBuffer;
987 ctx->Driver.ReadBuffer = i810ReadBuffer;
988 ctx->Driver.ShadeModel = i810ShadeModel;
989 ctx->Driver.DepthRange = i810DepthRange;
990 ctx->Driver.Viewport = i810Viewport;
991 ctx->Driver.PointSize = i810PointSize;
992
993 if (IS_I815(I810_CONTEXT(ctx))) {
994 ctx->Driver.LightModelfv = i810LightModelfv_i815;
995 } else {
996 ctx->Driver.LightModelfv = i810LightModelfv;
997 }
998 }