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