Fixed off by one errors in clipping.
[mesa.git] / src / mesa / drivers / dri / i915 / i915_state.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28
29 #include "glheader.h"
30 #include "context.h"
31 #include "macros.h"
32 #include "enums.h"
33 #include "dd.h"
34 #include "tnl/tnl.h"
35 #include "tnl/t_context.h"
36
37 #include "texmem.h"
38
39 #include "intel_screen.h"
40 #include "intel_batchbuffer.h"
41
42 #include "i915_context.h"
43 #include "i915_reg.h"
44
45 static int translate_compare_func( GLenum func )
46 {
47 switch(func) {
48 case GL_NEVER:
49 return COMPAREFUNC_NEVER;
50 case GL_LESS:
51 return COMPAREFUNC_LESS;
52 case GL_LEQUAL:
53 return COMPAREFUNC_LEQUAL;
54 case GL_GREATER:
55 return COMPAREFUNC_GREATER;
56 case GL_GEQUAL:
57 return COMPAREFUNC_GEQUAL;
58 case GL_NOTEQUAL:
59 return COMPAREFUNC_NOTEQUAL;
60 case GL_EQUAL:
61 return COMPAREFUNC_EQUAL;
62 case GL_ALWAYS:
63 default:
64 return COMPAREFUNC_ALWAYS;
65 }
66 }
67
68
69 static void i915StencilFunc(GLcontext *ctx, GLenum func, GLint ref,
70 GLuint mask)
71 {
72 i915ContextPtr i915 = I915_CONTEXT(ctx);
73 int test = translate_compare_func( func );
74
75 mask = mask & 0xff;
76
77 if (INTEL_DEBUG&DEBUG_DRI)
78 fprintf(stderr, "%s : func: %s, ref : 0x%x, mask: 0x%x\n", __FUNCTION__,
79 _mesa_lookup_enum_by_nr(func), ref, mask);
80
81
82 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
83 i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_TEST_MASK;
84 i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_TEST_MASK |
85 STENCIL_TEST_MASK(mask));
86
87 i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_REF_MASK |
88 S5_STENCIL_TEST_FUNC_MASK);
89
90 i915->state.Ctx[I915_CTXREG_LIS5] |= ((ref << S5_STENCIL_REF_SHIFT) |
91 (test << S5_STENCIL_TEST_FUNC_SHIFT));
92 }
93
94 static void i915StencilMask(GLcontext *ctx, GLuint mask)
95 {
96 i915ContextPtr i915 = I915_CONTEXT(ctx);
97
98 if (INTEL_DEBUG&DEBUG_DRI)
99 fprintf(stderr, "%s : mask 0x%x\n", __FUNCTION__, mask);
100
101 mask = mask & 0xff;
102
103 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
104 i915->state.Ctx[I915_CTXREG_STATE4] &= ~MODE4_ENABLE_STENCIL_WRITE_MASK;
105 i915->state.Ctx[I915_CTXREG_STATE4] |= (ENABLE_STENCIL_WRITE_MASK |
106 STENCIL_WRITE_MASK(mask));
107 }
108
109 static int translate_stencil_op( GLenum op )
110 {
111 switch(op) {
112 case GL_KEEP:
113 return STENCILOP_KEEP;
114 case GL_ZERO:
115 return STENCILOP_ZERO;
116 case GL_REPLACE:
117 return STENCILOP_REPLACE;
118 case GL_INCR:
119 return STENCILOP_INCRSAT;
120 case GL_DECR:
121 return STENCILOP_DECRSAT;
122 case GL_INCR_WRAP:
123 return STENCILOP_INCR;
124 case GL_DECR_WRAP:
125 return STENCILOP_DECR;
126 case GL_INVERT:
127 return STENCILOP_INVERT;
128 default:
129 return 0;
130 }
131 }
132
133 static void i915StencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
134 GLenum zpass)
135 {
136 i915ContextPtr i915 = I915_CONTEXT(ctx);
137 int fop = translate_stencil_op(fail);
138 int dfop = translate_stencil_op(zfail);
139 int dpop = translate_stencil_op(zpass);
140
141
142 if (INTEL_DEBUG&DEBUG_DRI)
143 fprintf(stderr, "%s: fail : %s, zfail: %s, zpass : %s\n", __FUNCTION__,
144 _mesa_lookup_enum_by_nr(fail),
145 _mesa_lookup_enum_by_nr(zfail),
146 _mesa_lookup_enum_by_nr(zpass));
147
148 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
149
150 i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_FAIL_MASK |
151 S5_STENCIL_PASS_Z_FAIL_MASK |
152 S5_STENCIL_PASS_Z_PASS_MASK);
153
154 i915->state.Ctx[I915_CTXREG_LIS5] |= ((fop << S5_STENCIL_FAIL_SHIFT) |
155 (dfop << S5_STENCIL_PASS_Z_FAIL_SHIFT) |
156 (dpop << S5_STENCIL_PASS_Z_PASS_SHIFT));
157 }
158
159 static void i915AlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
160 {
161 i915ContextPtr i915 = I915_CONTEXT(ctx);
162 int test = translate_compare_func( func );
163 GLubyte refByte;
164
165 UNCLAMPED_FLOAT_TO_UBYTE(refByte, ref);
166
167 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
168 i915->state.Ctx[I915_CTXREG_LIS6] &= ~(S6_ALPHA_TEST_FUNC_MASK |
169 S6_ALPHA_REF_MASK);
170 i915->state.Ctx[I915_CTXREG_LIS6] |= ((test << S6_ALPHA_TEST_FUNC_SHIFT) |
171 (((GLuint)refByte) << S6_ALPHA_REF_SHIFT));
172 }
173
174 /* This function makes sure that the proper enables are
175 * set for LogicOp, Independant Alpha Blend, and Blending.
176 * It needs to be called from numerous places where we
177 * could change the LogicOp or Independant Alpha Blend without subsequent
178 * calls to glEnable.
179 */
180 static void i915EvalLogicOpBlendState(GLcontext *ctx)
181 {
182 i915ContextPtr i915 = I915_CONTEXT(ctx);
183
184 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
185
186 if (ctx->Color._LogicOpEnabled) {
187 i915->state.Ctx[I915_CTXREG_LIS5] |= S5_LOGICOP_ENABLE;
188 i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
189 } else {
190 i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_LOGICOP_ENABLE;
191
192 if (ctx->Color.BlendEnabled) {
193 i915->state.Ctx[I915_CTXREG_LIS6] |= S6_CBUF_BLEND_ENABLE;
194 } else {
195 i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_CBUF_BLEND_ENABLE;
196 }
197 }
198 }
199
200 static void i915BlendColor(GLcontext *ctx, const GLfloat color[4])
201 {
202 i915ContextPtr i915 = I915_CONTEXT(ctx);
203 GLubyte r, g, b, a;
204
205 if (INTEL_DEBUG&DEBUG_DRI)
206 fprintf(stderr, "%s\n", __FUNCTION__);
207
208 UNCLAMPED_FLOAT_TO_UBYTE(r, color[RCOMP]);
209 UNCLAMPED_FLOAT_TO_UBYTE(g, color[GCOMP]);
210 UNCLAMPED_FLOAT_TO_UBYTE(b, color[BCOMP]);
211 UNCLAMPED_FLOAT_TO_UBYTE(a, color[ACOMP]);
212
213 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
214 i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = (a<<24) | (r<<16) | (g<<8) | b;
215 }
216
217 static int translate_blend_factor( GLenum factor )
218 {
219 switch(factor) {
220 case GL_ZERO:
221 return BLENDFACT_ZERO;
222 case GL_SRC_ALPHA:
223 return BLENDFACT_SRC_ALPHA;
224 case GL_ONE:
225 return BLENDFACT_ONE;
226 case GL_SRC_COLOR:
227 return BLENDFACT_SRC_COLR;
228 case GL_ONE_MINUS_SRC_COLOR:
229 return BLENDFACT_INV_SRC_COLR;
230 case GL_DST_COLOR:
231 return BLENDFACT_DST_COLR;
232 case GL_ONE_MINUS_DST_COLOR:
233 return BLENDFACT_INV_DST_COLR;
234 case GL_ONE_MINUS_SRC_ALPHA:
235 return BLENDFACT_INV_SRC_ALPHA;
236 case GL_DST_ALPHA:
237 return BLENDFACT_DST_ALPHA;
238 case GL_ONE_MINUS_DST_ALPHA:
239 return BLENDFACT_INV_DST_ALPHA;
240 case GL_SRC_ALPHA_SATURATE:
241 return BLENDFACT_SRC_ALPHA_SATURATE;
242 case GL_CONSTANT_COLOR:
243 return BLENDFACT_CONST_COLOR;
244 case GL_ONE_MINUS_CONSTANT_COLOR:
245 return BLENDFACT_INV_CONST_COLOR;
246 case GL_CONSTANT_ALPHA:
247 return BLENDFACT_CONST_ALPHA;
248 case GL_ONE_MINUS_CONSTANT_ALPHA:
249 return BLENDFACT_INV_CONST_ALPHA;
250 default:
251 return BLENDFACT_ZERO;
252 }
253 }
254
255 #define DST_BLND_FACT(f) ((f)<<S6_CBUF_DST_BLEND_FACT_SHIFT)
256 #define SRC_BLND_FACT(f) ((f)<<S6_CBUF_SRC_BLEND_FACT_SHIFT)
257 #define DST_ABLND_FACT(f) ((f)<<IAB_DST_FACTOR_SHIFT)
258 #define SRC_ABLND_FACT(f) ((f)<<IAB_SRC_FACTOR_SHIFT)
259
260
261
262 static GLuint translate_blend_equation( GLenum mode )
263 {
264 switch (mode) {
265 case GL_FUNC_ADD: return BLENDFUNC_ADD;
266 case GL_MIN: return BLENDFUNC_MIN;
267 case GL_MAX: return BLENDFUNC_MAX;
268 case GL_FUNC_SUBTRACT: return BLENDFUNC_SUBTRACT;
269 case GL_FUNC_REVERSE_SUBTRACT: return BLENDFUNC_REVERSE_SUBTRACT;
270 default: return 0;
271 }
272 }
273
274 static void i915UpdateBlendState( GLcontext *ctx )
275 {
276 i915ContextPtr i915 = I915_CONTEXT(ctx);
277 GLuint iab = (i915->state.Ctx[I915_CTXREG_IAB] &
278 ~(IAB_SRC_FACTOR_MASK |
279 IAB_DST_FACTOR_MASK |
280 (BLENDFUNC_MASK << IAB_FUNC_SHIFT) |
281 IAB_ENABLE));
282
283 GLuint lis6 = (i915->state.Ctx[I915_CTXREG_LIS6] &
284 ~(S6_CBUF_SRC_BLEND_FACT_MASK |
285 S6_CBUF_DST_BLEND_FACT_MASK |
286 S6_CBUF_BLEND_FUNC_MASK));
287
288 GLuint eqRGB = ctx->Color.BlendEquationRGB;
289 GLuint eqA = ctx->Color.BlendEquationA;
290 GLuint srcRGB = ctx->Color.BlendSrcRGB;
291 GLuint dstRGB = ctx->Color.BlendDstRGB;
292 GLuint srcA = ctx->Color.BlendSrcA;
293 GLuint dstA = ctx->Color.BlendDstA;
294
295 if (eqRGB == GL_MIN || eqRGB == GL_MAX) {
296 srcRGB = dstRGB = GL_ONE;
297 }
298
299 if (eqA == GL_MIN || eqA == GL_MAX) {
300 srcA = dstA = GL_ONE;
301 }
302
303 lis6 |= SRC_BLND_FACT(translate_blend_factor(srcRGB));
304 lis6 |= DST_BLND_FACT(translate_blend_factor(dstRGB));
305 lis6 |= translate_blend_equation( eqRGB ) << S6_CBUF_BLEND_FUNC_SHIFT;
306
307 iab |= SRC_ABLND_FACT(translate_blend_factor(srcA));
308 iab |= DST_ABLND_FACT(translate_blend_factor(dstA));
309 iab |= translate_blend_equation( eqA ) << IAB_FUNC_SHIFT;
310
311 if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB)
312 iab |= IAB_ENABLE;
313
314 if (iab != i915->state.Ctx[I915_CTXREG_IAB] ||
315 lis6 != i915->state.Ctx[I915_CTXREG_LIS6]) {
316 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
317 i915->state.Ctx[I915_CTXREG_IAB] = iab;
318 i915->state.Ctx[I915_CTXREG_LIS6] = lis6;
319 }
320
321 /* This will catch a logicop blend equation */
322 i915EvalLogicOpBlendState(ctx);
323 }
324
325
326 static void i915BlendFuncSeparate(GLcontext *ctx, GLenum srcRGB,
327 GLenum dstRGB, GLenum srcA,
328 GLenum dstA )
329 {
330 i915UpdateBlendState( ctx );
331 }
332
333
334 static void i915BlendEquationSeparate(GLcontext *ctx, GLenum eqRGB,
335 GLenum eqA)
336 {
337 i915UpdateBlendState( ctx );
338 }
339
340
341 static void i915DepthFunc(GLcontext *ctx, GLenum func)
342 {
343 i915ContextPtr i915 = I915_CONTEXT(ctx);
344 int test = translate_compare_func( func );
345
346 if (INTEL_DEBUG&DEBUG_DRI)
347 fprintf(stderr, "%s\n", __FUNCTION__);
348
349 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
350 i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_FUNC_MASK;
351 i915->state.Ctx[I915_CTXREG_LIS6] |= test << S6_DEPTH_TEST_FUNC_SHIFT;
352 }
353
354 static void i915DepthMask(GLcontext *ctx, GLboolean flag)
355 {
356 i915ContextPtr i915 = I915_CONTEXT(ctx);
357
358 if (INTEL_DEBUG&DEBUG_DRI)
359 fprintf(stderr, "%s flag (%d)\n", __FUNCTION__, flag);
360
361 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
362
363 if (flag && ctx->Depth.Test)
364 i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_WRITE_ENABLE;
365 else
366 i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_WRITE_ENABLE;
367 }
368
369 /* =============================================================
370 * Polygon stipple
371 *
372 * The i915 supports a 4x4 stipple natively, GL wants 32x32.
373 * Fortunately stipple is usually a repeating pattern.
374 */
375 static void i915PolygonStipple( GLcontext *ctx, const GLubyte *mask )
376 {
377 i915ContextPtr i915 = I915_CONTEXT(ctx);
378 const GLubyte *m = mask;
379 GLubyte p[4];
380 int i,j,k;
381 int active = (ctx->Polygon.StippleFlag &&
382 i915->intel.reduced_primitive == GL_TRIANGLES);
383 GLuint newMask;
384
385 if (active) {
386 I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
387 i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE;
388 }
389
390 p[0] = mask[12] & 0xf; p[0] |= p[0] << 4;
391 p[1] = mask[8] & 0xf; p[1] |= p[1] << 4;
392 p[2] = mask[4] & 0xf; p[2] |= p[2] << 4;
393 p[3] = mask[0] & 0xf; p[3] |= p[3] << 4;
394
395 for (k = 0 ; k < 8 ; k++)
396 for (j = 3 ; j >= 0; j--)
397 for (i = 0 ; i < 4 ; i++, m++)
398 if (*m != p[j]) {
399 i915->intel.hw_stipple = 0;
400 return;
401 }
402
403 newMask = (((p[0] & 0xf) << 0) |
404 ((p[1] & 0xf) << 4) |
405 ((p[2] & 0xf) << 8) |
406 ((p[3] & 0xf) << 12));
407
408
409 if (newMask == 0xffff || newMask == 0x0) {
410 /* this is needed to make conform pass */
411 i915->intel.hw_stipple = 0;
412 return;
413 }
414
415 i915->state.Stipple[I915_STPREG_ST1] &= ~0xffff;
416 i915->state.Stipple[I915_STPREG_ST1] |= newMask;
417 i915->intel.hw_stipple = 1;
418
419 if (active)
420 i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE;
421 }
422
423
424 /* =============================================================
425 * Hardware clipping
426 */
427 static void i915Scissor(GLcontext *ctx, GLint x, GLint y,
428 GLsizei w, GLsizei h)
429 {
430 i915ContextPtr i915 = I915_CONTEXT(ctx);
431 intelScreenPrivate *screen = i915->intel.intelScreen;
432 int x1, y1, x2, y2;
433
434 if (!i915->intel.driDrawable)
435 return;
436
437 x1 = x;
438 y1 = i915->intel.driDrawable->h - (y + h);
439 x2 = x + w - 1;
440 y2 = y1 + h - 1;
441
442 if (INTEL_DEBUG&DEBUG_DRI)
443 fprintf(stderr, "[%s] x(%d) y(%d) w(%d) h(%d)\n", __FUNCTION__,
444 x, y, w, h);
445
446 if (x1 < 0) x1 = 0;
447 if (y1 < 0) y1 = 0;
448 if (x2 < 0) x2 = 0;
449 if (y2 < 0) y2 = 0;
450
451 if (x2 >= screen->width) x2 = screen->width-1;
452 if (y2 >= screen->height) y2 = screen->height-1;
453 if (x1 >= screen->width) x1 = screen->width-1;
454 if (y1 >= screen->height) y1 = screen->height-1;
455
456
457 I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
458 i915->state.Buffer[I915_DESTREG_SR1] = (y1 << 16) | (x1 & 0xffff);
459 i915->state.Buffer[I915_DESTREG_SR2] = (y2 << 16) | (x2 & 0xffff);
460 }
461
462 static void i915LogicOp(GLcontext *ctx, GLenum opcode)
463 {
464 i915ContextPtr i915 = I915_CONTEXT(ctx);
465 int tmp = 0;
466
467 if (INTEL_DEBUG&DEBUG_DRI)
468 fprintf(stderr, "%s\n", __FUNCTION__);
469
470 switch(opcode) {
471 case GL_CLEAR:
472 tmp = LOGICOP_CLEAR;
473 break;
474 case GL_AND:
475 tmp = LOGICOP_AND;
476 break;
477 case GL_AND_REVERSE:
478 tmp = LOGICOP_AND_RVRSE;
479 break;
480 case GL_COPY:
481 tmp = LOGICOP_COPY;
482 break;
483 case GL_COPY_INVERTED:
484 tmp = LOGICOP_COPY_INV;
485 break;
486 case GL_AND_INVERTED:
487 tmp = LOGICOP_AND_INV;
488 break;
489 case GL_NOOP:
490 tmp = LOGICOP_NOOP;
491 break;
492 case GL_XOR:
493 tmp = LOGICOP_XOR;
494 break;
495 case GL_OR:
496 tmp = LOGICOP_OR;
497 break;
498 case GL_OR_INVERTED:
499 tmp = LOGICOP_OR_INV;
500 break;
501 case GL_NOR:
502 tmp = LOGICOP_NOR;
503 break;
504 case GL_EQUIV:
505 tmp = LOGICOP_EQUIV;
506 break;
507 case GL_INVERT:
508 tmp = LOGICOP_INV;
509 break;
510 case GL_OR_REVERSE:
511 tmp = LOGICOP_OR_RVRSE;
512 break;
513 case GL_NAND:
514 tmp = LOGICOP_NAND;
515 break;
516 case GL_SET:
517 tmp = LOGICOP_SET;
518 break;
519 default:
520 return;
521 }
522
523 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
524 i915->state.Ctx[I915_CTXREG_STATE4] &= ~LOGICOP_MASK;
525 i915->state.Ctx[I915_CTXREG_STATE4] |= LOGIC_OP_FUNC(tmp);
526 }
527
528
529
530 static void i915CullFaceFrontFace(GLcontext *ctx, GLenum unused)
531 {
532 i915ContextPtr i915 = I915_CONTEXT(ctx);
533 GLuint mode;
534
535 if (INTEL_DEBUG&DEBUG_DRI)
536 fprintf(stderr, "%s\n", __FUNCTION__);
537
538 if (!ctx->Polygon.CullFlag) {
539 mode = S4_CULLMODE_NONE;
540 }
541 else if (ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) {
542 mode = S4_CULLMODE_CW;
543
544 if (ctx->Polygon.CullFaceMode == GL_FRONT)
545 mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
546 if (ctx->Polygon.FrontFace != GL_CCW)
547 mode ^= (S4_CULLMODE_CW ^ S4_CULLMODE_CCW);
548 }
549 else {
550 mode = S4_CULLMODE_BOTH;
551 }
552
553 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
554 i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_CULLMODE_MASK;
555 i915->state.Ctx[I915_CTXREG_LIS4] |= mode;
556 }
557
558 static void i915LineWidth( GLcontext *ctx, GLfloat widthf )
559 {
560 i915ContextPtr i915 = I915_CONTEXT( ctx );
561 int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_LINE_WIDTH_MASK;
562 int width;
563
564 if (INTEL_DEBUG&DEBUG_DRI)
565 fprintf(stderr, "%s\n", __FUNCTION__);
566
567 width = (int)(widthf * 2);
568 CLAMP_SELF(width, 1, 0xf);
569 lis4 |= width << S4_LINE_WIDTH_SHIFT;
570
571 if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
572 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
573 i915->state.Ctx[I915_CTXREG_LIS4] = lis4;
574 }
575 }
576
577 static void i915PointSize(GLcontext *ctx, GLfloat size)
578 {
579 i915ContextPtr i915 = I915_CONTEXT(ctx);
580 int lis4 = i915->state.Ctx[I915_CTXREG_LIS4] & ~S4_POINT_WIDTH_MASK;
581 GLint point_size = (int)size;
582
583 if (INTEL_DEBUG&DEBUG_DRI)
584 fprintf(stderr, "%s\n", __FUNCTION__);
585
586 CLAMP_SELF(point_size, 1, 255);
587 lis4 |= point_size << S4_POINT_WIDTH_SHIFT;
588
589 if (lis4 != i915->state.Ctx[I915_CTXREG_LIS4]) {
590 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
591 i915->state.Ctx[I915_CTXREG_LIS4] = lis4;
592 }
593 }
594
595
596 /* =============================================================
597 * Color masks
598 */
599
600 static void i915ColorMask(GLcontext *ctx,
601 GLboolean r, GLboolean g,
602 GLboolean b, GLboolean a)
603 {
604 i915ContextPtr i915 = I915_CONTEXT( ctx );
605 GLuint tmp = i915->state.Ctx[I915_CTXREG_LIS5] & ~S5_WRITEDISABLE_MASK;
606
607 if (INTEL_DEBUG&DEBUG_DRI)
608 fprintf(stderr, "%s r(%d) g(%d) b(%d) a(%d)\n", __FUNCTION__, r, g, b, a);
609
610 if (!r) tmp |= S5_WRITEDISABLE_RED;
611 if (!g) tmp |= S5_WRITEDISABLE_GREEN;
612 if (!b) tmp |= S5_WRITEDISABLE_BLUE;
613 if (!a) tmp |= S5_WRITEDISABLE_ALPHA;
614
615 if (tmp != i915->state.Ctx[I915_CTXREG_LIS5]) {
616 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
617 i915->state.Ctx[I915_CTXREG_LIS5] = tmp;
618 }
619 }
620
621 static void update_specular( GLcontext *ctx )
622 {
623 /* A hack to trigger the rebuild of the fragment program.
624 */
625 INTEL_CONTEXT(ctx)->NewGLState |= _NEW_TEXTURE;
626 I915_CONTEXT(ctx)->tex_program.translated = 0;
627 }
628
629 static void i915LightModelfv(GLcontext *ctx, GLenum pname,
630 const GLfloat *param)
631 {
632 if (INTEL_DEBUG&DEBUG_DRI)
633 fprintf(stderr, "%s\n", __FUNCTION__);
634
635 if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
636 update_specular( ctx );
637 }
638 }
639
640 static void i915ShadeModel(GLcontext *ctx, GLenum mode)
641 {
642 i915ContextPtr i915 = I915_CONTEXT(ctx);
643 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
644
645 if (mode == GL_SMOOTH) {
646 i915->state.Ctx[I915_CTXREG_LIS4] &= ~(S4_FLATSHADE_ALPHA |
647 S4_FLATSHADE_COLOR |
648 S4_FLATSHADE_SPECULAR);
649 } else {
650 i915->state.Ctx[I915_CTXREG_LIS4] |= (S4_FLATSHADE_ALPHA |
651 S4_FLATSHADE_COLOR |
652 S4_FLATSHADE_SPECULAR);
653 }
654 }
655
656 /* =============================================================
657 * Fog
658 */
659 static void update_fog( GLcontext *ctx )
660 {
661 i915ContextPtr i915 = I915_CONTEXT(ctx);
662 GLenum mode;
663 GLboolean enabled;
664 GLboolean try_pixel_fog;
665
666 if (ctx->FragmentProgram.Enabled && ctx->FragmentProgram.Current) {
667 /* Pull in static fog state from program */
668
669 mode = ctx->FragmentProgram.Current->FogOption;
670 enabled = (mode != GL_NONE);
671 try_pixel_fog = 1;
672 }
673 else {
674 enabled = ctx->Fog.Enabled;
675 mode = ctx->Fog.Mode;
676
677 try_pixel_fog = (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT &&
678 ctx->Hint.Fog == GL_NICEST &&
679 0); /* XXX - DISABLE -- Need ortho fallback */
680 }
681
682 if (!enabled) {
683 i915->vertex_fog = I915_FOG_NONE;
684 }
685 else if (try_pixel_fog) {
686
687 I915_STATECHANGE(i915, I915_UPLOAD_FOG);
688 i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK;
689 i915->vertex_fog = I915_FOG_PIXEL;
690
691 switch (mode) {
692 case GL_LINEAR:
693 if (ctx->Fog.End <= ctx->Fog.Start) {
694 /* XXX - this won't work with fragment programs. Need to
695 * either fallback or append fog instructions to end of
696 * program in the case of linear fog.
697 */
698 i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX;
699 i915->vertex_fog = I915_FOG_VERTEX;
700 }
701 else {
702 GLfloat c1 = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
703 GLfloat c2 = 1.0/(ctx->Fog.End-ctx->Fog.Start);
704
705 i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_C1_MASK;
706 i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_LINEAR;
707 i915->state.Fog[I915_FOGREG_MODE1] |=
708 ((GLuint)(c1 * FMC1_C1_ONE)) & FMC1_C1_MASK;
709
710 if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) {
711 i915->state.Fog[I915_FOGREG_MODE2] = (GLuint)(c2 * FMC2_C2_ONE);
712 }
713 else {
714 union { float f; int i; } fi;
715 fi.f = c2;
716 i915->state.Fog[I915_FOGREG_MODE2] = fi.i;
717 }
718 }
719 break;
720 case GL_EXP:
721 i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_EXP;
722 break;
723 case GL_EXP2:
724 i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_PIXEL_EXP2;
725 break;
726 default:
727 break;
728 }
729 }
730 else /* if (i915->vertex_fog != I915_FOG_VERTEX) */ {
731 I915_STATECHANGE(i915, I915_UPLOAD_FOG);
732 i915->state.Fog[I915_FOGREG_MODE1] &= ~FMC1_FOGFUNC_MASK;
733 i915->state.Fog[I915_FOGREG_MODE1] |= FMC1_FOGFUNC_VERTEX;
734 i915->vertex_fog = I915_FOG_VERTEX;
735 }
736
737 {
738 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
739 I915_ACTIVESTATE(i915, I915_UPLOAD_FOG, enabled);
740 if (enabled)
741 i915->state.Ctx[I915_CTXREG_LIS5] |= S5_FOG_ENABLE;
742 else
743 i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_FOG_ENABLE;
744 }
745
746 if (enabled) {
747 _tnl_allow_vertex_fog( ctx, (i915->vertex_fog == I915_FOG_VERTEX) );
748 _tnl_allow_pixel_fog( ctx, (i915->vertex_fog != I915_FOG_VERTEX) );
749 }
750 }
751
752 static void i915Fogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
753 {
754 i915ContextPtr i915 = I915_CONTEXT(ctx);
755
756 switch (pname) {
757 case GL_FOG_COORDINATE_SOURCE_EXT:
758 case GL_FOG_MODE:
759 case GL_FOG_START:
760 case GL_FOG_END:
761 update_fog( ctx );
762 break;
763
764 case GL_FOG_DENSITY:
765 I915_STATECHANGE(i915, I915_UPLOAD_FOG);
766
767 if (i915->state.Fog[I915_FOGREG_MODE1] & FMC1_FOGINDEX_Z) {
768 i915->state.Fog[I915_FOGREG_MODE3] = (GLuint)(ctx->Fog.Density *
769 FMC3_D_ONE);
770 }
771 else {
772 union { float f; int i; } fi;
773 fi.f = ctx->Fog.Density;
774 i915->state.Fog[I915_FOGREG_MODE3] = fi.i;
775 }
776 break;
777
778 case GL_FOG_COLOR:
779 I915_STATECHANGE(i915, I915_UPLOAD_FOG);
780 i915->state.Fog[I915_FOGREG_COLOR] =
781 (_3DSTATE_FOG_COLOR_CMD |
782 ((GLubyte)(ctx->Fog.Color[0]*255.0F) << 16) |
783 ((GLubyte)(ctx->Fog.Color[1]*255.0F) << 8) |
784 ((GLubyte)(ctx->Fog.Color[2]*255.0F) << 0));
785 break;
786
787 default:
788 break;
789 }
790 }
791
792 static void i915Hint(GLcontext *ctx, GLenum target, GLenum state)
793 {
794 switch (target) {
795 case GL_FOG_HINT:
796 update_fog( ctx );
797 break;
798 default:
799 break;
800 }
801 }
802
803 /* =============================================================
804 */
805
806 static void i915Enable(GLcontext *ctx, GLenum cap, GLboolean state)
807 {
808 i915ContextPtr i915 = I915_CONTEXT(ctx);
809
810 switch(cap) {
811 case GL_TEXTURE_2D:
812 break;
813
814 case GL_LIGHTING:
815 case GL_COLOR_SUM:
816 update_specular( ctx );
817 break;
818
819 case GL_ALPHA_TEST:
820 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
821 if (state)
822 i915->state.Ctx[I915_CTXREG_LIS6] |= S6_ALPHA_TEST_ENABLE;
823 else
824 i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_ALPHA_TEST_ENABLE;
825 break;
826
827 case GL_BLEND:
828 i915EvalLogicOpBlendState(ctx);
829 break;
830
831 case GL_COLOR_LOGIC_OP:
832 i915EvalLogicOpBlendState(ctx);
833
834 /* Logicop doesn't seem to work at 16bpp:
835 */
836 if (i915->intel.intelScreen->cpp == 2)
837 FALLBACK( &i915->intel, I915_FALLBACK_LOGICOP, state );
838 break;
839
840 case GL_FRAGMENT_PROGRAM_ARB:
841 update_fog( ctx );
842 break;
843
844 case GL_DITHER:
845 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
846 if (state)
847 i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
848 else
849 i915->state.Ctx[I915_CTXREG_LIS5] &= ~S5_COLOR_DITHER_ENABLE;
850 break;
851
852 case GL_DEPTH_TEST:
853 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
854 if (state)
855 i915->state.Ctx[I915_CTXREG_LIS6] |= S6_DEPTH_TEST_ENABLE;
856 else
857 i915->state.Ctx[I915_CTXREG_LIS6] &= ~S6_DEPTH_TEST_ENABLE;
858
859 i915DepthMask( ctx, ctx->Depth.Mask );
860 break;
861
862 case GL_SCISSOR_TEST:
863 I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
864 if (state)
865 i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
866 ENABLE_SCISSOR_RECT);
867 else
868 i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
869 DISABLE_SCISSOR_RECT);
870 break;
871
872 case GL_LINE_SMOOTH:
873 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
874 if (state)
875 i915->state.Ctx[I915_CTXREG_LIS4] |= S4_LINE_ANTIALIAS_ENABLE;
876 else
877 i915->state.Ctx[I915_CTXREG_LIS4] &= ~S4_LINE_ANTIALIAS_ENABLE;
878 break;
879
880 case GL_FOG:
881 update_fog( ctx );
882 break;
883
884 case GL_CULL_FACE:
885 i915CullFaceFrontFace(ctx, 0);
886 break;
887
888 case GL_STENCIL_TEST:
889 if (i915->intel.hw_stencil) {
890 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
891 if (state)
892 i915->state.Ctx[I915_CTXREG_LIS5] |= (S5_STENCIL_TEST_ENABLE |
893 S5_STENCIL_WRITE_ENABLE);
894 else
895 i915->state.Ctx[I915_CTXREG_LIS5] &= ~(S5_STENCIL_TEST_ENABLE |
896 S5_STENCIL_WRITE_ENABLE);
897 } else {
898 FALLBACK( &i915->intel, I915_FALLBACK_STENCIL, state );
899 }
900 break;
901
902 case GL_POLYGON_STIPPLE:
903 /* The stipple command worked on my 855GM box, but not my 845G.
904 * I'll do more testing later to find out exactly which hardware
905 * supports it. Disabled for now.
906 */
907 if (i915->intel.hw_stipple &&
908 i915->intel.reduced_primitive == GL_TRIANGLES)
909 {
910 I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
911 if (state)
912 i915->state.Stipple[I915_STPREG_ST1] |= ST1_ENABLE;
913 else
914 i915->state.Stipple[I915_STPREG_ST1] &= ~ST1_ENABLE;
915 }
916 break;
917
918 default:
919 ;
920 }
921 }
922
923
924 static void i915_init_packets( i915ContextPtr i915 )
925 {
926 intelScreenPrivate *screen = i915->intel.intelScreen;
927
928 /* Zero all state */
929 memset(&i915->state, 0, sizeof(i915->state));
930
931
932 {
933 I915_STATECHANGE(i915, I915_UPLOAD_CTX);
934 /* Probably don't want to upload all this stuff every time one
935 * piece changes.
936 */
937 i915->state.Ctx[I915_CTXREG_LI] = (_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
938 I1_LOAD_S(2) |
939 I1_LOAD_S(4) |
940 I1_LOAD_S(5) |
941 I1_LOAD_S(6) |
942 (4));
943 i915->state.Ctx[I915_CTXREG_LIS2] = 0;
944 i915->state.Ctx[I915_CTXREG_LIS4] = 0;
945 i915->state.Ctx[I915_CTXREG_LIS5] = 0;
946
947 if (screen->cpp == 2)
948 i915->state.Ctx[I915_CTXREG_LIS5] |= S5_COLOR_DITHER_ENABLE;
949
950
951 i915->state.Ctx[I915_CTXREG_LIS6] = (S6_COLOR_WRITE_ENABLE |
952 (2 << S6_TRISTRIP_PV_SHIFT));
953
954 i915->state.Ctx[I915_CTXREG_STATE4] = (_3DSTATE_MODES_4_CMD |
955 ENABLE_LOGIC_OP_FUNC |
956 LOGIC_OP_FUNC(LOGICOP_COPY) |
957 ENABLE_STENCIL_TEST_MASK |
958 STENCIL_TEST_MASK(0xff) |
959 ENABLE_STENCIL_WRITE_MASK |
960 STENCIL_WRITE_MASK(0xff));
961
962
963 i915->state.Ctx[I915_CTXREG_IAB] = (_3DSTATE_INDEPENDENT_ALPHA_BLEND_CMD |
964 IAB_MODIFY_ENABLE |
965 IAB_MODIFY_FUNC |
966 IAB_MODIFY_SRC_FACTOR |
967 IAB_MODIFY_DST_FACTOR);
968
969 i915->state.Ctx[I915_CTXREG_BLENDCOLOR0] = _3DSTATE_CONST_BLEND_COLOR_CMD;
970 i915->state.Ctx[I915_CTXREG_BLENDCOLOR1] = 0;
971
972 }
973
974 {
975 I915_STATECHANGE(i915, I915_UPLOAD_STIPPLE);
976 i915->state.Stipple[I915_STPREG_ST0] = _3DSTATE_STIPPLE;
977 }
978
979
980 {
981 I915_STATECHANGE(i915, I915_UPLOAD_FOG);
982 i915->state.Fog[I915_FOGREG_MODE0] = _3DSTATE_FOG_MODE_CMD;
983 i915->state.Fog[I915_FOGREG_MODE1] = (FMC1_FOGFUNC_MODIFY_ENABLE |
984 FMC1_FOGFUNC_VERTEX |
985 FMC1_FOGINDEX_MODIFY_ENABLE |
986 FMC1_FOGINDEX_W |
987 FMC1_C1_C2_MODIFY_ENABLE |
988 FMC1_DENSITY_MODIFY_ENABLE);
989 i915->state.Fog[I915_FOGREG_COLOR] = _3DSTATE_FOG_COLOR_CMD;
990 }
991
992
993 {
994 I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
995 i915->state.Buffer[I915_DESTREG_CBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
996 i915->state.Buffer[I915_DESTREG_CBUFADDR1] =
997 (BUF_3D_ID_COLOR_BACK |
998 BUF_3D_PITCH(screen->frontPitch * screen->cpp) |
999 BUF_3D_USE_FENCE);
1000
1001
1002 i915->state.Buffer[I915_DESTREG_DBUFADDR0] = _3DSTATE_BUF_INFO_CMD;
1003 i915->state.Buffer[I915_DESTREG_DBUFADDR1] =
1004 (BUF_3D_ID_DEPTH |
1005 BUF_3D_PITCH(screen->depthPitch * screen->cpp) |
1006 BUF_3D_USE_FENCE);
1007 i915->state.Buffer[I915_DESTREG_DBUFADDR2] = screen->depthOffset;
1008
1009
1010 i915->state.Buffer[I915_DESTREG_DV0] = _3DSTATE_DST_BUF_VARS_CMD;
1011
1012 switch (screen->fbFormat) {
1013 case DV_PF_555:
1014 case DV_PF_565:
1015 i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
1016 DSTORG_VERT_BIAS(0x8) | /* .5 */
1017 LOD_PRECLAMP_OGL |
1018 TEX_DEFAULT_COLOR_OGL |
1019 DITHER_FULL_ALWAYS |
1020 screen->fbFormat |
1021 DEPTH_FRMT_16_FIXED);
1022 break;
1023 case DV_PF_8888:
1024 i915->state.Buffer[I915_DESTREG_DV1] = (DSTORG_HORT_BIAS(0x8) | /* .5 */
1025 DSTORG_VERT_BIAS(0x8) | /* .5 */
1026 LOD_PRECLAMP_OGL |
1027 TEX_DEFAULT_COLOR_OGL |
1028 screen->fbFormat |
1029 DEPTH_FRMT_24_FIXED_8_OTHER);
1030 break;
1031 }
1032 i915->state.Buffer[I915_DESTREG_SENABLE] = (_3DSTATE_SCISSOR_ENABLE_CMD |
1033 DISABLE_SCISSOR_RECT);
1034 i915->state.Buffer[I915_DESTREG_SR0] = _3DSTATE_SCISSOR_RECT_0_CMD;
1035 i915->state.Buffer[I915_DESTREG_SR1] = 0;
1036 i915->state.Buffer[I915_DESTREG_SR2] = 0;
1037 }
1038
1039
1040 /* These will be emitted every at the head of every buffer, unless
1041 * we get hardware contexts working.
1042 */
1043 i915->state.active = (I915_UPLOAD_PROGRAM |
1044 I915_UPLOAD_STIPPLE |
1045 I915_UPLOAD_CTX |
1046 I915_UPLOAD_BUFFERS);
1047 }
1048
1049 void i915InitStateFunctions( struct dd_function_table *functions )
1050 {
1051 functions->AlphaFunc = i915AlphaFunc;
1052 functions->BlendColor = i915BlendColor;
1053 functions->BlendEquationSeparate = i915BlendEquationSeparate;
1054 functions->BlendFuncSeparate = i915BlendFuncSeparate;
1055 functions->ColorMask = i915ColorMask;
1056 functions->CullFace = i915CullFaceFrontFace;
1057 functions->DepthFunc = i915DepthFunc;
1058 functions->DepthMask = i915DepthMask;
1059 functions->Enable = i915Enable;
1060 functions->Fogfv = i915Fogfv;
1061 functions->FrontFace = i915CullFaceFrontFace;
1062 functions->Hint = i915Hint;
1063 functions->LightModelfv = i915LightModelfv;
1064 functions->LineWidth = i915LineWidth;
1065 functions->LogicOpcode = i915LogicOp;
1066 functions->PointSize = i915PointSize;
1067 functions->PolygonStipple = i915PolygonStipple;
1068 functions->Scissor = i915Scissor;
1069 functions->ShadeModel = i915ShadeModel;
1070 functions->StencilFunc = i915StencilFunc;
1071 functions->StencilMask = i915StencilMask;
1072 functions->StencilOp = i915StencilOp;
1073 }
1074
1075
1076 void i915InitState( i915ContextPtr i915 )
1077 {
1078 GLcontext *ctx = &i915->intel.ctx;
1079
1080 i915_init_packets( i915 );
1081
1082 intelInitState( ctx );
1083
1084 memcpy( &i915->initial, &i915->state, sizeof(i915->state) );
1085 i915->current = &i915->state;
1086 }
1087
1088
1089
1090
1091
1092
1093