1 /**************************************************************************
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
37 #include "intel_screen.h"
38 #include "intel_batchbuffer.h"
40 #include "i830_context.h"
43 static void i830StencilFunc(GLcontext
*ctx
, GLenum func
, GLint ref
,
46 i830ContextPtr i830
= I830_CONTEXT(ctx
);
51 if (INTEL_DEBUG
&DEBUG_DRI
)
52 fprintf(stderr
, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__
,
53 _mesa_lookup_enum_by_nr(func
), ref
, mask
);
57 test
= COMPAREFUNC_NEVER
;
60 test
= COMPAREFUNC_LESS
;
63 test
= COMPAREFUNC_LEQUAL
;
66 test
= COMPAREFUNC_GREATER
;
69 test
= COMPAREFUNC_GEQUAL
;
72 test
= COMPAREFUNC_NOTEQUAL
;
75 test
= COMPAREFUNC_EQUAL
;
78 test
= COMPAREFUNC_ALWAYS
;
84 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
85 i830
->state
.Ctx
[I830_CTXREG_STATE4
] &= ~MODE4_ENABLE_STENCIL_TEST_MASK
;
86 i830
->state
.Ctx
[I830_CTXREG_STATE4
] |= (ENABLE_STENCIL_TEST_MASK
|
87 STENCIL_TEST_MASK(mask
));
88 i830
->state
.Ctx
[I830_CTXREG_STENCILTST
] &= ~(STENCIL_REF_VALUE_MASK
|
89 ENABLE_STENCIL_TEST_FUNC_MASK
);
90 i830
->state
.Ctx
[I830_CTXREG_STENCILTST
] |= (ENABLE_STENCIL_REF_VALUE
|
91 ENABLE_STENCIL_TEST_FUNC
|
92 STENCIL_REF_VALUE(ref
) |
93 STENCIL_TEST_FUNC(test
));
96 static void i830StencilMask(GLcontext
*ctx
, GLuint mask
)
98 i830ContextPtr i830
= I830_CONTEXT(ctx
);
100 if (INTEL_DEBUG
&DEBUG_DRI
)
101 fprintf(stderr
, "%s : mask 0x%x\n", __FUNCTION__
, mask
);
105 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
106 i830
->state
.Ctx
[I830_CTXREG_STATE4
] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK
;
107 i830
->state
.Ctx
[I830_CTXREG_STATE4
] |= (ENABLE_STENCIL_WRITE_MASK
|
108 STENCIL_WRITE_MASK(mask
));
111 static void i830StencilOp(GLcontext
*ctx
, GLenum fail
, GLenum zfail
,
114 i830ContextPtr i830
= I830_CONTEXT(ctx
);
117 if (INTEL_DEBUG
&DEBUG_DRI
)
118 fprintf(stderr
, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__
,
119 _mesa_lookup_enum_by_nr(fail
),
120 _mesa_lookup_enum_by_nr(zfail
),
121 _mesa_lookup_enum_by_nr(zpass
));
123 fop
= 0; dfop
= 0; dpop
= 0;
127 fop
= STENCILOP_KEEP
;
130 fop
= STENCILOP_ZERO
;
133 fop
= STENCILOP_REPLACE
;
136 fop
= STENCILOP_INCRSAT
;
139 fop
= STENCILOP_DECRSAT
;
142 fop
= STENCILOP_INCR
;
145 fop
= STENCILOP_DECR
;
148 fop
= STENCILOP_INVERT
;
155 dfop
= STENCILOP_KEEP
;
158 dfop
= STENCILOP_ZERO
;
161 dfop
= STENCILOP_REPLACE
;
164 dfop
= STENCILOP_INCRSAT
;
167 dfop
= STENCILOP_DECRSAT
;
170 dfop
= STENCILOP_INCR
;
173 dfop
= STENCILOP_DECR
;
176 dfop
= STENCILOP_INVERT
;
183 dpop
= STENCILOP_KEEP
;
186 dpop
= STENCILOP_ZERO
;
189 dpop
= STENCILOP_REPLACE
;
192 dpop
= STENCILOP_INCRSAT
;
195 dpop
= STENCILOP_DECRSAT
;
198 dpop
= STENCILOP_INCR
;
201 dpop
= STENCILOP_DECR
;
204 dpop
= STENCILOP_INVERT
;
211 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
212 i830
->state
.Ctx
[I830_CTXREG_STENCILTST
] &= ~(STENCIL_OPS_MASK
);
213 i830
->state
.Ctx
[I830_CTXREG_STENCILTST
] |= (ENABLE_STENCIL_PARMS
|
214 STENCIL_FAIL_OP(fop
) |
215 STENCIL_PASS_DEPTH_FAIL_OP(dfop
) |
216 STENCIL_PASS_DEPTH_PASS_OP(dpop
));
219 static void i830AlphaFunc(GLcontext
*ctx
, GLenum func
, GLfloat ref
)
221 i830ContextPtr i830
= I830_CONTEXT(ctx
);
226 UNCLAMPED_FLOAT_TO_UBYTE(refByte
, ref
);
227 refInt
= (GLuint
)refByte
;
231 test
= COMPAREFUNC_NEVER
;
234 test
= COMPAREFUNC_LESS
;
237 test
= COMPAREFUNC_LEQUAL
;
240 test
= COMPAREFUNC_GREATER
;
243 test
= COMPAREFUNC_GEQUAL
;
246 test
= COMPAREFUNC_NOTEQUAL
;
249 test
= COMPAREFUNC_EQUAL
;
252 test
= COMPAREFUNC_ALWAYS
;
258 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
259 i830
->state
.Ctx
[I830_CTXREG_STATE2
] &= ~ALPHA_TEST_REF_MASK
;
260 i830
->state
.Ctx
[I830_CTXREG_STATE2
] |= (ENABLE_ALPHA_TEST_FUNC
|
261 ENABLE_ALPHA_REF_VALUE
|
262 ALPHA_TEST_FUNC(test
) |
263 ALPHA_REF_VALUE(refInt
));
267 * Makes sure that the proper enables are set for LogicOp, Independant Alpha
268 * Blend, and Blending. It needs to be called from numerous places where we
269 * could change the LogicOp or Independant Alpha Blend without subsequent
273 * This function is substantially different from the old i830-specific driver.
274 * I'm not sure which is correct.
276 static void i830EvalLogicOpBlendState(GLcontext
*ctx
)
278 i830ContextPtr i830
= I830_CONTEXT(ctx
);
280 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
282 if (ctx
->Color
._LogicOpEnabled
) {
283 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~(ENABLE_COLOR_BLEND
|
284 ENABLE_LOGIC_OP_MASK
);
285 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= (DISABLE_COLOR_BLEND
|
287 } else if (ctx
->Color
.BlendEnabled
) {
288 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~(ENABLE_COLOR_BLEND
|
289 ENABLE_LOGIC_OP_MASK
);
290 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= (ENABLE_COLOR_BLEND
|
293 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~(ENABLE_COLOR_BLEND
|
294 ENABLE_LOGIC_OP_MASK
);
295 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= (DISABLE_COLOR_BLEND
|
300 static void i830BlendColor(GLcontext
*ctx
, const GLfloat color
[4])
302 i830ContextPtr i830
= I830_CONTEXT(ctx
);
305 if (INTEL_DEBUG
&DEBUG_DRI
)
306 fprintf(stderr
, "%s\n", __FUNCTION__
);
308 UNCLAMPED_FLOAT_TO_UBYTE(r
, color
[RCOMP
]);
309 UNCLAMPED_FLOAT_TO_UBYTE(g
, color
[GCOMP
]);
310 UNCLAMPED_FLOAT_TO_UBYTE(b
, color
[BCOMP
]);
311 UNCLAMPED_FLOAT_TO_UBYTE(a
, color
[ACOMP
]);
313 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
314 i830
->state
.Ctx
[I830_CTXREG_BLENDCOLOR1
] = (a
<<24) | (r
<<16) | (g
<<8) | b
;
319 * Calculate the hardware blend factor setting. This same function is used
320 * for source and destination of both alpha and RGB.
323 * The hardware register value for the specified blend factor. This value
324 * will need to be shifted into the correct position for either source or
325 * destination factor.
327 static int translate_blend_factor( GLenum factor
)
331 return BLENDFACT_ZERO
;
333 return BLENDFACT_SRC_ALPHA
;
335 return BLENDFACT_ONE
;
337 return BLENDFACT_SRC_COLR
;
338 case GL_ONE_MINUS_SRC_COLOR
:
339 return BLENDFACT_INV_SRC_COLR
;
341 return BLENDFACT_DST_COLR
;
342 case GL_ONE_MINUS_DST_COLOR
:
343 return BLENDFACT_INV_DST_COLR
;
344 case GL_ONE_MINUS_SRC_ALPHA
:
345 return BLENDFACT_INV_SRC_ALPHA
;
347 return BLENDFACT_DST_ALPHA
;
348 case GL_ONE_MINUS_DST_ALPHA
:
349 return BLENDFACT_INV_DST_ALPHA
;
350 case GL_SRC_ALPHA_SATURATE
:
351 return BLENDFACT_SRC_ALPHA_SATURATE
;
352 case GL_CONSTANT_COLOR
:
353 return BLENDFACT_CONST_COLOR
;
354 case GL_ONE_MINUS_CONSTANT_COLOR
:
355 return BLENDFACT_INV_CONST_COLOR
;
356 case GL_CONSTANT_ALPHA
:
357 return BLENDFACT_CONST_ALPHA
;
358 case GL_ONE_MINUS_CONSTANT_ALPHA
:
359 return BLENDFACT_INV_CONST_ALPHA
;
361 return BLENDFACT_ZERO
;
367 * Sets both the blend equation (called "function" in i830 docs) and the
368 * blend function (called "factor" in i830 docs). This is done in a single
369 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
370 * change the interpretation of the blend function.
372 static void i830_set_blend_state( GLcontext
* ctx
)
374 i830ContextPtr i830
= I830_CONTEXT(ctx
);
383 funcRGB
= SRC_BLND_FACT( translate_blend_factor( ctx
->Color
.BlendSrcRGB
) )
384 | DST_BLND_FACT( translate_blend_factor( ctx
->Color
.BlendDstRGB
) );
386 switch(ctx
->Color
.BlendEquationRGB
) {
388 eqnRGB
= BLENDFUNC_ADD
;
391 eqnRGB
= BLENDFUNC_MIN
;
392 funcRGB
= SRC_BLND_FACT(BLENDFACT_ONE
) | DST_BLND_FACT(BLENDFACT_ONE
);
395 eqnRGB
= BLENDFUNC_MAX
;
396 funcRGB
= SRC_BLND_FACT(BLENDFACT_ONE
) | DST_BLND_FACT(BLENDFACT_ONE
);
398 case GL_FUNC_SUBTRACT
:
399 eqnRGB
= BLENDFUNC_SUB
;
401 case GL_FUNC_REVERSE_SUBTRACT
:
402 eqnRGB
= BLENDFUNC_RVRSE_SUB
;
405 fprintf( stderr
, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
406 __func__
, __LINE__
, ctx
->Color
.BlendEquationRGB
);
411 funcA
= SRC_ABLEND_FACT( translate_blend_factor( ctx
->Color
.BlendSrcA
) )
412 | DST_ABLEND_FACT( translate_blend_factor( ctx
->Color
.BlendDstA
) );
414 switch(ctx
->Color
.BlendEquationA
) {
416 eqnA
= BLENDFUNC_ADD
;
419 eqnA
= BLENDFUNC_MIN
;
420 funcA
= SRC_BLND_FACT(BLENDFACT_ONE
) | DST_BLND_FACT(BLENDFACT_ONE
);
423 eqnA
= BLENDFUNC_MAX
;
424 funcA
= SRC_BLND_FACT(BLENDFACT_ONE
) | DST_BLND_FACT(BLENDFACT_ONE
);
426 case GL_FUNC_SUBTRACT
:
427 eqnA
= BLENDFUNC_SUB
;
429 case GL_FUNC_REVERSE_SUBTRACT
:
430 eqnA
= BLENDFUNC_RVRSE_SUB
;
433 fprintf( stderr
, "[%s:%u] Invalid alpha blend equation (0x%04x).\n",
434 __func__
, __LINE__
, ctx
->Color
.BlendEquationA
);
439 | _3DSTATE_INDPT_ALPHA_BLEND_CMD
440 | ENABLE_SRC_ABLEND_FACTOR
| ENABLE_DST_ABLEND_FACTOR
441 | ENABLE_ALPHA_BLENDFUNC
;
442 s1
= eqnRGB
| funcRGB
443 | _3DSTATE_MODES_1_CMD
444 | ENABLE_SRC_BLND_FACTOR
| ENABLE_DST_BLND_FACTOR
445 | ENABLE_COLR_BLND_FUNC
;
447 if ( (eqnA
| funcA
) != (eqnRGB
| funcRGB
) )
448 iab
|= ENABLE_INDPT_ALPHA_BLEND
;
450 iab
|= DISABLE_INDPT_ALPHA_BLEND
;
452 if (iab
!= i830
->state
.Ctx
[I830_CTXREG_IALPHAB
] ||
453 s1
!= i830
->state
.Ctx
[I830_CTXREG_STATE1
]) {
454 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
455 i830
->state
.Ctx
[I830_CTXREG_IALPHAB
] = iab
;
456 i830
->state
.Ctx
[I830_CTXREG_STATE1
] = s1
;
459 /* This will catch a logicop blend equation. It will also ensure
460 * independant alpha blend is really in the correct state (either enabled
461 * or disabled) if blending is already enabled.
464 i830EvalLogicOpBlendState(ctx
);
467 fprintf(stderr
, "[%s:%u] STATE1: 0x%08x IALPHAB: 0x%08x blend is %sabled\n",
469 i830
->state
.Ctx
[I830_CTXREG_STATE1
],
470 i830
->state
.Ctx
[I830_CTXREG_IALPHAB
],
471 (ctx
->Color
.BlendEnabled
) ? "en" : "dis");
476 static void i830BlendEquationSeparate(GLcontext
*ctx
, GLenum modeRGB
,
479 if (INTEL_DEBUG
&DEBUG_DRI
)
480 fprintf(stderr
, "%s -> %s, %s\n", __FUNCTION__
,
481 _mesa_lookup_enum_by_nr(modeRGB
),
482 _mesa_lookup_enum_by_nr(modeA
));
486 i830_set_blend_state( ctx
);
490 static void i830BlendFuncSeparate(GLcontext
*ctx
, GLenum sfactorRGB
,
491 GLenum dfactorRGB
, GLenum sfactorA
,
494 if (INTEL_DEBUG
&DEBUG_DRI
)
495 fprintf(stderr
, "%s -> RGB(%s, %s) A(%s, %s)\n", __FUNCTION__
,
496 _mesa_lookup_enum_by_nr(sfactorRGB
),
497 _mesa_lookup_enum_by_nr(dfactorRGB
),
498 _mesa_lookup_enum_by_nr(sfactorA
),
499 _mesa_lookup_enum_by_nr(dfactorA
));
505 i830_set_blend_state( ctx
);
510 static void i830DepthFunc(GLcontext
*ctx
, GLenum func
)
512 i830ContextPtr i830
= I830_CONTEXT(ctx
);
515 if (INTEL_DEBUG
&DEBUG_DRI
)
516 fprintf(stderr
, "%s\n", __FUNCTION__
);
520 test
= COMPAREFUNC_NEVER
;
523 test
= COMPAREFUNC_LESS
;
526 test
= COMPAREFUNC_LEQUAL
;
529 test
= COMPAREFUNC_GREATER
;
532 test
= COMPAREFUNC_GEQUAL
;
535 test
= COMPAREFUNC_NOTEQUAL
;
538 test
= COMPAREFUNC_EQUAL
;
541 test
= COMPAREFUNC_ALWAYS
;
546 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
547 i830
->state
.Ctx
[I830_CTXREG_STATE3
] &= ~DEPTH_TEST_FUNC_MASK
;
548 i830
->state
.Ctx
[I830_CTXREG_STATE3
] |= (ENABLE_DEPTH_TEST_FUNC
|
549 DEPTH_TEST_FUNC(test
));
552 static void i830DepthMask(GLcontext
*ctx
, GLboolean flag
)
554 i830ContextPtr i830
= I830_CONTEXT(ctx
);
556 if (INTEL_DEBUG
&DEBUG_DRI
)
557 fprintf(stderr
, "%s flag (%d)\n", __FUNCTION__
, flag
);
559 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
561 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] &= ~ENABLE_DIS_DEPTH_WRITE_MASK
;
563 if (flag
&& ctx
->Depth
.Test
)
564 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] |= ENABLE_DEPTH_WRITE
;
566 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] |= DISABLE_DEPTH_WRITE
;
569 /* =============================================================
572 * The i830 supports a 4x4 stipple natively, GL wants 32x32.
573 * Fortunately stipple is usually a repeating pattern.
575 static void i830PolygonStipple( GLcontext
*ctx
, const GLubyte
*mask
)
577 i830ContextPtr i830
= I830_CONTEXT(ctx
);
578 const GLubyte
*m
= mask
;
581 int active
= (ctx
->Polygon
.StippleFlag
&&
582 i830
->intel
.reduced_primitive
== GL_TRIANGLES
);
586 I830_STATECHANGE(i830
, I830_UPLOAD_STIPPLE
);
587 i830
->state
.Stipple
[I830_STPREG_ST1
] &= ~ST1_ENABLE
;
590 p
[0] = mask
[12] & 0xf; p
[0] |= p
[0] << 4;
591 p
[1] = mask
[8] & 0xf; p
[1] |= p
[1] << 4;
592 p
[2] = mask
[4] & 0xf; p
[2] |= p
[2] << 4;
593 p
[3] = mask
[0] & 0xf; p
[3] |= p
[3] << 4;
595 for (k
= 0 ; k
< 8 ; k
++)
596 for (j
= 3 ; j
>= 0; j
--)
597 for (i
= 0 ; i
< 4 ; i
++, m
++)
599 i830
->intel
.hw_stipple
= 0;
603 newMask
= (((p
[0] & 0xf) << 0) |
604 ((p
[1] & 0xf) << 4) |
605 ((p
[2] & 0xf) << 8) |
606 ((p
[3] & 0xf) << 12));
609 if (newMask
== 0xffff || newMask
== 0x0) {
610 /* this is needed to make conform pass */
611 i830
->intel
.hw_stipple
= 0;
615 i830
->state
.Stipple
[I830_STPREG_ST1
] &= ~0xffff;
616 i830
->state
.Stipple
[I830_STPREG_ST1
] |= newMask
;
617 i830
->intel
.hw_stipple
= 1;
620 i830
->state
.Stipple
[I830_STPREG_ST1
] |= ST1_ENABLE
;
624 /* =============================================================
627 static void i830Scissor(GLcontext
*ctx
, GLint x
, GLint y
,
628 GLsizei w
, GLsizei h
)
630 i830ContextPtr i830
= I830_CONTEXT(ctx
);
631 intelScreenPrivate
*screen
= i830
->intel
.intelScreen
;
634 if (!i830
->intel
.driDrawable
)
638 y1
= i830
->intel
.driDrawable
->h
- (y
+ h
);
642 if (INTEL_DEBUG
&DEBUG_DRI
)
643 fprintf(stderr
, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__
,
651 if (x2
>= screen
->width
) x2
= screen
->width
-1;
652 if (y2
>= screen
->height
) y2
= screen
->height
-1;
653 if (x1
>= screen
->width
) x1
= screen
->width
-1;
654 if (y1
>= screen
->height
) y1
= screen
->height
-1;
657 I830_STATECHANGE(i830
, I830_UPLOAD_BUFFERS
);
658 i830
->state
.Buffer
[I830_DESTREG_SR1
] = (y1
<< 16) | (x1
& 0xffff);
659 i830
->state
.Buffer
[I830_DESTREG_SR2
] = (y2
<< 16) | (x2
& 0xffff);
662 static void i830LogicOp(GLcontext
*ctx
, GLenum opcode
)
664 i830ContextPtr i830
= I830_CONTEXT(ctx
);
667 if (INTEL_DEBUG
&DEBUG_DRI
)
668 fprintf(stderr
, "%s\n", __FUNCTION__
);
670 /* FIXME: This should be a look-up table, like the r200 driver. */
679 tmp
= LOGICOP_AND_RVRSE
;
684 case GL_COPY_INVERTED
:
685 tmp
= LOGICOP_COPY_INV
;
687 case GL_AND_INVERTED
:
688 tmp
= LOGICOP_AND_INV
;
700 tmp
= LOGICOP_OR_INV
;
712 tmp
= LOGICOP_OR_RVRSE
;
724 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
725 i830
->state
.Ctx
[I830_CTXREG_STATE4
] &= ~LOGICOP_MASK
;
726 i830
->state
.Ctx
[I830_CTXREG_STATE4
] |= LOGIC_OP_FUNC(tmp
);
731 static void i830CullFaceFrontFace(GLcontext
*ctx
, GLenum unused
)
733 i830ContextPtr i830
= I830_CONTEXT(ctx
);
736 if (INTEL_DEBUG
&DEBUG_DRI
)
737 fprintf(stderr
, "%s\n", __FUNCTION__
);
739 if (!ctx
->Polygon
.CullFlag
) {
740 mode
= CULLMODE_NONE
;
742 else if (ctx
->Polygon
.CullFaceMode
!= GL_FRONT_AND_BACK
) {
745 if (ctx
->Polygon
.CullFaceMode
== GL_FRONT
)
746 mode
^= (CULLMODE_CW
^ CULLMODE_CCW
);
747 if (ctx
->Polygon
.FrontFace
!= GL_CCW
)
748 mode
^= (CULLMODE_CW
^ CULLMODE_CCW
);
751 mode
= CULLMODE_BOTH
;
754 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
755 i830
->state
.Ctx
[I830_CTXREG_STATE3
] &= ~CULLMODE_MASK
;
756 i830
->state
.Ctx
[I830_CTXREG_STATE3
] |= ENABLE_CULL_MODE
| mode
;
759 static void i830LineWidth( GLcontext
*ctx
, GLfloat widthf
)
761 i830ContextPtr i830
= I830_CONTEXT( ctx
);
765 if (INTEL_DEBUG
&DEBUG_DRI
)
766 fprintf(stderr
, "%s\n", __FUNCTION__
);
768 width
= (int)(widthf
* 2);
769 CLAMP_SELF(width
, 1, 15);
771 state5
= i830
->state
.Ctx
[I830_CTXREG_STATE5
] & ~FIXED_LINE_WIDTH_MASK
;
772 state5
|= (ENABLE_FIXED_LINE_WIDTH
| FIXED_LINE_WIDTH(width
));
774 if (state5
!= i830
->state
.Ctx
[I830_CTXREG_STATE5
]) {
775 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
776 i830
->state
.Ctx
[I830_CTXREG_STATE5
] = state5
;
780 static void i830PointSize(GLcontext
*ctx
, GLfloat size
)
782 i830ContextPtr i830
= I830_CONTEXT(ctx
);
783 GLint point_size
= (int)size
;
785 if (INTEL_DEBUG
&DEBUG_DRI
)
786 fprintf(stderr
, "%s\n", __FUNCTION__
);
788 CLAMP_SELF(point_size
, 1, 256);
789 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
790 i830
->state
.Ctx
[I830_CTXREG_STATE5
] &= ~FIXED_POINT_WIDTH_MASK
;
791 i830
->state
.Ctx
[I830_CTXREG_STATE5
] |= (ENABLE_FIXED_POINT_WIDTH
|
792 FIXED_POINT_WIDTH(point_size
));
796 /* =============================================================
800 static void i830ColorMask(GLcontext
*ctx
,
801 GLboolean r
, GLboolean g
,
802 GLboolean b
, GLboolean a
)
804 i830ContextPtr i830
= I830_CONTEXT( ctx
);
807 if (INTEL_DEBUG
&DEBUG_DRI
)
808 fprintf(stderr
, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__
, r
, g
, b
, a
);
810 tmp
= ((i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] & ~WRITEMASK_MASK
) |
813 ((!r
) << WRITEMASK_RED_SHIFT
) |
814 ((!g
) << WRITEMASK_GREEN_SHIFT
) |
815 ((!b
) << WRITEMASK_BLUE_SHIFT
) |
816 ((!a
) << WRITEMASK_ALPHA_SHIFT
));
818 if (tmp
!= i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
]) {
819 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
820 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] = tmp
;
824 static void update_specular( GLcontext
*ctx
)
826 i830ContextPtr i830
= I830_CONTEXT( ctx
);
828 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
829 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~ENABLE_SPEC_ADD_MASK
;
831 if (NEED_SECONDARY_COLOR(ctx
))
832 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= ENABLE_SPEC_ADD
;
834 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= DISABLE_SPEC_ADD
;
837 static void i830LightModelfv(GLcontext
*ctx
, GLenum pname
,
838 const GLfloat
*param
)
840 if (INTEL_DEBUG
&DEBUG_DRI
)
841 fprintf(stderr
, "%s\n", __FUNCTION__
);
843 if (pname
== GL_LIGHT_MODEL_COLOR_CONTROL
) {
844 update_specular( ctx
);
848 /* In Mesa 3.5 we can reliably do native flatshading.
850 static void i830ShadeModel(GLcontext
*ctx
, GLenum mode
)
852 i830ContextPtr i830
= I830_CONTEXT(ctx
);
853 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
856 #define SHADE_MODE_MASK ((1<<10)|(1<<8)|(1<<6)|(1<<4))
858 i830
->state
.Ctx
[I830_CTXREG_STATE3
] &= ~SHADE_MODE_MASK
;
860 if (mode
== GL_FLAT
) {
861 i830
->state
.Ctx
[I830_CTXREG_STATE3
] |= (ALPHA_SHADE_MODE(SHADE_MODE_FLAT
) |
862 FOG_SHADE_MODE(SHADE_MODE_FLAT
) |
863 SPEC_SHADE_MODE(SHADE_MODE_FLAT
) |
864 COLOR_SHADE_MODE(SHADE_MODE_FLAT
));
866 i830
->state
.Ctx
[I830_CTXREG_STATE3
] |= (ALPHA_SHADE_MODE(SHADE_MODE_LINEAR
) |
867 FOG_SHADE_MODE(SHADE_MODE_LINEAR
) |
868 SPEC_SHADE_MODE(SHADE_MODE_LINEAR
) |
869 COLOR_SHADE_MODE(SHADE_MODE_LINEAR
));
873 /* =============================================================
876 static void i830Fogfv(GLcontext
*ctx
, GLenum pname
, const GLfloat
*param
)
878 i830ContextPtr i830
= I830_CONTEXT(ctx
);
880 if (INTEL_DEBUG
&DEBUG_DRI
)
881 fprintf(stderr
, "%s\n", __FUNCTION__
);
883 if (pname
== GL_FOG_COLOR
) {
884 GLuint color
= (((GLubyte
)(ctx
->Fog
.Color
[0]*255.0F
) << 16) |
885 ((GLubyte
)(ctx
->Fog
.Color
[1]*255.0F
) << 8) |
886 ((GLubyte
)(ctx
->Fog
.Color
[2]*255.0F
) << 0));
888 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
889 i830
->state
.Ctx
[I830_CTXREG_FOGCOLOR
] = (_3DSTATE_FOG_COLOR_CMD
| color
);
893 /* =============================================================
896 static void i830Enable(GLcontext
*ctx
, GLenum cap
, GLboolean state
)
898 i830ContextPtr i830
= I830_CONTEXT(ctx
);
903 update_specular( ctx
);
907 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
908 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~ENABLE_DIS_ALPHA_TEST_MASK
;
910 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= ENABLE_ALPHA_TEST
;
912 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= DISABLE_ALPHA_TEST
;
917 i830EvalLogicOpBlendState(ctx
);
920 case GL_COLOR_LOGIC_OP
:
921 i830EvalLogicOpBlendState(ctx
);
923 /* Logicop doesn't seem to work at 16bpp:
925 if (i830
->intel
.intelScreen
->cpp
== 2)
926 FALLBACK( &i830
->intel
, I830_FALLBACK_LOGICOP
, state
);
930 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
931 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] &= ~ENABLE_DITHER
;
934 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] |= ENABLE_DITHER
;
936 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] |= DISABLE_DITHER
;
940 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
941 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~ENABLE_DIS_DEPTH_TEST_MASK
;
944 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= ENABLE_DEPTH_TEST
;
946 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= DISABLE_DEPTH_TEST
;
948 /* Also turn off depth writes when GL_DEPTH_TEST is disabled:
950 i830DepthMask( ctx
, ctx
->Depth
.Mask
);
953 case GL_SCISSOR_TEST
:
954 I830_STATECHANGE(i830
, I830_UPLOAD_BUFFERS
);
957 i830
->state
.Buffer
[I830_DESTREG_SENABLE
] =
958 (_3DSTATE_SCISSOR_ENABLE_CMD
|
959 ENABLE_SCISSOR_RECT
);
961 i830
->state
.Buffer
[I830_DESTREG_SENABLE
] =
962 (_3DSTATE_SCISSOR_ENABLE_CMD
|
963 DISABLE_SCISSOR_RECT
);
968 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
970 i830
->state
.Ctx
[I830_CTXREG_AA
] &= ~AA_LINE_ENABLE
;
972 i830
->state
.Ctx
[I830_CTXREG_AA
] |= AA_LINE_ENABLE
;
974 i830
->state
.Ctx
[I830_CTXREG_AA
] |= AA_LINE_DISABLE
;
978 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
979 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~ENABLE_DIS_FOG_MASK
;
981 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= ENABLE_FOG
;
983 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= DISABLE_FOG
;
987 i830CullFaceFrontFace(ctx
, 0);
993 case GL_STENCIL_TEST
:
994 if (i830
->intel
.hw_stencil
) {
995 I830_STATECHANGE(i830
, I830_UPLOAD_CTX
);
998 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= ENABLE_STENCIL_TEST
;
999 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] |= ENABLE_STENCIL_WRITE
;
1001 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] &= ~ENABLE_STENCIL_TEST
;
1002 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] &= ~ENABLE_STENCIL_WRITE
;
1003 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] |= DISABLE_STENCIL_TEST
;
1004 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] |= DISABLE_STENCIL_WRITE
;
1007 FALLBACK( &i830
->intel
, I830_FALLBACK_STENCIL
, state
);
1011 case GL_POLYGON_STIPPLE
:
1012 /* The stipple command worked on my 855GM box, but not my 845G.
1013 * I'll do more testing later to find out exactly which hardware
1014 * supports it. Disabled for now.
1016 if (i830
->intel
.hw_stipple
&&
1017 i830
->intel
.reduced_primitive
== GL_TRIANGLES
)
1019 I830_STATECHANGE(i830
, I830_UPLOAD_STIPPLE
);
1020 i830
->state
.Stipple
[I830_STPREG_ST1
] &= ~ST1_ENABLE
;
1022 i830
->state
.Stipple
[I830_STPREG_ST1
] |= ST1_ENABLE
;
1032 static void i830_init_packets( i830ContextPtr i830
)
1034 intelScreenPrivate
*screen
= i830
->intel
.intelScreen
;
1036 /* Zero all state */
1037 memset(&i830
->state
, 0, sizeof(i830
->state
));
1039 /* Set default blend state */
1040 i830
->state
.TexBlend
[0][0] = (_3DSTATE_MAP_BLEND_OP_CMD(0) |
1042 ENABLE_TEXOUTPUT_WRT_SEL
|
1043 TEXOP_OUTPUT_CURRENT
|
1044 DISABLE_TEX_CNTRL_STAGE
|
1046 TEXOP_MODIFY_PARMS
|
1049 i830
->state
.TexBlend
[0][1] = (_3DSTATE_MAP_BLEND_OP_CMD(0) |
1051 ENABLE_TEXOUTPUT_WRT_SEL
|
1052 TEXOP_OUTPUT_CURRENT
|
1054 TEXOP_MODIFY_PARMS
|
1056 i830
->state
.TexBlend
[0][2] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) |
1059 TEXBLENDARG_MODIFY_PARMS
|
1060 TEXBLENDARG_DIFFUSE
);
1061 i830
->state
.TexBlend
[0][3] = (_3DSTATE_MAP_BLEND_ARG_CMD(0) |
1064 TEXBLENDARG_MODIFY_PARMS
|
1065 TEXBLENDARG_DIFFUSE
);
1067 i830
->state
.TexBlendWordsUsed
[0] = 4;
1070 i830
->state
.Ctx
[I830_CTXREG_VF
] = 0;
1071 i830
->state
.Ctx
[I830_CTXREG_VF2
] = 0;
1073 i830
->state
.Ctx
[I830_CTXREG_AA
] = (_3DSTATE_AA_CMD
|
1074 AA_LINE_ECAAR_WIDTH_ENABLE
|
1075 AA_LINE_ECAAR_WIDTH_1_0
|
1076 AA_LINE_REGION_WIDTH_ENABLE
|
1077 AA_LINE_REGION_WIDTH_1_0
|
1080 i830
->state
.Ctx
[I830_CTXREG_ENABLES_1
] = (_3DSTATE_ENABLES_1_CMD
|
1082 DISABLE_STENCIL_TEST
|
1083 DISABLE_DEPTH_BIAS
|
1086 DISABLE_ALPHA_TEST
|
1087 DISABLE_COLOR_BLEND
|
1088 DISABLE_DEPTH_TEST
);
1090 if (i830
->intel
.hw_stencil
) {
1091 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] = (_3DSTATE_ENABLES_2_CMD
|
1092 ENABLE_STENCIL_WRITE
|
1096 /* set no color comps disabled */
1097 ENABLE_COLOR_WRITE
|
1098 ENABLE_DEPTH_WRITE
);
1100 i830
->state
.Ctx
[I830_CTXREG_ENABLES_2
] = (_3DSTATE_ENABLES_2_CMD
|
1101 DISABLE_STENCIL_WRITE
|
1105 /* set no color comps disabled */
1106 ENABLE_COLOR_WRITE
|
1107 ENABLE_DEPTH_WRITE
);
1110 i830
->state
.Ctx
[I830_CTXREG_STATE1
] = (_3DSTATE_MODES_1_CMD
|
1111 ENABLE_COLR_BLND_FUNC
|
1113 ENABLE_SRC_BLND_FACTOR
|
1114 SRC_BLND_FACT(BLENDFACT_ONE
) |
1115 ENABLE_DST_BLND_FACTOR
|
1116 DST_BLND_FACT(BLENDFACT_ZERO
) );
1118 i830
->state
.Ctx
[I830_CTXREG_STATE2
] = (_3DSTATE_MODES_2_CMD
|
1119 ENABLE_GLOBAL_DEPTH_BIAS
|
1120 GLOBAL_DEPTH_BIAS(0) |
1121 ENABLE_ALPHA_TEST_FUNC
|
1122 ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS
) |
1123 ALPHA_REF_VALUE(0) );
1125 i830
->state
.Ctx
[I830_CTXREG_STATE3
] = (_3DSTATE_MODES_3_CMD
|
1126 ENABLE_DEPTH_TEST_FUNC
|
1127 DEPTH_TEST_FUNC(COMPAREFUNC_LESS
) |
1128 ENABLE_ALPHA_SHADE_MODE
|
1129 ALPHA_SHADE_MODE(SHADE_MODE_LINEAR
) |
1130 ENABLE_FOG_SHADE_MODE
|
1131 FOG_SHADE_MODE(SHADE_MODE_LINEAR
) |
1132 ENABLE_SPEC_SHADE_MODE
|
1133 SPEC_SHADE_MODE(SHADE_MODE_LINEAR
) |
1134 ENABLE_COLOR_SHADE_MODE
|
1135 COLOR_SHADE_MODE(SHADE_MODE_LINEAR
) |
1139 i830
->state
.Ctx
[I830_CTXREG_STATE4
] = (_3DSTATE_MODES_4_CMD
|
1140 ENABLE_LOGIC_OP_FUNC
|
1141 LOGIC_OP_FUNC(LOGICOP_COPY
) |
1142 ENABLE_STENCIL_TEST_MASK
|
1143 STENCIL_TEST_MASK(0xff) |
1144 ENABLE_STENCIL_WRITE_MASK
|
1145 STENCIL_WRITE_MASK(0xff));
1147 i830
->state
.Ctx
[I830_CTXREG_STENCILTST
] = (_3DSTATE_STENCIL_TEST_CMD
|
1148 ENABLE_STENCIL_PARMS
|
1149 STENCIL_FAIL_OP(STENCILOP_KEEP
) |
1150 STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP
) |
1151 STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP
) |
1152 ENABLE_STENCIL_TEST_FUNC
|
1153 STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS
) |
1154 ENABLE_STENCIL_REF_VALUE
|
1155 STENCIL_REF_VALUE(0) );
1157 i830
->state
.Ctx
[I830_CTXREG_STATE5
] = (_3DSTATE_MODES_5_CMD
|
1158 FLUSH_TEXTURE_CACHE
|
1159 ENABLE_SPRITE_POINT_TEX
|
1160 SPRITE_POINT_TEX_OFF
|
1161 ENABLE_FIXED_LINE_WIDTH
|
1162 FIXED_LINE_WIDTH(0x2) | /* 1.0 */
1163 ENABLE_FIXED_POINT_WIDTH
|
1164 FIXED_POINT_WIDTH(1) );
1166 i830
->state
.Ctx
[I830_CTXREG_IALPHAB
] = (_3DSTATE_INDPT_ALPHA_BLEND_CMD
|
1167 DISABLE_INDPT_ALPHA_BLEND
|
1168 ENABLE_ALPHA_BLENDFUNC
|
1171 i830
->state
.Ctx
[I830_CTXREG_FOGCOLOR
] = (_3DSTATE_FOG_COLOR_CMD
|
1173 FOG_COLOR_GREEN(0) |
1176 i830
->state
.Ctx
[I830_CTXREG_BLENDCOLOR0
] = _3DSTATE_CONST_BLEND_COLOR_CMD
;
1177 i830
->state
.Ctx
[I830_CTXREG_BLENDCOLOR1
] = 0;
1179 i830
->state
.Ctx
[I830_CTXREG_MCSB0
] = _3DSTATE_MAP_COORD_SETBIND_CMD
;
1180 i830
->state
.Ctx
[I830_CTXREG_MCSB1
] = (TEXBIND_SET3(TEXCOORDSRC_VTXSET_3
) |
1181 TEXBIND_SET2(TEXCOORDSRC_VTXSET_2
) |
1182 TEXBIND_SET1(TEXCOORDSRC_VTXSET_1
) |
1183 TEXBIND_SET0(TEXCOORDSRC_VTXSET_0
));
1186 i830
->state
.Stipple
[I830_STPREG_ST0
] = _3DSTATE_STIPPLE
;
1188 i830
->state
.Buffer
[I830_DESTREG_CBUFADDR0
] = _3DSTATE_BUF_INFO_CMD
;
1189 i830
->state
.Buffer
[I830_DESTREG_CBUFADDR1
] =
1190 (BUF_3D_ID_COLOR_BACK
|
1191 BUF_3D_PITCH(screen
->frontPitch
* screen
->cpp
) |
1195 i830
->state
.Buffer
[I830_DESTREG_DBUFADDR0
] = _3DSTATE_BUF_INFO_CMD
;
1196 i830
->state
.Buffer
[I830_DESTREG_DBUFADDR1
] =
1198 BUF_3D_PITCH(screen
->depthPitch
* screen
->cpp
) |
1200 i830
->state
.Buffer
[I830_DESTREG_DBUFADDR2
] = screen
->depthOffset
;
1203 i830
->state
.Buffer
[I830_DESTREG_DV0
] = _3DSTATE_DST_BUF_VARS_CMD
;
1205 switch (screen
->fbFormat
) {
1208 i830
->state
.Buffer
[I830_DESTREG_DV1
] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
1209 DSTORG_VERT_BIAS(0x8) | /* .5 */
1212 DEPTH_FRMT_16_FIXED
);
1215 i830
->state
.Buffer
[I830_DESTREG_DV1
] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
1216 DSTORG_VERT_BIAS(0x8) | /* .5 */
1219 DEPTH_FRMT_24_FIXED_8_OTHER
);
1223 i830
->state
.Buffer
[I830_DESTREG_SENABLE
] = (_3DSTATE_SCISSOR_ENABLE_CMD
|
1224 DISABLE_SCISSOR_RECT
);
1225 i830
->state
.Buffer
[I830_DESTREG_SR0
] = _3DSTATE_SCISSOR_RECT_0_CMD
;
1226 i830
->state
.Buffer
[I830_DESTREG_SR1
] = 0;
1227 i830
->state
.Buffer
[I830_DESTREG_SR2
] = 0;
1231 void i830InitStateFuncs( struct dd_function_table
*functions
)
1233 functions
->AlphaFunc
= i830AlphaFunc
;
1234 functions
->BlendColor
= i830BlendColor
;
1235 functions
->BlendEquationSeparate
= i830BlendEquationSeparate
;
1236 functions
->BlendFuncSeparate
= i830BlendFuncSeparate
;
1237 functions
->ColorMask
= i830ColorMask
;
1238 functions
->CullFace
= i830CullFaceFrontFace
;
1239 functions
->DepthFunc
= i830DepthFunc
;
1240 functions
->DepthMask
= i830DepthMask
;
1241 functions
->Enable
= i830Enable
;
1242 functions
->Fogfv
= i830Fogfv
;
1243 functions
->FrontFace
= i830CullFaceFrontFace
;
1244 functions
->LightModelfv
= i830LightModelfv
;
1245 functions
->LineWidth
= i830LineWidth
;
1246 functions
->LogicOpcode
= i830LogicOp
;
1247 functions
->PointSize
= i830PointSize
;
1248 functions
->PolygonStipple
= i830PolygonStipple
;
1249 functions
->Scissor
= i830Scissor
;
1250 functions
->ShadeModel
= i830ShadeModel
;
1251 functions
->StencilFunc
= i830StencilFunc
;
1252 functions
->StencilMask
= i830StencilMask
;
1253 functions
->StencilOp
= i830StencilOp
;
1256 void i830InitState( i830ContextPtr i830
)
1258 GLcontext
*ctx
= &i830
->intel
.ctx
;
1260 i830_init_packets( i830
);
1262 intelInitState( ctx
);
1264 memcpy( &i830
->initial
, &i830
->state
, sizeof(i830
->state
) );
1266 i830
->current
= &i830
->state
;
1267 i830
->state
.emitted
= 0;
1268 i830
->state
.active
= (I830_UPLOAD_TEXBLEND(0) |
1269 I830_UPLOAD_STIPPLE
|
1271 I830_UPLOAD_BUFFERS
);