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